# MDF Ops Web UI — Specification ## Overview A web dashboard for daily server operations. Runs as a Docker container behind Traefik at `cockpit.tekmidian.com`. Wraps the existing `ops` CLI and `offsite.py` module on the Hetzner server. ## Architecture - **Frontend:** Single-page app (vanilla HTML/CSS/JS or lightweight framework like Alpine.js + Tailwind) - **Backend:** Python FastAPI app that shells out to `ops` CLI and imports `offsite.py` - **Deployment:** Docker container, Traefik labels for HTTPS routing - **Auth:** Simple token-based auth (single admin user, configurable password) ## Pages / Features ### 1. Dashboard (home) - All containers with status, health, uptime (from `ops status --json`) - Color-coded: green=healthy, red=unhealthy/exited, yellow=starting - Group by project (MDF, SeriousLetter, RingsADay, KioskPilot, Coolify) - Auto-refresh every 30s ### 2. Backups - **Local backups**: list per project/env with size, age (from `ops backups --json`) - **Offsite backups**: list per project/env (from `ops offsite list --json`) - **Backup now** button: triggers `ops backup [env]` - **Upload to offsite** button: triggers `ops offsite upload [env]` - **Apply retention** button: triggers `ops offsite retention` - Show backup age warnings (>24h = yellow, >48h = red) ### 3. Restore - Select source: local or offsite - Select project and environment - If offsite: download first, then restore - Dry-run option - Confirmation dialog before executing - Show progress/output in real-time (SSE or websocket) ### 4. Services - Per-project service controls: restart container, view logs (last 100 lines) - Link to Coolify dashboard for deeper management - Domain links (click to open site) ### 5. System - Disk usage (from `ops disk`) - Health check results (from `ops health`) - Systemd timer status (backup-all, cert-sync) - Server uptime, load average ## API Endpoints (FastAPI) ``` GET /api/status → ops status --json GET /api/backups → ops backups --json GET /api/backups/offsite → ops offsite list --json POST /api/backup/{project}/{env} → ops backup project env POST /api/backup/offsite/upload/{project}/{env} → ops offsite upload POST /api/backup/offsite/retention → ops offsite retention POST /api/restore/{project}/{env} → ops restore (with source param) GET /api/logs/{project}/{env}/{service}?lines=100 → docker logs POST /api/restart/{project}/{env}/{service} → docker restart GET /api/system/disk → ops disk (parsed) GET /api/system/health → ops health (parsed) GET /api/system/timers → systemctl list-timers (parsed) ``` ## Server Paths - ops CLI: `/opt/infrastructure/ops` - offsite module: `/opt/data/scripts/offsite.py` - Python: `/opt/data/π/bin/python3` - registry: `/opt/infrastructure/servers/hetzner-vps/registry.yaml` ## Docker Compose - Container name: `ops-dashboard` - Traefik labels for `cockpit.tekmidian.com` - Mount `/opt/infrastructure`, `/opt/data`, `/var/run/docker.sock` (for docker commands) - Port: 8080 internal ## Design - Dark theme, clean, minimal - Responsive (works on phone too) - No heavy JS frameworks — keep it light and fast