Ops & agents
Releases and self-update
Every release is signed, verified and installed without touching a running VM.
flash self-update is FlashVMM's built-in update channel: it fetches one Ed25519-signed release manifest, verifies the signature against a key compiled into the binary before reading any field, checks every artifact against the SHA-256 and size inside that manifest, and installs with an atomic rename(): Linux binaries and guest bundles file by file, a signed .pkg on macOS and an .msi on Windows.
The updater is the installed flash itself, so there is no second program to install or keep current. Installation is designed around long-lived VMs: a running flashvm keeps executing the image it started with, and a new guest bundle lands beside the old one. See Self-update and Security.
Key facts
| Runs on | Linux (x86_64, arm64), macOS (Apple silicon), Windows (x64, arm64) |
|---|---|
| Interfaces | CLI flash self-update · MCP flash_cli(args: ["self-update", ...]) |
| Manifest | update-manifest.json + detached update-manifest.json.sig, schema_version 1 |
| Signature | Ed25519, verified before parsing; trust anchor compiled in, plus a second key during a rotation window |
| Per-artifact check | SHA-256 and byte size from inside the signed manifest |
| Ordering | Anti-rollback floor on the manifest's updated_at; never-downgrade per artifact |
| Unattended | Off by default (Windows' one-line install turns it on); --install-timer arms a systemd timer on Linux, a launchd daemon on macOS, a SYSTEM scheduled task on Windows; --interval default 15min |
How it works
Verify, then parse
flashdownloads the manifest and its signature from the release channel.- It verifies the Ed25519 signature against the key built into this binary. An unsigned or wrongly signed manifest never reaches the JSON parser. The channel URL moves where the manifest is fetched from; the trusted key is fixed at build time.
- It compares the manifest's
updated_atwith the newest manifest this machine has accepted (stored aslast-manifest-tsin the state directory) and accepts it when it is the same age or newer. - Every path in the manifest is channel-relative, so each download comes from the same channel the manifest did.
- Each artifact is downloaded, checked against its signed SHA-256 and size, and installed. An artifact older than what is installed is left as it is.
What each OS installs
Each OS uses its native install mechanism:
- Linux updates each binary (
flash, flashvm, the daemons) by writing the verified file beside it and renaming it into place. The guest bundle for the host's own architecture (kernel and root filesystem) carries a monotonicserialrecorded inbundle.json, installs into a new versioned directory under/opt/flashvm/bundles, and thecurrentsymlink is swung onto it withrename(). The GPU engine and theflash demofiles update the same way, one signed tarball per architecture. - macOS downloads the release
.pkgnamed in the manifest'sinstallerslist, then checks it a second time withpkgutil --check-signaturefor FlashVMM's Developer ID Installer certificate before handing it to the system installer. - Windows downloads the release
.msifrom the same signed list and installs it withmsiexec.
Running VMs carry on
rename() replaces a directory entry while the old file stays alive for every process that has it open. A running flashvm keeps executing the binary it was started from, and the next flash run starts the new one. A VM holding the old root filesystem keeps it, because the old bundle directory is never written to. Nothing is signalled and nothing restarts, so a sleeping or parked VM wakes exactly as it slept.
Ownership
When a package manager owns the binary, or a machine-managed systemd unit runs the install, self-update names that owner and leaves the version to it; --force updates anyway and says what it overrode.
Interfaces
CLI
flash self-update --show-trust # channel and the SHA-256 fingerprint of the trusted key
flash self-update --status # installed against published, changes nothing
flash self-update --dry-run # what would change
flash self-update # verify and install
flash self-update --install-timer --interval 1h # run it unattended (as root / Administrator)
MCP
flash_cli(args: ["self-update", "--status"])
flash_cli(args: ["self-update"])
REST
GET /v1/flashvm/version # a running VM's binary and the artifact formats it speaks
GET /v1/version # flashhostd, flashpoold, flashgpud and the controller report theirs
Contract: self-update exits with an error and installs nothing when the signature does not verify, the manifest is older than the accepted floor, or an artifact's SHA-256 or size differs from the manifest.
Guarantees
- Signed end to end. Every byte installed is covered by one Ed25519 signature checked against a compiled-in key.
- Always forward. The anti-rollback floor and per-artifact version check keep every machine moving to newer releases.
- Atomic. Each file and each bundle switches in a single
rename(). - Zero disruption. Running, sleeping and pooled VMs keep the binary and bundle they started with.
- Your schedule. Updates run when you run them, or on the timer you arm.