Skip to content
AgentDock

Self-hosting

Configuration reference

Every environment variable of the API and the web app.

AgentDock is configured with environment variables: the API reads its own set, and the web app takes two, partly at build time. This page lists every one of them with its default. The runner has its own config file, covered in the runner reference.

In a source checkout the files are apps/api/.env, apps/web/.env and docker/.env, each with a commented .env.example next to it. In the Docker Compose stack, the API reads env/api.env plus DATABASE_URL and REDIS_URL from the compose file.

API: core

VariableDefaultMeaning
PORT8180Port the API listens on. REST and the /live, /runner and /terminal WebSockets share it.
APP_ENVdevelopmentproduction marks the session and CSRF cookies Secure, so serve over HTTPS. test keeps every background worker off (used by the test suites).
API_URLhttp://localhost:8180The API origin runners pair with. The UI uses it to build the pairing command. Behind the reference proxy: https://<host>/api.
WEB_URLhttp://localhost:3517The web app's origin. It is the only CORS origin and the only Origin the /live and /terminal WebSockets accept.
APP_URLunsetPublic URL of the web app, used for links in Telegram messages and as the GitHub App manifest redirect. The GitHub App falls back to WEB_URL; Telegram messages have no link without it.
TRUST_PROXYloopbackExpress trust proxy: whose X-Forwarded-For to believe for the client IP (per-IP login throttle). Accepts true, false, a hop count, or addresses and names such as uniquelocal. See TRUST_PROXY.
DATABASE_URLnonePostgreSQL connection string. Required. Example: postgresql://postgres:<password>@postgres:5432/agentdock?schema=public.
REDIS_URLnoneRedis for BullMQ (cron schedules), redis:// or rediss://. Required unless SCHEDULER_ENABLED=false; the API refuses to start without it. Example: redis://:<password>@redis:6379/0.
QUEUE_PREFIXagentdockKey prefix of every BullMQ queue. Change it only to share one Redis between instances.
APP_ENCRYPTION_KEYunset32 random bytes, base64 (openssl rand -base64 32). Seals stored secrets with AES-256-GCM. Required for Telegram, inbound triggers, outbound webhooks and the GitHub App. Without a valid key the API still starts, but those features refuse to store secrets; a malformed key is logged once at start-up.

API: features and workers

VariableDefaultMeaning
SCHEDULER_ENABLEDtruefalse runs no schedules worker on this instance, and then REDIS_URL is not needed. Useful for maintenance.
WEBHOOKS_WORKER_ENABLEDtruefalse keeps the outbound webhook dispatcher and delivery worker off. Inbound triggers still answer.
PUBLIC_URLunsetPublic HTTPS base GitHub can reach, for POST <PUBLIC_URL>/hooks/github. Set it before creating the GitHub App. Unset: the App's webhook is created inactive and runners keep polling every 60 seconds. Behind the reference proxy: https://<host>/api.
GITHUB_API_BASEhttps://api.github.comGitHub REST API base. Tests point it at a mock.
TELEGRAM_API_BASEhttps://api.telegram.orgTelegram Bot API base. Tests point it at a mock.
TELEGRAM_POLL_TIMEOUT_S30Long-poll timeout for getUpdates, in seconds, from 1 to 50.
APP_TIMEZONEUTCDefault IANA time zone a new budget's day, week or month is cut in, for example Europe/Berlin. An unknown zone falls back to UTC.
TERMINAL_IDLE_TIMEOUT_SEC900A terminal attach with no input (read-write) or no traffic (read-only) for this long closes with idle.
TERMINAL_MAX_DURATION_SEC14400Any terminal attach closes with max_duration after this long (4 hours).
AUDIT_VERIFY_CRON0 3 * * *Cron schedule (server time) of the nightly audit hash-chain verification.
USAGE_RECOMPUTE_BATCH1000Requests re-priced per transaction when an admin re-prices a date range.
ACTIVITY_POLL_MS2000Poll interval of the activity feed and run history projector, in milliseconds. 0 turns the loop off.
ACTIVITY_GAP_GRACE_MS10000How long a gap in event ids is waited on before it is treated as a rolled-back id, in milliseconds.
ACTIVITY_RETENTION_DAYS180Days an activity feed item is kept. A daily job deletes older ones.

API: first admin

VariableDefaultMeaning
ADMIN_EMAILunsetWith ADMIN_PASSWORD, makes admin:create run without prompts.
ADMIN_PASSWORDunsetThe admin's password. Remove both after use.
ADMIN_NAMEunsetOptional display name.

API: development and tests

These matter only when you work on AgentDock itself.

VariableDefaultMeaning
TEST_DATABASE_URLnoneDatabase the end-to-end tests wipe and migrate on every run. Its name must end in _test.
TEST_REDIS_URLnoneRedis the end-to-end tests use, for example database 1.
BUN_BINbun on PATHBun binary the runner end-to-end test starts the real runner with.

Web app

VariableDefaultWhenMeaning
API_URLhttp://localhost:8180build and runTarget of the same-origin /api rewrite (fixed at build time) and the address server components call at runtime. In Compose: http://api:8180, as both a build argument and a container variable.
NEXT_PUBLIC_LIVE_URLws://localhost:8180/livebuildWebSocket URL of the live-updates endpoint, baked into the browser bundle. In production: wss://<host>/api/live. The web image refuses to build without it.

The web image also sets PORT=3517, HOSTNAME=0.0.0.0 (the standalone server binds to loopback otherwise), NODE_ENV=production and NEXT_TELEMETRY_DISABLED=1. A plain next dev from source does not disable Next.js telemetry; set NEXT_TELEMETRY_DISABLED=1 yourself if you care.

Changing NEXT_PUBLIC_LIVE_URL or the build-time API_URL means rebuilding the web image. Restarting the container is not enough.

Local database (docker/.env)

Used only by the development compose file in docker/, which bun run db:setup starts.

VariableExampleMeaning
POSTGRES_PASSWORDchange-mePassword of the postgres user. Must match DATABASE_URL in apps/api/.env.
REDIS_PASSWORDchange-meRedis password. Must match REDIS_URL (and TEST_REDIS_URL) in apps/api/.env.

The local stack publishes PostgreSQL on port 5421 and Redis on port 6421.

Ports

PortWhat
8180API (PORT)
3517Web app
5421PostgreSQL, local development compose only
6421Redis, local development compose only
127.0.0.1:4318The runner's OTLP receiver on each agent machine (loopback only)

A production example

env/api.env
PORT=8180
APP_ENV=production
API_URL=https://agentdock.example.com/api
WEB_URL=https://agentdock.example.com
APP_URL=https://agentdock.example.com
PUBLIC_URL=https://agentdock.example.com/api
TRUST_PROXY=uniquelocal
APP_TIMEZONE=Europe/Berlin
APP_ENCRYPTION_KEY=<output of openssl rand -base64 32>

Next steps