Savannah Cloud

Self-hosting on Hetzner VPS

Deploy Savannah Cloud to a Hetzner VPS — production instance at 178.105.152.34.

Production instance: 178.105.152.34 · App directory: /opt/riftcloud


Prerequisites

  • A Hetzner Cloud VPS (Ubuntu 24.04 recommended)
  • SSH access as root
  • All required environment variables ready

Initial Server Setup

ssh root@YOUR_SERVER_IP

apt update && apt install -y docker.io docker-compose-plugin git

git clone https://github.com/Mbuthia71/distributed-task-queue.git /opt/riftcloud
cd /opt/riftcloud

# Create .env with all required variables
nano .env

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

Services will be available at:

ServiceURL
APIhttp://YOUR_SERVER_IP:8080
Dashboardhttp://YOUR_SERVER_IP:80
Healthhttp://YOUR_SERVER_IP:8080/health

Updating After Code Changes

ssh -i ~/.ssh/id_ed25519 root@178.105.152.34
cd /opt/riftcloud
git pull
docker compose up -d --build app dashboard

Do NOT use --build without specifying services. Always use --build app dashboard to avoid rebuilding the postgres container and wiping data.


If Postgres Auth Fails After Rebuild

cd /opt/riftcloud
bash fix_scram.sh

This resets the SCRAM-SHA-256 password hash and restarts the app. The pg_hba.conf in the repo uses trust for Docker's 172.x.x.x network — auth failures should not recur. See Postgres Auth Notes.


Monitoring

# API health — checks postgres + redis
curl http://178.105.152.34:8080/health
# → {"status":"ok","postgres":"ok","redis":"ok"}

# Prometheus metrics
curl http://178.105.152.34:8080/metrics

# Live logs
docker compose logs -f app

# All container statuses
docker compose ps

Firewall Recommendations

PortPurpose
22SSH
80Dashboard (React + Nginx)
8080Go API
53PowerDNS (custom domain DNS)

Keep ports 5432 (Postgres), 6379 (Redis), and 8081 (PowerDNS API) closed to external traffic — they should only be accessible within the Docker network.


Running Tests

go test ./... -v
go test -run TestPushJob -v
go test -race ./...

On this page