SynVirt Build Guide
Synced read-only from
/home/synnet/mirrors/synvirt-product/docs/build.md. Edit at the source, not here.
SynVirt Build Guide
Section titled “SynVirt Build Guide”Last updated: 2026-05-01
Table of Contents
Section titled “Table of Contents”- Prerequisites
- Compiling the Daemon
- Running in Dev Mode
- Building the ISO
- Iterating against a running appliance
- Troubleshooting
Prerequisites
Section titled “Prerequisites”All compilation happens on a Debian 13 Trixie host — the same distro the live ISO targets, so the dev environment and the shipping runtime stay binary-compatible.
System packages
Section titled “System packages”sudo apt update && sudo apt install -y \ build-essential \ curl \ git \ pkg-config \ libssl-dev \ xorriso \ isolinux \ syslinux-common \ cpio \ gzip \ rsync \ live-build \ sshpassRust toolchain
Section titled “Rust toolchain”curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | shsource "$HOME/.cargo/env"rustup toolchain install 1.95rustc --version # should print rustc 1.95.xThe repository pins the toolchain in rust-toolchain.toml; rustup
will automatically select the right version whenever you invoke cargo
inside the project directory.
Optional: local VM runtime for ISO smoke-tests
Section titled “Optional: local VM runtime for ISO smoke-tests”Any hypervisor that can boot both BIOS-legacy and strict-UEFI firmware
works. The recommended default on Debian 13 is native QEMU with UEFI
(ovmf) because it reuses the same codebase SynVirt ships — install
with sudo apt install -y qemu-system-x86 ovmf.
Compiling the Daemon
Section titled “Compiling the Daemon”# Debug build (faster compile, larger binary, unoptimised)cargo build -p synvirt-daemon
# Release build (slower compile, optimised)cargo build -p synvirt-daemon --releaseBuild output locations:
| Build type | Binary path |
|---|---|
| Debug | target/debug/synvirt-daemon |
| Release | target/release/synvirt-daemon |
Workspace shape
Section titled “Workspace shape”The project is a Cargo workspace. Cargo.toml at the root lists the
full crate set; CLAUDE.md §2 documents each crate’s role.
Running in Dev Mode
Section titled “Running in Dev Mode”cargo run -p synvirt-daemon -- --devThen open https://localhost:8443 in your browser and accept the self-signed certificate warning (expected in dev mode).
Dev mode behaviour
Section titled “Dev mode behaviour”| Behaviour | Dev (--dev) |
Production |
|---|---|---|
| Listen port | 8443 | 443 |
| TLS certificate | Self-signed, auto-generated | Supplied via config / env |
| Static assets path | crates/daemon/assets/ |
/opt/synvirt/web-ux/ |
| Log format | Pretty (human-readable) | JSON structured |
| Default log level | debug | info |
Environment variable overrides
Section titled “Environment variable overrides”# Override portSYNVIRT_PORT=9443 cargo run -p synvirt-daemon -- --dev
# Override log levelSYNVIRT_LOG=trace cargo run -p synvirt-daemon -- --devBuilding the ISO
Section titled “Building the ISO”cd iso-builder./build.shThe script:
- Compiles
synvirt-daemon,synvirt-console,synvirt-boot-splash,synvirt-live, and supporting binaries in release mode. - Fetches pinned upstream artefacts for the guest-tools ISO
(virtio-win) into
iso-builder/vendor/guest-tools/. - Drives
live-buildthrough bootstrap + chroot + binary stages, reusingiso-builder/live-build/cache/across runs so kernel + ZFS DKMS compile only once untilFORCE_REBUILD=1purges the cache. - Emits
iso-builder/output/SynVirt-<VERSION>-amd64.iso(hybrid BIOS-legacy + strict-UEFI) plus the siblingguest-tools.iso.
Build times:
| Path | Duration |
|---|---|
First build or FORCE_REBUILD=1 |
30–45 minutes |
| Incremental rebuild (cache hit) | 2–5 minutes |
Iterating against a running appliance
Section titled “Iterating against a running appliance”scripts/deploy-to-host.sh hot-swaps the daemon binary + systemd units
- dashboard tree onto a running SynVirt node without rebuilding the ISO. Useful during active development — the full build + ISO + reinstall cycle only runs at the end of a feature.
SSHPASS=<password> HOST=<ip> ./scripts/deploy-to-host.sh hotStages:
| Stage | Description |
|---|---|
inspect |
Report the appliance’s current release, enabled units, and active tty state. |
build |
cargo build --release -p synvirt-daemon -p synvirt-console -p synvirt-boot-splash. |
push |
scp the new binaries + service unit files to /tmp/ on the host. |
apply |
Install the binaries into /opt/synvirt/bin/, reload systemd, restart the daemon. |
web-ux |
Pack + scp + atomically replace /opt/synvirt/web-ux/. |
reboot |
Issue a reboot and wait for ping-back. |
verify |
Post-reboot smoke-check of tty1 ownership + active units. |
all |
inspect → build → push → apply → web-ux → reboot → verify. |
hot |
Fast loop for dev: build → push → apply → web-ux (no reboot). |
Running guests survive the daemon restart because libvirt and QEMU own the per-VM VNC listener sockets, not the daemon. The daemon process swap is invisible to active VNC sessions; the browser WebSocket is the only thing that needs to reconnect.
Troubleshooting
Section titled “Troubleshooting”1. TLS certificate errors in the browser
Section titled “1. TLS certificate errors in the browser”Symptom: Browser shows “NET::ERR_CERT_AUTHORITY_INVALID” or similar.
Cause: The self-signed certificate is not trusted by the OS certificate store. Expected in dev mode.
Fix: Click “Advanced” → “Proceed” in Chromium-based browsers, or
“Accept the Risk and Continue” in Firefox. For permanent trust, import
the certificate from /etc/synvirt/tls/ into your OS trust store.
2. cargo: command not found after a fresh shell
Section titled “2. cargo: command not found after a fresh shell”Cause: The Rust toolchain is installed under $HOME/.cargo/bin/
but the current shell has not sourced the profile snippet that adds it
to PATH.
Fix:
source "$HOME/.cargo/env"rustc --versionPersist by appending to ~/.profile:
export PATH="$HOME/.cargo/bin:$PATH"3. ISO download fails during build
Section titled “3. ISO download fails during build”Symptom: iso-builder/build.sh stops with a download or checksum
error.
Fix: Clear the cached Debian netinstall image at
iso-builder/cache/ and re-run. If a specific mirror keeps failing,
edit the DEBIAN_MIRROR variable at the top of build.sh to a
closer one (see https://www.debian.org/mirror/list).
4. /dev/kvm absent in the dev VM
Section titled “4. /dev/kvm absent in the dev VM”Symptom: libvirt refuses to start guests, or VMs run in TCG mode
(slow).
Cause: Nested virtualisation is not enabled on the outer hypervisor.
Fix: Enable nested virtualisation on the host that runs the dev
VM, reboot, and confirm /dev/kvm exists on the dev VM. Dev mode
works in TCG fallback for smoke-testing but performance will be
unrepresentative of production.