ATHELOS
Getting StartedSelf-hosted

Configuration

Environment variables, service tuning, and secret handling for a self-hosted ATHELOS.

Configuration

This page covers how to configure a self-hosted ATHELOS — which environment variables matter, how to tune services, and how to handle secrets.

The three env files

ATHELOS reads configuration from three files:

FileUsed by
.envScripts and Drizzle Kit (repo root)
apps/web/.env.localThe web application at runtime
docker/.envDocker Compose services

Each has an .example template. Copy and fill in real values.

Root .env

Used by scripts that run outside the web app — database migrations, seeds, and maintenance tasks.

VariablePurpose
DATABASE_URLPostgres connection string
REDIS_URLRedis connection string
MEILI_HOSTMeilisearch HTTP endpoint
MEILI_MASTER_KEYMeilisearch admin key
AUTH_SECRETSession signing secret

apps/web/.env.local

The full runtime config for the web app.

Required

VariablePurpose
DATABASE_URLPostgres connection string
AUTH_SECRETSession signing key — write-once
AUTH_TRUST_HOSTSet true for local dev behind a proxy
NEXTAUTH_URLPublic URL of the app
REDIS_URLRedis connection string
MEILI_HOSTMeilisearch HTTP endpoint
MEILI_MASTER_KEYMeilisearch admin key
MINIO_ENDPOINTMinIO hostname
MINIO_PORTMinIO port
MINIO_USE_SSLfalse locally, true in production
MINIO_ACCESS_KEYMinIO access key
MINIO_SECRET_KEYMinIO secret key
MINIO_BUCKETBucket for evidence files
TOTP_ENCRYPTION_KEYAES-256-GCM key for TOTP secrets — write-once

Optional — AI

VariableDefault
OLLAMA_HOSThttp://localhost:11434
OLLAMA_MODELllama3.2:3b
OLLAMA_NUM_CTX2048
OLLAMA_EMBED_MODELnomic-embed-text

Optional — WebAuthn

VariablePurpose
WEBAUTHN_RP_IDRelying Party ID — the domain
WEBAUTHN_RP_NAMEDisplay name shown in browser prompts
WEBAUTHN_ORIGINThe origin (e.g. https://athelos.example.com)

Optional — SMTP

VariablePurpose
SMTP_HOSTMail server
SMTP_PORTPort (587 or 465)
SMTP_USERLogin
SMTP_PASSWORDPassword
SMTP_FROMFrom address
SMTP_TODestination address
SMTP_SECUREtrue for implicit TLS

Optional — Webhooks

VariablePurpose
WEBHOOK_URLEndpoint to POST notifications to
WEBHOOK_SECRETHMAC signing secret

docker/.env

Used by Docker Compose.

VariablePurpose
POSTGRES_PASSWORDPostgres password for the soc user
REDIS_PASSWORDRedis AUTH password
MINIO_ROOT_USERMinIO admin username
MINIO_ROOT_PASSWORDMinIO admin password
MEILI_MASTER_KEYMeilisearch admin key

Important: values here must match the corresponding values in apps/web/.env.local. The app needs the passwords to connect.

Write-once secrets

Three secrets must never change after first use:

SecretConsequence of changing
AUTH_SECRETAll active sessions invalidated
TOTP_ENCRYPTION_KEYExisting TOTP secrets become undecryptable
RESTIC_PASSWORDExisting backup snapshots become unreadable

Back each one up to a password manager and on paper. Never commit them. Never email them.

Generating strong values

For passwords and secrets:

openssl rand -base64 32

For hex secrets:

openssl rand -hex 32

Use a different random value for each variable. Never reuse.

Reloading after changes

Environment changes require a restart:

  • Web app — kill and restart pnpm dev or the production service
  • Worker — kill and restart
  • Docker services — docker compose up -d re-reads docker/.env

The web app doesn't hot-reload env changes.

Service tuning

Postgres

Default settings are fine for a single-operator install. If you process large evidence files or run many concurrent queries, bump shared_buffers in docker-compose.yml:

postgres:
  command:
    - postgres
    - -c
    - shared_buffers=512MB
    - -c
    - work_mem=16MB

Redis

Redis is used for sessions, rate limits, and background jobs. Defaults are fine.

To change the max memory policy:

redis:
  command:
    - redis-server
    - --maxmemory
    - 256mb
    - --maxmemory-policy
    - allkeys-lru

MinIO

MinIO has no meaningful configuration beyond its credentials. It stores what you give it.

Meilisearch

Meilisearch defaults are fine. To cap memory:

meilisearch:
  environment:
    MEILI_MAX_INDEXING_MEMORY: 512Mb

Ollama (AI)

If you're running local AI, Ollama's memory usage depends on the model:

  • 3B models — 4 GB RAM minimum
  • 7B models — 8 GB recommended
  • 13B models — 16 GB recommended

To reduce memory, use a smaller model or lower OLLAMA_NUM_CTX.

Secrets management

Never store secrets in git. Never email them. Never paste them in a chat.

Where secrets live:

  • .env files — chmod 600, gitignored
  • Password manager — the master copy
  • Paper — offline backup for critical secrets

Where secrets do NOT live:

  • Source code
  • Config files in git
  • Documentation
  • Chat or email

To verify a file is gitignored:

git check-ignore -v apps/web/.env.local

Should output the .gitignore rule that ignores it.

Rotation

Secrets should be rotated annually per best practice — but three secrets are write-once (see above). The others can be rotated:

  • Postgres password — change in docker/.env, apps/web/.env.local, and the running database
  • Redis password — change in docker/.env and apps/web/.env.local
  • MinIO credentials — change in docker/.env and apps/web/.env.local
  • Meilisearch key — change in docker/.env, apps/web/.env.local, and apps/site/.env.local

After rotating, restart all services.

Production hardening

For a production install:

  • Full-disk encryption (LUKS)
  • SSH key-only, no password auth
  • UFW firewall enabled
  • Services bound to 127.0.0.1
  • .env files at 600 permissions
  • HTTPS via Caddy or a reverse proxy
  • Access via VPN (Tailscale or WireGuard)
  • No public exposure
  • Backups tested

See Security for the full threat model and hardening checklist.

Where to go next