Skip to content

Installation

cyb3rjerry edited this page May 23, 2026 · 1 revision

Installation

A fresh-machine guide. For the design behind the pieces see Architecture; for the day-to-day workflow see Operating.

Prerequisite matrix

Orchestrator host

The orchestrator is a single Go binary with no kernel dependencies. It runs on any Linux that can host a Go 1.22+ binary.

Component Requirement
OS Linux x86_64 (other archs untested)
Go 1.22+ to build from source
storage SQLite (default, no separate process) or Postgres 14+
disk ~100 MB for binary + var/lib/fangs growth
network outbound to registry.npmjs.org for the watcher; inbound on -addr for runners + UI

Runner host

The runner needs a real Linux kernel with eBPF + cgroup v2 + BTF support, and Docker.

Component Requirement
Kernel 4.18+ for tracepoint + BTF; 5.5+ recommended (sock-fd walk for connected-UDP DNS)
BTF /sys/kernel/btf/vmlinux readable — Ubuntu/Debian since 5.4, RHEL 8.4+, all current cloud images
cgroup v2 unified hierarchy required; check mount | grep cgroup2
Docker recent (any with Docker API v1.41+) — runner talks via stdlib net/http to /var/run/docker.sock
clang needed at BUILD time to compile the eBPF C; not needed at runtime
bpftool needed at BUILD time to dump vmlinux.h from the host BTF
Capabilities CAP_BPF + CAP_PERFMON on the runner binary, OR run as root
Mounts /sys/kernel/btf/vmlinux readable; /sys/kernel/tracing mounted (or auto-mounted at startup)

Distros that work out of the box

Distro Notes
Ubuntu 22.04+ clang via apt install clang; bpftool via apt install linux-tools-generic then symlink
Debian 12+ same packages; tracefs typically already mounted
Fedora 38+ dnf install clang bpftool; SELinux usually permissive enough for Docker socket
Arch pacman -S clang bpf
WSL2 Ubuntu works for dev; sensor needs cgroup-v2 cmdline + tracefs auto-mount (FANGS does this)
RHEL 8.4+ / 9 older bpftool may not be CO-RE; use linux-tools-* from EPEL or build from libbpf source

Distros with gotchas

Distro What's wrong
Ubuntu 20.04 bpftool ships old; install linux-tools-$(uname -r) and add to PATH
Kali 2024+ libssl.so.3 ships mode 644 (not executable); uprobe attach fails unless you chmod +x /usr/lib/x86_64-linux-gnu/libssl.so.3. Sensor degrades gracefully without it.
Alpine libc differences not yet tested; CO-RE should still work but no QA

Build

git clone https://github.com/irchaosclub/FANGS.git
cd FANGS
make install-hooks   # one-time per clone: gofmt pre-commit
make all             # generate vmlinux.h, compile eBPF C, build 4 binaries

Build outputs in bin/:

Binary Role
fangs-orchestrator control plane: HTTP API, watcher, differ, notifier, UI, pruner
fangs-runner execution agent: persistent eBPF sensor + sandbox driver
fangs operator CLI: package/run/deviation/baseline/notifier/allow/scan/pending
sensor-smoketest standalone sensor harness — dev/debug only

Build is reproducible (-trimpath); no CGO; the SQLite driver is modernc.org/sqlite (pure Go) so cross-compiling works.

First-time setup

1. Orchestrator

./bin/fangs-orchestrator

Defaults:

  • Listens on 127.0.0.1:8443 (plain HTTP)
  • SQLite at var/lib/fangs/fangs.db (parent dir auto-created)
  • Watcher enabled, polling registry.npmjs.org every 5 min
  • UI at /ui/, Prometheus at /metrics
  • Reads config/orchestrator.yaml if present
  • Retention pruner runs daily, deleting events older than 90 days

2. Runner

sudo ./bin/fangs-runner

The runner registers with the orchestrator on startup, then long-polls for jobs. Heartbeats every 30s. Sudo is required for CAP_BPF + Docker socket access; capability-based setup is covered below.

3. Verify

./bin/fangs run list                                       # empty
./bin/fangs scan submit -package lodash -version 4.18.1    # one-off scan
./bin/fangs run list                                       # the lodash scan

Open http://127.0.0.1:8443/ui/ for the dashboard. The scan should finish in 10–30 seconds depending on Node image pull. First run for a package always becomes the baseline (zero deviations).

Postgres backend

The orchestrator's SQLite default is fine for single-host operations. For multi-orchestrator setups (HA, regional deployments) you'll want Postgres so multiple orchestrators share state.

# Create a fangs database
createdb fangs
createuser fangs --pwprompt

# Point the orchestrator at it
export FANGS_PG_DSN="postgres://fangs:secret@db.internal:5432/fangs?sslmode=verify-full"
./bin/fangs-orchestrator -storage postgres

The same migrations run; the dual-backend storage contract suite in CI verifies every storage method behaves identically on both backends.

Capability-based runner

Running the runner as root is the easy path. For production you can drop privileges to a dedicated fangs-runner user holding only CAP_BPF + CAP_PERFMON + Docker socket group membership:

sudo useradd -r -s /sbin/nologin -G docker fangs-runner
sudo setcap cap_bpf,cap_perfmon+ep /opt/fangs/bin/fangs-runner
sudo -u fangs-runner /opt/fangs/bin/fangs-runner \
  -orchestrator https://fangs.internal:8443 \
  -tls-ca /etc/fangs/ca.crt \
  -tls-cert /etc/fangs/runner.crt \
  -tls-key /etc/fangs/runner.key

The setcap call must be reapplied if the binary is replaced (capabilities are extended attributes on the inode).

CAP_PERFMON is for kernel 5.8+; older kernels still need CAP_SYS_ADMIN on the runner binary.

systemd units

Example service files for both processes:

/etc/systemd/system/fangs-orchestrator.service:

[Unit]
Description=FANGS orchestrator
After=network.target

[Service]
Type=simple
User=fangs
Group=fangs
WorkingDirectory=/var/lib/fangs
ExecStart=/opt/fangs/bin/fangs-orchestrator -config /etc/fangs/orchestrator.yaml -addr 0.0.0.0:8443 -tls-cert /etc/fangs/server.crt -tls-key /etc/fangs/server.key -tls-client-ca /etc/fangs/ca.crt
Restart=on-failure
RestartSec=5
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/lib/fangs

[Install]
WantedBy=multi-user.target

/etc/systemd/system/fangs-runner.service:

[Unit]
Description=FANGS runner
After=network.target docker.service
Requires=docker.service

[Service]
Type=simple
User=fangs-runner
Group=docker
AmbientCapabilities=CAP_BPF CAP_PERFMON
ExecStart=/opt/fangs/bin/fangs-runner -orchestrator https://fangs.internal:8443 -tls-ca /etc/fangs/ca.crt -tls-cert /etc/fangs/runner.crt -tls-key /etc/fangs/runner.key
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Enable + start:

sudo systemctl daemon-reload
sudo systemctl enable --now fangs-orchestrator fangs-runner
sudo journalctl -fu fangs-orchestrator

Storage paths

What FANGS writes on disk:

var/lib/fangs/fangs.db          sqlite database (orchestrator-owned)
var/lib/fangs/fangs.db-wal      WAL journal (transient)
var/lib/fangs/fangs.db-shm      shared memory (transient)
/sys/fs/cgroup/.../fangs/<rid>/  per-scan cgroup parent (runner-owned, transient)

Crashed runners can leave orphan cgroup directories under /sys/fs/cgroup/.../fangs/*. They're empty and safe to rmdir once the container has exited.

Upgrading

Pull, rebuild, restart. Migrations run automatically on next orchestrator start. The dual-backend contract suite in CI catches schema drift between SQLite and Postgres.

git pull
make all
sudo systemctl restart fangs-orchestrator fangs-runner

Uninstall

FANGS leaves no persistent host state outside the binary directory and the database:

sudo systemctl stop fangs-orchestrator fangs-runner
sudo systemctl disable fangs-orchestrator fangs-runner
sudo rm /etc/systemd/system/fangs-{orchestrator,runner}.service
sudo rm -rf /opt/fangs /etc/fangs /var/lib/fangs
sudo userdel fangs-runner fangs

Clone this wiki locally