132 lines
4.5 KiB
Nginx Configuration File
132 lines
4.5 KiB
Nginx Configuration File
server {
|
|
listen 7777;
|
|
server_name _;
|
|
root /usr/share/nginx/html;
|
|
index index.html;
|
|
|
|
# Gzip compression
|
|
gzip on;
|
|
gzip_vary on;
|
|
gzip_min_length 1024;
|
|
gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json application/vnd.apple.mpegurl video/MP2T;
|
|
|
|
# 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 "no-referrer-when-downgrade" always;
|
|
|
|
# PWA Support - proper MIME types
|
|
location ~* \.(?:manifest|webmanifest|json)$ {
|
|
add_header Cache-Control "public, max-age=3600";
|
|
add_header Content-Type application/manifest+json;
|
|
}
|
|
|
|
location ~* \.(?:js|css|woff2|woff|ttf|otf|eot|svg|png|jpg|jpeg|gif|ico)$ {
|
|
expires 1y;
|
|
add_header Cache-Control "public, immutable";
|
|
}
|
|
|
|
# ── Backend API proxy ──────────────────────────────────────
|
|
location /api/ {
|
|
resolver 127.0.0.11 valid=30s ipv6=off;
|
|
set $api_upstream http://api:4000;
|
|
|
|
rewrite ^/api(.*) $1 break;
|
|
proxy_pass $api_upstream;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
# Trust the outer reverse proxy's X-Forwarded-Proto when present,
|
|
# otherwise fall back to the connection scheme.
|
|
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
|
|
# Preserve the original /api prefix so NIP-98 URL verification
|
|
# can reconstruct the URL the client actually signed.
|
|
proxy_set_header X-Forwarded-Prefix /api;
|
|
proxy_read_timeout 300s;
|
|
proxy_send_timeout 300s;
|
|
|
|
# Handle large video uploads (up to 5GB)
|
|
client_max_body_size 5g;
|
|
}
|
|
|
|
# ── MinIO storage proxy (public bucket) ────────────────────
|
|
# Serves poster images, HLS segments, etc. with caching
|
|
location /storage/ {
|
|
resolver 127.0.0.11 valid=30s ipv6=off;
|
|
set $minio_upstream http://minio:9000;
|
|
|
|
rewrite ^/storage/(.*) /indeedhub-public/$1 break;
|
|
proxy_pass $minio_upstream;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host minio:9000;
|
|
|
|
# Cache static assets aggressively
|
|
proxy_cache_valid 200 1d;
|
|
proxy_cache_valid 404 1m;
|
|
expires 1d;
|
|
add_header Cache-Control "public, max-age=86400";
|
|
add_header X-Cache-Status $upstream_cache_status;
|
|
}
|
|
|
|
# ── MinIO storage proxy (private bucket -- for HLS key delivery) ─
|
|
location /storage-private/ {
|
|
resolver 127.0.0.11 valid=30s ipv6=off;
|
|
set $minio_upstream http://minio:9000;
|
|
|
|
rewrite ^/storage-private/(.*) /indeedhub-private/$1 break;
|
|
proxy_pass $minio_upstream;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Host minio:9000;
|
|
|
|
# Do NOT cache private content
|
|
add_header Cache-Control "no-store";
|
|
}
|
|
|
|
# ── WebSocket proxy to Nostr relay (Docker service) ────────
|
|
location /relay {
|
|
resolver 127.0.0.11 valid=30s ipv6=off;
|
|
set $relay_upstream http://relay:8080;
|
|
|
|
rewrite ^/relay(.*) /$1 break;
|
|
proxy_pass $relay_upstream;
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
proxy_set_header Host $host;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
proxy_read_timeout 86400s;
|
|
proxy_send_timeout 86400s;
|
|
}
|
|
|
|
# ── Vue Router - SPA fallback ──────────────────────────────
|
|
location / {
|
|
try_files $uri $uri/ /index.html;
|
|
}
|
|
|
|
# Service Worker
|
|
location /sw.js {
|
|
add_header Cache-Control "no-cache";
|
|
proxy_cache_bypass $http_pragma;
|
|
proxy_cache_revalidate on;
|
|
expires off;
|
|
access_log off;
|
|
}
|
|
|
|
location /workbox-*.js {
|
|
add_header Cache-Control "no-cache";
|
|
proxy_cache_bypass $http_pragma;
|
|
proxy_cache_revalidate on;
|
|
expires off;
|
|
access_log off;
|
|
}
|
|
|
|
# Health check endpoint
|
|
location /health {
|
|
access_log off;
|
|
return 200 "healthy\n";
|
|
add_header Content-Type text/plain;
|
|
}
|
|
}
|