- Updated the SSL certificate for yuri.phx-erp.de with a new signed certificate. - Added a new NGINX configuration file for pgAdmin reverse proxy under the subpath /pgadmin4. - Enhanced the main NGINX configuration with improved logging, security headers, and real IP handling. - Implemented health check endpoints for both system and worker services with IP whitelisting. - Created a new entrypoint script for pgAdmin to manage .pgpass and servers.json configuration. - Removed the redis.conf file and commented out Redis session caching in the configuration.
392 lines
15 KiB
Nginx Configuration File
392 lines
15 KiB
Nginx Configuration File
# Main process configuration
|
||
worker_processes 1;
|
||
|
||
events {
|
||
worker_connections 1024;
|
||
}
|
||
|
||
http {
|
||
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 doesn’t 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;
|
||
|
||
resolver 127.0.0.11 valid=10s;
|
||
resolver_timeout 5s;
|
||
|
||
upstream phoenix_system_cluster {
|
||
zone phoenix_system_cluster 64k;
|
||
least_conn;
|
||
server phoenix-system:3000 resolve fail_timeout=1s max_fails=0;
|
||
# ADD_SYSTEM_SERVERS_HERE
|
||
}
|
||
|
||
upstream phoenix_worker_cluster {
|
||
zone phoenix_worker_cluster 64k;
|
||
least_conn;
|
||
server phoenix-worker:3001 resolve fail_timeout=1s max_fails=0;
|
||
# ADD_WORKER_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;
|
||
|
||
# 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
|
||
access_log /var/log/nginx/access.log main_with_realip if=$loggable;
|
||
# End of logs
|
||
|
||
##################################################################
|
||
# 🧩 HTTP Server Block
|
||
##################################################################
|
||
server {
|
||
listen 80;
|
||
server_name _;
|
||
|
||
# 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;
|
||
|
||
# Frontend SPA fallback
|
||
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
|
||
}
|
||
|
||
location /admin-api {
|
||
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;
|
||
|
||
# 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
|
||
}
|
||
|
||
# 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
|
||
}
|
||
|
||
# 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 _;
|
||
|
||
# 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
|
||
}
|
||
|
||
location /admin-api {
|
||
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
|
||
}
|
||
}
|
||
} |