How it works¶
Stack¶
- Litestar (ASGI) for the REST API, served by uvicorn.
- SQLAlchemy async via Advanced Alchemy on SQLite (
aiosqlite) for state. - libvirt + QEMU/KVM for the VMs, seeded with cloud-init.
The hcloud Python client is a dependency only because it's the most convenient oracle for the wire format (the conformance test drives it); the server itself never imports it.
The Actions model¶
hcloud is asynchronous: every mutating call returns an action that the client polls until it reaches success or error. cloudalone mirrors this exactly:
- A request (e.g.
POST /v1/servers) writes theServer+Actionrows and returns201immediately. - A background task runs the blocking libvirt work off the event loop (
asyncio.to_thread) and flips the action'sstatus. - The client polls
GET /v1/actions?id=…, the same as it would against Hetzner.
This keeps the API responsive while VMs boot, and it's why hcloud server create returns instantly and then "waits" for the action.
POST /v1/servers ──▶ write Server + Action (201) ──▶ background task
├─ allocate IPv6
├─ create libvirt domain
└─ action.status = success
GET /v1/actions?id=… ◀── client polls until success/error
Backends¶
The VM work lives behind a small Backend Protocol with two implementations:
| Backend | Selected by | Does |
|---|---|---|
stub |
CLOUDALONE_BACKEND=stub (default) |
No virtualization; records state only. Runs on any OS, used for dev and tests. |
libvirt |
CLOUDALONE_BACKEND=libvirt |
Real VMs via QEMU/KVM. Linux host only; behind the optional libvirt extra. |
Because the backend is a Protocol, the entire API + Actions model is exercised on macOS/CI with the stub; only the actual boot needs a Linux host.
Design¶
cloudalone follows functional core / imperative shell: pure logic (wire-format builders, address allocation, cloud-init/XML renderers) is separated from the side-effecting edges (DB, libvirt, the network). The worker runs outside the request scope, so it uses its own session_maker rather than Litestar's dependency injection.
See the Developer guide for the code layout.