Skip to the content.

How to deploy RedGNAT with Docker Compose

This guide covers a production-ready Docker Compose deployment with Postgres, Redis, the Celery worker and beat scheduler, and the FastAPI server.


Prerequisites


1 — Prepare configuration

Create a config/ directory with your production config:

cp config/config.ini.example config/redgnat.ini
$EDITOR config/redgnat.ini

Minimum changes from the template for a Docker deployment:

[redgnat]
# Use Docker service hostnames, not localhost
db_url = postgresql://redgnat:redgnat@postgres:5432/redgnat
redis_url = redis://redis:6379/0
dry_run = false

[gnat]
config_path = /run/secrets/gnat.ini

The docker-compose.yml mounts ./config/redgnat.ini into every service at /app/config/redgnat.ini.


2 — Set the API key

The API server reads its key from the REDGNAT_API_KEY environment variable. Set it in a .env file (never commit this):

echo "REDGNAT_API_KEY=$(openssl rand -hex 32)" > .env

The compose file references ${REDGNAT_API_KEY} for the api service.


3 — Build and start

docker compose up --build -d

Services start in dependency order:

postgres (healthy) ─┬─► worker ─► beat
redis (healthy)    ─┘─► api

Check that everything is running:

docker compose ps
NAME        IMAGE      STATUS          PORTS
postgres    postgres   Up (healthy)    0.0.0.0:5432->5432/tcp
redis       redis      Up (healthy)    0.0.0.0:6379->6379/tcp
worker      redgnat    Up
beat        redgnat    Up
api         redgnat    Up              0.0.0.0:8000->8000/tcp

4 — Apply migrations

Migrations run automatically on first Postgres start (they are mounted into /docker-entrypoint-initdb.d/). Verify the schema was applied:

docker compose exec postgres psql -U redgnat -c "\dt"

You should see intel_feeds, emulation_scenarios, emulation_runs, and technique_results tables.


5 — Verify the deployment

curl -s http://localhost:8000/api/v1/health
# {"status":"ok","service":"redgnat"}

curl -s -X POST http://localhost:8000/api/v1/intel/ingest \
  -H "X-API-Key: $(grep REDGNAT_API_KEY .env | cut -d= -f2)"

6 — View logs

# All services
docker compose logs -f

# Specific service
docker compose logs -f worker
docker compose logs -f api

Updating

git pull
docker compose build
docker compose up -d

Rolling updates are not currently supported — all services restart together.


Stopping and data retention

# Stop without deleting data
docker compose down

# Stop AND delete the Postgres volume (loses all scenario/run data)
docker compose down -v

The redgnat_pgdata Docker volume persists all database state across restarts. Back it up before any destructive operation:

docker compose exec postgres pg_dump -U redgnat redgnat | gzip > redgnat-backup.sql.gz

Production hardening checklist