Install / Docker

Docker Installation

Versioned images with Compose examples for file mode, PostgreSQL, and CP/DP deployments.

Pull the Image

bash
# Docker Hub (public pulls); pin a published tag
docker pull ferrumedge/ferrum-edge:v0.9.10

# Verify
docker run --rm ferrumedge/ferrum-edge:v0.9.10 version

Image Variants

The default image ships a no-op mock eBPF capture backend, which is what you want for ordinary gateway proxying. Real ambient mesh capture needs one of the Linux-only variants.

TagUse it forNotes
v0.9.10 Gateway proxying on any platform Default. Mock eBPF capture backend — not real capture.
v0.9.10-ebpf Real ambient / node-waypoint eBPF capture Linux only; kernel ≥ 5.7 with cgroup v2 + bpffs. Distroless — no /bin/sh, no iptables, so FERRUM_NODE_AGENT_FALLBACK_MODE=iptables crash-loops here.
v0.9.10-ebpf-tools iptables fallback and Ambient host-network UDP lifecycle Same eBPF build on Debian slim, carrying sh, iptables, ip6tables, and ip.
bash
# Real eBPF capture (Linux only, distroless)
docker pull ferrumedge/ferrum-edge:v0.9.10-ebpf

# eBPF plus iptables/shell fallback tooling
docker pull ferrumedge/ferrum-edge:v0.9.10-ebpf-tools

Required kernel capabilities differ by kernel version — see node agent security. For Kubernetes, see the Kubernetes install guide.

Quick Start Examples

File Mode (no DB)
bash
docker run -d \
  --name ferrum-edge \
  -p 8000:8000 \
  -v "$(pwd)/ferrum.yaml:/etc/ferrum/config.yaml:ro" \
  -e FERRUM_MODE=file \
  -e FERRUM_FILE_CONFIG_PATH=/etc/ferrum/config.yaml \
  ferrumedge/ferrum-edge:v0.9.10
Database Mode
bash
docker run -d \
  --name ferrum-edge \
  -p 8000:8000 \
  -p 8443:8443 \
  -e FERRUM_MODE=database \
  -e FERRUM_DB_TYPE=postgres \
  -e FERRUM_DB_URL="postgres://ferrum:secret@postgres:5432/ferrum" \
  -e FERRUM_ADMIN_JWT_SECRET="please-change-me-to-a-32+character-secret" \
  -e FERRUM_ADMIN_BIND_ADDRESS=127.0.0.1 \
  ferrumedge/ferrum-edge:v0.9.10
⚠
Admin API security: in writable database/cp modes the gateway refuses to start a plaintext admin listener on a non-loopback address without a FERRUM_ADMIN_ALLOWED_CIDRS allowlist. To reach admin from outside the container, set FERRUM_ADMIN_BIND_ADDRESS=0.0.0.0 and serve it over TLS (FERRUM_ADMIN_TLS_CERT_PATH/FERRUM_ADMIN_TLS_KEY_PATH, publish 9443) or restrict callers with FERRUM_ADMIN_ALLOWED_CIDRS and publish port 9000. Include loopback in the allowlist for local health probes. See docs/docker.md.

Docker Compose — Database Mode (PostgreSQL)

yaml — docker-compose.yml
services:
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: ferrum
      POSTGRES_USER: ferrum
      POSTGRES_PASSWORD: ferrum_secret
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ferrum"]
      interval: 5s
      timeout: 5s
      retries: 5

  ferrum-edge:
    image: ferrumedge/ferrum-edge:v0.9.10
    depends_on:
      postgres:
        condition: service_healthy
    ports:
      - "8000:8000"
      - "8443:8443"
    environment:
      FERRUM_MODE: database
      FERRUM_DB_TYPE: postgres
      FERRUM_DB_URL: postgres://ferrum:ferrum_secret@postgres:5432/ferrum
      FERRUM_ADMIN_JWT_SECRET: "change-this-to-a-32-plus-character-secret"
      FERRUM_ADMIN_BIND_ADDRESS: 127.0.0.1
      FERRUM_LOG_LEVEL: info
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "/app/ferrum-edge", "health"]
      interval: 10s
      timeout: 5s
      retries: 3

volumes:
  postgres_data:

Docker Compose — File Mode (no database)

yaml — docker-compose.file.yml
services:
  ferrum-edge:
    image: ferrumedge/ferrum-edge:v0.9.10
    ports:
      - "8000:8000"
    volumes:
      - ./ferrum.yaml:/etc/ferrum/config.yaml:ro
    environment:
      FERRUM_MODE: file
      FERRUM_FILE_CONFIG_PATH: /etc/ferrum/config.yaml
      FERRUM_LOG_LEVEL: info
    restart: unless-stopped

Docker Compose — Control Plane / Data Plane

yaml — docker-compose.cpdp.yml
services:
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: ferrum
      POSTGRES_USER: ferrum
      POSTGRES_PASSWORD: ferrum_secret
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ferrum"]
      interval: 5s
      timeout: 5s
      retries: 5

  control-plane:
    image: ferrumedge/ferrum-edge:v0.9.10
    depends_on:
      postgres:
        condition: service_healthy
    ports:
      - "50051:50051"  # CP gRPC
    environment:
      FERRUM_MODE: cp
      FERRUM_DB_TYPE: postgres
      FERRUM_DB_URL: postgres://ferrum:ferrum_secret@postgres:5432/ferrum
      FERRUM_ADMIN_JWT_SECRET: "change-this-to-a-32-plus-character-secret"
      FERRUM_CP_GRPC_LISTEN_ADDR: "0.0.0.0:50051"
      FERRUM_CP_DP_GRPC_JWT_SECRET: "change-this-cp-dp-secret-min-32-chars"
      FERRUM_CP_DP_GRPC_ALLOW_PLAINTEXT: "true"  # local dev only — use TLS in production
    restart: unless-stopped

  data-plane-1:
    image: ferrumedge/ferrum-edge:v0.9.10
    depends_on:
      - control-plane
    ports:
      - "8000:8000"
      - "8443:8443"
    environment:
      FERRUM_MODE: dp
      FERRUM_DP_CP_GRPC_URLS: http://control-plane:50051
      FERRUM_CP_DP_GRPC_JWT_SECRET: "change-this-cp-dp-secret-min-32-chars"
      FERRUM_CP_DP_GRPC_ALLOW_PLAINTEXT: "true"
    restart: unless-stopped

  data-plane-2:
    image: ferrumedge/ferrum-edge:v0.9.10
    depends_on:
      - control-plane
    ports:
      - "8001:8000"
      - "8444:8443"
    environment:
      FERRUM_MODE: dp
      FERRUM_DP_CP_GRPC_URLS: http://control-plane:50051
      FERRUM_CP_DP_GRPC_JWT_SECRET: "change-this-cp-dp-secret-min-32-chars"
      FERRUM_CP_DP_GRPC_ALLOW_PLAINTEXT: "true"
    restart: unless-stopped

volumes:
  postgres_data:

Docker Environment Variables

VariableDescriptionRequired
FERRUM_MODEfile | database | cp | dp | mesh | injector | node_agent | migrateYes
FERRUM_FILE_CONFIG_PATHConfig file path (file mode)file mode
FERRUM_DB_TYPEpostgres | mysql | sqlite | mongodbdb/cp modes
FERRUM_DB_URLDatabase connection stringdb/cp modes
FERRUM_ADMIN_JWT_SECRETJWT secret for Admin API (min 32 chars)db/cp modes
FERRUM_DP_CP_GRPC_URLSComma-separated Control Plane URLs (DP mode, failover order)dp mode
FERRUM_CP_DP_GRPC_JWT_SECRETShared secret for CP↔DP sync (min 32 chars)cp/dp modes
FERRUM_CP_GRPC_LISTEN_ADDRgRPC listen address (CP mode)No (def: 50051)
FERRUM_LOG_LEVELerror | warn | info | debug | traceNo (def: warn)
📤
Port reference: 8000 HTTP proxy • 8443 HTTPS proxy • 9000 Admin HTTP • 9443 Admin HTTPS • 50051 CP gRPC
Kubernetes Install → Admin API Reference