109 lines
4.0 KiB
Nginx Configuration File
109 lines
4.0 KiB
Nginx Configuration File
map $http_origin $cors_origin {
|
|
default "";
|
|
"https://local.example.com:5173" $http_origin;
|
|
"https://app.example.com" $http_origin;
|
|
}
|
|
|
|
# Garage S3 web endpoint (port 3902 for public reads via website mode)
|
|
upstream garage_web {
|
|
server 10.10.10.39:3902;
|
|
server 10.10.10.40:3902 backup;
|
|
server 10.10.10.41:3902 backup;
|
|
}
|
|
|
|
server {
|
|
listen 5500;
|
|
server_name _;
|
|
|
|
# Use Docker's embedded DNS for dynamic container resolution
|
|
# Prevents stale IPs when containers restart and get new addresses
|
|
resolver 127.0.0.11 valid=10s;
|
|
set $upstream_web web:8000;
|
|
|
|
# 🔒 SECURITY: Remote Oathkeeper proxies here with auth headers already added
|
|
# Flow: Internet → Oathkeeper → This Nginx → Django/S3
|
|
|
|
# Internal auth check endpoint for S3 media
|
|
# Forwards all Oathkeeper headers so Django middleware can authenticate
|
|
location = /internal-auth-check {
|
|
internal;
|
|
proxy_pass http://$upstream_web/api/media-auth/;
|
|
proxy_pass_request_body off;
|
|
proxy_set_header Content-Length "";
|
|
proxy_set_header X-Original-URI $request_uri;
|
|
|
|
# Forward standard headers
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
|
|
# 🔒 Forward all Oathkeeper auth headers for middleware validation
|
|
proxy_set_header X-Oathkeeper-Secret $http_x_oathkeeper_secret;
|
|
proxy_set_header X-User-Id $http_x_user_id;
|
|
proxy_set_header X-User-Email $http_x_user_email;
|
|
proxy_set_header X-User-First-Name $http_x_user_first_name;
|
|
proxy_set_header X-User-Last-Name $http_x_user_last_name;
|
|
proxy_set_header X-User-Phone $http_x_user_phone;
|
|
proxy_set_header X-User-Profile-Type $http_x_user_profile_type;
|
|
proxy_set_header X-Django-Profile-Id $http_x_django_profile_id;
|
|
}
|
|
|
|
# S3-backed media serving with auth_request
|
|
# Flow: auth_request → Django validates → proxy to Garage S3
|
|
location /api/media/ {
|
|
# Auth check before proxying to S3
|
|
auth_request /internal-auth-check;
|
|
|
|
# Strip /api/media/ prefix and proxy to Garage web endpoint
|
|
# Website mode serves bucket content at root path
|
|
rewrite ^/api/media/(.*)$ /$1 break;
|
|
proxy_pass http://garage_web/;
|
|
proxy_http_version 1.1;
|
|
|
|
# Set Host header to bucket name for Garage website mode
|
|
proxy_set_header Host nexus-media.web.garage.nebula;
|
|
|
|
# Video streaming support - forward range requests
|
|
proxy_set_header Range $http_range;
|
|
proxy_set_header If-Range $http_if_range;
|
|
add_header Accept-Ranges bytes;
|
|
|
|
# Cache headers for static content (private = browser only, not CDN)
|
|
add_header Cache-Control "private, max-age=3600";
|
|
}
|
|
|
|
# Legacy internal location (kept for backwards compatibility during migration)
|
|
# Can be removed once S3 migration is verified
|
|
location /media-internal/ {
|
|
internal;
|
|
alias /app/media/;
|
|
add_header Accept-Ranges bytes;
|
|
sendfile on;
|
|
sendfile_max_chunk 1m;
|
|
tcp_nopush on;
|
|
tcp_nodelay on;
|
|
}
|
|
|
|
# All other requests proxy to Django
|
|
# Oathkeeper has already validated session and added headers before reaching here
|
|
location / {
|
|
proxy_pass http://$upstream_web;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Forwarded-Host $host;
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
proxy_http_version 1.1;
|
|
|
|
# WebSocket support (for GraphQL subscriptions)
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
|
|
# Large file uploads (videos) - increased from 50m
|
|
client_max_body_size 250m;
|
|
proxy_buffering off;
|
|
proxy_request_buffering off;
|
|
proxy_read_timeout 600s;
|
|
proxy_send_timeout 600s;
|
|
}
|
|
}
|