Configuration

Running it

Configuration

The installer writes every setting to /opt/cloudly/.env, and all three services read that one file. Most things you'd want to change (keys, plan sign-ins, allowed users, the spend limit, sandbox tools) are set in the browser instead, under Settings, and stored encrypted in the database.

After editing .env, restart the services:

sudo systemctl restart cloudly-api cloudly-worker cloudly-web

Keep .env readable only by its owner and the API's group (the installer sets 0640). It holds your database password and the key that encrypts your settings.

Addresses

VariableWhat it is
PUBLIC_URLWhere people reach the instance, for example https://203.0.113.10.
WEB_ORIGINThe web app's origin; normally the same as PUBLIC_URL.
API_ORIGINThe API as the browser sees it: PUBLIC_URL plus /api.
DOMAINOptional. A domain pointing at the VM, for HTTPS on that domain.

Database

VariableWhat it is
DATABASE_URLThe Postgres connection string.
LOCAL_POSTGRES1 runs Postgres in Docker on the VM, bound to localhost. 0 uses DATABASE_URL as is.
POSTGRES_PASSWORDThe bundled database's password.
API_PORTThe API's local port. Default 8787; it is never exposed.

Setup and encryption

VariableWhat it is
CLOUDLY_SETUP_TOKENThe one-time token that protects /setup.
CLOUDLY_SECRET_KEYEncrypts everything saved in the browser. Don't change it: settings saved with the old key become unreadable without the recovery key.

Fallback credentials

These are normally entered in the browser. A value in .env is only used when nothing is saved in Settings.

VariableWhat it is
ANTHROPIC_API_KEY, OPENAI_API_KEY, GEMINI_API_KEYModel API keys.
ALLOWED_GITHUB_LOGINSGitHub logins allowed to sign in, comma-separated.
GITHUB_APP_ID, GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, GITHUB_APP_INSTALLATION_ID, GITHUB_APP_PRIVATE_KEY_PATHThe GitHub App, if you created it by hand.
RESEND_API_KEYFor spend-limit emails.

Agents

VariableWhat it is
GEMINI_MODELGemini CLI's default model. Default gemini-3-flash-preview; auto lets Gemini choose.

Runs

VariableWhat it is
WORKER_CONCURRENCYTurns that run at the same time, across all sessions. auto (the default) runs about one per 1.5 GB of memory, from 1 to 4, and splits the sandbox memory between them. A number sets it.
SANDBOX_MEMORYMemory per run container. Default: the VM's RAM minus 768 MB, at least 512 MB.
SANDBOX_PIDSProcess limit per run container. Default 2048.
CLOUDLY_REPO_CACHEWhere the worker keeps a copy of each repo so turns start fast. Default ~/.cloudly/repo-cache; off clones the whole repo every turn.
CLOUDLY_REPO_CACHE_DAYSA repo's copy is removed after this many days without a turn. Default 14.
CLOUDLY_AGENT_UPDATE_HOURSHow often added agents are checked for newer versions. Default 6; 0 turns the checks off.

Fast starts

Each turn needs its own copy of the repo. Cloning a big repo from GitHub every time is slow (about a minute for t3code), so the worker keeps one copy of each repo on the VM. A turn fetches only what changed since the last one, makes its copy from that, and borrows the history instead of copying it. The agent still gets a normal git repo with the full history and every branch.

On t3code, a turn's workspace takes about 7 seconds instead of 58 once the repo has been used once. The first turn on a repo is as slow as before.

The copy only holds what's on GitHub, never your token. If it's ever damaged, the turn clones in full and the copy is rebuilt.

Desktops and previews

See Desktop and previews. The installer sets the first two.

VariableWhat it is
PREVIEW_ORIGINWhere previews open: your address on port 8443 (HTTPS) or 3141 (plain HTTP). Without it, previews only show on the sandbox's desktop.
PREVIEW_BINDWhich address the relay's preview port listens on. 127.0.0.1 behind Caddy, 0.0.0.0 on plain HTTP.
PREVIEW_PORTThe relay's preview port on the VM. Default 3141.
PREVIEW_MAXPreviews that may run at once. Default 1.
PREVIEW_TTL_MINUTESHow long a preview runs before it's stopped. Default 60.
RELAY_PORTThe relay's desktop port, on the VM only. Default 3140.

Prices

Used to estimate Codex and Gemini cost, in US dollars per million tokens. Claude Code reports exact cost and ignores these.

VariableExample
PRICE_CODEX_INPUT_PER_MTOK1.25
PRICE_CODEX_OUTPUT_PER_MTOK10
PRICE_GEMINI_INPUT_PER_MTOK0.30
PRICE_GEMINI_OUTPUT_PER_MTOK2.50

Agents added under Settings → Agents record no cost until you set their prices. Their variables are named after the agent's id, in capitals with underscores: for acp-cursor, PRICE_ACP_CURSOR_INPUT_PER_MTOK and PRICE_ACP_CURSOR_OUTPUT_PER_MTOK. They use the token counts the agent reports, so they're an estimate, and only agents that report tokens can be priced.

VariableExample
ACP_REGISTRY_URLWhere the API reads the ACP registry. Default https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json.

Alerts

VariableWhat it is
ALERT_FROMThe sender for spend-limit emails, for example Cloudly <alerts@example.com>.