Skip to content
Installation

Installation

Overview

The central platform (backend, frontend, Icinga 2, PostgreSQL, VictoriaMetrics, ClickHouse, Redis, Zeek, and Caddy) is deployed as a single Docker Compose stack. There are two compose files:

  • docker-compose.yml (repository root) — the development stack. Builds images from source, exposes database ports on the host for local inspection, and uses hardcoded development credentials.
  • deploy/docker-compose.prod.yml — the production stack. Pulls pre-built eonaethis/* images, keeps internal services off the host network (only Caddy’s ports are published), and reads all credentials from .env with no built-in defaults for secrets.

The Aethis Agent, Aethis Probe, and Perimeter Probe are installed separately on the hosts and networks they observe — see Agents & Probes.

Prerequisites

  • Docker Engine with the Compose plugin (docker compose version works)
  • A host that can reach the internet for Let’s Encrypt (production, if not using self-signed or a supplied certificate)
  • Inbound access on the ports Caddy publishes (443/80 by default)

Development

From the repository root:

cp .env.example .env
# set ANTHROPIC_API_KEY if you want the AI features; everything else has a
# working development default
docker compose up

This starts nine services: caddy, backend, frontend, icinga2, postgres, victoriametrics, redis, zeek, and clickhouse. The development compose file publishes each service’s port on the host (5432, 8428, 6379, 5665, 9000/8123) for local debugging, and the backend and frontend containers bind-mount their source directories. Reach the UI at https://localhost (self-signed certificate by default — CADDY_TLS=internal).

ZEEK_INTERFACE defaults to eth0; set it in .env to the interface you want Zeek to sniff. The zeek service runs with network_mode: host and needs NET_RAW/NET_ADMIN, so it sees the host’s real interfaces rather than a Docker bridge.

Production

Production installs ship as a package built by deploy/build-package.sh (Docker images bundled as images.tar alongside deploy/docker-compose.prod.yml, deploy/install.sh, deploy/upgrade.sh, and deploy/.env.example). On the target server:

tar xzf eonaethis-<tag>.tar.gz
cd eonaethis
./install.sh

install.sh loads the bundled images, installs the shipped docker-compose.yml (only if one doesn’t already exist — it never overwrites an existing install), and creates .env from deploy/.env.example if missing. It then stops and tells you to edit .env before starting the stack; at minimum, change:

  • POSTGRES_PASSWORD
  • JWT_SECRET (generate with openssl rand -hex 32)
  • ICINGA2_API_PASSWORD
  • SMTP_FROM
  • CADDY_DOMAIN

CLICKHOUSE_PASSWORD also has no default in deploy/docker-compose.prod.yml and must be set manually — install.sh’s own printed reminder doesn’t currently list it, but the stack won’t come up with ClickHouse authenticated correctly until it’s set.

Alternatively, run deploy/setup.sh for an interactive wizard that prompts for domain/TLS, email, the Anthropic API key, the network interface, and the admin account, and writes .env for you — note that it does not currently ask about ClickHouse at all, and the .env it writes omits CLICKHOUSE_DB/CLICKHOUSE_USER/CLICKHOUSE_PASSWORD entirely, so add those to the generated .env by hand before starting the stack (the production compose file requires CLICKHOUSE_PASSWORD with no default). Once .env is filled in:

docker compose up -d

See Configuration for the full list of environment variables, and Configuration — First-boot admin account for creating the initial admin user without calling the register endpoint by hand.

Ports

By default Caddy is the only service that binds host ports:

PortServicePurpose
443CaddyHTTPS UI/API (override with CADDY_HTTPS_PORT)
80CaddyHTTP, used for ACME challenges (override with CADDY_HTTP_PORT)

Override CADDY_HTTPS_PORT/CADDY_HTTP_PORT when another reverse proxy on the host already owns 443/80. All other services (backend, icinga2, postgres, victoriametrics, redis, zeek, clickhouse) are reachable only on the Compose network, not the host, in the production compose file.

TLS

Caddy handles TLS for the platform, in one of three modes set via CADDY_TLS:

  1. Self-signed (default): CADDY_TLS=internal.
  2. Let’s Encrypt: leave CADDY_TLS empty and set CADDY_DOMAIN to a publicly resolvable domain, with port 80 reachable for the ACME challenge.
  3. Your own certificate: CADDY_TLS="/etc/caddy/certs/fullchain.pem /etc/caddy/certs/privkey.pem" and point CADDY_CERTS_DIR at the directory containing those files on the host (mounted read-only into the container at /etc/caddy/certs).

Demo traffic generator

The production compose file includes a demo-probe service behind the demo Compose profile, disabled by default. It writes synthetic flow events and must not be enabled on a real production install:

docker compose --profile demo up -d

Verifying the install

docker compose ps
curl -k https://localhost/health

The backend’s healthcheck hits its own /health endpoint and depends on PostgreSQL, Icinga 2, VictoriaMetrics, and ClickHouse all reporting healthy first, so docker compose ps showing backend as healthy implies the whole storage/monitoring layer came up correctly.

Upgrading

tar xzf eonaethis-<newer-tag>.tar.gz
cd eonaethis   # same directory as the existing install
./upgrade.sh

upgrade.sh loads the new images, backs up the current docker-compose.yml and .env to a timestamped .upgrade-backup-* directory, adds any new env vars introduced since your last install (with defaults), shows a diff against the shipped compose file for manual merging if your live file has diverged, then runs docker compose up -d. Postgres migrations and the ClickHouse schema bootstrap are applied automatically by the backend on startup, and the script waits for /health to go green before finishing.

For upgrades that also change infrastructure (not just the backend image), use deploy/major-upgrade.sh instead — check its output for what it does in your specific package version before running it, since it goes further than the routine upgrade.sh flow.