# DOMINUS — Reverse proxy configuration for Nginx. # Place in /etc/nginx/sites-available/dominus and symlink to # /etc/nginx/sites-enabled/dominus, then reload nginx. # # Adapt the server_name, ssl_certificate paths, and HOST to your setup. http { upstream dominus_backend { # When DOMINUS runs in a Docker container: server 127.0.0.1:3000; # When DOMINUS runs via systemd: # server 127.0.0.1:3000; keepalive 64; } # Rate limiting zone (shared across workers). limit_req_zone is an # http-context directive: it lives here, not inside a server block. limit_req_zone $binary_remote_addr zone=dominus:10m rate=10r/s; # HTTP → HTTPS redirect server { listen 80; server_name dominus.example.com; return 301 https://$host$request_uri; } server { listen 443 ssl http2; server_name dominus.example.com; ssl_certificate /etc/ssl/certs/dominus.example.com.pem; ssl_certificate_key /etc/ssl/private/dominus.example.com.key; ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers HIGH:!aNULL:!MD5; # Security headers add_header X-Content-Type-Options nosniff; add_header X-Frame-Options DENY; add_header X-XSS-Protection "0"; add_header Strict-Transport-Security "max-age=63072000" always; location / { proxy_pass http://dominus_backend; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # Rate limit application limit_req zone=dominus burst=20 nodelay; # Timeouts proxy_connect_timeout 5s; proxy_send_timeout 10s; proxy_read_timeout 30s; } location /api/health { # No rate limiting for health checks proxy_pass http://dominus_backend; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # Prometheus/operator metrics are internal-only (scraped on the Docker # network). Never expose them through the public proxy. location /api/v1/metrics/ { return 404; } # Public static assets (CSS, images, favicon, OG images, robots/sitemap # are handled by the app). Express serves these from public/static and # sets its own Cache-Control; mirror a matching 1-day TTL at the proxy. location /public/static/ { proxy_pass http://dominus_backend; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; expires 1d; add_header Cache-Control "public"; } } }