Nether Cloud: architecture direction — decisions & roadmap (2026-07-12) #21
Labels
No labels
Good First Issue
Help Wanted
Infra
Code
Infra
Email
Infra
Matrix
Infra
Other
Infra
SSO
Infra
Wiki
Kind
Bug
Kind/Documentation
Kind
Enhancement
Needs Info
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Security
Status
Abandoned
Status
Blocked
Status
Won't Fix
Testing
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
nether/meta#21
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Nether Cloud: architecture direction — decisions & roadmap (2026-07-12)
Summary of a long design conversation (Fox + Claude) covering admin tooling for the Tuwunel stack, how etke.cc actually works, k8s vs. simpler models, and a Guix-based architecture for a community-run, donated-hardware "Nether Cloud." Filed as a meta issue so decisions and open forks are captured in one place.
Research findings
Admin UI / Tuwunel. Ketesa (the renamed etke.cc synapse-admin) does not support Tuwunel — its "multi-backend" support means Synapse + MAS admin APIs. Tuwunel has no HTTP admin API at all; administration is admin-room text commands (conduwuit convention). Porting Ketesa is the worst option (its whole data layer is Synapse REST resources). Realistic paths: Tuwunel grows a native/Synapse-compatible admin API upstream (requested, uncommitted), or purpose-built UIs on the command channel.
knadh/tuwunel-adminis the current stopgap (sub-1.0, author-warned); if deployed, bind it to the private overlay network only. Moderation is unaffected — Draupnir works over the client-server API.etke.cc architecture. No k8s: one dedicated Hetzner VPS (or on-prem box) per customer, provisioned by
matrix-docker-ansible-deploy(which they maintain), Docker containers under systemd, customer changes = playbook vars + an Ansible run. Validates the single-tenant-isolation, config-driven model; the hard part is the config-management layer, not orchestration tech.K8s assessment. Wrong shape for this workload: stateful single-tenant monoliths that never scale horizontally; k8s tax (control plane, storage/network plumbing, upgrade treadmill) buys features that go unused, while its weaknesses (soft multi-tenancy, shared blast radius, non-portability of deployments) hit exactly where this model needs strength.
Guix orchestration gap (verified).
guix system containeris an instantiation mechanism, not a management plane. The missing container daemon was identified by the feature's own author in 2015 and never built; the 2026 cookbook still describes the script-emitting workflow; the heaviest production users (GeneNetwork) manage containers with hand-written systemd units and manual GC-root symlinks. The community's revealed preference when needing a management plane is to package one (first-class Ganeti service type; Incus packaged). Incus package exists in Guix; anincus-service-typedoes not appear in upstream manual/services (to be re-confirmed against current master).Ganeti (context): Google-originated cluster VM manager with DRBD-replicated disks, live migration, failover — the paved road if state-preserving failover is ever wanted, at the replicated-storage complexity cost we're deliberately declining.
Vaultwarden. OIDC SSO is upstream now. SSO handles authentication only; the master password derives the encryption key client-side and never reaches the server (zero-knowledge), so "unlock vault with the SSO password" is impossible by design — and that's the selling point for us: infrastructure compromise/seizure cannot open vaults. Key Connector (master-password-less) won't come to Vaultwarden (Bitwarden license). Decide the emergency-access/recovery story before rollout; a forgotten master password = unrecoverable vault.
Web clients. Sable (Cinny fork) is a React SPA — trivially self-hostable as static files behind Caddy. Commet has a web build but it's the weakest platform (Flutter/CanvasKit: heavy, laggy reports, verification quirks); officially supported targets are Windows/Linux/Android. Confirm intended web-support status with Airyzz before offering it.
Architecture direction (agreed in conversation; ratify/amend here)
The stack sandwich. Guix System (+ nonguix for firmware) on bare metal → Incus as the tenancy/management layer → guests preferably Guix (
guix system image) generated by a singletenant->operating-systemfunction over per-tenant manifests; non-Guix guests allowed as a pressure valve, used sparingly. Inside guests: native Guix services for the boring layer;oci-container-service-type(digest-pinned images) for the fast-moving Matrix application layer (Tuwunel, bridges, Draupnir) until native packages/service types exist.Trust ladder — isolation level is an instantiation choice, same declarations:
guix system containerunder Shepherd.Git is the control plane. Desired state (node declarations + tenant manifests) lives in a Forgejo-hosted infrastructure channel. The future provisioning webui does not talk to servers: it writes signed commits/PRs; CI (Forgejo runner) validates and test-builds closures; merge triggers
guix deployfrom a dedicated control node. Technical users edit Scheme/manifests directly — both interfaces converge on the same commits, one audit log, one rollback story (git revert /guix system roll-back). The control node + infra repo are the crown jewels; key custody, signed commits, and merge rights get design effort up front.Decline the scheduler ("cattle-shaped pets"). Static service placement recorded declaratively; fault tolerance defined as time-to-rebuild, not HA. Node-level monitoring alerts into a Matrix ops room; recovery =
guix system init+ state restore from aggressive off-node backups (≥2 nodes + off-fleet), runbooks kept as literate org files in the repo, executable by any trusted member. Later: a warden bot (Matrix bot-federation pattern) that diagnoses and executes runbook steps on human ack — recovery decisions visible in a public-to-community room. Automated cross-node failover deliberately out of scope (Raft/replicated-storage cliff; donated-hardware churn is the failure mode such clusters hate).Networking. Per-tenant Incus bridges (+ ACLs; nftables on host as backstop); tenant-internal networks invisible outside their VM; overlay network (Headscale/Tailscale) as the only fabric; public ingress only via designated edge Caddy nodes reverse-proxying inward. Every boundary declared in text — auditable by reading three files.
Storage/secrets. btrfs over ZFS on Guix hosts (out-of-tree module treadmill avoided; keeps snapshots/CoW). Secrets never enter
/gnu/store(world-readable): out-of-band provisioning (e.g. age-encrypted files deployed to runtime paths) — pick the boring mechanism early, before the webui needs it.Build vs. buy ruling
incus-service-type(do now): config record + shepherd-service for incusd + account/activation extensions (~100–200 lines, patterned on libvirt's). Few sessions, unblocks the whole architecture, upstreamable to Guix. First concrete action item.Roadmap sketch (10-year shape)
Open questions / next actions
incus-service-typeabsence on current Guix master (guix system search incus; grep gnu/services)incus-service-typeon a Guix host; plan upstream submissionknadh/tuwunel-adminon the private overlay only; track upstream Tuwunel admin-API discussiontenant->operating-systemskeletonFiled by robocub on Fox's request, summarizing the 2026-07-12 design conversation.