Files
linearvoid/infrastructure/nginx/nginx.conf
T
zwitschi 5b5cdc4cd8
CI / test (push) Successful in 9m11s
CI / docker (push) Failing after 2m39s
CI / release (push) Skipped
Release / release (push) Canceled after 2m11s
chore: release v1.0.7
Playout: slate fallback, strict ffprobe validation, Prometheus metrics
Chat: history on join, DM offline delivery, env-config rate limits,
  Redis auto-reconnect, heartbeat, ban/mute enforcement, DM metrics
Viewer: presence indicators, schedule overlay, public /api/schedule
Admin: playlist drag-reorder, schedule overrides CRUD, user actions,
  inline mod buttons, CSV export, config editor, restart buttons,
  upload normalization gate, analytics time range
nginx: CORS preflight, JSON health, stub_status
Docs: test-lab vs production distinction across all configs/docs
Infra: Redis maxmemory, CD health IP-agnostic, slate volume mount
2026-08-06 17:41:52 +02:00

225 lines
7.6 KiB
Nginx Configuration File

events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
resolver 127.0.0.11 ipv6=off valid=30s;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name www.linearvoid.tv;
return 301 https://linearvoid.tv$request_uri;
}
server {
listen 80 default_server;
server_name linearvoid.tv localhost 127.0.0.1;
# Resumable admin upload chunks are 8MB by default; allow safe headroom.
client_max_body_size 64m;
root /srv/frontend;
index index.html;
location = /admin {
return 301 /admin/;
}
location = /admin/login {
return 301 /admin/login/;
}
location = /_admin_auth {
internal;
set $chat_upstream http://chat:3000;
proxy_pass $chat_upstream/api/admin/session;
proxy_http_version 1.1;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header Cookie $http_cookie;
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;
}
location /admin/login/ {
try_files $uri $uri/ /admin/login/index.html;
}
location /admin/ {
auth_request /_admin_auth;
error_page 401 = @admin_login_redirect;
try_files $uri $uri/ /admin/index.html;
}
location /assets/ {
try_files $uri =404;
}
# Serve static frontend
location / {
try_files $uri $uri/ /index.html;
}
# Proxy chat WebSocket
location /ws {
set $chat_upstream http://chat:3000;
proxy_pass $chat_upstream;
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-Forwarded-Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
location = /api/admin/login {
set $chat_upstream http://chat:3000;
proxy_pass $chat_upstream;
proxy_http_version 1.1;
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_set_header Cookie $http_cookie;
}
location = /api/admin/logout {
set $chat_upstream http://chat:3000;
proxy_pass $chat_upstream;
proxy_http_version 1.1;
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_set_header Cookie $http_cookie;
}
location = /api/admin/session {
set $chat_upstream http://chat:3000;
proxy_pass $chat_upstream;
proxy_http_version 1.1;
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_set_header Cookie $http_cookie;
}
location /api/admin/ {
auth_request /_admin_auth;
error_page 401 = @admin_api_unauthorized;
set $chat_upstream http://chat:3000;
proxy_pass $chat_upstream;
proxy_http_version 1.1;
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_set_header Cookie $http_cookie;
}
location /api/ {
set $chat_upstream http://chat:3000;
proxy_pass $chat_upstream;
proxy_http_version 1.1;
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;
}
location = /metrics {
set $chat_upstream http://chat:3000;
proxy_pass $chat_upstream;
proxy_http_version 1.1;
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;
}
location @admin_api_unauthorized {
add_header Content-Type application/json;
return 401 '{"error":"unauthorized"}';
}
location @admin_login_redirect {
return 302 /admin/login/;
}
location = /hls/playlist.m3u8 {
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, OPTIONS";
add_header Access-Control-Max-Age 86400;
return 204;
}
alias /srv/hls/playlist.m3u8;
add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0";
add_header Access-Control-Allow-Origin "*";
}
location = /hls/init.mp4 {
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, OPTIONS";
add_header Access-Control-Max-Age 86400;
return 204;
}
alias /srv/hls/init.mp4;
add_header Cache-Control "public, max-age=31536000, immutable";
add_header Access-Control-Allow-Origin "*";
}
location ~* ^/hls/(.+\.(ts|m4s))$ {
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, OPTIONS";
add_header Access-Control-Max-Age 86400;
return 204;
}
alias /srv/hls/$1;
add_header Cache-Control "public, max-age=31536000, immutable";
add_header Access-Control-Allow-Origin "*";
}
# Local/dev fallback HLS origin. Production media should use MEDIA_DOMAIN.
location /hls/ {
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin "*";
add_header Access-Control-Allow-Methods "GET, OPTIONS";
add_header Access-Control-Max-Age 86400;
return 204;
}
alias /srv/hls/;
add_header Cache-Control "public, max-age=60";
add_header Access-Control-Allow-Origin "*";
}
# Health checks — aggregated from upstream services
location /health {
default_type application/json;
return 200 '{"status":"ok","service":"nginx","timestamp":"$time_iso8601"}';
}
location /nginx-status {
stub_status on;
allow 127.0.0.1;
allow 172.16.0.0/12;
allow 192.168.0.0/16;
deny all;
}
}
}