Skip to content

Hosted GUI architecture

The hosted GUI lets colleagues see their forecasts cycling in a browser, with authentication and role-based access. It is an operator-deployed substrate on an on-prem head-node pair — distinct from the unprivileged local GUI launcher, which any user can run loopback-only.

ServiceRole
CaddyTLS edge (Let’s Encrypt / internal ACME / operator PEM), IP allowlist, security headers (HSTS, X-Frame-Options, nosniff), WebSocket pass-through for GraphQL subscriptions. Reverse-proxies to JupyterHub on loopback.
JupyterHubMulti-user session broker. PAMAuthenticator against the head node’s existing AAA (LDAP/AD/2FA — whatever is already there). A pre-spawn hook checks cylc-admins/cylc-viewers group membership and injects the role.
cylc-uiserverSpawned per user, running as the real Unix user, proxied at /user/<name>/. Cross-user access is capped at READ by a site authorization ceiling.
PostgreSQLJupyterHub session state, on shared NFS, loopback-only, started/stopped by keepalived to enforce active-passive.
keepalivedActive-passive VRRP HA over a shared VIP; health-checks a loopback /healthz; on failover remounts NFS and starts services in order.

PAM authentication → JupyterHub session → group-check pre-spawn hook → per-user cylc-uiserver as the Unix user → cross-user access gated at READ by the site ceiling and by filesystem permissions.

The tech-stack modernization recommends, for this substrate:

  • a Content-Security-Policy at the Caddy edge (today SRI is the only CDN guard);
  • rootless Apptainer/Podman recipes so the CI harness and any containerized path do not require a Docker daemon;
  • pinning the gui/app/ front-end through a Vite build (retiring in-browser Babel) so any served bundle uses production React.

The substrate is shipped and tested via a Docker Compose CI harness (eight Playwright e2e specs). The hard-MVP gate — real PAM/cert/cluster/VIP and an end-to-end forecast on real infrastructure — is performed by the maintainer on real hardware and is not exercised in CI. See the implementation plan in the repository for the runbook.