Ingress hub page: service dashboard with iframe embedding (flakes-bti9)
A hub web page served inside each container that auto-discovers running services and presents them as a navigable list with iframe embedding. Built on existing Caddy + ingress-sync infrastructure.
Design
Overview
Single hub page per container at hub.<hostname>.incus — left sidebar lists discovered services, right pane shows selected service in an iframe.
Service Discovery
Extend existing generate-ingress-config script to also produce /var/lib/ingress/services.json:
ss -tlnp→ port + PID + process name (existing logic)readlink /proc/<pid>/cwd→ working directory (new)- Shorten cwd (strip home prefix, show last 1-2 path segments)
- Output format:
[{"port": 3000, "process": "node", "cwd": "my-app", "url": "https://3000.hostname.incus"}] - Hub port excluded from the list (avoid self-reference)
Hub Page (Caddy Templates)
- Static HTML file with embedded CSS/JS, served by Caddy
templatesdirective - JS fetches
services.jsonat load time - Left sidebar: service list showing
<short_path> <process> :<port> - Right pane: iframe loading selected service URL
- Iframe failure detection → fallback “open in new tab” link
Caddy Config Changes
- New route:
hub.<hostname>.incusserving the hub HTML +services.json - Strip
X-Frame-Optionsand rewriteContent-Security-Policyheaders on all proxied routes (enables iframe embedding) - Internal TLS unchanged
Nix Integration
- All changes in
mixins/nixos/container/ingress.nix - Hub HTML as a Nix file/package
ingress-syncregenerates both Caddy config andservices.jsoningresscommand unchanged
Tasks
- Extend
generate-ingress-configto read/proc/<pid>/cwdand writeservices.json - Create hub HTML template (sidebar + iframe layout, JS service loader, iframe error fallback)
- Add Caddy route for
hub.<hostname>.incusserving hub page + services.json - Strip X-Frame-Options/CSP headers on proxied routes
- Test with multiple running services
Not in v1
- Manual label overrides
- Cross-container aggregation (host-level hub)
- Auto-refresh on service change (manual page reload for now)
- Service grouping/categorization
Summary of Changes
Implemented ingress hub page for container service dashboard:
- Hub page served at
hub.<hostname>.incus(internal) and<container>-hub.<host>.yjpark.org(external) - Service discovery via
ss -tlnpwith process name and working directory from/proc/<pid>/cwd - Sidebar + iframe layout with resizable sidebar, compact mode (icon toolbar), and service list sorted by port
- Smart URL routing: uses
https://<container>-<port>.<host>.yjpark.org(real LE certs) when accessed externally,http://<port>.<hostname>.incusinternally - Sync button triggers
generate-ingress-configvia Python API, showsingressstatus output in dismissable modal - Favicon proxy at
/api/icon/<port>fetches favicons from services (tries/favicon.icothen parses HTML<link rel=icon>), falls back to colored letter icons - Header stripping: removes
X-Frame-OptionsandContent-Security-Policyon proxied routes for iframe embedding - Host ingress: added
<container>-hubroute toincus-ingress.nixfor external access
Files changed:
mixins/nixos/container/ingress.nix— hub HTML, sync API, enhanced generate-ingress-configmixins/nixos/services/incus-ingress.nix— hub route for host-level Caddy