source: Klonkt/deploy/nginx.conf.example@ b5bae24

main
Last change on this file since b5bae24 was b5bae24, checked in by Robin Genis <roboburr@…>, 3 months ago

reconcile: commit uncommitted live /srv state (playback fix + prefetch, SF favicon, smooth scroll, scripts)

The live working tree /srv/prutfolio was ahead of the bare repo with direct
server edits that had never been committed back. The deploy hook does
checkout -f main, so the next deploy would have reverted the 3 modified
tracked files to f33db01 and lost this work:

  • audio-player.js: robust playback — retry+backoff on network hiccups (no longer skipping immediately) + next-track prefetch (downloads the next track while the current one plays -> ended->next swaps instantly, covering the autoplay lapse). Fix for the sometimes-next-doesn't-play bug.
  • server.js: favicon mark p -> SF (SoundFabrics rebrand). shell.ejs: audio-player.js cache buster ?v=5 -> ?v=6 + favicon ?v=sf.
  • Plus previously untracked project files committed: lenis.min.js + smooth-scroll.js (not yet wired), scripts/ (v9 import/migration), deploy/ docs (DEPLOY.md/backup.sh/nginx/verify.ps1), .well-known/assetlinks.json. audio-player.js.bak.20260614 deliberately NOT committed.

Co-Authored-By: Claude <noreply@…>

  • Property mode set to 100644
File size: 5.0 KB
Line 
1# ──────────────────────────────────────────────────────────────────
2# PrutCMS v10 — nginx reverse proxy
3#
4# Place this in /etc/nginx/sites-available/prutcms and symlink to
5# /etc/nginx/sites-enabled/. Replace <YOUR-DOMAIN> with the real host.
6#
7# Key points:
8# • SSL termination here; Node listens on 127.0.0.1:3000 only.
9# • WebSocket upgrade headers wired through (Prutter live messaging).
10# • Static assets cached aggressively (Node gives them 1y maxAge anyway).
11# • Audio streaming endpoint /audio/stream/* must NOT be cached by nginx —
12# each request carries a different signed token and is byte-range based.
13# • HSTS + security headers added at the proxy.
14#
15# After installing:
16# sudo ln -s /etc/nginx/sites-available/prutcms /etc/nginx/sites-enabled/
17# sudo nginx -t
18# sudo systemctl reload nginx
19#
20# Then provision SSL:
21# sudo certbot --nginx -d <YOUR-DOMAIN> -d www.<YOUR-DOMAIN>
22# certbot will edit this file in place to insert the cert paths.
23# ──────────────────────────────────────────────────────────────────
24
25# WebSocket connection upgrade map (let nginx set it once globally)
26map $http_upgrade $connection_upgrade {
27 default upgrade;
28 '' close;
29}
30
31# Redirect HTTP → HTTPS
32server {
33 listen 80;
34 listen [::]:80;
35 server_name <YOUR-DOMAIN> www.<YOUR-DOMAIN>;
36
37 # Let's Encrypt http-01 challenge path
38 location /.well-known/acme-challenge/ {
39 root /var/www/letsencrypt;
40 }
41
42 location / {
43 return 301 https://$host$request_uri;
44 }
45}
46
47server {
48 listen 443 ssl http2;
49 listen [::]:443 ssl http2;
50 server_name <YOUR-DOMAIN> www.<YOUR-DOMAIN>;
51
52 # certbot will fill these in:
53 # ssl_certificate /etc/letsencrypt/live/<YOUR-DOMAIN>/fullchain.pem;
54 # ssl_certificate_key /etc/letsencrypt/live/<YOUR-DOMAIN>/privkey.pem;
55 ssl_protocols TLSv1.2 TLSv1.3;
56 ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
57 ssl_prefer_server_ciphers off;
58 ssl_session_cache shared:SSL:10m;
59 ssl_session_timeout 1d;
60 ssl_stapling on;
61 ssl_stapling_verify on;
62
63 # Security headers (Helmet adds them at the app too — these are belt+braces)
64 add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
65 add_header X-Frame-Options "SAMEORIGIN" always;
66 add_header X-Content-Type-Options "nosniff" always;
67 add_header Referrer-Policy "no-referrer-when-downgrade" always;
68
69 # Reasonable body size — accommodates 50 MB MP3 uploads with headroom
70 client_max_body_size 60M;
71
72 # Compression
73 gzip on;
74 gzip_types text/plain text/css application/json application/javascript application/xml application/atom+xml application/rss+xml image/svg+xml;
75 gzip_min_length 256;
76
77 # ── Static assets: serve via Node, but tell upstream they're long-cached.
78 location /assets/ {
79 proxy_pass http://127.0.0.1:3000;
80 proxy_set_header Host $host;
81 proxy_cache_valid 200 1y;
82 add_header Cache-Control "public, max-age=31536000, immutable";
83 }
84
85 # ── Audio streaming: pass through, no caching, no buffering (HTML5 <audio>
86 # needs to seek using byte-range; nginx must not slurp the whole file).
87 location /audio/stream/ {
88 proxy_pass http://127.0.0.1:3000;
89 proxy_set_header Host $host;
90 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
91 proxy_set_header X-Forwarded-Proto $scheme;
92 proxy_buffering off;
93 proxy_request_buffering off;
94 proxy_read_timeout 600s;
95 add_header Cache-Control "private, no-store" always;
96 }
97
98 # ── WebSocket: Prutter live chat. Long-lived connection.
99 location /ws/ {
100 proxy_pass http://127.0.0.1:3000;
101 proxy_http_version 1.1;
102 proxy_set_header Upgrade $http_upgrade;
103 proxy_set_header Connection $connection_upgrade;
104 proxy_set_header Host $host;
105 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
106 proxy_set_header X-Forwarded-Proto $scheme;
107 proxy_read_timeout 3600s; # let pings keep it alive an hour
108 proxy_send_timeout 3600s;
109 }
110
111 # ── Everything else: standard reverse proxy
112 location / {
113 proxy_pass http://127.0.0.1:3000;
114 proxy_http_version 1.1;
115 proxy_set_header Host $host;
116 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
117 proxy_set_header X-Forwarded-Proto $scheme;
118 proxy_set_header X-Real-IP $remote_addr;
119
120 # Upgrade headers in case any other route ever uses WS
121 proxy_set_header Upgrade $http_upgrade;
122 proxy_set_header Connection $connection_upgrade;
123
124 proxy_read_timeout 90s;
125 }
126}
Note: See TracBrowser for help on using the repository browser.