events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; # DNS Docker: risolve di nuovo l'IP di rails dopo ogni recreate container. resolver 127.0.0.11 valid=5s ipv6=off; map $http_upgrade $connection_upgrade { default upgrade; '' close; } map $http_cookie $hls_cookie { default $http_cookie; "" "cookieCheck=1"; } # NPM termina TLS: lo schema reale arriva in X-Forwarded-Proto. map $http_x_forwarded_proto $forwarded_proto { default $http_x_forwarded_proto; "" $scheme; } server { listen 80; server_name _; client_max_body_size 20M; set $rails_backend rails:3000; # Replay MP4/thumbnail: solo lettura da Garage (URL presigned da Rails). location /media/ { limit_except GET HEAD { deny all; } rewrite ^/media/(.*)$ /$1 break; proxy_pass http://garage:3900; proxy_http_version 1.1; proxy_buffering off; proxy_request_buffering off; proxy_connect_timeout 5s; proxy_read_timeout 3600s; # Presigned S3 firmati sull'endpoint interno garage:3900 proxy_set_header Host garage:3900; 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 $scheme; proxy_set_header Range $http_range; proxy_set_header If-Range $http_if_range; } # HLS live/regia: proxy diretto a MediaMTX (non passa da Puma). location /hls/ { limit_except GET HEAD { deny all; } rewrite ^/hls/(.*)$ /$1 break; proxy_pass http://mediamtx:8888; proxy_http_version 1.1; proxy_buffering off; proxy_request_buffering off; proxy_connect_timeout 5s; proxy_read_timeout 3600s; proxy_set_header Host $host; proxy_set_header Cookie $hls_cookie; 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; # MediaMTX risponde 302 con Location http://… — il browser HTTPS lo blocca. proxy_redirect http://$host/ https://$host/; proxy_redirect http://$http_host/ https://$host/; # MediaMTX risponde 302 verso /live/match_{uuid}/… — riscrive per restare sotto /hls/ proxy_redirect /live/ /hls/live/; proxy_redirect ~^/live/(.*)$ /hls/live/$1; } # HLS cookie redirect di MediaMTX: passa da Rails (proxy con follow interno). location ~ ^/live/match_[0-9a-f-]+/ { limit_except GET HEAD { deny all; } proxy_pass http://$rails_backend; proxy_http_version 1.1; proxy_buffering off; proxy_request_buffering off; proxy_connect_timeout 5s; proxy_read_timeout 3600s; 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; } location = /edge-health { access_log off; add_header Content-Type text/plain; return 200 "ok\n"; } # Health check ops: pass-through senza pagina di cortesia. location = /up { proxy_pass http://$rails_backend; proxy_connect_timeout 2s; proxy_read_timeout 10s; 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 $scheme; } location = /up/deep { proxy_pass http://$rails_backend; proxy_connect_timeout 2s; proxy_read_timeout 30s; 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 $scheme; } location /cable { proxy_pass http://$rails_backend; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection $connection_upgrade; 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 $scheme; proxy_read_timeout 86400; proxy_connect_timeout 2s; error_page 502 503 504 = @maintenance; } location / { proxy_pass http://$rails_backend; proxy_connect_timeout 2s; proxy_read_timeout 120s; 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 $scheme; error_page 502 503 504 = @maintenance; } location @maintenance { internal; root /usr/share/nginx/maintenance; try_files /index.html =503; add_header Retry-After 15 always; add_header Cache-Control "no-store" always; } } }