Skip to content

Deployment

How to serve CARA to a team from one machine: making it reachable, sizing it, securing it, and keeping its data safe across upgrades.

Before you begin

CARA runs with Docker Compose on the server (Installation).

Opening it to the network

The web app listens on port 8501 of every network interface; the API and the database listen on the machine itself only. Set the name people use to reach the server in .env, then restart:

CARA_PUBLIC_HOST=cara.example.org
docker compose up -d

Annotators then open http://cara.example.org:8501. Their accounts are created by an admin, under Study settings in a study's header (Name and team).

HTTPS

Logins travel in the clear over plain HTTP. On any network you don't fully trust, put a reverse proxy with a certificate in front of the web app. With Caddy, which fetches the certificate by itself, the whole configuration is:

cara.example.org {
    reverse_proxy localhost:8501
}

The proxy must pass WebSocket connections through, which Caddy does by default; nginx needs the Upgrade and Connection headers set. Then close port 8501 to the outside, so the proxy is the only way in.

Server settings

Set in .env (the template is .env.example); restart with docker compose up -d after a change.

Variable Default Meaning
CARA_SECRET_KEY required Signs login tokens: a random string of 32 or more characters (openssl rand -hex 32). Changing it logs everyone out.
CARA_ADMIN_USERNAME, CARA_ADMIN_PASSWORD admin, set by quickstart.sh The first superuser, created when the API starts on a database without users.
CARA_PUBLIC_HOST localhost The name people open the web app by.
POSTGRES_PASSWORD cara The database password.
CARA_WORKERS 4 API processes.
CARA_DB_POOL_SIZE, CARA_DB_MAX_OVERFLOW 10, 10 Database connections per API process; keep CARA_WORKERS × (pool + overflow) under Postgres' limit of 100.
CARA_TOKEN_MINUTES 720 How long a login lasts.
HF_TOKEN empty For gated models when encoding (Encoding).

CARA sends no usage statistics and makes no outbound calls, except model downloads when you encode.

Capacity

Every click is saved at once, so nothing is lost when a browser closes, and annotators resume where they left off. Measured on one 12-core machine with the defaults:

10 users 50 users 100 users
Saves per second, users clicking without pause 333 318 275
Save latency, 95th percentile 59 ms 217 ms 481 ms

The web app is the tighter limit, because every browser session runs in one Python process: when 10 people open a 200-image query at the same moment, the page takes about 6 s to appear, and clicks afterwards about 0.2 s. For larger teams, run several frontend containers behind a load balancer with sticky sessions.

Backups

All of CARA's state (accounts, studies, judgments, the action log and the embeddings) is in Postgres; the images stay in data/. Back up the database while CARA runs:

docker compose exec -T db pg_dump -U cara -Fc cara > cara-$(date +%F).dump

To restore a backup into a fresh database:

docker compose down -v && docker compose up -d db
docker compose exec -T db pg_restore -U cara -d cara --no-owner < cara-2026-11-02.dump
docker compose up -d

Warning

docker compose down -v deletes the database volume. Run it only to restore a backup you have checked.

Upgrading

docker compose exec -T db pg_dump -U cara -Fc cara > cara-before-upgrade.dump
git pull
docker compose up -d --build

The API applies any database migrations when it starts, so an upgrade needs no further step. The release notes list what changed.