# Ops Dashboard Pattern ## When to use Build an infrastructure operations dashboard when you need a single pane of glass showing cron health, service status, backup freshness, API reachability, server inventory, and system resource usage -- all updating automatically. ## Architecture ``` Python data collector (every 5m via no_agent cron) | v writes JSON to /var/www//data/ops-status.json | v served by Caddy /data/ops-status.json | v fetched by index.html (dark theme dashboard) | v auto-refresh every 30s dashboard stays live ``` ## Key pieces ### 1. Data collector script - Self-contained (stdlib only: subprocess, urllib, json, pathlib, os, datetime, socket) - Each data source wrapped in safe() -- one failure never crashes the whole cycle - Sources: Hermes cron jobs, systemd services, disk/memory, S3 backups (aws CLI), API health checks, versions, Hetzner server list, netcup server info - Output: /var/www/ops/data/ops-status.json (~6KB JSON) - Error log: /var/log/ops-collector.log - Runs via cron: --schedule "*/5 * * * *" --no_agent --script ops-data-collector.py ### 2. Dashboard HTML - Dark theme: bg #0f172a, cards #1e293b, amber accents #f59e0b - NO external dependencies (no Tailwind, no CDN, no frameworks) -- inline CSS + JS - Mobile-first responsive, PWA meta tags for iPhone Safari - Sections: Overall Health Bar, Scheduled Jobs, Services, S3 Backups, API Health, Server Inventory, Routers (placeholder), Versions - Fetch /data/ops-status.json on load, auto-refresh every 30s - If fetch fails: red banner "Dashboard data not available -- collector may be offline" ### 3. Caddy serving ``` ops.itpropartner.com { root * /var/www/ops encode gzip file_server log { output file /var/log/caddy/ops.log } } ``` ### 4. CORS for the data file ``` header /data/* { Access-Control-Allow-Origin "*" } ``` ## Pitfalls - S3 auth requires endpoint-url for Wasabi: aws s3 ls --recursive --endpoint-url https://s3.us-east-1.wasabisys.com - Datetime timezone mismatch: S3 ls returns naive datetimes. The collector must .replace(tzinfo=timezone.utc) before subtracting. - Python 3.13 deprecation: datetime.utcnow() is deprecated. Use datetime.now(timezone.utc) instead. - AWS CLI path: must activate /opt/awscli-venv/bin/activate before calling aws commands - Placeholder sections: Show amber cards with "Coming soon" for empty sections