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 <project> [env]
- Upload to offsite button: triggers
ops offsite upload <project> [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