diff --git a/nginx.conf b/nginx.conf index b68d5f4..8981b8b 100644 --- a/nginx.conf +++ b/nginx.conf @@ -17,7 +17,7 @@ http { sendfile on; tcp_nopush on; types_hash_max_size 2048; - server_tokens off; # hide version + server_tokens off; # hide version include /etc/nginx/mime.types; default_type application/octet-stream; @@ -25,29 +25,29 @@ http { ## # TLS Defaults (site blocks can override) ## - ssl_protocols TLSv1.2 TLSv1.3; # drop TLSv1.0/1.1 + ssl_protocols TLSv1.2 TLSv1.3; # drop TLSv1.0/1.1 ssl_prefer_server_ciphers on; ## # External vs internal detector ## geo $is_external { - default 1; # assume external unless matched below - 10.0.0.0/8 0; - 172.16.0.0/12 0; - 192.168.0.0/16 0; - 127.0.0.0/8 0; - ::1/128 0; - fc00::/7 0; # Unique local (ULA) - fe80::/10 0; # Link-local + default 1; # assume external unless matched below + 10.0.0.0/8 0; + 172.16.0.0/12 0; + 192.168.0.0/16 0; + 127.0.0.0/8 0; + ::1/128 0; + fc00::/7 0; # Unique local (ULA) + fe80::/10 0; # Link-local } ## # AI bot block map (optional; enforce in server with: if ($block_ai) { return 403; }) ## map $http_user_agent $block_ai { - default 0; - ~*(GPTBot|ChatGPT-User|OAI-SearchBot|CCBot|Claude(Bot)?|PerplexityBot|Bytespider|Google-Extended|Amazonbot|DataForSeoBot|facebookexternalhit|DuckAssist|YouBot) 1; + default 0; + ~*(GPTBot|ChatGPT-User|OAI-SearchBot|CCBot|Claude(Bot)?|PerplexityBot|Bytespider|Google-Extended|Amazonbot|DataForSeoBot|facebookexternalhit|DuckAssist|YouBot) 1; } ## @@ -55,33 +55,33 @@ http { ## log_format json escape=json '{' - '"time":"$time_iso8601",' - '"req_id":"$msec-$connection-$request_length",' - '"is_external":$is_external,' - '"is_ai_bot":$block_ai,' - '"client_ip":"$remote_addr",' - '"client_port":"$remote_port",' - '"xff":"$http_x_forwarded_for",' - '"scheme":"$scheme",' - '"host":"$host",' - '"method":"$request_method",' - '"uri":"$uri",' - '"query":"$query_string",' - '"proto":"$server_protocol",' - '"status":$status,' - '"ref":"$http_referer",' - '"ua":"$http_user_agent",' - '"req_bytes":$request_length,' - '"body_bytes_sent":$body_bytes_sent,' - '"bytes_sent":$bytes_sent,' - '"req_time":$request_time,' - '"upstream_addr":"$upstream_addr",' - '"upstream_status":"$upstream_status",' - '"upstream_connect_time":"$upstream_connect_time",' - '"upstream_header_time":"$upstream_header_time",' - '"upstream_response_time":"$upstream_response_time",' - '"ssl_protocol":"$ssl_protocol",' - '"ssl_cipher":"$ssl_cipher"' + '"time":"$time_iso8601",' + '"req_id":"$msec-$connection-$request_length",' + '"is_external":$is_external,' + '"is_ai_bot":$block_ai,' + '"client_ip":"$remote_addr",' + '"client_port":"$remote_port",' + '"xff":"$http_x_forwarded_for",' + '"scheme":"$scheme",' + '"host":"$host",' + '"method":"$request_method",' + '"uri":"$uri",' + '"query":"$query_string",' + '"proto":"$server_protocol",' + '"status":$status,' + '"ref":"$http_referer",' + '"ua":"$http_user_agent",' + '"req_bytes":$request_length,' + '"body_bytes_sent":$body_bytes_sent,' + '"bytes_sent":$bytes_sent,' + '"req_time":$request_time,' + '"upstream_addr":"$upstream_addr",' + '"upstream_status":"$upstream_status",' + '"upstream_connect_time":"$upstream_connect_time",' + '"upstream_header_time":"$upstream_header_time",' + '"upstream_response_time":"$upstream_response_time",' + '"ssl_protocol":"$ssl_protocol",' + '"ssl_cipher":"$ssl_cipher"' '}'; access_log /var/log/nginx/access.json json if=$is_external; @@ -95,8 +95,8 @@ http { gzip_vary on; gzip_proxied any; gzip_types - text/plain text/css text/javascript application/javascript application/json - application/xml application/rss+xml image/svg+xml font/ttf font/otf; + text/plain text/css text/javascript application/javascript application/json + application/xml application/rss+xml image/svg+xml font/ttf font/otf; ## # Rate/Conn limit zones (used in site file) diff --git a/nik4nao.home.arpa.conf b/nik4nao.home.arpa.conf index 83a4b68..3aafc88 100644 --- a/nik4nao.home.arpa.conf +++ b/nik4nao.home.arpa.conf @@ -3,7 +3,7 @@ # WebSocket upgrade helper (for Jellyfin) map $http_upgrade $connection_upgrade { default upgrade; - '' close; + '' close; } server { @@ -11,24 +11,32 @@ server { server_name nik4nao.home.arpa; access_log off; - error_log /var/log/nginx/nik4naohomearpa_error.log warn; + error_log /var/log/nginx/nik4naohomearpa_error.log warn; # ---- 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 + location = / { + return 302 /admin/; + } + location = /pihole { + return 302 /admin/; + } + location /pihole/ { + return 301 /admin/; + } # ---- Jellyfin at /jellyfin/ ---- - location = /jellyfin { return 302 /jellyfin/; } # enforce trailing slash + location = /jellyfin { + return 302 /jellyfin/; + } location /jellyfin/ { - proxy_pass http://jellyfin_upstream/; # uses upstream (or use the raw URL) + 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_set_header X-Forwarded-Host $host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Prefix /jellyfin; # (Optional) if you see odd redirects, uncomment: @@ -36,17 +44,19 @@ server { } # ---- Jellyfin at /anime/ ---- - location = /anime { return 302 /anime/; } # enforce trailing slash + location = /anime { + return 302 /anime/; + } location /anime/ { - proxy_pass http://djellyfin_upstream/; # uses upstream (or use the raw URL) + proxy_pass http://djellyfin_upstream/; # uses upstream (or use the raw URL) proxy_next_upstream error timeout invalid_header http_502 http_503 http_504; include snippets/proxy-common.conf; # Jellyfin behind subpath specifics - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection $connection_upgrade; - proxy_set_header X-Forwarded-Host $host; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Prefix /anime; # (Optional) if you see odd redirects, uncomment: @@ -69,31 +79,35 @@ server { } # redirect /watch-party -> /watch-party/ - location = /watch-party { return 302 /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) + 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-Host $host; proxy_set_header X-Forwarded-Prefix /watch-party; # For Vite HMR / websockets - proxy_set_header Upgrade $http_upgrade; + proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } # ---- qBittorrent at /qbt/ ---- - location = /qbt { return 302 /qbt/; } + location = /qbt { + return 302 /qbt/; + } location ^~ /qbt/ { proxy_pass http://qbt_upstream/; include snippets/proxy-common.conf; - proxy_set_header Host $host; - 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-Forwarded-Prefix /qbt; @@ -103,26 +117,30 @@ server { } # ---- JDownloader2 at /jd2/ ---- - location = /jd2 { return 302 /jd2/; } + location = /jd2 { + return 302 /jd2/; + } location /jd2/ { - proxy_pass http://127.0.0.1:5800/; - include snippets/proxy-common.conf; + proxy_pass http://127.0.0.1:5800/; + include snippets/proxy-common.conf; - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Prefix /jd2; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Prefix /jd2; } # ---- JDownloader-Bridge at /jd-bridge/ ---- - location = /jd-bridge { return 302 /jd-bridge/; } + location = /jd-bridge { + return 302 /jd-bridge/; + } location /jd-bridge/ { - proxy_pass http://127.0.0.1:8088/; - include snippets/proxy-common.conf; + proxy_pass http://127.0.0.1:8088/; + include snippets/proxy-common.conf; - proxy_set_header X-Forwarded-Host $host; - proxy_set_header X-Forwarded-Prefix /jd-bridge; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Prefix /jd-bridge; } } diff --git a/nik4nao.xyz.conf b/nik4nao.xyz.conf index ffeeb34..cbe00bb 100644 --- a/nik4nao.xyz.conf +++ b/nik4nao.xyz.conf @@ -3,7 +3,7 @@ # WebSocket upgrade helper map $http_upgrade $connection_upgrade { default upgrade; - '' close; + '' close; } ############################ @@ -42,13 +42,13 @@ server { root /var/www/html; access_log /var/log/nginx/nik4naoxyz_access.json json if=$is_external; - error_log /var/log/nginx/nik4naoxyz_error.log warn; + error_log /var/log/nginx/nik4naoxyz_error.log warn; # --- Certbot-managed TLS files --- - ssl_certificate /etc/letsencrypt/live/nik4nao.xyz/fullchain.pem; + 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; + ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # --- Security & indexing headers --- add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always; @@ -64,7 +64,9 @@ server { error_page 500 502 503 504 /errors/50x.html; # (Optional) Block noncompliant AI bots (requires $block_ai map in nginx.conf) - if ($block_ai) { return 403; } + if ($block_ai) { + return 403; + } # Serve /robots.txt on HTTPS location = /robots.txt { @@ -73,7 +75,9 @@ server { } # Enforce trailing slash for subpath and land / on /watch-party/ - location = /watch-party { return 301 /watch-party/; } + location = /watch-party { + return 301 /watch-party/; + } location = / { try_files /nik4nao-xyz-landing.html =404; } @@ -87,27 +91,27 @@ server { # Main app proxy (keep /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 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 Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; } # API proxy with basic abuse controls location /api/ { - proxy_pass http://192.168.7.96:3000; # upstream /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_pass http://192.168.7.96:3000; # upstream /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; # Limits (zones defined in nginx.conf) - limit_req zone=api_rps burst=20 nodelay; - limit_conn perip 20; + limit_req zone=api_rps burst=20 nodelay; + limit_conn perip 20; # Timeouts & body limits client_max_body_size 10m; diff --git a/proxy-common.conf b/proxy-common.conf index d8a7f9a..412d646 100644 --- a/proxy-common.conf +++ b/proxy-common.conf @@ -1,12 +1,12 @@ # /etc/nginx/snippets/proxy-common.conf # Common reverse-proxy headers -proxy_set_header Host $http_host; -proxy_set_header X-Real-IP $remote_addr; -proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +proxy_set_header Host $http_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 Connection ""; +proxy_set_header Connection ""; # Reasonable timeouts (uploads/streams) client_max_body_size 0; diff --git a/prv-api.nik4nao.xyz.conf b/prv-api.nik4nao.xyz.conf index ea591b5..0a400c8 100644 --- a/prv-api.nik4nao.xyz.conf +++ b/prv-api.nik4nao.xyz.conf @@ -15,7 +15,7 @@ server { listen 443 ssl http2; server_name prv-api.nik4nao.xyz; - ssl_certificate /etc/letsencrypt/live/prv-api.nik4nao.xyz/fullchain.pem; + ssl_certificate /etc/letsencrypt/live/prv-api.nik4nao.xyz/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/prv-api.nik4nao.xyz/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3;