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 | 3000 | External port for the gateway (nginx). This is the only port you need. |
Architecture
docker compose up -d starts 4 containers:
┌─────────────────────────────────────────────────┐
│ Gateway (nginx:alpine) │
│ Port 3000 (configurable) │
│ │
│ /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.