Installation
obserae is a self-contained Network Detection & Response (NDR) daemon plus a small admin CLI. This page covers the two supported install paths (Docker and pre-built binaries), plus the basics of pointing your NetFlow exporters at it.
System requirements
| Resource | Recommended |
|---|---|
| OS / CPU | Linux, amd64 or arm64 (incl. Raspberry Pi 4/5 and ARM servers) |
| Memory | 4 GB for a small business; 8 GB at around 1,000 flows/s |
| CPU | 4 vCores for a small business; 8 at around 1,000 flows/s. Scales automatically up to ~50 cores. |
| Disk | Sized for your retention and traffic volume — NVMe or SSD, since much of the work is writing files. Start with a roomy volume and tune retention once you know daily growth. |
| Network | UDP ports for NetFlow (default 2055) and IPFIX (default 4739), TCP port for the GUI (default 8080) |
These are comfortable figures with headroom, not floors — obserae runs on less. For the measured per-store storage figures, the arithmetic to apply them to your own traffic, and a worked example, see Sizing.
obserae runs entirely on disk — no Elasticsearch, no Kafka, no Redis. The only external dependency at runtime is the IP-enrichment HTTPS fetcher (AWS / Azure / GCP), and it can be disabled.
Option 1 — One-line installer (recommended for bare-metal / VM)
On a bare-metal or VM Linux host, the installer does Option 3 and the whole systemd deployment in a single command — it picks the right architecture, verifies the release, installs the binaries, and creates the service user, directories, config and unit, then enables and starts it:
curl -fsSL https://get.obserae.com | sudo sh
It always checks the SHA256 checksum, and — if
cosign is installed —
the Sigstore keyless signature (add --verify-provenance for the SLSA build
provenance too). Without cosign it prints what to install for full verification
and continues on the checksum alone; pass --strict to require the signature.
See Verify a Release for what each check proves.
Useful flags (after -s --):
# just verify a release, install nothing (no root needed)
curl -fsSL https://get.obserae.com | sh -s -- --download-only
# pin a version / choose the binary directory
curl -fsSL https://get.obserae.com | sudo sh -s -- --version v0.27.0 --bin-dir /usr/local/bin
# remove it (add --purge to also delete data, config and the service user)
curl -fsSL https://get.obserae.com | sudo sh -s -- uninstall
On first boot obserae prints the generated admin password once
(journalctl -u obserae | grep -i password); back up
/var/lib/obserae/data/masterkey.bin offline.
Option 2 — Docker (recommended for containers)
The image is published to GitHub Container Registry as a multi-arch manifest: Docker automatically pulls the amd64 or arm64 build to match your CPU, so the same command works on a server, a desktop, or a Raspberry Pi.
docker run -d \
--name obserae \
--restart unless-stopped \
-p 2055:2055/udp \
-p 4739:4739/udp \
-p 127.0.0.1:8080:8080/tcp \
-v obserae-data:/var/lib/obserae \
ghcr.io/spartan-conseil/obserae:latest
What that does:
- Forwards UDP 2055 (NetFlow ingest), UDP 4739 (IPFIX ingest) and TCP 8080 (web GUI, localhost) from the host to the container.
- Mounts a named volume at
/var/lib/obseraeso traffic history, configuration, secrets and backups survive container restarts. - Loads the image’s default
obserae.yaml, pre-configured for container paths.
Open http://localhost:8080 to reach the web GUI.
The login keeps bouncing back to the login page (remote / plain HTTP)? This is the single most common Docker gotcha. The container binds the GUI on all interfaces, so the session cookie is marked
Secureby default — and a browser silently drops aSecurecookie received over plainhttp://from a remote IP. So your password is accepted but the session never sticks and you loop. (It works fromhttp://localhost:8080only because browsers treat localhost as a secure context.) Two fixes:
- Recommended — put TLS in front. Front obserae with a reverse proxy (Caddy, nginx, Traefik) terminating HTTPS and forwarding
X-Forwarded-Proto: https. The cookie staysSecureand login works.- Plain-HTTP LAN deployment (no TLS, trusted network): mount a config with
web.secure_cookies: false. The login then works over plain HTTP, but the session cookie travels unprotected — only do this on a trusted network. See Configuration.
Run as a non-root host user
By default the container runs as a built-in non-root user
(UID 65532). To make the files in the data volume owned by your
host user instead, run with --user and bind-mount a directory you
own:
Create the bind-mount directory yourself first. This one is not about obserae —
the daemon provisions everything it needs inside the volume — but about Docker:
a bind-mount source that does not exist is created by the Docker daemon as
root, and the container would then run as you with no write access to it.
mkdir -p ./obserae-data
docker run -d \
--name obserae \
--restart unless-stopped \
--user "$(id -u):$(id -g)" \
-p 2055:2055/udp \
-p 4739:4739/udp \
-p 127.0.0.1:8080:8080/tcp \
-v "$(pwd)/obserae-data:/var/lib/obserae" \
ghcr.io/spartan-conseil/obserae:latest
Override the config
docker run -d \
--name obserae \
-p 2055:2055/udp \
-p 4739:4739/udp \
-p 127.0.0.1:8080:8080/tcp \
-v "$(pwd)/obserae.yaml:/etc/obserae/obserae.yaml:ro" \
-v obserae-data:/var/lib/obserae \
ghcr.io/spartan-conseil/obserae:latest \
--config /etc/obserae/obserae.yaml
Docker Compose with TLS (Caddy) — recommended for remote access
For anything beyond http://localhost, run obserae behind a TLS reverse proxy so
the GUI login works (see the login-loop note above). A turnkey
obserae + Caddy stack ships in the
public distribution, but you fetch it through the branded installer — it brings
up HTTPS on :443 with a self-signed certificate, no domain or DNS required:
curl -fsSL https://get.obserae.com | sh -s -- compose
cd obserae-compose
docker compose up -d
# first-boot admin password (printed once)
docker compose logs obserae | grep "generated admin password"
Open https://ip and click through the one-time “not trusted” warning
(self-signed CA). Caddy terminates TLS and forwards X-Forwarded-Proto: https, so
obserae keeps the session cookie Secure and the login sticks.
What the stack runs:
- obserae — publishes only the flow-ingest ports (
2055/udp,4739/udp) to the host; the GUI (8080) is reachable only through Caddy, never as plain HTTP. - caddy — serves the GUI over HTTPS on
:443(and:80, used only when you switch to a real domain).
Real domain + browser-trusted certificate. Edit the bundled Caddyfile:
swap the self-signed block for the commented production block (your domain →
reverse_proxy obserae:8080), point the domain’s DNS at this host, and make ports
80 and 443 reachable from the internet. Caddy then provisions and auto-renews a
Let’s Encrypt certificate — no more warnings.
Run the admin CLI against the container
docker exec -it obserae obserae-cli status
Option 3 — Pre-built binaries
The branded installer selects your architecture, downloads the newest release, verifies its checksum and signature, and saves the release files in the current directory without installing anything:
mkdir obserae-release && cd obserae-release
curl -fsSL https://get.obserae.com | sh -s -- --download-only
Which architecture? Run
uname -m:x86_64→ amd64,aarch64→ arm64.
Extract and run:
tar xzf obserae_linux_*.tar.gz
cd obserae_linux_*
./obserae --config obserae.yaml
obserae creates its data directory on the first start, along with everything
inside it. You never have to lay the tree out by hand — just make sure the
account running the daemon can write where storage.data_dir points.
What’s inside the tarball:
obserae_linux_<arch>/
├── obserae # daemon (collects NetFlow/IPFIX and serves the GUI)
├── obserae-cli # admin CLI
├── obserae.yaml # minimal config (edit before production use)
├── EULA.txt # license / terms of use
└── docs/ # the full user documentation
The daemon prints INFO control api listening and
INFO collector listening once it is ready. Open
http://localhost:8080 to reach the web GUI. To stop, press Ctrl+C.
For a long-running install, see Operations for the systemd unit.
Verify before you run. The release is keyless-signed and ships an SBOM and provenance attestation. To check the tarball’s integrity, signature and origin, see Verify a Release.
After installing — send flows to obserae
obserae listens on UDP 2055 (NetFlow v5/v9) and UDP 4739 (IPFIX). Point
each device or software probe at <obserae-host> on the matching port.
Per-device setup for Cisco, Juniper, MikroTik, FortiGate, Palo Alto, pfSense/OPNsense, Open vSwitch, host probes and many more — and how to confirm flows are arriving — has its own page: Configuring Exporters.
Next steps
- Configuring Exporters — configure your devices and probes to send flows.
- Quickstart — your first cartography, first rules, and first query.
- Configuration — full configuration reference.
- Operations — running obserae as a systemd service, backups, troubleshooting.