Refactor Nginx configuration files for improved readability and consistency

This commit is contained in:
Nik Afiq 2026-01-24 20:21:33 +09:00
parent 071e52a0d8
commit c56c154635
5 changed files with 118 additions and 96 deletions

View File

@ -17,7 +17,7 @@ http {
sendfile on; sendfile on;
tcp_nopush on; tcp_nopush on;
types_hash_max_size 2048; types_hash_max_size 2048;
server_tokens off; # hide version server_tokens off; # hide version
include /etc/nginx/mime.types; include /etc/nginx/mime.types;
default_type application/octet-stream; default_type application/octet-stream;
@ -25,29 +25,29 @@ http {
## ##
# TLS Defaults (site blocks can override) # 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; ssl_prefer_server_ciphers on;
## ##
# External vs internal detector # External vs internal detector
## ##
geo $is_external { geo $is_external {
default 1; # assume external unless matched below default 1; # assume external unless matched below
10.0.0.0/8 0; 10.0.0.0/8 0;
172.16.0.0/12 0; 172.16.0.0/12 0;
192.168.0.0/16 0; 192.168.0.0/16 0;
127.0.0.0/8 0; 127.0.0.0/8 0;
::1/128 0; ::1/128 0;
fc00::/7 0; # Unique local (ULA) fc00::/7 0; # Unique local (ULA)
fe80::/10 0; # Link-local fe80::/10 0; # Link-local
} }
## ##
# AI bot block map (optional; enforce in server with: if ($block_ai) { return 403; }) # AI bot block map (optional; enforce in server with: if ($block_ai) { return 403; })
## ##
map $http_user_agent $block_ai { map $http_user_agent $block_ai {
default 0; default 0;
~*(GPTBot|ChatGPT-User|OAI-SearchBot|CCBot|Claude(Bot)?|PerplexityBot|Bytespider|Google-Extended|Amazonbot|DataForSeoBot|facebookexternalhit|DuckAssist|YouBot) 1; ~*(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 log_format json escape=json
'{' '{'
'"time":"$time_iso8601",' '"time":"$time_iso8601",'
'"req_id":"$msec-$connection-$request_length",' '"req_id":"$msec-$connection-$request_length",'
'"is_external":$is_external,' '"is_external":$is_external,'
'"is_ai_bot":$block_ai,' '"is_ai_bot":$block_ai,'
'"client_ip":"$remote_addr",' '"client_ip":"$remote_addr",'
'"client_port":"$remote_port",' '"client_port":"$remote_port",'
'"xff":"$http_x_forwarded_for",' '"xff":"$http_x_forwarded_for",'
'"scheme":"$scheme",' '"scheme":"$scheme",'
'"host":"$host",' '"host":"$host",'
'"method":"$request_method",' '"method":"$request_method",'
'"uri":"$uri",' '"uri":"$uri",'
'"query":"$query_string",' '"query":"$query_string",'
'"proto":"$server_protocol",' '"proto":"$server_protocol",'
'"status":$status,' '"status":$status,'
'"ref":"$http_referer",' '"ref":"$http_referer",'
'"ua":"$http_user_agent",' '"ua":"$http_user_agent",'
'"req_bytes":$request_length,' '"req_bytes":$request_length,'
'"body_bytes_sent":$body_bytes_sent,' '"body_bytes_sent":$body_bytes_sent,'
'"bytes_sent":$bytes_sent,' '"bytes_sent":$bytes_sent,'
'"req_time":$request_time,' '"req_time":$request_time,'
'"upstream_addr":"$upstream_addr",' '"upstream_addr":"$upstream_addr",'
'"upstream_status":"$upstream_status",' '"upstream_status":"$upstream_status",'
'"upstream_connect_time":"$upstream_connect_time",' '"upstream_connect_time":"$upstream_connect_time",'
'"upstream_header_time":"$upstream_header_time",' '"upstream_header_time":"$upstream_header_time",'
'"upstream_response_time":"$upstream_response_time",' '"upstream_response_time":"$upstream_response_time",'
'"ssl_protocol":"$ssl_protocol",' '"ssl_protocol":"$ssl_protocol",'
'"ssl_cipher":"$ssl_cipher"' '"ssl_cipher":"$ssl_cipher"'
'}'; '}';
access_log /var/log/nginx/access.json json if=$is_external; access_log /var/log/nginx/access.json json if=$is_external;
@ -95,8 +95,8 @@ http {
gzip_vary on; gzip_vary on;
gzip_proxied any; gzip_proxied any;
gzip_types gzip_types
text/plain text/css text/javascript application/javascript application/json text/plain text/css text/javascript application/javascript application/json
application/xml application/rss+xml image/svg+xml font/ttf font/otf; application/xml application/rss+xml image/svg+xml font/ttf font/otf;
## ##
# Rate/Conn limit zones (used in site file) # Rate/Conn limit zones (used in site file)

View File

@ -3,7 +3,7 @@
# WebSocket upgrade helper (for Jellyfin) # WebSocket upgrade helper (for Jellyfin)
map $http_upgrade $connection_upgrade { map $http_upgrade $connection_upgrade {
default upgrade; default upgrade;
'' close; '' close;
} }
server { server {
@ -11,24 +11,32 @@ server {
server_name nik4nao.home.arpa; server_name nik4nao.home.arpa;
access_log off; access_log off;
error_log /var/log/nginx/nik4naohomearpa_error.log warn; error_log /var/log/nginx/nik4naohomearpa_error.log warn;
# ---- Convenience redirects ---- # ---- Convenience redirects ----
location = / { return 302 /admin/; } # land on Pi-hole admin by default location = / {
location = /pihole { return 302 /admin/; } # /pihole -> /admin/ return 302 /admin/;
location /pihole/ { return 301 /admin/; } # keep only /admin/ path }
location = /pihole {
return 302 /admin/;
}
location /pihole/ {
return 301 /admin/;
}
# ---- Jellyfin at /jellyfin/ ---- # ---- Jellyfin at /jellyfin/ ----
location = /jellyfin { return 302 /jellyfin/; } # enforce trailing slash location = /jellyfin {
return 302 /jellyfin/;
}
location /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; include snippets/proxy-common.conf;
# Jellyfin behind subpath specifics # Jellyfin behind subpath specifics
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade; proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Prefix /jellyfin; proxy_set_header X-Forwarded-Prefix /jellyfin;
# (Optional) if you see odd redirects, uncomment: # (Optional) if you see odd redirects, uncomment:
@ -36,17 +44,19 @@ server {
} }
# ---- Jellyfin at /anime/ ---- # ---- Jellyfin at /anime/ ----
location = /anime { return 302 /anime/; } # enforce trailing slash location = /anime {
return 302 /anime/;
}
location /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; proxy_next_upstream error timeout invalid_header http_502 http_503 http_504;
include snippets/proxy-common.conf; include snippets/proxy-common.conf;
# Jellyfin behind subpath specifics # Jellyfin behind subpath specifics
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade; proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Prefix /anime; proxy_set_header X-Forwarded-Prefix /anime;
# (Optional) if you see odd redirects, uncomment: # (Optional) if you see odd redirects, uncomment:
@ -69,31 +79,35 @@ server {
} }
# redirect /watch-party -> /watch-party/ # 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 # proxy ONLY /watch-party/*, keeping the prefix
location ^~ /watch-party/ { 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; 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; proxy_set_header X-Forwarded-Prefix /watch-party;
# For Vite HMR / websockets # For Vite HMR / websockets
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade; proxy_set_header Connection $connection_upgrade;
} }
# ---- qBittorrent at /qbt/ ---- # ---- qBittorrent at /qbt/ ----
location = /qbt { return 302 /qbt/; } location = /qbt {
return 302 /qbt/;
}
location ^~ /qbt/ { location ^~ /qbt/ {
proxy_pass http://qbt_upstream/; proxy_pass http://qbt_upstream/;
include snippets/proxy-common.conf; include snippets/proxy-common.conf;
proxy_set_header Host $host; proxy_set_header Host $host;
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-Proto $scheme;
proxy_set_header X-Forwarded-Prefix /qbt; proxy_set_header X-Forwarded-Prefix /qbt;
@ -103,26 +117,30 @@ server {
} }
# ---- JDownloader2 at /jd2/ ---- # ---- JDownloader2 at /jd2/ ----
location = /jd2 { return 302 /jd2/; } location = /jd2 {
return 302 /jd2/;
}
location /jd2/ { location /jd2/ {
proxy_pass http://127.0.0.1:5800/; proxy_pass http://127.0.0.1:5800/;
include snippets/proxy-common.conf; include snippets/proxy-common.conf;
proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Host $host;
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-Proto $scheme;
proxy_set_header X-Forwarded-Prefix /jd2; proxy_set_header X-Forwarded-Prefix /jd2;
} }
# ---- JDownloader-Bridge at /jd-bridge/ ---- # ---- JDownloader-Bridge at /jd-bridge/ ----
location = /jd-bridge { return 302 /jd-bridge/; } location = /jd-bridge {
return 302 /jd-bridge/;
}
location /jd-bridge/ { location /jd-bridge/ {
proxy_pass http://127.0.0.1:8088/; proxy_pass http://127.0.0.1:8088/;
include snippets/proxy-common.conf; 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 /jd-bridge; proxy_set_header X-Forwarded-Prefix /jd-bridge;
} }
} }

View File

@ -3,7 +3,7 @@
# WebSocket upgrade helper # WebSocket upgrade helper
map $http_upgrade $connection_upgrade { map $http_upgrade $connection_upgrade {
default upgrade; default upgrade;
'' close; '' close;
} }
############################ ############################
@ -42,13 +42,13 @@ server {
root /var/www/html; root /var/www/html;
access_log /var/log/nginx/nik4naoxyz_access.json json if=$is_external; 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 --- # --- 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; ssl_certificate_key /etc/letsencrypt/live/nik4nao.xyz/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf; include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# --- Security & indexing headers --- # --- Security & indexing headers ---
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always; add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
@ -64,7 +64,9 @@ server {
error_page 500 502 503 504 /errors/50x.html; error_page 500 502 503 504 /errors/50x.html;
# (Optional) Block noncompliant AI bots (requires $block_ai map in nginx.conf) # (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 # Serve /robots.txt on HTTPS
location = /robots.txt { location = /robots.txt {
@ -73,7 +75,9 @@ server {
} }
# Enforce trailing slash for subpath and land / on /watch-party/ # 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 = / { location = / {
try_files /nik4nao-xyz-landing.html =404; try_files /nik4nao-xyz-landing.html =404;
} }
@ -87,27 +91,27 @@ server {
# Main app proxy (keep /watch-party/ prefix) # Main app proxy (keep /watch-party/ prefix)
location /watch-party/ { location /watch-party/ {
proxy_pass http://192.168.7.96:3000; proxy_pass http://192.168.7.96:3000;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade; proxy_set_header Connection $connection_upgrade;
} }
# API proxy with basic abuse controls # API proxy with basic abuse controls
location /api/ { location /api/ {
proxy_pass http://192.168.7.96:3000; # upstream /api proxy_pass http://192.168.7.96:3000; # upstream /api
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
# Limits (zones defined in nginx.conf) # Limits (zones defined in nginx.conf)
limit_req zone=api_rps burst=20 nodelay; limit_req zone=api_rps burst=20 nodelay;
limit_conn perip 20; limit_conn perip 20;
# Timeouts & body limits # Timeouts & body limits
client_max_body_size 10m; client_max_body_size 10m;

View File

@ -1,12 +1,12 @@
# /etc/nginx/snippets/proxy-common.conf # /etc/nginx/snippets/proxy-common.conf
# Common reverse-proxy headers # Common reverse-proxy headers
proxy_set_header Host $http_host; proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Connection ""; proxy_set_header Connection "";
# Reasonable timeouts (uploads/streams) # Reasonable timeouts (uploads/streams)
client_max_body_size 0; client_max_body_size 0;

View File

@ -15,7 +15,7 @@ server {
listen 443 ssl http2; listen 443 ssl http2;
server_name prv-api.nik4nao.xyz; 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_certificate_key /etc/letsencrypt/live/prv-api.nik4nao.xyz/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3; ssl_protocols TLSv1.2 TLSv1.3;