Files
vip-coordinator/docs/deployment/HTTPS_SETUP.md
kyle 440884666d
Some checks failed
CI/CD Pipeline / Backend Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Tests (push) Has been cancelled
CI/CD Pipeline / Build Docker Images (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
CI/CD Pipeline / Deploy to Production (push) Has been cancelled
docs: Organize documentation into structured folders
Organized documentation into cleaner structure:

Root directory (user-facing):
- README.md - Main documentation
- CLAUDE.md - AI context (referenced by system)
- QUICKSTART.md - Quick start guide

docs/ (technical documentation):
- CASL_AUTHORIZATION.md - Authorization guide
- ERROR_HANDLING.md - Error handling patterns
- REQUIREMENTS.md - Project requirements

docs/deployment/ (production deployment):
- HTTPS_SETUP.md - SSL/TLS setup
- PRODUCTION_ENVIRONMENT_TEMPLATE.md - Env vars template
- PRODUCTION_VERIFICATION_CHECKLIST.md - Deployment checklist

Removed:
- DOCKER_TROUBLESHOOTING.md - Outdated (referenced Google OAuth, old domain)

Updated references:
- Fixed links to moved files in CASL_AUTHORIZATION.md
- Fixed links to moved files in ERROR_HANDLING.md
- Removed reference to deleted BUILD_STATUS.md in QUICKSTART.md

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-31 17:13:47 +01:00

3.3 KiB

Enabling HTTPS with Certbot and Nginx

The production Docker stack ships with an Nginx front-end (the frontend service). Follow these steps to terminate HTTPS traffic with Let's Encrypt certificates.

1. Prerequisites

  • DNS A records for your domain (e.g. vip.example.com) pointing to 162.243.171.221.
  • Ports 80 and 443 open in the DigitalOcean firewall.
  • Docker Compose production stack deployed.
  • Certbot installed on the droplet (apt-get install -y certbot already run).

2. Obtain certificates

Run Certbot in standalone mode (temporarily stop the frontend container during issuance if it is already binding to port 80):

# Stop the frontend container temporarily
docker compose -f docker-compose.prod.yml stop frontend

# Request the certificate (replace the domain names)
sudo certbot certonly --standalone \
  -d vip.example.com \
  -d www.vip.example.com

# Restart the frontend container
docker compose -f docker-compose.prod.yml start frontend

Certificates will be stored under /etc/letsencrypt/live/vip.example.com/.

3. Mount certificates into the frontend container

Copy the key pair into the repository (or mount the original directory as a read-only volume). For example:

sudo mkdir -p /opt/vip-coordinator/certs
sudo cp /etc/letsencrypt/live/vip.example.com/fullchain.pem /opt/vip-coordinator/certs/
sudo cp /etc/letsencrypt/live/vip.example.com/privkey.pem /opt/vip-coordinator/certs/
sudo chown root:root /opt/vip-coordinator/certs/*.pem
sudo chmod 600 /opt/vip-coordinator/certs/privkey.pem

Update docker-compose.prod.yml to mount the certificate directory (uncomment the example below):

frontend:
  volumes:
    - /opt/vip-coordinator/certs:/etc/nginx/certs:ro

4. Enable the TLS server block

Edit frontend/nginx.conf:

  1. Uncomment the TLS server block and point to /etc/nginx/certs/fullchain.pem and privkey.pem.
  2. Change the port 80 server block to redirect to HTTPS (e.g. return 301 https://$host$request_uri;).

Example TLS block:

server {
  listen 443 ssl http2;
  server_name vip.example.com www.vip.example.com;

  ssl_certificate /etc/nginx/certs/fullchain.pem;
  ssl_certificate_key /etc/nginx/certs/privkey.pem;

  include /etc/nginx/snippets/ssl-params.conf; # optional hardening

  proxy_cache_bypass $http_upgrade;
  ...
}

Rebuild and redeploy the frontend container:

docker compose -f docker-compose.prod.yml build frontend
docker compose -f docker-compose.prod.yml up -d frontend

5. Automate renewals

Certbot installs a systemd timer that runs certbot renew twice a day. After renewal, copy the updated certificates into /opt/vip-coordinator/certs/ and reload the frontend container:

sudo certbot renew --dry-run
sudo cp /etc/letsencrypt/live/vip.example.com/{fullchain.pem,privkey.pem} /opt/vip-coordinator/certs/
docker compose -f docker-compose.prod.yml exec frontend nginx -s reload

Consider scripting the copy + reload to run after each renewal (e.g. with a cron job).

6. Hardening checklist

  • Add ssl_ciphers, ssl_prefer_server_ciphers, and HSTS headers to Nginx.
  • Restrict ADMIN_PASSWORD to a strong value and rotate JWT_SECRET.
  • Enable a firewall (DigitalOcean VPC or ufw) allowing only SSH, HTTP, HTTPS.
  • Configure automatic backups for PostgreSQL (snapshot or pg_dump).