# No user directive needed for non-root containers worker_processes auto; pid /var/run/nginx.pid; events { worker_connections 1024; use epoll; multi_accept on; } http { # Basic Settings sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; client_max_body_size 100M; server_tokens off; # MIME Types include /etc/nginx/mime.types; default_type application/octet-stream; # Logging - Output to stdout/stderr for container log collection log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; log_format timed '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" ' 'rt=$request_time uct=$upstream_connect_time uht=$upstream_header_time urt=$upstream_response_time'; access_log /dev/stdout timed; error_log /dev/stderr warn; # Gzip compression gzip on; gzip_vary on; gzip_min_length 1024; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/atom+xml application/activity+json application/ld+json image/svg+xml; # Rate limiting removed - handled at ingress level for better client IP detection # Upstream for uWSGI upstream piefed_app { server 127.0.0.1:8000; keepalive 2; } server { listen 80; server_name _; # Security headers add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; # HTTPS enforcement and mixed content prevention add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header Content-Security-Policy "upgrade-insecure-requests" always; # Real IP forwarding (for Kubernetes ingress) real_ip_header X-Forwarded-For; set_real_ip_from 10.0.0.0/8; set_real_ip_from 172.16.0.0/12; set_real_ip_from 192.168.0.0/16; # Serve static files directly with nginx (following PieFed official recommendation) location /static/ { alias /app/app/static/; expires max; add_header Cache-Control "public, max-age=31536000, immutable"; add_header Vary "Accept-Encoding"; # Security headers for static assets add_header X-Frame-Options "SAMEORIGIN" always; add_header X-Content-Type-Options "nosniff" always; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; add_header Content-Security-Policy "upgrade-insecure-requests" always; # Handle trailing slashes gracefully try_files $uri $uri/ =404; } # Media files (user uploads) - long cache since they don't change location /media/ { alias /app/media/; expires 1d; add_header Cache-Control "public, max-age=31536000"; } # Health check endpoint location /health { access_log off; return 200 "healthy\n"; add_header Content-Type text/plain; } # NodeInfo endpoints - no override needed, PieFed already sets application/json correctly location ~ ^/nodeinfo/ { proxy_pass http://piefed_app; 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 https; proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; } # Webfinger endpoint - ensure correct Content-Type per WebFinger spec location ~ ^/\.well-known/webfinger { proxy_pass http://piefed_app; 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 https; # Force application/jrd+json Content-Type for webfinger (per WebFinger spec) proxy_hide_header Content-Type; add_header Content-Type "application/jrd+json" always; # Ensure CORS headers are present for federation discovery add_header Access-Control-Allow-Origin "*" always; add_header Access-Control-Allow-Methods "GET, OPTIONS" always; add_header Access-Control-Allow-Headers "Content-Type, Authorization, Accept, User-Agent" always; proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; } # API and federation endpoints location ~ ^/(api|\.well-known|inbox) { proxy_pass http://piefed_app; 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 https; # Force HTTPS scheme proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; } # All other requests location / { proxy_pass http://piefed_app; 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 https; # Force HTTPS scheme proxy_connect_timeout 30s; proxy_send_timeout 30s; proxy_read_timeout 30s; } # Error pages error_page 404 /404.html; error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } } }