Architecture Overview¶
MFCloud is a control plane plus an agent. The control plane (the master) runs the web console, the REST API, the task queue, and the database. Agents run on every compute / storage / LXD node and execute work the master schedules for them.
High-level data flow¶
┌────────────────────────────────────────────────────────┐
│ OPERATOR BROWSER │
└────────────────────────────┬───────────────────────────┘
│ HTTPS (Caddy TLS)
▼
┌────────────────────────────────────────────────────────────────────┐
│ MFCLOUD MASTER │
│ │
│ ┌─────────┐ ┌──────────────┐ ┌────────────┐ ┌────────┐ │
│ │ Caddy │───▶│ FastAPI app │───▶│ Celery │───▶│ Redis │ │
│ │ (TLS) │ │ (Uvicorn) │ │ Beat │ │ broker │ │
│ └─────────┘ └──────┬───────┘ └─────┬──────┘ └────┬───┘ │
│ │ async │ │ │
│ ▼ │ │ │
│ ┌─────────────────┐ │ │ │
│ │ TimescaleDB │ │ │ │
│ │ (Patroni HA) │ │ │ │
│ └─────────────────┘ │ │ │
└──────────────────────────────────────────────┼────────────────┼────┘
│ per-host queue │
▼ ▼
┌─────────────────────────────────────────────────────┐
│ COMPUTE / STORAGE NODES │
│ │
│ ┌────────────┐ ┌──────────────┐ ┌───────────┐ │
│ │ mfcloud- │ │ libvirt / │ │ LXD / │ │
│ │ agent (TLS)│ │ KVM │ │ Incus │ │
│ └─────┬──────┘ └──────────────┘ └───────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────┐ │
│ │ Ceph OSDs / LINSTOR + DRBD / ZFS / NFS │ │
│ └──────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
Master components¶
| Component | What it does |
|---|---|
| Caddy | TLS termination, HTTP/2, reverse-proxy to the FastAPI app, also serves the KB at /kb/. |
| FastAPI | Web UI + JSON REST API. Sync routes use psycopg2; async routes asyncpg. |
| Celery worker | Master-side queue (celery) for tasks that run inside the master container. |
| Celery beat | Cron-style scheduler for periodic tasks (HA monitor, telemetry rollup, etc.). |
| Redis | Celery broker. |
| TimescaleDB | Persistent state. Patroni provides HA failover; HAProxy routes writes to the primary. |
Node components¶
| Component | What it does |
|---|---|
| mfcloud-agent | Per-host Celery worker subscribed to compute-<ip-with-dashes>. Runs the per-host tasks (VM create, snapshot, backup, etc.). |
| Emergency Host UI | TLS web UI on 8443 — runs even when the master is down so an operator can reach the node directly. |
| libvirt / QEMU | KVM virtualization. |
| LXD / Incus | Container backend (optional — only enrolled nodes). |
Auth flow¶
Operator login (POST /api/login)
├─ Try local users.password (passlib bcrypt) ← ALWAYS first
├─ If miss + LDAP enabled → bind to AD as service account
│ → bind as user → auto-mirror with auth_provider='ad'
└─ Issues JWT (24 h, signed with SECRET_KEY)
Operator login (SSO — /api/auth/oidc/start)
├─ Generate state, nonce, PKCE S256
├─ Sign into 10-min HttpOnly cookie
├─ 302 → IdP authorize endpoint
├─ /callback: validate cookie + state + PKCE
├─ Exchange code → ID token, verify against IdP JWKS
└─ Auto-mirror with auth_provider='oidc' → issue JWT
All routes (REST + WebSocket) accept the JWT in Authorization: Bearer <token> or, for WebSockets, in Sec-WebSocket-Protocol.
Storage routing¶
A VM disk is just a libvirt-managed file or block device. The backend decision is made at VM-create time:
- LINSTOR / DRBD → block device backed by
/dev/drbd<N>, replicated synchronously across 2–3 nodes. - Ceph RBD → librbd-backed block device, accessible from any node in the cluster.
- ZFS → qcow2 file at
/<pool>/<vm>.qcow2on the node's local pool; not live-migratable, but can be asynchronously replicated to another host in the same cluster and restored there if the source goes down. - NFS → qcow2 file on the mounted share; migratable but limited by NFS performance.
The Repair Agent flow pushes core/lxd.py, core/ssh.py, and the entire tasks/ directory to a node so any update to those (e.g. a fingerprint-pinning patch) takes effect without re-deploying the OS image.