# /etc/nginx/conf.d/drawit.conf # # Assumes: # - drawit is listening on 127.0.0.1:3000 (PORT=3000) # - TLS is terminated here at nginx (recommended) # - Certbot / Let's Encrypt has already issued a certificate # # Enable: # sudo nginx -t # sudo systemctl reload nginx # ── Upstream ────────────────────────────────────────────────────────────────── upstream drawit_backend { server 127.0.0.1:3000; # Keep a pool of connections to the backend so nginx does not open a new # TCP connection for every WebSocket upgrade. #keepalive 64; } server { listen 80; listen [::]:80; server_name your.domain.com; # Let's Encrypt ACME challenge — must be reachable over plain HTTP. location /.well-known/acme-challenge/ { root /var/www/certbot; } # Everything else redirects to HTTPS. location / { return 301 https://$host$request_uri; } } server { listen 443 ssl; listen [::]:443 ssl; http2 on; server_name your.domain.com; # Let's Encrypt Cert location ssl_certificate /etc/letsencrypt/live/your.domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/your.domain.com/privkey.pem; # Modern TLS only — drops IE11 and very old Android. ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305; ssl_prefer_server_ciphers off; ssl_session_cache shared:SSL:10m; ssl_session_timeout 1d; ssl_session_tickets off; # Security Headers add_header Referrer-Policy "no-referrer" always; add_header X-Content-Type-Options "nosniff" always; add_header X-Frame-Options "SAMEORIGIN" always; # Or DENY add_header X-Permitted-Cross-Domain-Policies "none" always; add_header X-Robots-Tag "noindex, nofollow" always; add_header X-XSS-Protection "1; mode=block" always; add_header Permissions-Policy "geolocation=(self), midi=(self), sync-xhr=(self), microphone=(self), camera=(self), magnetometer=(self), gyroscope=(self), fullscreen=(self), payment=(self), interest-cohort=()"; #add_header Strict-Transport-Security "max-age=63072000; includeSubDomains" always; # Only enable this when you are ready! # Logging access_log /var/log/nginx/drawit_access.log; error_log /var/log/nginx/drawit_error.log info; # Or, disable logging altogether #access_log off; #error_log /dev/null crit; # Proxy rules location / { 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 https; proxy_set_header Host $http_host; proxy_redirect off; proxy_ssl_verify off; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_read_timeout 86400; proxy_http_version 1.1; proxy_pass http://drawit_backend; } # Block sensitive files location ~* /(data|node_modules|src)/.*\.(db|db-shm|db-wal)$ { deny all; } location ~* /(node_modules|src)/.*$ { deny all; } # Block everything else # Anything else gets a 444 (faster but confusing, change to 404 if you want) from nginx before it reaches the backend. location ~* \.(php|asp|aspx|jsp|cgi|go|env|env.local|mod|sum|yaml|yml|md|gitignore|git|github|gitea|ts|mjs)$ { return 444; } }