Roadmap
Synced read-only from
/home/synnet/mirrors/synvirt-product/docs/roadmap.md. Edit at the source, not here.
SynVirt Roadmap
Section titled “SynVirt Roadmap”The SynVirt roadmap is tracked by version number only. Calendar targets (months, quarters, “Hito N — April 2026” style deferrals) were retired. Version numbers are stable commitments; dates drift.
The authoritative current version is whatever iso-builder/VERSION says.
Read it; don’t assume. As of this revision it reads 0.15.0
(release id <semver>+build.<N>, e.g. 0.15.0+build.1175; the -FixN
suffix was retired 2026-06-23).
Summary
Section titled “Summary”| Version | Name | Status |
|---|---|---|
| 0.6.x | Standalone only, live-build ISO, storage modes | Shipped |
| 0.7.0 | Host roles + VM dashboard MVP + synvirt-libvirt | Shipped |
| 0.7.1–0.7.5 | Vendoring, wizard hardening, ZFS cachefile, admin-record | Shipped |
| 0.7.6 | Fix release (XML boot conflict, tty1 TUI, 20 GB sys) | Shipped |
| 0.7.7 | Boot-splash interactive recovery screen | Shipped |
| 0.7.8 | Hotfix — duplicate openapi.json route panic at daemon startup | Shipped |
| 0.8.0 | Web Console module — original SPICE shape (gateway + guest-tools ISO + USB policy). Replaced wholesale in 0.9.0-alpha.2 by VNC-only. | Shipped (legacy) |
| 0.8.1 | Hardening series over 0.8.0 (metrics, VmDetail, XP install flow) | Shipped |
| 0.8.2 | Production-prep hardening — fonts, i18n, Cache-Control, panic sweep | Shipped |
| 0.9–0.15.0 | VNC + WebRTC Direct Console (SPICE removed), migrator, snapshots/clone, telemetry, data-plane splits (R1 synvirt-network, R2 synvirt-storaged), cluster control plane + Backup P1, federation/Cloud |
Shipped (current line: 0.15.0) |
| Roadmap | RBAC, S3 backup engine (P2+), advanced placement/affinity rules | Planned |
| Roadmap | Replica role (async cross-cluster DR) + live-migration polish | Planned |
| 1.0 GA | Role composition GA, air-gap signed USB update, confidential compute | Planned |
Within the 0.7.x line, any decision that touches ZFS-on-root boot chain
(ZFSBootMenu vs GRUB + ext4 /boot), distributed block replication
layering (LINSTOR / DRBD on top of zvols), or boot-environment lifecycle
is re-opened in 0.9, not sooner — that is when the replica trait and
crates/storage-replica stabilise enough to validate the stack end-to-end.
Shipped — 0.6.x
Section titled “Shipped — 0.6.x”Standalone node only. Live-build ISO (preseed retired in 0.5). Browser
wizard + daemon install API. Two storage modes (single_disk_zfs,
multi_disk). Diagnostic synvirt/debug user with auto-cleanup on
first boot after wizard completion. Vue 3 + Pinia + Tailwind dashboard
stub served after setup.completed.
The pre-0.6 history (Foundation MVP, preseed + d-i, Ratatui first-boot unattended driver, br-mgmt, DCUI, setup wizard) is archived in the git log and in superseded ADRs. It is not part of the forward roadmap.
Shipped — 0.7.0 — Host roles + VM dashboard MVP
Section titled “Shipped — 0.7.0 — Host roles + VM dashboard MVP”Introduce host role composition (HCI / Compute / Storage) so operators can start deploying SynVirt as something other than a single standalone node. Ship the first real VM management experience in the dashboard.
Delivered
Section titled “Delivered”- Host roles — CLAUDE.md §6 +
docs/architecture/host-roles.md. HCI (compute + storage on the same node), Compute-only, Storage-only. Role selection persisted in/etc/synvirt/host-role. synvirt-libvirtcrate —virshsubprocess wrapper, 30-second timeout, async API. All libvirt interaction routed through this crate.- VM management dashboard MVP —
crates/web-ux(Vue 3 + Pinia + Tailwind + Lucide, everything vendored). Create, start, stop, pause, delete. Dark theme default. - Daemon Basic Auth via PAM — admin login backed by local PAM
(
auth required pam_unix.so), password bcrypt-hashed in a daemon admin-record. Session JWT, CSRF, rate limit on/api/v1/auth/*. - Console TUI —
crates/console(20 screens on tty1),crates/boot-splashfor tty1 boot progress, sharedcrates/tui-theme. Emergency root shell available on tty2 via Troubleshooting screen (default off).
Mode support
Section titled “Mode support”Standalone + HCI + Compute + Storage roles. No clustering yet.
Shipped — 0.7.1 through 0.7.5 — Hardening series
Section titled “Shipped — 0.7.1 through 0.7.5 — Hardening series”Five fix/polish releases between 0.7.0 and 0.7.6. Collected here because none introduced a new top-level feature.
- 0.7.1 — Vendoring polish: every npm/pnpm/cargo dependency pinned and offline-buildable. No network fetches during ISO build.
- 0.7.2 — Wizard storage modes:
single_disk_zfsvsmulti_disksurfaced in the wizard with per-mode validation; picker logic moved to paso 3 with auto-pick byrecommended_for_system. - 0.7.3 — Diagnostic
synvirt/debuguser with first-boot auto-cleanup (synvirt-debug-cleanup.service, gated byConditionPathExists=/etc/synvirt/setup.completed). - 0.7.4 — Vue 3 dashboard hardening: error boundaries, loading states, optimistic updates, keyboard-navigable tables.
- 0.7.5 — ZFS cachefile seeded at install so
zfs-import-cache.serviceactually activates on first boot; admin record seeded at install time so the post-install dashboard has credentials on its first render; light theme shipped as default.
Mode support
Section titled “Mode support”Standalone + host roles.
Shipped — 0.7.6 — Fix release
Section titled “Shipped — 0.7.6 — Fix release”Fix the bugs exposed by operator acceptance testing on the 0.7.5 live ISO. No new features.
Delivered
Section titled “Delivered”- VM create XML — libvirt domain XML no longer emits a conflicting
boot element when
os/bootand per-diskboot ordercoexist. - Post-install TUI on tty1 —
crates/consoletakes tty1 (masksgetty@tty1) so the operator sees the branded menu instead of the bare Debian getty. - Dashboard redirect — redirects honour the incoming
Host:header instead of hard-coding the management IP. - Install-log breadcrumbs — every install stage writes a breadcrumb
to
/var/log/synvirt/install.log; on failure the daemon returns the last 5 breadcrumbs in/api/install/status. - Boot-splash watchdog —
crates/boot-splashtimes out after 45 s if systemd never signals READY; prints a fallback message and drops to the console TUI. - Live-TUI Starting screen — the live ISO shows a “Starting” screen
while the daemon boots, then gates on
/readyzbefore painting the welcome screen. - Fixed 20 GB system partition — no wizard input for system-partition size; always 20 GB ext4 on p3. Reduces operator error and shrinks the test matrix.
Mode support
Section titled “Mode support”Standalone + host roles (same as 0.7.0).
Shipped — 0.7.7 — Boot-splash recovery
Section titled “Shipped — 0.7.7 — Boot-splash recovery”Close the last known operator-facing gap in the boot-splash: make
Failed steps actionable. Before 0.7.7, a failed step showed a
silent ✗ next to one line and the 45 s watchdog eventually
released tty1 without any indication of which service had wedged
or what the operator could do. 0.7.7 turns that into an interactive
recovery screen.
Delivered
Section titled “Delivered”- Interactive recovery view — when any of the 12 boot steps
flips to
Failed,crates/boot-splashswaps the splash for a recovery screen with a red degrade banner (✗ Step NN of 12 failed: <label>), a context block with reason + systemd unit + watchdog reminder, and five keyboard actions:Rretry,Ireimport ZFS pools (conditional onImportPoolsbeing the failure),Lemergency shell on tty3,Dtoggle verbose boot log,Breboot. - Unit-aware retry —
Stepnow carriesunit_name: Option<&'static str>. Steps tied to a systemd unit (udev, zfs-import-cache, openvswitch-switch, systemd-networkd, libvirtd, synvirt-daemon, chrony) retry viasystemctl restart <unit>; internal-check steps retry by resetting toPendingso the watcher re-evaluates. - Watchdog still enforced — the 0.7.6
MAX_WAIT = 45 sbound applies in recovery mode too, so an ignored recovery prompt never blocks the post-install Direct Console forever. - Crate version parity —
synvirt-boot-splash,synvirt-tui-theme, andsynvirt-consoleall bumped to 0.7.7 so the displayedCARGO_PKG_VERSIONtaglines matchiso-builder/VERSION.
Mode support
Section titled “Mode support”Standalone + host roles (same as 0.7.0).
Shipped — 0.7.8 — Hotfix: daemon startup panic
Section titled “Shipped — 0.7.8 — Hotfix: daemon startup panic”Unbreak the 0.7.7 ISO. Operator testing on 192.168.128.129 showed the
Live-TUI stuck on Starting… indefinitely — root cause was a
duplicate axum route in the daemon that panicked at router
construction and prevented port 443 from ever opening. 0.7.8 is a
single-fix hotfix.
Delivered
Section titled “Delivered”- Removed duplicate
GET /api/v1/openapi.jsonregistration incrates/daemon/src/web/routes.rs. Both an explicit.route("/api/v1/openapi.json", get(openapi_json))and theSwaggerUi::new("/docs").url("/api/v1/openapi.json", spec)merge registered a handler for the same method+path, so axum 0.7 panicked withOverlapping method route. Handler for GET /api/v1/openapi.json already existsat the end ofbuild_router— 29 ms aftermain(), before the listener bound. systemd then cycled the unit 15 times in 20 s and hitStart request repeated too quickly, leaving the unit FAILED permanently. The SwaggerUi merge already registers both the/docsUI and the JSON spec URL, so the explicit route was pure duplication. Fix drops the redundant route line, the orphanedopenapi_jsonhandler, and itsIntoResponse/Jsonimports. - Crate version bump —
synvirt-boot-splash,synvirt-tui-theme,synvirt-console,iso-builder/VERSIONall bumped to 0.7.8 so the running TUIs advertise the shipped version.
Mode support
Section titled “Mode support”Standalone + host roles (same as 0.7.0).
Planned — 0.8 — Operator-facing virtualisation features
Section titled “Planned — 0.8 — Operator-facing virtualisation features”Turn the 0.7.x VM MVP into something operators ship production workloads on. Multi-user, RBAC, snapshots, and a browser-based VM console.
Planned deliverables
Section titled “Planned deliverables”- VM snapshots and clone — ZFS zvol snapshots with operator-visible
lifecycle; clone from snapshot via
zfs clone+ libvirt redefine. - Browser console — VNC web console (noVNC) proxied over
WebSocket from the daemon to
crates/web-ux*. SPICE was deleted in 0.9.0-alpha.2. - ISO upload from the browser — multipart upload to
/api/v1/media, backed by a dataset on rpool (or the compute role’s dedicated pool) with SHA-256 verification. - Time-series graphs — CPU / RAM / disk / net per VM and per host. Embedded time-series store; no external dependency.
- Dashboard pool management — create, extend, import, export ZFS pools from the UI for the Storage role.
- Multi-user + RBAC — roles: admin, operator, viewer. Session history, audit log (who did what, when).
- Backup role — writes VM-level backups to an S3-compatible endpoint with object lock / immutable retention. New role: a node can be designated Backup-only.
crates/computetrait — compute-facing logic extracted from the daemon into a trait so the Compute and HCI roles share one implementation.
Mode support
Section titled “Mode support”Standalone + host roles + Backup role.
Planned — 0.9 — Cross-cluster replication and migration
Section titled “Planned — 0.9 — Cross-cluster replication and migration”Asynchronous DR across two clusters. Live-migration polish so moving a VM between compute nodes is boring. Begin predictive maintenance.
Planned deliverables
Section titled “Planned deliverables”- Replica role — a node dedicated to receiving async replicas from a source cluster.
crates/replica+crates/storage-replica— replication trait on top of ZFSsend/receiveincremental streams, scheduled by the daemon.- Live migration polish — CPU feature negotiation, pre-flight compatibility check, progress reporting, fallback to offline migration on feature mismatch.
- Predictive maintenance ML — local-only models (no cloud upload). Trains on the host’s own time-series and SMART data to flag likely disk failures, thermal trends, and memory-pressure patterns.
- Re-evaluation of deferred decisions — ZFSBootMenu vs GRUB integration, single vs shared ESP for boot environments, LINSTOR / DRBD layering choices. Pinned to 0.9 because the replica trait stresses the storage stack enough to produce signal.
Mode support
Section titled “Mode support”Standalone + host roles + Backup role + Replica role. Clustering still out of scope.
Planned — 1.0 — Role composition GA + enterprise hardening
Section titled “Planned — 1.0 — Role composition GA + enterprise hardening”Full role-composition GA with air-gap updates, confidential-computing primitives, GPU passthrough, and first-class Spanish localisation for the Mexico / LATAM market.
Planned deliverables
Section titled “Planned deliverables”- Role composition GA — any combination of HCI / Compute / Storage / Backup / Replica on a single host, or split across a cluster.
- Air-gap update via signed USB — the daemon accepts update bundles from a USB stick signed by the SynVirt release key; no internet connectivity required during upgrade.
- Confidential computing — TDX and SEV-SNP support exposed as a VM attribute; dashboard surfaces attestation state.
- GPU passthrough UI with SR-IOV — operator picks a physical GPU (or SR-IOV VF) and attaches it to a VM from the dashboard.
es_MXi18n catalog — first shipped locale. All UI strings, console TUI screens, and daemon-emitted operator messages gain a Spanish translation. Other locales are a post-1.0 task.- Commercial enablement — tiered per-CPU-socket licensing portal integration, SLA definitions, onboarding runbook.
Mode support
Section titled “Mode support”All roles in any composition.
Pending / open questions
Section titled “Pending / open questions”Items we know we want to answer eventually but have not pinned to a specific version yet. Written down so they don’t get lost.
- WebRTC console transport (post-1.0 evaluation). noVNC has been the single console path since 0.9.0-alpha.2. WebRTC is the candidate successor — lower latency, native browser pipeline, no RFB-over-TCP framing — but only as a replacement, not a coexistence path. Trial after 1.0 ships and the operator base has a stable VNC baseline to compare against. SPICE is not coming back regardless of how that evaluation lands.
- Compile our own kernel. Today we ship Debian 13’s stock
linux-image-amd64(kernel 6.12 LTS). A SynVirt-owned kernel build would let us: strip unused subsystems to shrink boot time and attack surface; pin exactly the KVM / OVS / ZFS patches we need; control our own CVE backports; and ship a minimal signed image for air-gap updates. Open questions: build infrastructure (reproducible builds, signing key management, CI time), maintenance cost vs shipping stock, whether DKMS for OpenZFS still makes sense against a custom kernel (probably replace with in-tree build), and when the payoff justifies the ongoing tax. Likely candidate window: between 0.9 and 1.0 so the confidential-computing and air-gap-update features land on a kernel we control. - Clustering primitives (etcd Raft, distributed scheduler, anti-affinity, rolling cluster upgrade). Previously pencilled in for a post-1.0 “Cluster mode” but deliberately not pinned to a version. Re-open after 1.0 ships.
- ARM / RISC-V support. Currently out of scope (x86-64 only). Will be revisited when a customer segment actually asks for it; until then the engineering cost is not justified.
- Kubernetes integration. Out of scope as a platform — SynVirt is a VM hypervisor, not a container orchestrator. Operators run Kubernetes inside SynVirt VMs. The open question is whether we ship a first-class “Kubernetes node pool” VM template in some future version to make that pattern one click.
Out of scope
Section titled “Out of scope”- Container orchestration as a platform feature (see above).
- Public cloud integration as a replicator target — the replica role in 0.9 targets SynVirt → SynVirt, not SynVirt → public cloud. Customers asking for cloud DR get the Backup role (0.8) pointed at S3-compatible object lock storage.
- Windows as the host OS. SynVirt ships its own live-build ISO based on Debian 13 trixie. The dev workstation runs whatever the developer prefers; the product runs its own OS.
Post-0.14.0 backlog (tracked 2026-05-01)
Section titled “Post-0.14.0 backlog (tracked 2026-05-01)”These items surfaced during the 0.14.0 release cycle but are not blockers for the release itself. Tracked here instead of in an external issue tracker.
Clippy sweep (workspace-wide)
Section titled “Clippy sweep (workspace-wide)”- 34 clippy errors with
-D warningsflag accumulated inmigrator,live, and adapter crates. All pre-existing, not introduced by the SPICE removal or noVNC work. - Specific patterns observed: unused imports,
push_strwith single char (should bepush), redundant guards, manual character pattern matches. - Suggested approach: dedicated branch,
cargo clippy --workspace --fix --allow-dirtyas starting point, manual review, single commitchore: clippy sweep across workspace. - Owner: TBD
- Target: before next minor bump (0.15.0)
Migrate disk::allocate_qcow2 to vm_layout::ensure_qcow2
Section titled “Migrate disk::allocate_qcow2 to vm_layout::ensure_qcow2”crates/synvirt-libvirt/src/vm.rscurrently has#[allow(deprecated)]on a call todisk::allocate_qcow2.- Replacement is
synvirt_core::storage::vm_layout::ensure_qcow2which is already in tree. - Migration is mechanical: replace the call site, drop the allow attribute, run tests.
- Owner: TBD
- Target: 0.15.0
Dual console auth path consolidation
Section titled “Dual console auth path consolidation”- v0.14.0 introduced
POST /api/console/:vm_uuid(UUID-based, JWT HS256, 30s TTL, aud=vnc) for the new noVNC flow. - The legacy path
POST /api/v1/auth/ticket+GET /api/v1/vms/:name/console/vncstill coexists and usesvalid_name()which rejects VM names with spaces (e.g. “Windows Server 2022”). - Effect: VMs with names containing spaces only work via the new UUID-based path. Legacy path silently rejects them with 400.
- Suggested action: deprecate the legacy path, document the breakage window, remove in 0.16.0 after one minor cycle of dual operation.
- Owner: TBD
- Target: deprecation 0.15.0, removal 0.16.0
Linter / rust-analyzer revert investigation
Section titled “Linter / rust-analyzer revert investigation”- During v0.14.0 cycle, three separate runs observed the linter or
rust-analyzer auto-import bringing back removed symbols:
spice_socket_dir,video_migrationimports/paths/schemas, and related fields. Each time required a manual pickup commit. - Hypothesis: rust-analyzer auto-import on save, or a pre-commit hook
running
cargo fixagainst a stale cache. - Suggested action: review
.vscode/settings.json(if present),.cargo/config.toml, and anypre-commithooks. Disable auto-import for symbols whose modules have been deleted. - Owner: TBD
- Target: investigate before 0.15.0 work starts
synvirt.toml legacy fields cleanup on synvirt-01
Section titled “synvirt.toml legacy fields cleanup on synvirt-01”/etc/synvirt/synvirt.tomlon synvirt-01 still containsspice_enabled = trueandrdp_enabled = true. The daemon ignores unknown fields silently (serde default), so this is cosmetic only.- Cleanup happens automatically on next config deploy that touches console flags. No action needed.
- Owner: N/A (self-healing)
- Target: opportunistic