# BetterFrame Docker nginx config. # # Production proxy routes for the Docker Compose stack. Upstreams use compose # service names and only this proxy is published on the host. upstream betterframe_admin { server server:18080; keepalive 16; } upstream betterframe_api { server server:18081; keepalive 16; } upstream betterframe_ws { server server:18082; } upstream betterframe_nodered { server nodered:1880; keepalive 8; } limit_req_zone $binary_remote_addr zone=bf_public:10m rate=30r/s; server { listen 80; server_name _; client_max_body_size 16M; location /admin/ { proxy_pass http://betterframe_admin; 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_http_version 1.1; proxy_set_header Connection ""; } location = /admin { return 301 /admin/; } location /setup { proxy_pass http://betterframe_admin; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location /auth/ { proxy_pass http://betterframe_admin; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location /static/ { proxy_pass http://betterframe_admin; } location /api/kiosk/ { proxy_pass http://betterframe_api; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_http_version 1.1; proxy_set_header Connection ""; } location /api/pair/ { limit_req zone=bf_public burst=10 nodelay; proxy_pass http://betterframe_api; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location /api/admin/ { proxy_pass http://betterframe_admin; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location /ws/kiosk { proxy_pass http://betterframe_ws; 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; } # Admin debug WS (journal + terminal) under /admin/ so Angie's existing # /admin/* routing applies. Proxied to coordinator-ws (18082) not admin-http. location /admin/ws/debug/ { proxy_pass http://betterframe_ws/ws/admin/debug/; 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_set_header Cookie $http_cookie; proxy_read_timeout 86400s; proxy_send_timeout 86400s; } location /nrdp/ { auth_request /api/admin/_check; proxy_pass http://betterframe_nodered; proxy_set_header Host $host; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } location = /nrdp { return 301 /nrdp/; } location /dash/ { auth_request /api/kiosk/_check; auth_request_set $bf_kiosk_id $upstream_http_x_betterframe_kiosk_id; proxy_pass http://betterframe_nodered; proxy_set_header Host $host; proxy_set_header X-BetterFrame-Kiosk-Id $bf_kiosk_id; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } location /in/public/ { limit_req zone=bf_public burst=20 nodelay; rewrite ^/in/public/(.*) /$1 break; proxy_pass http://betterframe_nodered; } location /in/kiosk/ { auth_request /api/kiosk/_check; auth_request_set $bf_kiosk_id $upstream_http_x_betterframe_kiosk_id; rewrite ^/in/kiosk/(.*) /$1 break; proxy_pass http://betterframe_nodered; proxy_set_header X-BetterFrame-Kiosk-Id $bf_kiosk_id; } location = /api/admin/_check { internal; proxy_pass http://betterframe_admin; proxy_pass_request_body off; proxy_set_header Content-Length ""; proxy_set_header Cookie $http_cookie; proxy_set_header Authorization $http_authorization; proxy_set_header X-Real-IP $remote_addr; } location = /api/kiosk/_check { internal; proxy_pass http://betterframe_api; proxy_pass_request_body off; proxy_set_header Content-Length ""; proxy_set_header Authorization $http_authorization; proxy_set_header X-Real-IP $remote_addr; } location /api/ { return 404; } location /ws/ { return 404; } location ~ ^/(healthz|readyz|version)$ { proxy_pass http://betterframe_admin; } location = / { proxy_pass http://betterframe_admin; } location / { proxy_pass http://betterframe_nodered; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }