Getting Started

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

ResourceRecommended
OS / CPULinux, amd64 or arm64 (incl. Raspberry Pi 4/5 and ARM servers)
Memory4 GB for a small business; 8 GB at around 1,000 flows/s
CPU4 vCores for a small business; 8 at around 1,000 flows/s. Scales automatically up to ~50 cores.
DiskSized 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.
NetworkUDP 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.


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.


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/obserae so 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 Secure by default — and a browser silently drops a Secure cookie received over plain http:// from a remote IP. So your password is accepted but the session never sticks and you loop. (It works from http://localhost:8080 only 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 stays Secure and 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

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