combined/nginx.conf
Rama main · réplica de lectura del repositorio original.
# See web/nginx.conf.template (kept in sync) for why each directive is what it is.
map $http_host $aonarr_host {
"" $host;
default $http_host;
}
# The Starr API below takes the API key as a query parameter (Overseerr, Bazarr and Homepage send it that way), and the default
# access log would write it to the container log. This format logs the path only.
log_format aonarr_starr '$remote_addr - [$time_local] "$request_method $uri" $status $body_bytes_sent';
server {
listen 9876;
server_name _;
root /usr/share/nginx/html;
index index.html;
add_header Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline' https: http:; img-src 'self' data: blob: https: http:; font-src 'self' data: https: http:; connect-src 'self'; worker-src 'self'; object-src 'none'; base-uri 'self'" always;
# The Sonarr, Radarr, Lidarr and Readarr API AoNarr answers for Prowlarr, Overseerr, Bazarr, Homepage and
# similar tools (server/src/starr): a tool's URL base is /sonarr, /radarr, /lidarr or /readarr. Only the
# API and /ping go to the server; the app's own pages are never under these names.
location ~ ^/(sonarr|radarr|lidarr|readarr)/(api|ping)(/|$) {
access_log /var/log/nginx/access.log aonarr_starr;
proxy_pass http://127.0.0.1:8989;
proxy_set_header Host $aonarr_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
client_max_body_size 10m;
proxy_connect_timeout 30s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
location /api/ {
proxy_pass http://127.0.0.1:8989/api/;
proxy_set_header Host $aonarr_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
client_max_body_size 10m;
# A handful of endpoints (large-file recycle/import operations, bulk exports) can
# legitimately run past nginx's 60s defaults — that's a slow-but-alive backend and should
# surface as a real timeout (504), not the ambiguous "connection just dropped" a client
# sees once the browser/any intermediate proxy gives up first.
proxy_connect_timeout 30s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
# Backup restore accepts up to 1gb (routes/system.ts); /api/'s 10m cap answered a real
# library's backup with nginx's own 413. Request buffering stays on so a slow upload is spooled
# by nginx first instead of running into Node's 300s request timeout (408). auth_request checks
# the caller is an admin before the body is read, so an anonymous upload is never spooled.
location = /api/system/backup/restore {
auth_request /__aonarr_admin_check;
proxy_pass http://127.0.0.1:8989;
proxy_set_header Host $aonarr_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
client_max_body_size 1g;
proxy_connect_timeout 30s;
proxy_send_timeout 600s;
proxy_read_timeout 600s;
}
# The restore upload's admin check: /api/system is admin-only; headers are passed, the body isn't.
location = /__aonarr_admin_check {
internal;
proxy_pass http://127.0.0.1:8989/api/system/resources;
client_max_body_size 1g;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header Host $aonarr_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
}
# Server-Sent Events (Activity queue push, System → Logs live tail): unbuffered so no event can
# wait in an nginx buffer, with a read timeout far past the server's 30s heartbeat.
location ~ ^/api/(activity/stream|system/logs/stream)$ {
proxy_pass http://127.0.0.1:8989;
proxy_set_header Host $aonarr_host;
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_buffering off;
proxy_cache off;
proxy_connect_timeout 30s;
proxy_read_timeout 3600s;
}
location / {
try_files $uri /index.html;
}
# Vite's built JS/CSS filenames are content-hashed (index-<hash>.js) — a new build always gets a
# new filename, so these are safe to cache forever. index.html is the opposite: it's the one file
# that references those hashed names, so it must never be cached, or the browser can keep serving
# a stale index.html pointing at JS that predates whatever update was just deployed — this was
# the actual cause of "the UI still looks the same after updating the container."
# `expires -1` sends the same Cache-Control: no-cache without an add_header here: any add_header
# in a location replaces every server-level one, which would leave the page itself (every SPA
# route lands here via try_files) without the Content-Security-Policy above.
location = /index.html {
expires -1;
}
# Browsers already re-check a registered service worker's script at most once every 24h by
# spec regardless of headers — this just makes sure that check, whenever it happens, isn't
# itself served from a stale HTTP cache.
# Its add_header also keeps the page's CSP off the worker, whose own fetch() re-requests every
# cross-origin poster and would be blocked by connect-src 'self'.
location = /sw.js {
add_header Cache-Control "no-cache";
}
location /assets/ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
}