Files
web_server/nginx/nginx_dev.conf.template
Adam French 00364aca23
All checks were successful
Deploy with Docker Compose / deploy (push) Successful in 22s
Fix nginx stale DNS caching causing backend to appear down after restarts
Use Docker's embedded DNS resolver (127.0.0.11) with nginx variables in
proxy_pass directives so upstream hostnames are re-resolved at runtime
instead of being cached forever at startup.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 16:29:50 +01:00

381 lines
13 KiB
Plaintext

events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
server_tokens off;
charset utf-8;
resolver 127.0.0.11 valid=10s;
client_max_body_size 50M;
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/s;
limit_req_zone $binary_remote_addr zone=upload:10m rate=5r/m;
log_format compact
'$remote_addr "$request" $status rt=$request_time';
access_log /var/log/nginx/access.log compact;
types {
text/javascript mjs;
}
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_min_length 256;
gzip_types
text/plain
text/css
text/javascript
application/javascript
application/json
application/xml
image/svg+xml
font/woff2
application/font-woff2;
server {
listen 80;
server_name $DOMAIN www.$DOMAIN;
set $upstream_backend http://$BACKEND_HOST:$BACKEND_PORT;
set $upstream_icecast http://$ICECAST_HOST:$ICECAST_PORT;
set $upstream_gitea http://$GITEA_HOST:$GITEA_PORT;
set $upstream_hasura http://$HASURA_HOST:$HASURA_PORT;
set $upstream_quartz http://$QUARTZ_HOST:$QUARTZ_PORT;
set $upstream_searxng http://$SEARXNG_HOST:$SEARXNG_PORT;
location /uploads/ {
alias /uploads/;
add_header X-Content-Type-Options nosniff always;
add_header Content-Disposition "inline" always;
add_header Content-Security-Policy "default-src 'none'; img-src 'self'; style-src 'none'; script-src 'none'" always;
}
location / {
proxy_pass http://vue:5173;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
location $BACKEND_ENDPOINT {
return 301 $BACKEND_ENDPOINT/;
}
location $BACKEND_ENDPOINT/ws {
rewrite ^$BACKEND_ENDPOINT/(.*)$ /$1 break;
proxy_pass $upstream_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
location $BACKEND_ENDPOINT/auth/login {
limit_req zone=login burst=3 nodelay;
rewrite ^$BACKEND_ENDPOINT/(.*)$ /$1 break;
proxy_pass $upstream_backend;
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;
}
location $BACKEND_ENDPOINT/messages/upload {
limit_req zone=upload burst=3 nodelay;
rewrite ^$BACKEND_ENDPOINT/(.*)$ /$1 break;
proxy_pass $upstream_backend;
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;
}
location $BACKEND_ENDPOINT/ {
limit_req zone=api burst=20 nodelay;
rewrite ^$BACKEND_ENDPOINT/(.*)$ /$1 break;
proxy_pass $upstream_backend;
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;
}
location /radio {
return 301 /radio/;
}
location /radio/ {
rewrite ^/radio/(.*)$ /$1 break;
proxy_pass $upstream_icecast;
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;
}
location /gitea {
return 301 /gitea/;
}
location /gitea/ {
rewrite ^/gitea/(.*)$ /$1 break;
proxy_pass $upstream_gitea;
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;
}
location /hasura {
return 301 /hasura/;
}
location /hasura/ {
auth_request /internal/auth/admin-validate;
error_page 401 403 = @auth_denied;
rewrite ^/hasura/(.*)$ /$1 break;
proxy_pass $upstream_hasura;
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 "upgrade";
}
location /notes {
return 301 /notes/;
}
location /notes/ {
auth_request /internal/auth/admin-validate;
error_page 401 403 = @auth_denied;
rewrite ^/notes/(.*)$ /$1 break;
proxy_pass $upstream_quartz;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
location = /internal/auth/admin-validate {
internal;
rewrite ^ /auth/validate-admin break;
proxy_pass $upstream_backend;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header Cookie $http_cookie;
}
location @auth_denied {
return 302 /admin/login?redirect=$request_uri;
}
location /searxng {
return 301 /searxng/;
}
location /searxng/ {
auth_request /internal/auth/admin-validate;
error_page 401 403 = @auth_denied;
rewrite ^/searxng/(.*)$ /$1 break;
proxy_pass $upstream_searxng;
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;
}
}
server {
listen 443 ssl;
server_name $DOMAIN www.$DOMAIN;
ssl_certificate /etc/letsencrypt/live/localhost/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/localhost/privkey.pem;
set $upstream_backend http://$BACKEND_HOST:$BACKEND_PORT;
set $upstream_icecast http://$ICECAST_HOST:$ICECAST_PORT;
set $upstream_gitea http://$GITEA_HOST:$GITEA_PORT;
set $upstream_hasura http://$HASURA_HOST:$HASURA_PORT;
set $upstream_quartz http://$QUARTZ_HOST:$QUARTZ_PORT;
set $upstream_searxng http://$SEARXNG_HOST:$SEARXNG_PORT;
location /uploads/ {
alias /uploads/;
add_header X-Content-Type-Options nosniff always;
add_header Content-Disposition "inline" always;
add_header Content-Security-Policy "default-src 'none'; img-src 'self'; style-src 'none'; script-src 'none'" always;
}
location / {
proxy_pass http://vue:5173;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
location $BACKEND_ENDPOINT {
return 301 $BACKEND_ENDPOINT/;
}
location $BACKEND_ENDPOINT/ws {
rewrite ^$BACKEND_ENDPOINT/(.*)$ /$1 break;
proxy_pass $upstream_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
location $BACKEND_ENDPOINT/auth/login {
limit_req zone=login burst=3 nodelay;
rewrite ^$BACKEND_ENDPOINT/(.*)$ /$1 break;
proxy_pass $upstream_backend;
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;
}
location $BACKEND_ENDPOINT/messages/upload {
limit_req zone=upload burst=3 nodelay;
rewrite ^$BACKEND_ENDPOINT/(.*)$ /$1 break;
proxy_pass $upstream_backend;
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;
}
location $BACKEND_ENDPOINT/ {
limit_req zone=api burst=20 nodelay;
rewrite ^$BACKEND_ENDPOINT/(.*)$ /$1 break;
proxy_pass $upstream_backend;
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;
}
location /radio {
return 301 /radio/;
}
location /radio/ {
rewrite ^/radio/(.*)$ /$1 break;
proxy_pass $upstream_icecast;
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;
}
location /gitea {
return 301 /gitea/;
}
location /gitea/ {
rewrite ^/gitea/(.*)$ /$1 break;
proxy_pass $upstream_gitea;
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;
}
location /hasura {
return 301 /hasura/;
}
location /hasura/ {
auth_request /internal/auth/admin-validate;
error_page 401 403 = @auth_denied;
rewrite ^/hasura/(.*)$ /$1 break;
proxy_pass $upstream_hasura;
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 "upgrade";
}
location /notes {
return 301 /notes/;
}
location /notes/ {
auth_request /internal/auth/admin-validate;
error_page 401 403 = @auth_denied;
rewrite ^/notes/(.*)$ /$1 break;
proxy_pass $upstream_quartz;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
location = /internal/auth/admin-validate {
internal;
rewrite ^ /auth/validate-admin break;
proxy_pass $upstream_backend;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header Cookie $http_cookie;
}
location @auth_denied {
return 302 /admin/login?redirect=$request_uri;
}
location /searxng {
return 301 /searxng/;
}
location /searxng/ {
auth_request /internal/auth/admin-validate;
error_page 401 403 = @auth_denied;
rewrite ^/searxng/(.*)$ /$1 break;
proxy_pass $upstream_searxng;
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;
}
}
}