- Replace OpenStreetMap CDN with self-hosted Protomaps PMTiles
(Wisconsin + Florida regional extracts, served from nginx)
- Add protomaps-leaflet for vector tile rendering in dark theme
- Update CSP to remove openstreetmap.org, add blob: for vector workers
- Add nginx location block for /tiles/ with byte range support
- Mount tiles directory as volume (not baked into image)
- Remove alert_fired/alert_resolved toast notifications that spammed
"undefined" at fleet scale — dashboard still updates via query invalidation
- Add *.pmtiles to .gitignore (large binaries)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add WebSocket upgrade map to nginx and proxy /ws/ssh to poller:8080
- Update CSP connect-src to allow ws: and wss: for terminal connections
- Add tunnel port range 49000-49100, SSH relay env vars, ulimits, and healthcheck to poller in both override and prod compose files
- Increase poller memory limit to 512M in prod for tunnel/SSH overhead
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Without a resolver directive, nginx resolves upstream hostnames once at
startup and caches the IP forever. When the API container restarts it gets
a new Docker-assigned IP, causing 502 Bad Gateway until nginx is reloaded.
Fix:
- Add 'resolver 127.0.0.11 valid=10s' (Docker embedded DNS)
- Use a variable in proxy_pass ('set \ api') so nginx
re-resolves on every request using the resolver above
- Variable proxy_pass passes the full request URI as-is, so /api/...
correctly maps to http://api:8000/api/... without double-pathing