diff --git a/jellyfin.conf b/jellyfin.conf index 2b17e44..3a8d155 100644 --- a/jellyfin.conf +++ b/jellyfin.conf @@ -1,4 +1,6 @@ # /etc/nginx/sites-available/jellyfin + +# WebSocket upgrade helper (for Jellyfin) map $http_upgrade $connection_upgrade { default upgrade; '' close; @@ -8,62 +10,59 @@ server { listen 80; server_name nik4nao.home.arpa; - # Jellyfin (unchanged) - location = /jellyfin { return 302 /jellyfin/; } + # ---- Convenience redirects ---- + location = / { return 302 /admin/; } # land on Pi-hole admin by default + location = /pihole { return 302 /admin/; } # /pihole -> /admin/ + location /pihole/ { return 301 /admin/; } # keep only /admin/ path + + # ---- Jellyfin at /jellyfin/ ---- + location = /jellyfin { return 302 /jellyfin/; } # enforce trailing slash + location /jellyfin/ { - proxy_pass http://192.168.7.96:8096/; - 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; - proxy_set_header X-Forwarded-Prefix /jellyfin; + proxy_pass http://jellyfin_upstream/; # uses upstream (or use the raw URL) + include snippets/proxy-common.conf; + + # Jellyfin behind subpath specifics proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; - proxy_buffering off; - client_max_body_size 0; - proxy_read_timeout 600; - proxy_send_timeout 600; - send_timeout 600; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Prefix /jellyfin; + + # (Optional) if you see odd redirects, uncomment: + # proxy_redirect off; } - # ---- Pi-hole at /admin/ (no subpath tricks) ---- - - # Optional: make / and /pihole go to /admin/ - location = / { return 302 /admin/; } - location = /pihole { return 302 /admin/; } - location /pihole/ { return 301 /admin/; } - - # Pi-hole UI + # ---- Pi-hole admin at /admin/ ---- + # Pi-hole’s UI lives under /admin/, so keep the trailing slash in proxy_pass. location /admin/ { - proxy_pass http://127.0.0.1:8081/admin/; - - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - proxy_http_version 1.1; - proxy_set_header Connection ""; - - proxy_buffering off; - client_max_body_size 0; - proxy_read_timeout 600; - proxy_send_timeout 600; - send_timeout 600; + proxy_pass http://pihole_upstream/admin/; + include snippets/proxy-common.conf; + proxy_set_header X-Forwarded-Host $host; } - # Pi-hole API (some UI calls hit /api) + # Pi-hole API (some UI calls hit /api/) location /api/ { - proxy_pass http://127.0.0.1:8081/api/; + proxy_pass http://pihole_upstream/api/; + include snippets/proxy-common.conf; + proxy_set_header X-Forwarded-Host $host; + } - proxy_set_header Host $host; - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - - proxy_http_version 1.1; - proxy_set_header Connection ""; + # redirect /watch-party -> /watch-party/ + location = /watch-party { return 302 /watch-party/; } + + # proxy ONLY /watch-party/*, keeping the prefix + location ^~ /watch-party/ { + proxy_pass http://watchparty_upstream; # ← no trailing slash (preserve /watch-party) + include snippets/proxy-common.conf; + + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Prefix /watch-party; + + # For Vite HMR / websockets + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + + # Uncomment if you see odd redirects + # proxy_redirect off; } } diff --git a/proxy-common.conf b/proxy-common.conf index d20f87a..e2fcbca 100644 --- a/proxy-common.conf +++ b/proxy-common.conf @@ -1,3 +1,5 @@ +# /etc/nginx/snippets/proxy-common.conf + # Common reverse-proxy headers proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; diff --git a/robots.txt b/robots.txt new file mode 100644 index 0000000..3f14a8f --- /dev/null +++ b/robots.txt @@ -0,0 +1,19 @@ +# Block everything by default +User-agent: * +Disallow: / +User-agent: GPTBot +Disallow: / +User-agent: ChatGPT-User +Disallow: / +User-agent: OAI-SearchBot +Disallow: / +User-agent: CCBot +Disallow: / +User-agent: ClaudeBot +Disallow: / +User-agent: PerplexityBot +Disallow: / +User-agent: Google-Extended +Disallow: / +User-agent: Applebot-Extended +Disallow: / \ No newline at end of file diff --git a/upstreams.conf b/upstreams.conf new file mode 100644 index 0000000..53506f2 --- /dev/null +++ b/upstreams.conf @@ -0,0 +1,15 @@ +# /etc/nginx/conf.d/upstreams.conf +upstream jellyfin_upstream { + server 192.168.7.96:8096; + keepalive 16; +} + +upstream pihole_upstream { + server 127.0.0.1:8081; + keepalive 16; +} + +upstream watchparty_upstream { + server 192.168.7.96:3000; + keepalive 16; +} \ No newline at end of file diff --git a/watch-party.conf b/watch-party.conf new file mode 100644 index 0000000..5bde062 --- /dev/null +++ b/watch-party.conf @@ -0,0 +1,84 @@ +# /etc/nginx/sites-available/watch-party (CLEAN) + +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +############################ +# HTTP: ACME + Redirect +############################ +server { + listen 80; # IPv4 only + server_name nik4nao.xyz; + + # Let’s Encrypt HTTP-01 challenge lives on HTTP + location ^~ /.well-known/acme-challenge/ { + root /var/www/html; + default_type "text/plain"; + allow all; + } + + # Serve /robots.txt from disk regardless of proxying + location = /robots.txt { + alias /var/www/html/robots.txt; + default_type text/plain; + } + + # Redirect everything else to HTTPS + location / { + return 301 https://$host$request_uri; + } +} + +############################ +# HTTPS: Proxy /watch-party/ +############################ +server { + listen 443 ssl; + server_name nik4nao.xyz; + + # --- Certbot-managed TLS files (must exist) --- + ssl_certificate /etc/letsencrypt/live/nik4nao.xyz/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/nik4nao.xyz/privkey.pem; + include /etc/letsencrypt/options-ssl-nginx.conf; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; + add_header X-Robots-Tag "noindex, nofollow, noimageindex, nosnippet, noarchive" always; + + # Enforce trailing slash + location = /watch-party { return 301 /watch-party/; } + location = / { return 302 /watch-party/; } + + # IMPORTANT: no URI on proxy_pass so upstream receives /watch-party/ prefix + location /watch-party/ { + proxy_pass http://192.168.7.96:3000; + 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; + + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + } + + # NEW: forward API to the same frontend (which then forwards to backend) + location /api/ { + proxy_pass http://192.168.7.96:3000; # hits container's /api + 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; + } + + # Serve /robots.txt on HTTPS + location = /robots.txt { + alias /var/www/html/robots.txt; + default_type text/plain; + } + + # Don’t serve anything else + location / { + return 404; + } +} \ No newline at end of file