Runbooks & Refs • Operational
Runbook: One-Click Self-Hosting with Auto-TLS
This runbook deploys the Porch platform — a private, invite-only social app — from zero to a TLS-secured production host. The same flow targets Hetzner, AWS, GCP, or an existing Ubuntu box; the launch scripts provision the server, install Docker, render config, and bring the stack up behind Caddy.
Stack that gets deployed
Go 1.25 API (:8080) · Next.js 15 frontend (:3000) · PostgreSQL 16 · Redis 7 ·
MinIO (S3-compatible) · FFmpeg transcoding worker · Caddy 2 reverse proxy
(:80/:443, automatic Let’s Encrypt). Everything runs under Docker Compose in
/opt/porch.
1. Configure secrets
cp .env.example .env.prod
openssl rand -hex 64 # JWT_SECRET
openssl rand -hex 20 # DB_PASSWORD / REDIS_PASSWORD
npx web-push generate-vapid-keys # VAPID_PUBLIC_KEY / VAPID_PRIVATE_KEY
# then set DOMAIN, MAILGUN_*, and (optionally) TWILIO_* in .env.prod
2. Provision & deploy (pick one)
# Hetzner / AWS / GCP — provisions the server and deploys in one shot
./scripts/launch-hetzner.sh --domain porch.example.com --email [email protected] --generate-secrets
./scripts/launch-aws.sh --domain porch.example.com --email [email protected] --generate-secrets
./scripts/launch-gcp.sh --domain porch.example.com --email [email protected] --generate-secrets
# Existing Ubuntu 22.04/24.04 server
./scripts/deploy.sh root@<server-ip>
3. Point DNS & verify TLS
Add an A record for your domain to the IP the script prints. Wait ~30–60s for
propagation; Caddy then issues the certificate on first request. Visit
https://porch.example.com to confirm.
4. Bootstrap the first admin
ssh root@<server-ip> && cd /opt/porch && source .env
# create an invite token, register at /register?invite=<token>, then:
docker exec -i porch-postgres psql -U "$DB_USER" -d "$DB_NAME" \
-c "UPDATE users SET role = 'admin' WHERE email = '[email protected]';"
Ongoing operations
./scripts/deploy.sh root@<server-ip> update # git pull + rebuild + up -d
docker compose -f docker-compose.prod.yml logs -f api # tail backend
docker compose -f docker-compose.prod.yml ps # service status
/opt/porch/scripts/backup.sh # manual backup
Backups run nightly at 03:00 to the MinIO porch-backups bucket (gzipped
Postgres dump + media tarball, 30-day retention). Defaults worth knowing:
deploy dir /opt/porch, public ports 80/443, persistent porch_postgres
and porch_media_data volumes, and Caddy routing /api/* to the backend and
everything else to the frontend.