Savannah Cloud

Running with Docker

Start the full 5-service Savannah Cloud stack locally using Docker Compose.

Services

docker-compose.yml defines 5 services:

ContainerImagePortPurpose
riftcloud-app-1Built from Dockerfile8080Go API + Worker pool
riftcloud-dashboard-1Built from dashboard/80React UI (Nginx)
riftcloud-postgres-1postgres:16-alpine5432PostgreSQL database
riftcloud-redis-1redis:7-alpine6379Job queue + sessions
riftcloud-pdns-1PowerDNS Auth 4.953, 8081Custom domain DNS

First-time Setup

# 1. Clone the repo
git clone https://github.com/Mbuthia71/distributed-task-queue.git
cd distributed-task-queue

# 2. Create .env with minimum required variables
echo "JWT_SECRET=$(openssl rand -hex 32)" > .env
echo "RESEND_API_KEY=re_..." >> .env
echo "AT_API_KEY=atsk_..." >> .env
echo "AT_USERNAME=your_at_username" >> .env

# 3. Build and start all 5 services
docker compose up -d --build

DATABASE_URL, REDIS_URL, and PDNS_API_URL are set automatically by Docker Compose.


Common Commands

# Start all services (no rebuild)
docker compose up -d

# Rebuild after code changes — ONLY rebuild app and dashboard, NOT postgres
docker compose up -d --build app dashboard

# Stop all services (data preserved)
docker compose down

# Wipe all data (fresh start)
docker compose down -v

# Live logs
docker compose logs -f app

# Check service status
docker compose ps

Never run docker compose up -d --build without specifying services in production — it will rebuild postgres and may cause auth issues. Always use --build app dashboard.


Health Checks

All services should show Up (healthy) within ~30 seconds:

# Full health check — postgres and redis status included
curl http://localhost:8080/health
# → {"status":"ok","postgres":"ok","redis":"ok"}

# Container status
docker compose ps

# Verify Redis
docker compose exec riftcloud-redis-1 redis-cli ping
# → PONG

PostgreSQL Authentication

The stack mounts a custom pg_hba.conf (tracked in repo) into the postgres container. It uses trust for Docker's internal 172.x.x.x network — no password needed for inter-container communication:

host  all  all  172.0.0.0/8  trust
host  all  all  0.0.0.0/0    scram-sha-256

This permanently prevents SCRAM auth failures when the app container is rebuilt. See Postgres Auth Notes for full details.


Dockerfile

Multi-stage build:

  1. Stage 1 (builder) — compiles Go binary + builds React dashboard (npm run build)
  2. Stage 2 (runtime) — copies binaries into a minimal base image

See Environment Variables for the full variable reference.

On this page