External PanDA production monitoring frontend for the ePIC experiment at the Electron Ion Collider. Provides open-internet access to PanDA monitoring services that live behind BNL's firewall.
Live at https://epic-devcloud.org/
Browser → epic-devcloud.org (Django/Apache)
↓ proxy (full rendered HTML)
SSH tunnel (autossh, persistent)
↓
swf-monitor (BNL) → PanDA database
- Web pages — the hub, all PanDA views, and all PCS views — are
proxied as full rendered HTML from swf-monitor through the SSH tunnel
(
remote_app/monitor_client.proxy), which rewrites swf-monitor URLs to local/prod/paths and swaps in local auth controls. Same URL structure. Only swf-remote's own pages render locally (see Local vs proxied pages). - MCP relay at
/prod/mcp/forwards every swf-monitor tool exceptai_decide_proposalandepic_register_ai_assessment, through the tunnel as the signed-in user, with state-changing tools authority-gated upstream. Headless clients authenticate with a per-user token (see Live-data access). - No local PanDA data — all data comes from swf-monitor in real time.
- TeamComms — HTTP, MCP and streaming under
/prod/teamcomms/, using existing devcloud accounts and tokens. The integration contract describes authentication, AI identity, introspection and deployment.
- swf-monitor — Django web service at BNL with PanDA DB access, REST API, MCP server
- swf-testbed — Streaming workflow testbed orchestration and agents
- swf-common-lib — Shared utilities for SWF agents
| Path | Description |
|---|---|
/ |
PanDA Hub — links to all monitoring views |
/panda/activity/ |
Activity overview — job/task counts by status, user, site |
/panda/jobs/ |
Job list with DataTables filtering and search |
/panda/jobs/<pandaid>/ |
Job detail — full record, files, errors, log URLs |
/panda/tasks/ |
JEDI task list with DataTables filtering |
/panda/tasks/<taskid>/ |
Task detail with constituent jobs |
/panda/errors/ |
Error summary — top patterns ranked by frequency |
/panda/diagnostics/ |
Failed jobs with full error details |
/snapper/<scope>/report/ |
Coherent operational state snaps and history |
/snapper/<scope>/system/ |
Snapper capture policy, scheduler, and component registry |
/system/ |
Aggregate SWF system health |
/mcp/ |
Token-secured MCP relay: every monitor tool except ai_decide_proposal and epic_register_ai_assessment; state-changing tools retain upstream authority checks. GET serves the setup page |
/account/tokens/ |
Create and revoke API tokens |
# Clone both repos side by side
git clone https://github.com/BNLNPPS/swf-remote.git
git clone https://github.com/BNLNPPS/swf-monitor.git
# Set up dev environment (venv, symlinks to swf-monitor templates)
cd swf-remote
bash setup-dev.sh
# Set up database and .env
bash setup-server.sh
# Run dev server
cd src && ../.venv/bin/python manage.py runserver# Full setup: rsync, venv, deps, symlinks, migrations. Apache and TLS belong to the host's ingress: the site is
# served by ePIC's own Apache instance behind Caddy, managed in tjrepo ops/ec2dev/apache-epic and
# ops/ec2dev/caddy (README § The two Apache instances).
bash deploy/setup-apache.shThe tunnel is managed by systemd via autossh. See
deploy/swf-remote-tunnel.service. Requires SSH key access from
the hosting server to swf-monitor's host via an SSH gateway.
sudo cp deploy/swf-remote-tunnel.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now swf-remote-tunnel
sudo systemctl status swf-remote-tunnel- Django 5.2 (Python 3.11) — upgrading to Django 6.0 / Python 3.12 after OS upgrade
- PostgreSQL (local, for Django internals only)
- Apache + mod_wsgi
- httpx for upstream REST calls
- autossh + systemd for persistent SSH tunnel
- Let's Encrypt for HTTPS
Environment variables prefixed SWF_REMOTE_ to avoid collisions with
other apps on the same server. See .env.example.
Proxied pages are built by swf-monitor and fetched over the tunnel, so
viewing one requires an account. Anonymous visitors reach a locally rendered
landing page, the login path, static assets and the cached computing-centre
snapshot at /prod/panda/comp/snapshot.json. The snapshot permits browser
reads from https://etaverse.com through its upstream CORS header.
An account is established either by a local username and password or
by signing in with GitHub, which creates it on first use. Signing in is all
that reading requires. Acting on the production system requires authority,
held as two attributes on the account in swf-monitor and enforced there:
observed eic organization membership, and granted rights. A command-line client authenticates with a
per-user token created on /prod/account/tokens/ and sent as
Authorization: Bearer <token>; it reaches swf-monitor as that user. The
cross-component policy is defined in
Live-data access policy.
Most pages — the hub, all PanDA views, Alarms, and all PCS views — are served as
full rendered HTML proxied from swf-monitor (remote_app/views.py), so
they carry swf-monitor's own templates, nav, and styling. swf-remote
renders a smaller set itself using its own base.html: the MCP setup page,
the tokens page, and the login / password-change pages. Their nav is
swf-monitor's own, taken from the production hub through the tunnel
(monitor_client.nav_html), rewritten to local paths with local auth
controls like every proxied page, and cached for a minute; the last fetched
copy stands in during a tunnel outage. swf-remote holds no nav markup, so
the monitor's nav is the only one. Alarm code from the old local
implementation remains in the tree for rollback/reference, but live
/prod/alarms/... pages proxy to swf-monitor.
The proxy (monitor_client.proxy) preserves swf-monitor's page body and
<style>, rewriting only URLs and the auth controls — so swf-monitor's
own nav and styling reach the browser intact on proxied pages.
The red e favicon uses the lowercase letter outline from the collaboration's
ePIC logo.
public/favicon.svg is the vector asset; public/favicon.ico contains 16, 32
and 48 pixel versions. scripts/build_favicon.py renders the fallback from
the SVG with Chromium and Pillow.
DevcloudBrandingMiddleware adds the same icon links to local and proxied
HTML pages. It leaves streams, downloads and non-HTML responses unchanged.
The deploy script installs both files into the existing host landing directory,
where /favicon.ico also supplies the root and documentation pages. Apache
configuration does not change.
swf-remote keeps a symlink to swf-monitor's templates (created by
setup-dev.sh) for the shared assets the local pages pull in. URL names
use app_name = 'monitor_app' so {% url %} tags resolve to swf-remote's
own routes.