Port Igniter
Get Started

Configuration

Every environment variable Reef reads, what it defaults to, and when you need to change it.

Reef Support Home

All configuration is done through environment variables. See the included .env.example below for the full, commented list. Three of them are required; everything else has a working default.

# Copy to .env and fill in real values:  cp .env.example .env
# .env is gitignored and is read by both docker compose and the app container.

# --- Django ---------------------------------------------------------------
# Generate with:
#   python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'
DJANGO_SECRET_KEY=replace-me
# "true" enables debug mode. Leave false for anything shared/deployed.
DJANGO_DEBUG=false
# Required when DJANGO_DEBUG=false. Comma-separated, no spaces.
# The compose service name `web` is added automatically (the agent, worker and
# beat containers reach the web service by that name); override with
# REEF_INTERNAL_WEB_HOST if you rename the service.
DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1
# Any host/IP you open the UI on. Reaching it by LAN IP or hostname without
# adding it here gives a bare "Bad Request (400)" page.
#   e.g. DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1,192.168.1.50,reef.example.com
#
# CSRF trust for POST actions (login, acknowledge, run scan, ...). Leave BLANK
# and every concrete host above is trusted automatically on http+https, bare and
# :8000. Set it explicitly (scheme required) only to override that:
#   e.g. DJANGO_CSRF_TRUSTED_ORIGINS=https://reef.example.com
DJANGO_CSRF_TRUSTED_ORIGINS=
# "true" when a TLS-terminating proxy / load balancer sits in front (it forwards
# plain http to the app). Makes Django trust X-Forwarded-Proto / -Host.
DJANGO_TRUST_PROXY=false

# --- Superuser -----------------------------------------------------------
# Created on first container start by entrypoint.sh (manage.py ensure_superuser).
DJANGO_SUPERUSER_USERNAME=admin
DJANGO_SUPERUSER_PASSWORD=replace-me
DJANGO_SUPERUSER_EMAIL=admin@example.com

# --- API keys ----------------------------------------------------------
# Accepted in the `X-API-Key` header by the token-protected API routes and by
# the agent. Comma-separated; supply several to allow rotation.
# Generate one with:  python -c 'import secrets; print(secrets.token_urlsafe(32))'
DJANGO_API_KEYS=

# --- Agent -------------------------------------------------------------
# The agent authenticates with this key; it MUST be one of DJANGO_API_KEYS.
REEF_AGENT_API_KEY=
# Optional; defaults to the monitored host's /etc/hostname (stable across restarts).
REEF_AGENT_NAME=
# Seconds between job polls / heartbeats.
REEF_POLL_INTERVAL=15

# --- Reef behaviour --------------------------------------------------
# Findings at or above this severity raise a notification (info|low|medium|high|critical).
REEF_NOTIFY_MIN_SEVERITY=high
# An agent with no check-in for this long is marked offline.
REEF_AGENT_OFFLINE_AFTER_SECONDS=300
# When "true", the auditd scan loads Reef's audit.rules into the host kernel
# (auditctl -R). Leave "false" to only *report* which rules are missing. To also
# persist the ruleset across reboots, add a read-write mount of /etc/audit to the
# agent service in docker-compose.yml.
REEF_AUDIT_MANAGE=false
# Size cap for the agent's scan scratch tmpfs (syft/grype temp files + the
# intermediate SBOM the grype scan builds). RAM-backed: size it to what the host
# can spare. A scan that needs more space fails cleanly with ENOSPC rather than
# filling the host disk. Grype's vuln DB lives on the grype-db volume, not here.
REEF_SCAN_TMP_SIZE=2g

# --- Celery ---------------------------------------------------------
# docker-compose sets these; override here if pointing at an external Redis.
# CELERY_BROKER_URL=redis://redis:6379/0
# CELERY_RESULT_BACKEND=redis://redis:6379/1

# --- SQLite3 ------------------------------------------------------
# Path inside the container (mounted volume so the DB survives rebuilds).
SQLITE_PATH=/data/db.sqlite3

# --- AI interpretation (optional, opt-in) -----------------------------
# Adds an "Interpret" button to the scan detail page and finding modals that
# sends scan/finding data to a local Ollama model and shows back a plain-
# language summary. Off unless OLLAMA_ENABLED=true. Needs real memory/CPU to
# run acceptably -- leave this off on a small box.
#
# 1. Uncomment the four lines below.
# 2. Start the bundled Ollama service too:
#      COMPOSE_PROFILES=ollama docker compose up -d
#    (or add `COMPOSE_PROFILES=ollama` as its own line in this file). The
#    `ollama-init` one-shot service pulls OLLAMA_MODEL on first start.
# OLLAMA_ENABLED=true
# OLLAMA_URL=http://ollama:11434
# OLLAMA_MODEL=llama3.2:3b
# OLLAMA_MEM_LIMIT=8g
You must set DJANGO_SECRET_KEY, DJANGO_API_KEYS, and REEF_AGENT_API_KEY before running anything beyond local dev.

Django & networking

Variable Default Meaning
DJANGO_DEBUG false true for local dev
DJANGO_ALLOWED_HOSTS localhost,127.0.0.1 comma-separated; REEF_INTERNAL_WEB_HOST is always added
REEF_INTERNAL_WEB_HOST web compose/k8s name of the web service — trusted in ALLOWED_HOSTS so agent/worker calls (Host: web) aren’t rejected
DJANGO_CSRF_TRUSTED_ORIGINS derived from ALLOWED_HOSTS leave blank to auto-trust every concrete host; set explicitly to override
DJANGO_TRUST_PROXY false true behind a TLS-terminating proxy — trusts X-Forwarded-Proto / -Host

Authentication

Variable Default Meaning
DJANGO_API_KEYS comma-separated; accepted in the X-API-Key header
REEF_AGENT_API_KEY the key the agent uses — must be one of DJANGO_API_KEYS
DJANGO_SUPERUSER_* credentials for the superuser created on first web start

Agent identity & polling

Variable Default Meaning
REEF_AGENT_NAME container hostname agent identity
REEF_SCAN_ROOT /host where the agent scans (compose mounts host / there)
REEF_POLL_INTERVAL 15 agent poll / heartbeat seconds

Notifications & job/agent health

Variable Default Meaning
REEF_NOTIFY_MIN_SEVERITY high findings at or above this severity raise a notification
REEF_AGENT_OFFLINE_AFTER_SECONDS 300 silence before an agent is marked “offline”
REEF_JOB_STALE_AFTER_SECONDS 3600 a claimed/running job with no result becomes expired

Metrics retention

Variable Default Meaning
REEF_METRIC_MIN_INTERVAL_SECONDS 20 minimum gap between stored agent resource samples (per agent)
REEF_METRIC_RETENTION_DAYS 14 agent resource samples older than this are pruned hourly

Scan tuning

Variable Default Meaning
REEF_FIM_DEFAULT_PATHS /etc,/bin,/sbin,/usr/bin,/usr/sbin,/boot FIM watch list
REEF_AUDIT_MANAGE false true → the auditd scan loads Reef’s ruleset into the host kernel
REEF_AUDIT_RULES_PATH <repo>/audit.rules ruleset the server diffs loaded rules against
REEF_SCAN_TMP_SIZE 2g size cap for the agent’s scan-scratch tmpfs (TMPDIR=/scan-tmp)
REEF_RAW_OUTPUT_MAX_BYTES 24000000 raw output larger than this is truncated for storage; DATA_UPLOAD_MAX_MEMORY_SIZE is derived from it
REEF_GRYPE_SOFT_MAX_BYTES 16000000 agent-side: trims descriptions/URLs/CVSS vectors if the trimmed Grype payload would still exceed this

Storage & Celery

Variable Default Meaning
SQLITE_PATH /data/db.sqlite3 database file (mounted volume)
GRYPE_DB_CACHE_DIR /var/cache/grype Grype’s vulnerability DB, persisted on the grype-db volume
CELERY_BROKER_URL / CELERY_RESULT_BACKEND redis://redis:6379/0 / /1 set by compose
DJANGO_EMAIL_BACKEND console notification email copies

Optinal AI Integration

Variable Default Meaning
OLLAMA_ENABLED true whether or not web expects an AI endpoint to be enabled
OLLAMA_URL http://ollama:11434 the api endpoint for your local ollama instance
OLLAMA_MODEL llama3.2:3b which model you want to use to perform the interpretation
OLLAMA_MEM_LIMIT 8g RAM limit for the ollama container (only applies if using the in cluded one)

Two gotchas worth knowing up front

  • 400 DisallowedHost on every agent/worker call. The agent and worker reach web as http://web:8000, which carries Host: web. Settings always appends REEF_INTERNAL_WEB_HOST (default web) to ALLOWED_HOSTS — without it, nothing ever checks in.
  • Bare “Bad Request (400)” opening the UI on a LAN IP or hostname. Add that host to DJANGO_ALLOWED_HOSTS. Each concrete host there is then auto-added to CSRF_TRUSTED_ORIGINS (http+https, bare and :8000), so POST actions — login, acknowledge, run scan, mark-read — work without a second variable. Behind a TLS-terminating proxy, also set DJANGO_TRUST_PROXY=true.

See Troubleshooting for more failure modes.

Top