feat(proxy): plain-HTTP LAN entry for waiter (:80) and manager (:8081), no certs required
Phones can now open the waiter app at http://<LAN IP> with no domain, DNS record or certificate (works around DNS-rebinding failures, KI-001). The manager gets http://<LAN IP>:8081, with http://<LAN IP>/manager redirecting there. waiter.*/manager.* hostnames on :80 still redirect to https, so legacy domain sites behave as before. - Both plain-HTTP servers are LAN-only (allow RFC1918/loopback/ULA/link-local, deny all -> 403), so a router port-forward can't expose an unencrypted POS - nginx-proxy/nginx.conf and the install.sh heredoc are now byte-identical (one canonical config, routing map in its header) - install.sh generates a 10-year self-signed cert when certs/ is empty (nginx won't start its TLS listeners without one), detects HOST_IP via 'ip route get', prompts for it on fresh installs and backfills it into an existing .env, always starts the stack, prints the LAN URLs - docker-compose publishes 8081; .env.example documents HOST_IP - pack README: ports/request path updated, CS-5 byte-identical check Verified: nginx -t; install.sh in Debian (fresh / upgrade without HOST_IP / re-run - no duplicate HOST_IP, cert SAN includes HOST_IP, key 600); full stack from freshly built images: every entry point returns the expected 200/301/302, and removing the gateway's range from the allow list yields 403 on :80 and :8081. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+150
-6
@@ -1,19 +1,101 @@
|
||||
# Repo/dev proxy config. install.sh writes its own copy on client sites — keep both in sync.
|
||||
# Every proxied location must forward WebSocket upgrades (/api/ws/connect) and
|
||||
# must not buffer (SSE), otherwise live events never reach waiters / KDS.
|
||||
# Xenia POS — on-site proxy config.
|
||||
# install.sh writes this exact file on client sites; nginx-proxy/nginx.conf in the
|
||||
# repo is a byte-identical copy. Change both together (global Working Rule 9).
|
||||
#
|
||||
# :80 waiter.* / manager.* hostnames → redirect to https (legacy domain setup)
|
||||
# :80 anything else (bare LAN IP) → waiter app over plain HTTP, LAN only
|
||||
# /manager → redirect to :8081
|
||||
# :8081 → manager dashboard over plain HTTP, LAN only
|
||||
# :443 waiter.* / manager.* / bare IP → https (needs certs/cert.pem + key.pem)
|
||||
# :4443 → manager over https
|
||||
#
|
||||
# Every proxied location forwards WebSocket upgrades (/api/ws/connect) and
|
||||
# disables buffering (SSE), otherwise live events never reach phones / KDS.
|
||||
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
|
||||
# ── Plain HTTP ────────────────────────────────────────────────────────────────
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name waiter.* manager.*;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 80 default_server;
|
||||
server_name _;
|
||||
|
||||
# LAN only: plain HTTP must never be reachable from the internet, even if the
|
||||
# client forwards ports on their router. Relies on Docker preserving the real
|
||||
# client IP (default iptables port publishing on Linux).
|
||||
allow 10.0.0.0/8;
|
||||
allow 172.16.0.0/12;
|
||||
allow 192.168.0.0/16;
|
||||
allow 127.0.0.0/8;
|
||||
allow fc00::/7;
|
||||
allow fe80::/10;
|
||||
allow ::1;
|
||||
deny all;
|
||||
|
||||
location ~ ^/manager/?$ {
|
||||
return 302 http://$host:8081/;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://waiter_pwa:80;
|
||||
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 3600s;
|
||||
proxy_send_timeout 3600s;
|
||||
proxy_buffering off;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 8081 default_server;
|
||||
server_name _;
|
||||
|
||||
# LAN only: plain HTTP must never be reachable from the internet, even if the
|
||||
# client forwards ports on their router. Relies on Docker preserving the real
|
||||
# client IP (default iptables port publishing on Linux).
|
||||
allow 10.0.0.0/8;
|
||||
allow 172.16.0.0/12;
|
||||
allow 192.168.0.0/16;
|
||||
allow 127.0.0.0/8;
|
||||
allow fc00::/7;
|
||||
allow fe80::/10;
|
||||
allow ::1;
|
||||
deny all;
|
||||
|
||||
location / {
|
||||
proxy_pass http://manager_dashboard:80;
|
||||
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 3600s;
|
||||
proxy_send_timeout 3600s;
|
||||
proxy_buffering off;
|
||||
}
|
||||
}
|
||||
|
||||
# ── HTTPS ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name waiter.* _;
|
||||
server_name waiter.*;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/cert.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/key.pem;
|
||||
@@ -36,8 +118,70 @@ server {
|
||||
}
|
||||
|
||||
server {
|
||||
listen 4443 ssl;
|
||||
server_name manager.* _;
|
||||
listen 443 ssl;
|
||||
server_name manager.*;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/cert.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/key.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
location / {
|
||||
proxy_pass http://manager_dashboard:80;
|
||||
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 3600s;
|
||||
proxy_send_timeout 3600s;
|
||||
proxy_buffering off;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl default_server;
|
||||
server_name _;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/cert.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/key.pem;
|
||||
ssl_protocols TLSv1.2 TLSv1.3;
|
||||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||
|
||||
location /api/ {
|
||||
proxy_pass http://backend:8000;
|
||||
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 3600s;
|
||||
proxy_send_timeout 3600s;
|
||||
proxy_buffering off;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://waiter_pwa:80;
|
||||
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 3600s;
|
||||
proxy_send_timeout 3600s;
|
||||
proxy_buffering off;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 4443 ssl default_server;
|
||||
server_name _;
|
||||
|
||||
ssl_certificate /etc/nginx/certs/cert.pem;
|
||||
ssl_certificate_key /etc/nginx/certs/key.pem;
|
||||
|
||||
Reference in New Issue
Block a user