Configuration
Central platform (.env)
All central-platform configuration is read from environment variables, set
in the .env file next to docker-compose.yml (development) or
deploy/docker-compose.prod.yml (production). Defaults below are the Go
backend’s built-in defaults — most are declared on the Config struct in
go-backend/internal/config/config.go, but a few aren’t: CLICKHOUSE_URL,
CLICKHOUSE_READ_TIMEOUT, and PROBE_EVENT_RETENTION_DAYS are read directly
via os.Getenv in internal/service/clickhouse/client.go; GEOIP_DB_DIR is
read via os.Getenv in cmd/server/main.go; and GEOIP_HOST_DIR isn’t read
by the Go binary at all — it’s a Compose-only variable used to pick the host
directory bind-mounted into the container. So config.go isn’t a single
source of truth for all of these. The production deploy/.env.example
deliberately omits defaults for secrets so an install can’t accidentally go
live with a known password.
Required in production
| Variable | Description |
|---|---|
POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD | Application database credentials |
JWT_SECRET | Session token signing secret. The backend refuses to start if unset or left as change-me-in-production |
ICINGA2_API_PASSWORD | Must match the password baked into the Icinga 2 container’s api-users.conf |
CLICKHOUSE_PASSWORD | ClickHouse credential — do not leave at the dev default in production |
CADDY_DOMAIN | Public domain/IP(s) Caddy serves; also the ACME domain in Let’s Encrypt mode |
Backend (Go API)
| Variable | Default | Description |
|---|---|---|
DATABASE_URL | postgres://eon:eon@localhost:5432/eon_aethis | PostgreSQL connection string. postgresql+asyncpg:// prefixes are normalized to postgres:// automatically |
REDIS_URL | redis://localhost:6379/0 | Redis connection string |
ICINGA2_API_URL | https://localhost:5665 | Icinga 2 REST API base URL |
ICINGA2_API_USER | root | Icinga 2 API user |
ICINGA2_API_PASSWORD | icinga | Icinga 2 API password |
VICTORIAMETRICS_URL | http://localhost:8428 | VictoriaMetrics query endpoint |
CLICKHOUSE_URL | — | ClickHouse DSN, e.g. clickhouse://user:pass@clickhouse:9000/db |
CLICKHOUSE_READ_TIMEOUT | 30s | Inter-packet read timeout for ClickHouse queries (Go duration), read via os.Getenv in internal/service/clickhouse/client.go. deploy/docker-compose.prod.yml and deploy/upgrade.sh set/enforce a 300s floor in production specifically so the one-time network_flows backfill migration doesn’t time out on upgrade (symptom otherwise: backend crashloops with read tcp ...: i/o timeout); a dev deployment that never sets this var gets the 30s in-binary default |
PROBE_EVENT_RETENTION_DAYS | 30 | Retention for probe telemetry in ClickHouse |
ANTHROPIC_API_KEY | — | Claude API key. Leave unset to disable the AI features |
JWT_SECRET | — (required) | Session token signing secret |
JWT_ALGORITHM | HS256 | JWT signing algorithm |
JWT_EXPIRATION | 86400 | Token lifetime in seconds |
PORT | 8000 | Backend listen port |
TLS_CERT, TLS_KEY | — | Optional: terminate TLS directly on the backend rather than at Caddy (e.g. agent-only edge sites). Generate dev certs with cd go-backend && go run ./cmd/gencert --host localhost,127.0.0.1 |
CORS_ORIGINS | http://localhost:5173,https://localhost | Allowed CORS origins |
ZEEK_LOG_DIR | — | Path to Zeek’s rotated log directory (mounted read-only from the zeek-logs volume, typically /var/log/zeek/current) |
SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASSWORD, SMTP_FROM | port 587, from noreply@eonaethis.local | Outbound mail for notifications. In Compose, SMTP_HOST defaults to host.docker.internal (dev) or 172.17.0.1 (prod) to reach a local MTA on the host |
GEO_HOME_LAT, GEO_HOME_LON | 52.3702, 4.8952 | Reference coordinates for geo-based features |
AETHIS_PUBLIC_BASE_URL | https://localhost:1443 | This instance’s externally reachable URL, used to build callback URLs sent to the Perimeter Probe |
BOOTSTRAP_ADMIN_EMAIL, BOOTSTRAP_ADMIN_PASSWORD, BOOTSTRAP_ADMIN_NAME | — | See First-boot admin account below |
RATE_LIMIT_AUTH_PER_MIN, RATE_LIMIT_API_PER_MIN | 0 (built-in defaults: 30/min auth, 600/min API) | Per-IP, per-minute rate limits. Set explicitly to tighten or disable for testing |
AETHIS_ENV | development | Set to production to make the backend refuse to start with known dev-default credentials (Icinga API password icinga, Postgres eon:eon, ClickHouse RO password eon_aethis_ro_dev) instead of just warning |
GEOIP_DB_DIR / GEOIP_HOST_DIR | /var/lib/eon/geoip / ./data/geoip | Container path / host path for optional MaxMind GeoLite2 databases (GeoLite2-ASN.mmdb, GeoLite2-Country.mmdb). If the host path doesn’t exist, enrichment falls back to category-only |
First-boot admin account
If BOOTSTRAP_ADMIN_EMAIL and BOOTSTRAP_ADMIN_PASSWORD are both set and
the users table is empty, the backend creates a single admin user with
those values on startup. On every subsequent boot the check is a no-op (the
table is no longer empty), so it’s safe to leave the variables set
permanently. deploy/install.sh also offers an interactive prompt for the
same purpose — use whichever fits: env vars for zero-interaction/CI
installs, the prompt for manual ones.
Zeek
| Variable | Default | Description |
|---|---|---|
ZEEK_INTERFACE | eth0 | Network interface Zeek sniffs |
ZEEK_PROFILE | prod | prod = minimal logging; dev = verbose full-protocol capture |
ZEEK_LOG_RETENTION_HOURS | 24 (prod) / 72 (dev) | Rotated logs older than this are deleted |
ZEEK_MAX_DISK_MB | 20480 | Hard disk ceiling for /var/log/zeek; the janitor force-prunes the oldest rotated files once exceeded, as a last-resort guard against disk-fill |
Caddy / TLS
| Variable | Default | Description |
|---|---|---|
CADDY_DOMAIN | localhost | Domain(s)/IP(s) Caddy serves, comma-separated |
CADDY_DEFAULT_SNI | value of CADDY_DOMAIN | Fallback SNI for connections without a Server Name (e.g. IP-based access) |
CADDY_TLS | internal | internal = self-signed; empty = ACME (Let’s Encrypt/ZeroSSL, needs port 80 open); or "<cert path> <key path>" for a supplied certificate |
CADDY_CERTS_DIR | — | Host directory mounted read-only at /etc/caddy/certs when supplying your own certificate |
CADDY_HTTPS_PORT, CADDY_HTTP_PORT | 443, 80 | Host ports Caddy binds (production compose only) — change when another reverse proxy already owns 443/80 on the host |
Postgres / ClickHouse container credentials
| Variable | Description |
|---|---|
POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD | Passed straight through to the postgres:16-alpine image |
CLICKHOUSE_DB, CLICKHOUSE_USER, CLICKHOUSE_PASSWORD | Passed straight through to the clickhouse/clickhouse-server image; the backend’s CLICKHOUSE_URL must reference the same values |
Aethis Agent (eon-aethis.conf, YAML)
See Agents & Probes — Aethis Agent
for the full field reference. Defaults if a field is omitted:
server.tls_verify: true, checks.interval: 60s,
checks.plugins_dir: /usr/lib/eon-aethis/plugins,
checks.system_plugins_dir: /usr/lib/nagios/plugins, and all metrics.*
flags true.
Aethis Probe (probe.yaml)
See Agents & Probes — Aethis Probe
for the full field reference: backend_url, probe_id, auth_token,
ca_path, tls_verify, push_interval, buffer_path,
buffer_max_events, buffer_max_bytes, interfaces (list of
{name, mode, bpf}), control_port, log_level.
Perimeter Probe (probe.yaml)
See Agents & Probes — Perimeter Probe
for the full field reference: addr, server_cert, server_key,
operator_ca, client_cert, client_key.