Skip to main content

Production Deployment

1. DNS Setup

Point your A record to the VM public IP.

  • app.yourdomain.com for the main UI and API
  • oauth.yourdomain.com (optional) for Hydra public OAuth2

2. Update .env for Production

# Public URLs
BASE_URL=https://app.yourdomain.com
HYDRA_PUBLIC_URL=https://oauth.yourdomain.com # or https://app.yourdomain.com/oauth2
REACT_APP_URL=https://app.yourdomain.com

# Domains for WebAuthn RP (no protocol/port)
DOMAIN=yourdomain.com
APP_DOMAIN=app.yourdomain.com
WEBAUTHN_ORIGIN=https://app.yourdomain.com

# Security hardening
ENVIRONMENT=production
GIN_MODE=release
REQUIRE_SERVER_AUTH=true
CORS_ALLOW_ORIGIN=https://app.yourdomain.com
TENANT_DOMAIN_SUFFIX=yourdomain.com

# SMTP provider
SMTP_HOST=smtp.yourmailprovider.com
SMTP_PORT=587
SMTP_USER=noreply@yourdomain.com
SMTP_PASSWORD=your-smtp-password

3. Configure TLS (Let's Encrypt)

sudo apt install -y certbot
sudo certbot certonly --standalone -d app.yourdomain.com
sudo chmod -R 755 /etc/letsencrypt/live/ /etc/letsencrypt/archive/

Enable TLS server blocks and cert paths in nginx/nginx.conf, then restart:

docker compose restart nginx

Auto-renew:

echo "0 3 * * * certbot renew --quiet && docker compose -f /path/to/onprem/docker-compose.yaml restart nginx" \
| sudo tee -a /etc/cron.d/certbot-renew

4. Firewall Rules

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable

Keep Postgres, Redis, and Hydra admin ports private (localhost only).

Final hardening step: Security Checklist.