Compose Deployment
The defaultdocker-compose.yml is the recommended remote-dev deployment. It starts:
server: the AoA API, UI, workers, adapters, and plugin runtime on port3100db: PostgreSQL with pgvector enabled viapgvector/pgvector:pg18
bootstrap service (behind the bootstrap Compose
profile) for pre-issuing an admin invite. See Instance admin
below — you do not need it for a normal deploy, where the first Google sign-in
becomes admin.
Authentication
The default stack runs inauthenticated mode, which requires Google OAuth.
Supply the OAuth client credentials before the first boot, or the server will
refuse to start:
authenticated: the container binds 0.0.0.0
for port publishing, and local_trusted (the keyless mode) is loopback-only,
so it cannot be used here. For a keyless local trial, run the native aoa CLI
instead of Docker — it binds 127.0.0.1 and supports local_trusted.
If you are exposing the container directly during early testing, AOA_PUBLIC_URL=http://<server-ip>:3100 is enough. Behind a reverse proxy, also set AOA_TRUST_PROXY=1; for a public internet deployment set AOA_DEPLOYMENT_EXPOSURE=public.
Defaults:
- Host port:
3100(AOA_PORT=3200changes it) - App data volume:
aoa-datamounted at/aoa - Database volume:
aoa-postgres - Database URL:
postgres://aoa:aoa@db:5432/aoa - Image tag:
aoa:local
/var/lib/postgresql. Do not point the new aoa-postgres volume directly at
an old Postgres 17 data directory; take a pg_dump/backup from the old stack
and restore it into the new database.
On a blank /aoa volume, the entrypoint creates:
/aoa/instances/default/config.json/aoa/instances/default/.envwith generatedBETTER_AUTH_SECRETandAOA_AGENT_JWT_SECRET- local storage, logs, backup, secrets, and workspace directories
AOA_MIGRATION_AUTO_APPLY=true.
Instance admin
Both admin paths run inauthenticated mode with Google configured — pick one
by how exposed the instance is:
- First sign-in wins (zero config). The first user to sign in with Google becomes the instance admin automatically. Best for a solo or trusted instance (behind a firewall / not publicly reachable) where no one else can sign in before you.
-
Pre-issued invite (recommended when the URL is exposed before you sign in).
Generate an admin invite and hand it to the intended founder, so a stranger
who reaches the sign-in page first can’t claim admin. The
bootstrapservice mints this invite; it is behind an opt-in profile and does not run during a normaldocker compose up. The instance must already be up (Google configured, server healthy):It exits cleanly when the instance already has an admin user; passBOOTSTRAP_FORCE=trueto mint another invite anyway. (The invite is redeemed via Google sign-in — it designates who becomes admin, it is not a way to run without Google.)
Configuration
Common overrides can be passed as environment variables:DATABASE_URL assembly. The default multi-service stack buildsFor S3-compatible storage:DATABASE_URLfrom theAOA_POSTGRES_*pieces inscripts/docker-entrypoint.sh, percent-encoding the user and password (URL-reserved characters need no manual escaping). Set your ownDATABASE_URL(host shell or.env) to override assembly and point at an external database. Quickstart and the standalonedocker runflow set noAOA_POSTGRES_*and stay on embedded PostgreSQL. Rotating the password. Postgres stores the role password at first initialization inside theaoa-postgresvolume. ChangingAOA_POSTGRES_PASSWORDlater does not re-set it — runALTER ROLE ... WITH PASSWORD ...(e.g. via thepsqltools profile) or recreate the volume.
/var/run/docker.sock is intentionally not enabled by default because it gives the container root-equivalent access to the host; add a local Compose override only for deployments that explicitly need sandbox-docker execution.
Single-Container Quickstart
For quick local trials,docker-compose.quickstart.yml runs one AoA container with embedded PostgreSQL:
${AOA_DATA_DIR:-./data/docker-aoa} and mounted at /aoa in the container.
The default host directory is ./data/docker-aoa; set AOA_DATA_DIR to
override it. The image uses /aoa as its persistent data directory.
Like the main stack, quickstart runs in authenticated mode and needs Google
OAuth credentials (the first Google sign-in becomes the instance admin):
Docker cannot run keyless.Override quickstart paths and ports with:local_trustedmode (the keyless path) only binds loopback, but a port-published container must bind0.0.0.0, whichlocal_trustedrefuses. For a keyless local trial without Google, run the nativeaoaCLI instead of Docker — it binds127.0.0.1and supportslocal_trusted.
Manual Docker Run
Build and run the image directly. The image defaults toauthenticated mode, so both
examples pass Google OAuth credentials — the server refuses to boot without them (see the
environment table above; for a keyless local trial use the native aoa CLI instead):
DATABASE_URL, this uses embedded PostgreSQL. To use an external database:
/aoa/instances/default/.env. You may still pass BETTER_AUTH_SECRET and
AOA_AGENT_JWT_SECRET explicitly if secrets are managed outside the container.
Data Persistence
The/aoa volume stores instance config, generated secrets, local
encrypted-secret key material, uploaded assets, run logs, backups, and agent
workspace data. Do not run authenticated deployments without a durable /aoa
mount or volume.