Files
Alpha/nginx/nginx.conf
Yuri-Lima 414e40619f Check
2025-09-24 15:58:23 +02:00

531 lines
21 KiB
Nginx Configuration File
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Main process configuration
worker_processes 1;
events {
worker_connections 1024;
}
http {
# ## Track by client IP; 20MB ≈ ~1200 active IPs
# limit_req_zone $binary_remote_addr zone=rl_zone:20m rate=50r/s;
# # Return 429 instead of 503 when throttled
# limit_req_status 429; # 429 is the HTTP status code for Too Many Requests
# # Log 429s at warn (not error)
# limit_req_log_level warn;
geo $frontend_whitelist {
default 1;
127.0.0.1 1;
172.20.0.0/16 1; # Frontend Docker subnet
5.75.153.161 1; # Grafana or monitoring
167.235.254.4 1; # Ansible server IP
}
geo $backend_whitelist {
default 1;
127.0.0.1 1;
172.19.0.0/16 1; # Backend Docker subnet
5.75.153.161 1; # Grafana or monitoring
167.235.254.4 1; # Ansible server IP
}
# These settings ensure that $remote_addr reflects the real client IP forwarded by https-portal, which is needed for your allow rules to work correctly
# Recommended for resolving client IP behind proxy
# Docker networks where both frontend and backend containers communicate through NGINX.
# To avoid potential misclassification of real client IPs from backend routes.
# The set_real_ip_from directive doesnt allow access — it just instructs NGINX to trust the X-Forwarded-For header from those IPs.
set_real_ip_from 172.20.0.0/16; # Replace with your Docker network subnet (matches your `frontend` network)
set_real_ip_from 172.19.0.0/16; # Replace with your Docker network subnet (matches your `backend` network)
real_ip_header X-Forwarded-For;
real_ip_recursive on;
# DNS resolver configuration for better reliability
resolver 127.0.0.11 valid=60s ipv6=off;
resolver_timeout 60s;
upstream phoenix_system_cluster {
zone phoenix_system_cluster 64k;
least_conn;
server phoenix-system:3000 resolve fail_timeout=60s max_fails=10;
server 127.0.0.1:81 backup; # Backup server for unavailable service
# ADD_SYSTEM_SERVERS_HERE
}
upstream phoenix_worker_cluster {
zone phoenix_worker_cluster 64k;
least_conn;
server phoenix-worker:3001 resolve fail_timeout=60s max_fails=10;
server 127.0.0.1:81 backup; # Backup server for unavailable service
# ADD_WORKER_SERVERS_HERE
}
upstream pgadmin4-ui {
zone pgadmin4-ui 64k;
least_conn;
server pgadmin4-ui:80 resolve fail_timeout=120s max_fails=20;
# server 127.0.0.1:81 backup; # Backup server for unavailable service
# ADD_PGADMIN4_SERVERS_HERE
}
server_tokens off; # Disable NGINX version tokens to avoid leaking NGINX version.
# File handling & upload limits
sendfile on;
client_max_body_size 64m;
# Global proxy timeout settings (can be overridden per location)
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
proxy_next_upstream_timeout 30s;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
# Prevent warning when setting many proxy headers, like we do
proxy_headers_hash_max_size 1024;
proxy_headers_hash_bucket_size 128;
# Gzip compression (for better bandwidth efficiency)
gzip on;
gzip_min_length 1000;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# Trust the protocol from upstream proxy/load balancer
map $http_x_forwarded_proto $forwarded_proto {
default $scheme;
https https;
http http;
}
# File types and default mime type
include /etc/nginx/mime.types;
default_type application/octet-stream;
# 🧩 Logs
map $request_uri $loggable {
default 1;
~^/stub_status 0;
~^/health/system 0;
~^/health/worker 0;
}
# log_format main_with_realip '$remote_addr - $realip_remote_addr [$time_local] '
# '"$request" $status $body_bytes_sent '
# '"$http_referer" "$http_user_agent"';
log_format json_compatible escape=json '{'
'"time":"$time_iso8601",'
'"remote_addr":"$remote_addr",'
'"proxy_addr":"$proxy_protocol_addr",'
'"x_forwarded_for":"$http_x_forwarded_for",'
'"request_method":"$request_method",'
'"request_uri":"$request_uri",'
'"status":$status,'
'"body_bytes_sent":$body_bytes_sent,'
'"request_time":$request_time,'
'"upstream_response_time":"$upstream_response_time",'
'"http_referer":"$http_referer",'
'"http_user_agent":"$http_user_agent",'
'"host":"$host",'
'"realip":"$realip_remote_addr"'
'}';
access_log /var/log/nginx/access_json.log json_compatible if=$loggable; # JSON format for Loki/Grafana/Prometheus/Fail2ban
# access_log /var/log/nginx/access.log main_with_realip if=$loggable;
# End of logs
##################################################################
# 🔧 Backup Server for Unavailable Services
##################################################################
server {
listen 127.0.0.1:81;
server_name _;
# limit_req zone=rl_zone burst=30 nodelay;
# Return service unavailable for health checks
location /health {
add_header Content-Type application/json always;
return 503 '{"status":"unavailable","message":"Service is currently down"}';
}
# Return service unavailable for all other requests
location / {
add_header Content-Type text/html always;
return 503 '<html><body><h1>Service Temporarily Unavailable</h1><p>The requested service is currently down for maintenance.</p></body></html>';
}
# Return service unavailable for pgAdmin4
location /pgadmin4 {
add_header Content-Type text/html always;
return 503 '<html><body><h1>Service Temporarily Unavailable</h1><p>The requested service is currently down for maintenance.</p></body></html>';
}
location /health/worker {
add_header Content-Type application/json always;
return 503 '{"status":"unavailable","message":"Service is currently down"}';
}
}
##################################################################
# 🧩 HTTP Server Block
##################################################################
server {
listen 80;
server_name _;
# limit_req zone=rl_zone burst=30 nodelay;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
root /usr/share/nginx/html;
index index.html index.htm;
# --- Return real 404 for common bot targets (must be before SPA fallback) ---
# Block direct file probes like .php, .env, .git, backups, etc.
location ~* \.(php|env|git|sql|bak|ini|config|swp|old|backup)$ {
return 404;
}
# Block well-known bad paths used by scanners
location ~* ^/(wp-admin|wp-login\.php|xmlrpc\.php|phpinfo\.php|vendor/phpunit|setup\.php|manager/html|id\.php|shell\.php|\.DS_Store) {
return 404;
}
# Test for Fail2ban
# location = /__f2b_test_404__ { return 404; }
# Frontend SPA fallback (keep this AFTER the blocks above)
location / {
try_files $uri $uri/ /index.html;
}
# Backend API routes
location /backend-api/ {
proxy_pass http://phoenix_system_cluster/;
# Include headers for proxying
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-Host $host;
proxy_set_header X-Forwarded-Proto $forwarded_proto;
# End of headers
client_max_body_size 500m; # Increase the body size limit for admin API requests to 500mb
# Increase timeout settings for file uploads
proxy_connect_timeout 1800; # 30 minutes for regular API with file uploads
proxy_send_timeout 1800; # 30 minutes to send request to backend
proxy_read_timeout 1800; # 30 minutes to read response from backend
send_timeout 1800; # 30 minutes to send response to client
}
location /admin-api {
client_max_body_size 1024m; # Increase the body size limit for admin API requests to 1gb
proxy_connect_timeout 3600; # 60 minutes to establish connection to backend
proxy_send_timeout 3600; # 60 minutes to send request to backend
proxy_read_timeout 3600; # 60 minutes to read response from backend
send_timeout 3600; # 60 minutes to send response to client
proxy_pass http://phoenix_system_cluster/admin-api;
# Include headers for proxying
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-Host $host;
proxy_set_header X-Forwarded-Proto $forwarded_proto;
# End of headers
}
location /remote-assets {
proxy_pass http://phoenix_system_cluster/remote-assets;
# Include headers for proxying
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-Host $host;
proxy_set_header X-Forwarded-Proto $forwarded_proto;
# End of headers
}
location /sti {
proxy_pass http://phoenix_system_cluster/sti;
# Include headers for proxying
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-Host $host;
proxy_set_header X-Forwarded-Proto $forwarded_proto;
# End of headers
}
# WebSocket support
location /ws {
proxy_pass http://phoenix_system_cluster/graphql;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Include headers for proxying
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-Host $host;
proxy_set_header X-Forwarded-Proto $forwarded_proto;
# End of headers
}
# Reverse proxy for pgAdmin (subpath support)
# include /etc/nginx/includes/*.conf;
location /pgadmin4 {
error_log /var/log/nginx/pgadmin4_error.log notice;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass http://pgadmin4-ui/;
proxy_set_header X-Script-Name /pgadmin4;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Forwarded-Proto $forwarded_proto;
# Improved timeout settings
proxy_connect_timeout 120s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
# Retry on errors
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_next_upstream_tries 5;
proxy_next_upstream_timeout 120s;
# Include headers for proxying
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-Host $host;
# End of headers
proxy_redirect off;
# ⚠️ Rewrite required to remove /pgadmin4 from the path
rewrite ^/pgadmin4(/.*)$ $1 break;
}
# Health check endpoints -> used by the health check exporter
location /health/system {
proxy_pass http://phoenix_system_cluster/health;
# Secure the health check endpoint
if ($backend_whitelist = 0) {
return 403;
}
# End of security
# Include headers for proxying
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 $forwarded_proto;
# End of headers
# Timeout settings
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}
# location /health/system/metrics {
# proxy_pass http://phoenix_system_cluster/health/metrics;
# # Secure the health check endpoint
# # if ($backend_whitelist = 0) {
# # return 403;
# # }
# # End of security
# # Include headers for proxying
# 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 $forwarded_proto;
# # End of headers
# }
location /health/worker {
proxy_pass http://phoenix_worker_cluster/health;
# Secure the health check endpoint
if ($backend_whitelist = 0) {
return 403;
}
# End of security
# Include headers for proxying
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 $forwarded_proto;
# End of headers
# Timeout settings
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
}
# location /health/worker/metrics {
# proxy_pass http://phoenix_worker_cluster/health/metrics;
# # Secure the health check endpoint
# # if ($backend_whitelist = 0) {
# # return 403;
# # }
# # End of security
# # Include headers for proxying
# 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 $forwarded_proto;
# # End of headers
# }
location /stub_status {
stub_status;
# Secure the stub status endpoint
if ($frontend_whitelist = 0) {
return 403;
}
# End of security
}
}
##################################################################
# 🔐 HTTPS Server Block
##################################################################
server {
listen 443 ssl;
http2 on;
server_name _;
# Apply globally inside this server
# limit_req zone=rl_zone burst=30 nodelay;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
ssl_certificate /etc/nginx/external-certificate/certificate.crt;
ssl_certificate_key /etc/nginx/external-certificate/certificate.key;
root /usr/share/nginx/html;
index index.html index.htm;
location / {
try_files $uri $uri/ /index.html;
}
# Secure API routes
location /backend-api/ {
proxy_pass http://phoenix_system_cluster/;
# Include headers for proxying
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-Host $host;
proxy_set_header X-Forwarded-Proto $forwarded_proto;
# End of headers
client_max_body_size 500m; # Increase the body size limit for admin API requests to 500mb
# Increase timeout settings for file uploads
proxy_connect_timeout 1800; # 30 minutes for regular API with file uploads
proxy_send_timeout 1800; # 30 minutes to send request to backend
proxy_read_timeout 1800; # 30 minutes to read response from backend
send_timeout 1800; # 30 minutes to send response to client
}
location /admin-api {
client_max_body_size 1024m; # Increase the body size limit for admin API requests to 1gb
proxy_connect_timeout 3600; # 60 minutes to establish connection to backend
proxy_send_timeout 3600; # 60 minutes to send request to backend
proxy_read_timeout 3600; # 60 minutes to read response from backend
send_timeout 3600; # 60 minutes to send response to client
proxy_pass http://phoenix_system_cluster/admin-api;
# Include headers for proxying
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-Host $host;
proxy_set_header X-Forwarded-Proto $forwarded_proto;
# End of headers
}
location /remote-assets {
proxy_pass http://phoenix_system_cluster/remote-assets;
# Include headers for proxying
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-Host $host;
proxy_set_header X-Forwarded-Proto $forwarded_proto;
# End of headers
}
location /sti {
proxy_pass http://phoenix_system_cluster/sti;
# Include headers for proxying
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-Host $host;
proxy_set_header X-Forwarded-Proto $forwarded_proto;
# End of headers
}
location /ws {
proxy_pass http://phoenix_system_cluster/graphql;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Include headers for proxying
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-Host $host;
proxy_set_header X-Forwarded-Proto $forwarded_proto;
# End of headers
}
# Reverse proxy for pgAdmin (subpath support)
include /etc/nginx/includes/*.conf;
location /health/system {
proxy_pass http://phoenix_system_cluster/health;
# Secure the health check endpoint
if ($backend_whitelist = 0) {
return 403;
}
# End of security
# Include headers for proxying
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 $forwarded_proto;
# End of headers
}
location /health/worker {
proxy_pass http://phoenix_worker_cluster/health;
# Secure the health check endpoint
if ($backend_whitelist = 0) {
return 403;
}
# End of security
# Include headers for proxying
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 $forwarded_proto;
# End of headers
}
location /stub_status {
stub_status;
# Secure the stub status endpoint
if ($frontend_whitelist = 0) {
return 403;
}
# End of security
}
}
}