Self-Hosted AI Agent Control Plane for Enterprises

Configuration

All configuration is done via environment variables in .env.

Required Variables

Variable Description
POSTGRES_PASSWORD Database password. Use a strong random value.
JWT_SECRET JWT signing secret. At least 32 random characters.

Backend Variables

Variable Default Description
DATABASE_URL auto-generated PostgreSQL connection string. Auto-set from POSTGRES_* vars in Docker.
DEFAULT_ADMIN_EMAIL admin@aberon.internal Admin login email, created on first startup.
DEFAULT_ADMIN_PASSWORD (auto-generated) Admin password. If empty, a random password is printed in backend logs.
JWT_SECRET_PREVIOUS (empty) Previous JWT secret for key rotation. Set when rotating JWT_SECRET.
LOG_LEVEL info Logging level: debug, info, warning, error.
WORKERS 2 Number of uvicorn worker processes.
RATE_LIMIT_PER_MINUTE 600 Max API requests per minute per IP.

Data Retention

Variable Default Description
TRACE_RETENTION_DAYS 30 Traces older than this are auto-deleted.
AUDIT_RETENTION_DAYS 365 Audit log entries older than this are auto-deleted.
APPROVAL_RETENTION_DAYS 90 Approval records older than this are auto-deleted.

Approvals

Variable Default Description
APPROVAL_TIMEOUT_SECONDS 300 Default timeout for approval requests (5 minutes).

License

Variable Default Description
LICENSE_FILE /app/license.key Path to license file inside the container. See how license files work.
LICENSE_ENFORCE false Legacy setting. Freemium model always allows startup.

Demo

Variable Default Description
SEED_DEMO false Set to true to pre-populate demo data on first startup. See Demo Mode.

Networking

Variable Default Description
PORT 8080 Published host port for the gateway (nginx): dashboard UI and /api/* on the same origin. Override in .env if needed.

Architecture

docker compose up -d starts 4 containers:

┌─────────────────────────────────────────────────┐
│              Gateway (nginx:alpine)              │
│         Port 8080 on host (see PORT)              │
│                                                  │
│  /api/*  ──→  backend:8080                       │
│  /health ──→  backend:8080                       │
│  /*      ──→  frontend:3000                      │
└─────────────────────────────────────────────────┘
           │                    │
    ┌──────┴──────┐     ┌──────┴──────┐
    │   Backend   │     │  Frontend   │
    │  (FastAPI)  │     │  (Next.js)  │
    │  port 8080  │     │  port 3000  │
    │  internal   │     │  internal   │
    └──────┬──────┘     └─────────────┘
           │
    ┌──────┴──────┐
    │  PostgreSQL │
    │  port 5432  │
    │  internal   │
    └─────────────┘

Only the gateway port is exposed externally. Backend, frontend, and PostgreSQL communicate on an internal Docker network.

Backup & Restore

Backup

docker compose exec postgres pg_dump -U aberon aberon | gzip > backup-$(date +%Y%m%d).sql.gz

Restore

docker compose down
docker compose up -d postgres
# Wait for postgres to be healthy, then:
gunzip -c backup.sql.gz | docker compose exec -T postgres psql -U aberon aberon
docker compose up -d

Updating to a New Version

Your data is safe — it lives in a Docker volume. Migrations run automatically on startup.

# 1. Backup
docker compose exec postgres pg_dump -U aberon aberon | gzip > backup.sql.gz

# 2. Stop
docker compose down

# 3. Load new images (include gateway/nginx — easy to forget)
docker load < aberon-backend.tar.gz
docker load < aberon-frontend.tar.gz
docker load < nginx-alpine.tar.gz
# Or: for f in *.tar.gz; do docker load < "$f"; done

# 4. Start (migrations apply automatically)
docker compose up -d

# 5. Verify
docker compose logs backend | tail -20

Your .env, license.key, and database volume are preserved across updates.