tablet-checkin/frontend/nginx.conf
jtricerolph f4625e0860 Fix nginx trailing-slash mixed-content redirect, add self-healing device reclaim
- location /tablet-checkin/api/devices/ (trailing slash, proxy_pass) made
  nginx auto-redirect the bare /api/devices list endpoint, and since this
  inner nginx sits behind NPM's TLS termination it built that redirect as
  http:// even over an https:// request — browsers block that as mixed
  content, surfacing as a bare 'Failed to fetch' on the Devices admin page
  with no other clue. Dropped the trailing slash on both the location
  pattern and proxy_pass target; still correctly prefix-matches every
  /devices/:id/... sub-route, no more auto-redirect at all.
- pushNavigate/send() now only reports delivered:true if a write
  demonstrably succeeded, not just because a stream entry exists for the
  device — a stale-but-not-formally-closed connection can silently accept
  a write that never reaches the far end.
- pushBookingToDevice can now self-heal a device stuck 'busy' with no live
  session behind it (session already expired unused) rather than requiring
  an admin to manually click Reset first. Real failure mode hit testing on
  a physical tablet 2026-09-01: two pushes worked end-to-end, a third's
  navigate event never reached the tablet (SSE connection silently died
  during an idle gap), leaving the device stuck with no way to recover
  except a manual admin reset.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-01 19:05:53 +00:00

65 lines
2.4 KiB
Nginx Configuration File

server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
client_max_body_size 12m;
location /tablet-checkin/api/auth/ {
proxy_pass http://10.10.10.101:3001/api/auth/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# SSE (devices/:id/stream) needs buffering off and no timeout — otherwise
# nginx buffers the event-stream response and the tablet's idle page
# never actually receives a push in real time.
#
# No trailing slash on either the location pattern or the proxy_pass
# target — with one, nginx auto-redirects any request matching this
# prefix *without* the trailing slash (i.e. exactly
# /tablet-checkin/api/devices, the plain device-list endpoint) to add
# it. That redirect broke real usage 2026-09-01: this inner nginx sits
# behind NPM's TLS termination, forwarded as plain HTTP, so it built
# the redirect's Location header as http:// even though the original
# request was https:// — browsers block that as mixed content, which
# surfaced as a bare "Failed to fetch" with no other clue. Dropping the
# trailing slash keeps this a plain prefix match (still correctly
# covers every /devices/:id/... sub-route) with no auto-redirect at all.
location /tablet-checkin/api/devices {
proxy_pass http://backend:3001/api/devices;
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_buffering off;
proxy_read_timeout 3600s;
add_header Cache-Control "no-store";
}
location /tablet-checkin/api/ {
proxy_pass http://backend:3001/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;
add_header Cache-Control "no-store";
}
location /tablet-checkin/health {
proxy_pass http://backend:3001/health;
}
location ~* /tablet-checkin/.*\.(js|css|png|ico|svg|woff2?)$ {
expires 1y;
add_header Cache-Control "public, immutable";
try_files $uri =404;
}
location /tablet-checkin/ {
add_header Cache-Control "no-cache" always;
try_files $uri /tablet-checkin/index.html;
}
location = / {
return 301 /tablet-checkin/;
}
}