Quick Start
Docker Compose Deployment
Prerequisites
- Linux host (Ubuntu 22.04+ / Debian 12+)
- Docker Engine 28+, Docker Compose v2
- At least one egress IP (proxy server)
1. Clone
git clone https://github.com/ZaneL1u/cloud-cli-proxy.git
cd cloud-cli-proxy2. Generate Environment Config
bash deploy/scripts/setup-env.shThe script supports two database modes:
- SQLite single-file database: auto-created, zero config, managed by Docker Compose with
/datapersistence.
Both modes auto-generate an admin password (20 chars) and JWT secret (48 chars).
Important
The script displays the admin password once. Save it immediately.
3. Start Services
# Start
docker compose pull
docker compose up -dIf prebuilt images are unavailable, build from source:
docker compose -f docker-compose.yml -f docker-compose.build.yaml --profile build-only build --no-cache
docker compose -f docker-compose.yml -f docker-compose.build.yaml up -d --force-recreate4. Verify
curl http://127.0.0.1:8080/healthz
# {"status":"ok","checks":{"database":"ok","agent":"ok"}}Service endpoints:
- API:
http://YOUR_HOST:8080 - Admin dashboard (embedded):
http://YOUR_HOST:8080 - SSH proxy:
YOUR_HOST:2222
Provisioning Users
Full workflow: login → add egress IP → create user → create host & bind → send connection command.
1. Get Admin Token
Log in via the admin dashboard or use the API:
TOKEN=$(curl -s -X POST http://YOUR_HOST:8080/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"your-admin-password"}' | grep -o '"token":"[^"]*"' | cut -d'"' -f4)2. Add Egress IP
Egress IPs use sing-box tun full-tunnel mode. Set tunnel_type to proxy and configure the upstream in proxy_config.
Supports 6 protocols: SOCKS5, VMess, VLESS, Shadowsocks, Trojan, HTTP.
# Shadowsocks
curl -s -X POST http://YOUR_HOST:8080/v1/admin/egress-ips \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"label": "jp-ss-01",
"ip_address": "198.51.100.5",
"tunnel_type": "proxy",
"provider": "manual",
"proxy_config": {
"type": "shadowsocks",
"server": "198.51.100.5",
"server_port": 8388,
"method": "aes-256-gcm",
"password": "your-ss-password"
}
}'# SOCKS5
curl -s -X POST http://YOUR_HOST:8080/v1/admin/egress-ips \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"label": "us-socks-01",
"ip_address": "192.0.2.50",
"tunnel_type": "proxy",
"provider": "manual",
"proxy_config": {
"type": "socks",
"server": "192.0.2.50",
"server_port": 1080,
"username": "user",
"password": "pass"
}
}'Test egress IP connectivity:
curl -s -X POST http://YOUR_HOST:8080/v1/admin/egress-ips/{ipID}/test \
-H "Authorization: Bearer $TOKEN"The test result covers connectivity, exit IP match, and DNS leak detection.
3. Create User
curl -s -X POST http://YOUR_HOST:8080/v1/admin/users \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"username": "zhangsan",
"password": "initial-password-for-user",
"expires_at": "2026-12-31T23:59:59Z"
}'4. Create Host & Bind Egress IP
# Create host
curl -s -X POST http://YOUR_HOST:8080/v1/admin/hosts \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"user_id": "user-uuid"}'
# Bind egress IP
curl -s -X POST http://YOUR_HOST:8080/v1/admin/bindings \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"host_id": "host-uuid", "egress_ip_id": "egress-ip-uuid"}'TIP
A host requires at least one bound egress IP to start.
5. Send Connection Info
After the host is created and the task shows the container is ready, copy the connection command from the host detail page in the admin dashboard.
Option A: curl + SSH
Send this command to the user (replace YOUR_HOST and SHORT_ID):
curl -sSf http://YOUR_HOST/entry/SHORT_ID | bashOr use the bootstrap flow (user enters their username):
curl -sSf http://YOUR_HOST:8080/v1/bootstrap/script | bashOption B: cloud-claude CLI (recommended)
In addition to the curl command above, share these three values:
| Field | Description |
|---|---|
| Gateway URL | Public HTTPS address of the control plane, e.g. https://gw.example.com |
| Short ID | Host short ID from the host detail page |
| Password | The user's password set in the admin dashboard |
After installing cloud-claude and running init with those values, the user runs cloud-claude from their project directory. The current directory is mounted at the same path inside the container via sshfs.
User Access
cloud-claude CLI (recommended)
Install
Homebrew (macOS / Linux):
brew tap ZaneL1u/tap
brew install cloud-claudeOne-liner:
curl -fsSL https://raw.githubusercontent.com/ZaneL1u/cloud-cli-proxy/main/scripts/install.sh | bashAlso available from Releases or go build ./cmd/cloud-claude.
First-time Setup
cloud-claude initFollow the prompts to enter gateway URL, Short ID, and password. Writes to ~/.cloud-claude/config.yaml.
Or use flags or environment variables:
cloud-claude init --gateway https://gw.example.com --short-id abc123 --password your-password
export CLOUD_CLAUDE_GATEWAY=https://gw.example.com
export CLOUD_CLAUDE_SHORT_ID=abc123
export CLOUD_CLAUDE_PASSWORD=your-password
cloud-claude initDaily Use
cd ~/your-project
alias claude=cloud-claude
cloud-claude
cloud-claude -p "refactor this function"Session management:
cloud-claude # default: attach existing session
cloud-claude --new-session # create a new isolated session
cloud-claude --take-over # take over primary session, detach others
cloud-claude sessions # list current sessionsMount modes:
cloud-claude --mount-mode=auto # default: HotSync preferred, falls back to SSHFS
cloud-claude --mount-mode=full # HotSync + SSHFS dual-track
cloud-claude --mount-mode=sshfs-only # SSHFS onlySelf-checks and troubleshooting:
cloud-claude doctor # full five-domain check
cloud-claude doctor mount --fix # mount check with auto-repair
cloud-claude explain MOUNT_SSHFS_DISCONNECTED # error code lookup
cloud-claude env check # verify remote timezone, egress IP, FUSE, etc.Common config (~/.cloud-claude/config.yaml):
proxy_commands— commands to run on the host (default["git"]); set to[]to disablehot_sync_max_file_mb— per-file throttling threshold (default 50MB)CLOUD_CLAUDE_NO_PROMOTION=1— disable cold-file read promotion
curl + SSH Access
Run the command your admin provided:
curl -sSf http://YOUR_HOST/entry/abc123 | bashEnter your password, wait for the container to be ready, and you will be connected via SSH automatically.
Pre-installed Tools
| Tool | Description |
|---|---|
| Claude Code | Run claude in terminal |
| KasmVNC + Chromium | Browser desktop via admin dashboard |
| Git / tmux / zsh | Common dev tools |
| Node.js | JavaScript runtime |
Using Claude Code
Once inside the container:
claudeAll Claude API requests are automatically routed through the egress IP. No proxy configuration needed.
Reconnecting
If SSH disconnects, re-run the same curl command to reconnect. The container keeps running.
Rebuilding
Click "Rebuild" in the admin dashboard to reset the environment. Home directory data is preserved.
Source Development
For contributing or customizing, set up a local dev environment as follows.
1. Install Dependencies
- Go 1.25.7+
- Node.js 20+ (recommend enabling
corepack) - pnpm 10+
- Docker Engine + Docker Compose v2
- GNU Make
2. Set Up
git clone https://github.com/ZaneL1u/cloud-cli-proxy.git
cd cloud-cli-proxy
make setup # install frontend deps, generate .env
make dev # backend + frontend hot reloadAfter startup:
- Admin frontend:
http://localhost:2568 - Control Plane API:
http://127.0.0.1:8080
3. Verify
curl http://127.0.0.1:8080/healthz
make testCommon Commands
make dev-api # backend only
make dev-web # frontend only
make help # list all commandsNext Steps
- Deployment Guide — systemd native deployment
- Configuration — environment variables and networking
- Architecture — system design and project structure
- API Reference — full Admin API docs
- FAQ & Troubleshooting — common issues and recovery