Skip to content

distribution

Desktop launcher internals

Desktop launcher internals

What this page does

Architecture walkthrough of the deputyos-desktop crate — the “download + double-click → wizard in browser” launcher for Linux, Windows, and macOS. The launcher is a Rust binary per platform that consumes existing deputyOS image artefacts (the same qcow2 / img.xz files that ship for the QEMU and Pi targets) and orchestrates the host’s native virtualization to boot them.

The user-facing surface is documented in Reference → CLI → deputyos-desktop; this page is the implementation-side reference for contributors and auditors.

Crate architecture

deputyos-desktop/
├── src/
│   ├── main.rs        ← CLI dispatch (clap)
│   ├── lib.rs         ← public modules
│   ├── config.rs      ← cache locations, version pinning, prefs
│   ├── manifest.rs    ← reuses deputyctl::release types for verify
│   ├── download.rs    ← image fetch + sha256 + minisig verify
│   ├── browser.rs     ← cross-platform "open URL" shim
│   ├── driver.rs      ← Driver trait + `current_driver()` factory
│   └── drivers/
│       ├── mod.rs
│       ├── linux.rs   ← qemu+KVM driver
│       ├── windows.rs ← WSL2-mandate driver
│       └── macos.rs   ← UTM-mandate driver
└── Cargo.toml

The user-facing CLI surface

deputyos-desktop install                 # prereq + download + cache + import
deputyos-desktop start                   # boot VM + open browser. Default action.
deputyos-desktop stop                    # graceful shutdown
deputyos-desktop status                  # running/stopped + URL
deputyos-desktop update                  # check manifest + (not yet implemented) apply
deputyos-desktop uninstall [--data]      # remove cache; --data also wipes data dir

Invoking with no subcommand mimics double-click: install (if needed), start, then open the wizard URL in the default browser. That’s the “non-technical user double-clicks the icon” path.

Driver model

Each platform implements the Driver trait:

pub trait Driver {
    fn check_prereqs(&self) -> Result<()>;
    fn start(&self, image_path: &Path) -> Result<VmStatus>;
    fn stop(&self) -> Result<()>;
    fn status(&self) -> Result<VmStatus>;
}

Where VmStatus reports running/stopped + the wizard URL (always http://localhost:8088/wizard per the loopback-only design).

Linux driver

  • Mandate: qemu+KVM. The driver checks /dev/kvm is accessible and qemu-system-x86_64 (or qemu-system-aarch64) is on PATH.
  • No bundled hypervisor. Linux distros all ship qemu+KVM; we don’t re-bundle.
  • Boot command: roughly qemu-system-<arch> -m 4G -accel kvm -drive file=<image>,if=virtio -netdev user,id=net0, hostfwd=tcp:127.0.0.1:8088-:8088 -device virtio-net,netdev=net0 -nographic -daemonize -pidfile <cache>/vm.pid.
  • Stop: SIGTERM to the pid in the pidfile.
  • Status: kill -0 <pid> plus curl -fsS http://localhost:8088/healthz.

Windows driver

  • Mandate: WSL2. The driver checks for the WSL2 distro that deputyos-desktop install imports (or that wsl/Install-DeputyOS.ps1 imported earlier).
  • No bundled hypervisor. WSL2 is the right shape on Windows; we don’t run nested qemu in WSL.
  • Boot command: wsl --distribution deputyos --user agent /opt/deputyos/start.sh.
  • Stop: wsl --terminate deputyos.
  • Status: wsl --list --running plus the healthz probe.

macOS driver

  • Mandate: UTM. The driver checks for UTM at /Applications/UTM.app and the utmctl CLI it ships.
  • No bundled hypervisor. Apple’s restrictions on third-party hypervisors plus UTM’s existing ecosystem make UTM the right shape.
  • Apple Silicon (aarch64): HVF acceleration; near-native speed.
  • Intel x86_64 macOS: TCG (slow) — supported but not recommended.
  • Boot: utmctl start deputyos.
  • Stop: utmctl stop deputyos.
  • Status: utmctl status deputyos.

Cross-compile per host triple

The make desktop-launcher target builds for the host triple by default; pass DESKTOP_TARGET=<rust-triple> to cross-compile:

HostTarget tripleNotes
Linux x86_64x86_64-unknown-linux-gnunative
Linux arm64aarch64-unknown-linux-gnunative
Windowsx86_64-pc-windows-msvcfrom Windows host
Windows (cross)x86_64-pc-windows-gnufrom Linux via cross
macOS Intelx86_64-apple-darwinmust build on a Mac
macOS Apple Siliconaarch64-apple-darwinmust build on a Mac

macOS builds need Apple’s toolchain blobs we cannot legally redistribute. macOS contributors build on a Mac.

Manifest fetch + sha + minisig verify

The launcher reuses deputyctl::release types — the same code path the on-device update verifier uses. Steps in download.rs:

  1. Fetch manifest.json and manifest.json.minisig from the deputyOS CDN URL (DEPUTYOS_DESKTOP_MANIFEST_URL env override; or the baked default).
  2. Verify the minisign signature against the pubkey baked into the binary at build time.
  3. Find the artefact for the host’s (target, profile) — for Linux this is qemu-x86_64 or qemu-aarch64, for Windows it’s wsl2, for macOS it’s macos-qemu.
  4. Download to the cache. Verify sha256. Verify per-artefact minisig.
  5. Cache hit → use cached image.

Cache locations

PlatformCache root
Linux${XDG_CACHE_HOME:-~/.cache}/deputyos-desktop/
Windows%LOCALAPPDATA%\deputyos-desktop\
macOS~/Library/Caches/deputyos-desktop/

Cache contents:

  • images/<release>/<artefact> — downloaded and verified images.
  • vm.pid (Linux) — running VM PID.
  • state.json — current install state.

deputyos-desktop uninstall removes the cache. --data also wipes the persistent data dir at:

PlatformData dir
Linux${XDG_DATA_HOME:-~/.local/share}/deputyos-desktop/
Windows%APPDATA%\deputyos-desktop\
macOS~/Library/Application Support/deputyos-desktop/

Code-signing per platform

Distributing the binary needs platform-specific signing — without it, Gatekeeper / SmartScreen will block the launch.

PlatformSigning requirementStatus
Linuxgpg-signed AppImagenot yet built
WindowsAuthenticode EV certnot yet built
macOSApple Developer ID + notarizationnot yet built

The CI signing infrastructure for these is not yet built. Today the launcher binaries are unsigned — distribution is “build it yourself with make desktop-launcher” pending the signing path.

Browser open

browser.rs is a thin shim over the platform default. Linux: xdg-open. Windows: start (via cmd). macOS: open. The launcher always opens http://localhost:8088/wizard; the wizard’s first-boot state is persistent in the data dir, so successive start invocations go straight to whatever step the user left off.

Update flow

deputyos-desktop update:

  1. Fetch the latest manifest.
  2. Compare to the cached manifest’s release_version.
  3. If newer: download + verify the new image. (This step is in the not yet implemented; today’s update is check-only.)
  4. On next start, boot the new image.

The launcher does not yet support A/B for desktop the way the appliance images do (planned). Replacement is in-place; the previous image is removed only after the new one verifies.

Verification

# Build for host
cargo build --release -p deputyos-desktop

# Run install + start (interactive)
./target/release/deputyos-desktop install
./target/release/deputyos-desktop start

# Status / logs
./target/release/deputyos-desktop status

Search

Search index isn't built yet. Run npm run build to generate it (Pagefind writes to dist/pagefind/).