Skip to content

Latest commit

 

History

History
203 lines (156 loc) · 8.71 KB

File metadata and controls

203 lines (156 loc) · 8.71 KB

Deploy with Docker Compose

1. Start

Docker Compose is the supported way to run CLI2API. Published images, the console System-page updater, pre-update SQLite snapshots, and automatic rollback all assume this single-container install. A source checkout of Go / Node is for development; it does not receive managed updates.

The deployment is one container containing the Go control plane, provider adapters, Node runtime, pinned qodercli, and frontend. SQLite and account credentials persist in the qoder-data volume; per-account ephemeral runtimes use tmpfs where the provider requires them.

From the repository root, use:

macOS / Linux:

./scripts/start.sh

Windows PowerShell:

powershell -ExecutionPolicy Bypass -File .\scripts\start.ps1

Both launchers create deploy/.env if needed, pull the published image, fall back to a local build when necessary, and wait for /health.

To run Compose directly:

docker compose --env-file deploy/.env -f deploy/docker-compose.yml up -d

Add --build to build from the checked-out source. Only 127.0.0.1:3010 is published. Account and credential operations require the key stored in SQLite.

2. Account login storage

After startup, add accounts from /accounts using the login methods supported by each provider: Qoder browser OAuth, PAT, or qoder-native-v1 import; WorkBuddy / Trae browser OAuth or their provider credential import where applicable. Provider credentials are stored in SQLite. Qoder workers materialize their auth files only under the per-account tmpfs runtime directory; in-process providers keep their adapter state in the Go process.

3. Gateway

For another container on the same Docker network:

base_url = http://qoder-api-proxy:3010/v1
api_key  = <same key printed on first startup>

4. Connect an OpenAI client

export CLI2API_API_KEY='paste-the-key-printed-on-first-start'

curl http://127.0.0.1:3010/v1/chat/completions \
  -H "Authorization: Bearer $CLI2API_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "<model-id-from-v1-models>",
    "messages": [{"role": "user", "content": "Reply with OK only"}],
    "stream": false
  }'

PowerShell equivalent:

$env:CLI2API_API_KEY = "paste-the-key-printed-on-first-start"
$Headers = @{ Authorization = "Bearer $env:CLI2API_API_KEY" }
$Body = @{
  model = "<model-id-from-v1-models>"
  messages = @(@{ role = "user"; content = "Reply with OK only" })
  stream = $false
} | ConvertTo-Json -Depth 4
Invoke-RestMethod -Method Post -Uri "http://127.0.0.1:3010/v1/chat/completions" -Headers $Headers -ContentType "application/json" -Body $Body

Pin a request to a specific account with the X-Qoder-Account: acc_... header (a historical header name that applies to every provider). Add X-CLI2API-Session when consecutive requests should prefer the same account.

5. Configuration

Variable Default Purpose
QODER_DATA_DIR /data SQLite database and durable account credentials
QODER_RUNTIME_DIR /run/cli2api Ephemeral per-account runtime homes for providers that use child processes
QODER_MAX_RETRY_ACCOUNTS 4 Maximum accounts attempted for one request (1-64)
QODER_WORKER_BASE_PORT 32100 Internal child-runtime port range
QODERCLI_JS image default Pinned Qoder Global CLI bundle
QODERCNCLI_JS image default Pinned Qoder CN CLI bundle
UPDATE_GITHUB_TOKEN empty Optional GitHub token for release checks
UPDATE_AGENT_URL empty Docker Desktop host updater URL, written by the installer
UPDATE_AGENT_TOKEN empty Docker Desktop updater token, written by the installer
CLI2API_UPDATER_SOCKET_DIR platform-specific Host directory mounted read-only for the Linux updater socket

Per-account concurrency is configured through max_inflight in the console; it is persisted with each account and passed to its runtime.

The API key is generated once and stored in SQLite. There is no environment-variable bootstrap path; changing container environment variables does not replace the stored key.

6. Endpoints

Method Path Purpose
GET /health Health probe; no API key required
GET /v1/models Model catalog
POST /v1/chat/completions OpenAI-compatible chat
POST /v1/messages Anthropic-compatible messages
POST /v1/responses OpenAI Responses-compatible API
GET/POST/PATCH/DELETE /api/* Console management API

All console and API routes except /health require the API key stored in SQLite.

7. Managed next-version update

Start qoder-api-proxy once before installing the optional host updater.

Host Container platform Updater asset
Linux x86-64 linux/amd64 cli2api-updater_linux_amd64
Linux ARM64 linux/arm64 cli2api-updater_linux_arm64
macOS Intel Docker Desktop linux/amd64 cli2api-updater_darwin_amd64
macOS Apple Silicon Docker Desktop linux/arm64 cli2api-updater_darwin_arm64
Windows x86-64 Docker Desktop Linux containers cli2api-updater_windows_amd64.exe
Windows ARM64 Docker Desktop Linux containers cli2api-updater_windows_arm64.exe

Release assets include a SHA256 manifest. Installers use a verified prebuilt updater whenever possible. They download the latest GitHub updater asset first, then the asset matching the running container, then copy /app/cli2api-updater from the container, and finally fall back to a local Go 1.25.6+ build. A managed console update stages the host binary from the target release, copies /app/cli2api-updater from the new Linux container when possible, then atomically replaces the running updater and exits so systemd or LaunchAgent starts the new process.

macOS + Docker Desktop:

./deploy/install-updater.sh
docker compose --env-file deploy/.env -f deploy/docker-compose.yml up -d --force-recreate qoder-api-proxy

Linux + systemd:

sudo ./deploy/install-updater.sh
docker compose --env-file deploy/.env -f deploy/docker-compose.yml up -d --force-recreate qoder-api-proxy

Windows + Docker Desktop in Linux-container mode, from the logged-in Docker user's PowerShell:

powershell -ExecutionPolicy Bypass -File .\deploy\install-updater.ps1
docker compose --env-file deploy\.env -f deploy\docker-compose.yml up -d --force-recreate qoder-api-proxy

The application container never receives the Docker socket. Linux uses a private Unix Socket. macOS runs a per-user LaunchAgent and Windows runs a current-user Scheduled Task; both Docker Desktop platforms use an authenticated updater bound to 127.0.0.1 and reached through host.docker.internal.

Before replacement, the Go process pauses new API requests, waits for active requests to drain, and creates a verified SQLite snapshot in /data/backups. The updater recreates only qoder-api-proxy; it never runs docker compose down -v, and it verifies that the same /data mount remains attached. If the new version fails its versioned health check, or the host-updater binary cannot be replaced, the updater restores the previous image and the pre-update SQLite snapshot, discards any staged .new host binary, then pins CLI2API_IMAGE to the previous version for future restarts. The five most recent snapshots are retained.

The updater remains unavailable for development builds without a semantic version. The System page updates directly to the latest stable release, lists the intermediate versions it passes over, and can roll back to one of the three previous stable releases. An older host updater that does not yet speak staged updates still completes one jump, then replaces itself.

Release updater assets and the /app/cli2api-updater binary inside the image are stamped with the same Version and Commit as the application. Status reports that version next to protocol 2.

The updater API currently reports protocol version 2. Protocol 1 remains accepted for staged-update hosts; unknown versions fail closed.

8. Platform notes

  • scripts/start.sh and deploy/install-updater.sh are for macOS/Linux.
  • scripts/start.ps1 and deploy/install-updater.ps1 are the Windows equivalents.
  • Published application images are Linux-only and multi-architecture; macOS and Windows run them through Docker Desktop.
  • Published host updater assets cover Linux, macOS, and Windows on amd64 and arm64.
  • Run the Windows updater installer as the same signed-in user that runs Docker Desktop; do not install it as LocalSystem.
  • Keep deploy/.env private because Docker Desktop mode stores the updater token there.
  • Do not remove qoder-data unless you intentionally want to delete SQLite accounts and credentials.