feat: add systemd-machined integration and SSH over VSOCK#453
Conversation
1abd1d3 to
a170c21
Compare
|
Thanks for the review! Force pushed with two fixes from testing:
machined-qemu tests pass now. |
b121fdb to
210ca3f
Compare
|
Sorry, quite busy. Will have another look over the weekend. |
18e4365 to
9ef95c1
Compare
There was a problem hiding this comment.
Pull request overview
Adds host/guest integration features for MicroVMs by registering VMs with systemd-machined (enabling machinectl visibility/control) and enabling SSH access over VSOCK, plus a small QEMU shutdown robustness tweak.
Changes:
- Extend the
microvmhost CLI with-sto SSH into a running VM via VSOCK and respect a configurablestateDir. - Add
registerWithMachined+machineIdoptions and generate/register machined metadata from the runner. - Add a NixOS test covering machined registration, and filter check variants by host platform/hypervisor support.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| pkgs/microvm-command.nix | Adds stateDir parameter, includes openssh, and implements microvm -s VSOCK SSH wrapper. |
| nixos-modules/microvm/vsock-ssh.nix | New guest module option to enable sshd for VSOCK connectivity. |
| nixos-modules/microvm/system.nix | Initializes guest /etc/machine-id and derives networking.hostId from microvm.machineId. |
| nixos-modules/microvm/options.nix | Adds registerWithMachined and machineId options. |
| nixos-modules/microvm/default.nix | Wires in the new vsock-ssh module. |
| nixos-modules/host/default.nix | Passes stateDir into the microvm CLI package; hooks machined register/unregister scripts into VM services. |
| lib/runner.nix | Generates machined register/unregister scripts; writes VSOCK CID + hypervisor metadata to runner output. |
| lib/runners/qemu.nix | Passes machine UUID via SMBIOS; makes shutdown script tolerate missing control socket. |
| checks/machined.nix | Adds a nixosTest validating machined registration and basic machinectl operations. |
| checks/default.nix | Filters the checks matrix to only hypervisors supported on the current platform. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
|
Pushed an update that should cover the open points.
Also added targeted tests for this:
Ran these locally:
All green here. |
2af4b4b to
fae4c42
Compare
|
I am going to push the final bits in this PR to get this merged. |
fae4c42 to
b3bc895
Compare
4c138be to
c221ad5
Compare
|
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 14 out of 14 changed files in this pull request and generated 9 comments.
Comments suppressed due to low confidence (1)
doc/src/faq.md:31
- The markdown code fence around the
microvm.shares = [...]example is now unbalanced: there’s a closingbut no openingnix before the snippet. Add the opening fence (or remove the closing one) so the rest of the FAQ renders correctly.
microvm.shares = [ {
# On the host
source = "/var/lib/microvms/${config.networking.hostName}/journal";
# In the MicroVM
mountPoint = "/var/log/journal";
tag = "journal";
proto = "virtiofs";
socket = "journal.sock";
} ];
</details>
---
💡 <a href="/microvm-nix/microvm.nix/new/main?filename=.github/instructions/*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.<br><br>You can also share your feedback on Copilot code review. [Take the survey](https://www.surveymonkey.com/r/XP6L3XJ).
Add optional integration with systemd-machined for VM visibility and management. - New option: microvm.registerWithMachined (default false) - New option: microvm.machineId for consistent UUID across machined/SMBIOS/guest - Shared makeMachineUuid function in lib to avoid duplication - QEMU sets SMBIOS UUID for guest visibility - Host module registers VM after hypervisor starts - Graceful shutdown handling when VM is killed via machinectl - NixOS test for machined integration
Enable SSH access to guests via VSOCK without network configuration. - New option: microvm.vsock.ssh.enable - New command: microvm -s <vmname> for VSOCK SSH - Supports qemu/crosvm/kvmtool (AF_VSOCK) and cloud-hypervisor (socket mux) - Guest uses systemd's ssh-generator for automatic sshd-vsock.socket
cd2acfa to
bfd0f24
Compare
|
One thing I noticed: the microvm-register script is not very robust and if the vm crashes early on, it may cannot be re-run, but since this is a new, by default off, feature, I am going fine with it, but we should improve that in the future and in another PR. |
Flake lock file updates:
• Updated input 'nixpkgs':
'github:nixos/nixpkgs/7df7ff7d8e00218376575f0acdcc5d66741351ee?narHash=sha256-gTrEEp5gEspIcCOx9PD8kMaF1iEmfBcTbO0Jag2QhQs%3D' (2025-10-02)
→ 'github:nixos/nixpkgs/aca4d95fce4914b3892661bcb80b8087293536c6?narHash=sha256-E1bxHxNKfDoQUuvriG71%2Bf%2Bs/NT0qWkImXsYZNFFfCs%3D' (2026-03-06)
• Updated input 'spectrum':
'git+https://spectrum-os.org/git/spectrum?ref=refs/heads/main&rev=c5d5786d3dc938af0b279c542d1e43bce381b4b9' (2025-10-03)
→ 'git+https://spectrum-os.org/git/spectrum?ref=refs/heads/main&rev=fe39e122d898f66e89ffa17d4f4209989ccb5358' (2026-02-27)
bfd0f24 to
96f47e1
Compare
| text = lib.replaceString "-" "" config.microvm.machineId + "\n"; | ||
| }; | ||
| # Generate hostId from machine-id like systemd would do | ||
| networking.hostId = lib.mkDefault ( |
There was a problem hiding this comment.
if a user sets machineId = null this will error out. should probably be guarded with mkIf machineId != null
There was a problem hiding this comment.
I've opened #499, but I only eye balled this, so it could be another issue like this in the code base.
|
|
||
| machineId = mkOption { | ||
| type = with types; nullOr str; | ||
| default = |
There was a problem hiding this comment.
This default bit me when updating, as it overwrote the generated machine-id that was in use previously (which caused a lot of dependent failures). This change is a breaking change for existing declarative instances
There was a problem hiding this comment.
I do not have a good idea how to make this migration smooth unless we introduce a state version.
Adds systemd-machined integration and SSH over VSOCK support for MicroVMs.
machined integration
microvm.registerWithMachined = trueregisters VMs with machined:machinectl list/status/showfor visibilitymachinectl terminate/killto stop VMsThis PR prefers
RegisterMachineExon systemd 259+ and falls back to legacy machined calls on older hosts.When available, it registers
VSockCID/SSHAddressmetadata (plus network interfaces).machinectl reboot/poweroff/terminate/killall stop the VM without auto-restart (systemd treats signals from machined as intentional stops). Usesystemctl restart microvm@<name>for restarts.SSH over VSOCK
microvm.vsock.ssh.enable = trueconfigures guest sshd to listen on VSOCK (requiresmicrovm.vsock.cid):Works with qemu/crosvm/kvmtool (native AF_VSOCK) and cloud-hypervisor (socket mux).
This PR also updates
microvm -sargument handling so SSH options can be forwarded via--, e.g.:microvm -s myvm -- -l root -i /path/to/keyOther changes
microvm -lrespects configuredmicrovm.stateDirmicrovm.machineIdoption for consistent UUID handling across machined/SMBIOS/guest machine-id usemicrovm@%itemplate tolerates missingmicrovm-register/microvm-unregisterscriptsTests
VSockCID,SSHAddress) where applicablemicrovm -sargument-handling testCloses #123