211 lines
11 KiB
Nginx Configuration File
211 lines
11 KiB
Nginx Configuration File
events {
|
|
worker_connections 1024;
|
|
}
|
|
|
|
http {
|
|
include /etc/nginx/mime.types;
|
|
default_type application/octet-stream;
|
|
sendfile on;
|
|
keepalive_timeout 65;
|
|
|
|
# ── DNS resolver for dynamic upstream hostname resolution ─────────────────────
|
|
# Docker's embedded DNS server (allows upstream hostnames to be re-resolved
|
|
# when containers are recreated with new IPs, avoiding stale cache issues).
|
|
resolver 127.0.0.11:53 valid=10s;
|
|
resolver_timeout 5s;
|
|
|
|
# ── Upstreams ──────────────────────────────────────────────────────────────
|
|
upstream portal_upstream { server portal:5001; }
|
|
upstream digiserver_upstream { server digiserver-app:5000; }
|
|
upstream itassets_upstream { server itassets-app:5000; }
|
|
upstream srvmonitor_upstream { server srvmonitor-app:5000; }
|
|
upstream nv_backend_upstream { server networkview-backend:3001; }
|
|
upstream nv_frontend_upstream { server networkview-frontend:80; }
|
|
|
|
# ── Rate limiting ──────────────────────────────────────────────────────────
|
|
limit_req_zone $binary_remote_addr zone=login:10m rate=10r/m;
|
|
|
|
server {
|
|
listen 80;
|
|
server_name _;
|
|
|
|
# ── Internal: portal JWT verification (used by auth_request) ──────────
|
|
location = /portal-verify {
|
|
internal;
|
|
proxy_pass http://portal_upstream/api/verify-token;
|
|
proxy_pass_request_body off;
|
|
proxy_set_header Content-Length "";
|
|
proxy_set_header Cookie $http_cookie;
|
|
proxy_set_header X-Original-URI $request_uri;
|
|
proxy_set_header X-Real-IP $remote_addr;
|
|
}
|
|
|
|
# ── Health check (unauthenticated, used by Docker healthcheck) ─────────
|
|
location = /health {
|
|
proxy_pass http://portal_upstream/health;
|
|
proxy_set_header Host $host;
|
|
}
|
|
|
|
# ── Portal — main dashboard & auth (no auth_request, it IS the auth) ──
|
|
location / {
|
|
limit_req zone=login burst=20 nodelay;
|
|
proxy_pass http://portal_upstream;
|
|
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 60s;
|
|
}
|
|
|
|
# ── DigiServer — Player device API (no portal auth) ──────────────────
|
|
# Players use their own Bearer token auth; portal JWT is not involved.
|
|
# This block MUST be declared before the broader /digiserver/ block.
|
|
location /digiserver/api/ {
|
|
proxy_pass http://digiserver_upstream/api/;
|
|
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_set_header X-Script-Name /digiserver;
|
|
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
|
|
# player-edit-media endpoint accepts binary uploads from devices
|
|
client_max_body_size 256M;
|
|
proxy_connect_timeout 300s;
|
|
proxy_send_timeout 300s;
|
|
proxy_read_timeout 300s;
|
|
}
|
|
|
|
# ── DigiServer — Static media downloads (no portal auth) ───────────────
|
|
# Content URLs built by DigiServer include this path; players must be
|
|
# able to fetch media files without a portal session cookie.
|
|
location /digiserver/static/uploads/ {
|
|
proxy_pass http://digiserver_upstream/static/uploads/;
|
|
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_set_header X-Script-Name /digiserver;
|
|
|
|
expires 60d;
|
|
add_header Cache-Control "public";
|
|
}
|
|
|
|
# ── DigiServer v2 — /digiserver/ ──────────────────────────────────────
|
|
location /digiserver/ {
|
|
auth_request /portal-verify;
|
|
auth_request_set $auth_user_id $upstream_http_x_auth_user_id;
|
|
auth_request_set $auth_username $upstream_http_x_auth_username;
|
|
auth_request_set $auth_role $upstream_http_x_auth_role;
|
|
|
|
proxy_pass http://digiserver_upstream/;
|
|
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_set_header X-Script-Name /digiserver;
|
|
proxy_set_header X-Auth-User-Id $auth_user_id;
|
|
proxy_set_header X-Auth-Username $auth_username;
|
|
proxy_set_header X-Auth-Role $auth_role;
|
|
proxy_read_timeout 300s;
|
|
proxy_send_timeout 300s;
|
|
proxy_connect_timeout 300s;
|
|
|
|
# Large content uploads by admins (images, videos, presentations)
|
|
client_max_body_size 2048M;
|
|
|
|
# WebSocket support (for any live-reload / realtime features)
|
|
proxy_http_version 1.1;
|
|
proxy_set_header Upgrade $http_upgrade;
|
|
proxy_set_header Connection "upgrade";
|
|
}
|
|
|
|
# ── IT Asset Management — /itassets/ ──────────────────────────────────
|
|
location /itassets/ {
|
|
auth_request /portal-verify;
|
|
auth_request_set $auth_user_id $upstream_http_x_auth_user_id;
|
|
auth_request_set $auth_username $upstream_http_x_auth_username;
|
|
auth_request_set $auth_role $upstream_http_x_auth_role;
|
|
|
|
proxy_pass http://itassets_upstream/;
|
|
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_set_header X-Script-Name /itassets;
|
|
proxy_set_header X-Auth-User-Id $auth_user_id;
|
|
proxy_set_header X-Auth-Username $auth_username;
|
|
proxy_set_header X-Auth-Role $auth_role;
|
|
proxy_read_timeout 120s;
|
|
|
|
# Allow larger uploads (for asset documents)
|
|
client_max_body_size 50M;
|
|
}
|
|
|
|
# ── Server Monitor — /srvmonitor/ ─────────────────────────────────────
|
|
location /srvmonitor/ {
|
|
auth_request /portal-verify;
|
|
auth_request_set $auth_user_id $upstream_http_x_auth_user_id;
|
|
auth_request_set $auth_username $upstream_http_x_auth_username;
|
|
auth_request_set $auth_role $upstream_http_x_auth_role;
|
|
|
|
proxy_pass http://srvmonitor_upstream/;
|
|
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_set_header X-Script-Name /srvmonitor;
|
|
proxy_set_header X-Auth-User-Id $auth_user_id;
|
|
proxy_set_header X-Auth-Username $auth_username;
|
|
proxy_set_header X-Auth-Role $auth_role;
|
|
# Ansible playbook runs can take a while to stream output
|
|
proxy_read_timeout 300s;
|
|
client_max_body_size 50M;
|
|
}
|
|
|
|
# ── NetworkView API — /networkview/api/ ────────────────────────────────
|
|
# Must be declared BEFORE the broader /networkview/ location
|
|
location /networkview/api/ {
|
|
auth_request /portal-verify;
|
|
auth_request_set $auth_user_id $upstream_http_x_auth_user_id;
|
|
auth_request_set $auth_username $upstream_http_x_auth_username;
|
|
|
|
proxy_pass http://nv_backend_upstream/api/;
|
|
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;
|
|
# NetworkView backend already reads these headers for actor tracking
|
|
proxy_set_header X-User-Id $auth_user_id;
|
|
proxy_set_header X-Username $auth_username;
|
|
}
|
|
|
|
# ── NetworkView Frontend SPA — /networkview/ ───────────────────────────
|
|
location /networkview/ {
|
|
auth_request /portal-verify;
|
|
|
|
proxy_pass http://nv_frontend_upstream/;
|
|
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;
|
|
}
|
|
|
|
# ── Auth failure handlers ──────────────────────────────────────────────
|
|
# 401: not authenticated → redirect to portal login
|
|
error_page 401 = @login_redirect;
|
|
location @login_redirect {
|
|
return 302 /login?next=$request_uri;
|
|
}
|
|
|
|
# 403: authenticated but no access to this app → portal access denied
|
|
error_page 403 = @access_denied;
|
|
location @access_denied {
|
|
return 302 /access-denied;
|
|
}
|
|
}
|
|
}
|