178 lines
6.3 KiB
Nginx Configuration File
178 lines
6.3 KiB
Nginx Configuration File
|
|
# 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;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|