Skip to content

feat: add systemd-machined integration and SSH over VSOCK#453

Merged
SuperSandro2000 merged 9 commits intomicrovm-nix:mainfrom
elsbrock:feature/machined-registration
Mar 9, 2026
Merged

feat: add systemd-machined integration and SSH over VSOCK#453
SuperSandro2000 merged 9 commits intomicrovm-nix:mainfrom
elsbrock:feature/machined-registration

Conversation

@elsbrock
Copy link
Copy Markdown
Contributor

@elsbrock elsbrock commented Dec 29, 2025

Adds systemd-machined integration and SSH over VSOCK support for MicroVMs.

machined integration

microvm.registerWithMachined = true registers VMs with machined:

$ machinectl list
MACHINE    CLASS SERVICE     OS VERSION ADDRESSES
authelia   vm    microvm.nix -  -       -
blackpearl vm    microvm.nix -  -       -
  • machinectl list/status/show for visibility
  • machinectl terminate/kill to stop VMs

This PR prefers RegisterMachineEx on systemd 259+ and falls back to legacy machined calls on older hosts.
When available, it registers VSockCID / SSHAddress metadata (plus network interfaces).

machinectl reboot/poweroff/terminate/kill all stop the VM without auto-restart (systemd treats signals from machined as intentional stops). Use systemctl restart microvm@<name> for restarts.

SSH over VSOCK

microvm.vsock.ssh.enable = true configures guest sshd to listen on VSOCK (requires microvm.vsock.cid):

$ microvm -s myvm
Connecting to myvm via VSOCK...
[myvm]$

Works with qemu/crosvm/kvmtool (native AF_VSOCK) and cloud-hypervisor (socket mux).

This PR also updates microvm -s argument handling so SSH options can be forwarded via --, e.g.:

  • microvm -s myvm -- -l root -i /path/to/key

Other changes

  • microvm -l respects configured microvm.stateDir
  • microvm.machineId option for consistent UUID handling across machined/SMBIOS/guest machine-id use
  • QEMU shutdown script handles missing control socket (fixes restart after external kill)
  • imperative microvm@%i template tolerates missing microvm-register / microvm-unregister scripts

Tests

  • expands machined test coverage for VM metadata (VSockCID, SSHAddress) where applicable
  • adds a focused microvm -s argument-handling test
  • adds imperative template test for start/stop without register scripts

Closes #123

Comment thread checks/machined.nix Outdated
Comment thread lib/runner.nix Outdated
Comment thread lib/runner.nix Outdated
Comment thread lib/runner.nix Outdated
Comment thread lib/runner.nix
Comment thread nixos-modules/microvm/vsock-ssh.nix Outdated
Comment thread pkgs/microvm-command.nix Outdated
Comment thread lib/runner.nix
Comment thread lib/runners/qemu.nix
Comment thread nixos-modules/microvm/options.nix
@elsbrock elsbrock force-pushed the feature/machined-registration branch from 1abd1d3 to a170c21 Compare January 3, 2026 22:07
@elsbrock
Copy link
Copy Markdown
Contributor Author

elsbrock commented Jan 3, 2026

Thanks for the review! Force pushed with two fixes from testing:

  • Added coreutils to PATH in register script (was missing tr)
  • Changed test to check Leader property instead of machinectl kill --signal=0 (not supported)

machined-qemu tests pass now.

@elsbrock elsbrock force-pushed the feature/machined-registration branch 2 times, most recently from b121fdb to 210ca3f Compare January 3, 2026 23:05
Comment thread nixos-modules/microvm/options.nix Outdated
Comment thread nixos-modules/microvm/options.nix
Comment thread nixos-modules/host/default.nix Outdated
Comment thread pkgs/microvm-command.nix Outdated
@elsbrock
Copy link
Copy Markdown
Contributor Author

elsbrock commented Jan 9, 2026

Sorry, quite busy. Will have another look over the weekend.

@SuperSandro2000 SuperSandro2000 force-pushed the feature/machined-registration branch from 18e4365 to 9ef95c1 Compare January 10, 2026 07:21
Comment thread nixos-modules/microvm/system.nix Outdated
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 microvm host CLI with -s to SSH into a running VM via VSOCK and respect a configurable stateDir.
  • Add registerWithMachined + machineId options 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.

Comment thread nixos-modules/microvm/options.nix Outdated
Comment thread lib/runner.nix Outdated
Comment thread lib/runners/qemu.nix
Comment thread pkgs/microvm-command.nix Outdated
Comment thread pkgs/microvm-command.nix Outdated
Comment thread nixos-modules/microvm/system.nix
Comment thread nixos-modules/microvm/options.nix
Comment thread nixos-modules/host/default.nix Outdated
@elsbrock
Copy link
Copy Markdown
Contributor Author

elsbrock commented Mar 8, 2026

Pushed an update that should cover the open points.

  • switched machined registration to use RegisterMachineEx on systemd 259+ (with fallback to old calls)
  • fixed the UUID byte conversion (strtonum($i))
  • passed VSockCID / SSHAddress where applicable
  • fixed microvm -s arg handling so -- can be used for ssh opts
  • made microvm@%i tolerate missing register/unregister scripts in imperative mode
  • updated microvm.machineId docs to match actual behavior
  • applied the replaceString "-" "" cleanup for machine-id

Also added targeted tests for this:

  • machined metadata checks
  • microvm -s arg parsing
  • imperative template behavior without register scripts

Ran these locally:

  • nix build .#hydraJobs.x86_64-linux.microvm-command
  • nix build .#hydraJobs.x86_64-linux.imperative-template
  • nix build .#hydraJobs.x86_64-linux.machined-qemu
  • nix build .#hydraJobs.x86_64-linux.machined-cloud-hypervisor

All green here.

@elsbrock elsbrock force-pushed the feature/machined-registration branch from 2af4b4b to fae4c42 Compare March 8, 2026 13:11
@SuperSandro2000
Copy link
Copy Markdown
Member

SuperSandro2000 commented Mar 8, 2026

I am going to push the final bits in this PR to get this merged.

@SuperSandro2000 SuperSandro2000 force-pushed the feature/machined-registration branch from fae4c42 to b3bc895 Compare March 8, 2026 13:27
@SuperSandro2000 SuperSandro2000 force-pushed the feature/machined-registration branch 7 times, most recently from 4c138be to c221ad5 Compare March 8, 2026 17:46
@SuperSandro2000 SuperSandro2000 requested a review from Copilot March 8, 2026 17:55
@SuperSandro2000
Copy link
Copy Markdown
Member

[root@storage1:~]# microvm -s librenms
Connecting to librenms via VSOCK...
Warning: Permanently added 'vsock/3597670762' (ED25519) to the list of known hosts.

  ______    ______
 / / / /   / /\ \ \
/ / / /   / /  \ \ \
\ \ \ \  / /   / / /
 \_\_\_\/_/   /_/_/

Last login: Sun Mar  8 18:50:48 2026 from 2a02:3100:2488:4500:2be6:4a66:e121:7468

[root@librenms:~]#

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 closing but 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).

Comment thread checks/microvm-command.nix Outdated
Comment thread checks/machined.nix
Comment thread doc/src/faq.md Outdated
Comment thread nixos-modules/microvm/system.nix
Comment thread nixos-modules/microvm/options.nix
Comment thread lib/runners/qemu.nix Outdated
Comment thread checks/microvm-command.nix Outdated
Comment thread pkgs/microvm-command.nix Outdated
Comment thread pkgs/microvm-command.nix Outdated
elsbrock and others added 3 commits March 8, 2026 19:26
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
@SuperSandro2000 SuperSandro2000 force-pushed the feature/machined-registration branch 4 times, most recently from cd2acfa to bfd0f24 Compare March 8, 2026 21:58
@SuperSandro2000
Copy link
Copy Markdown
Member

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.

elsbrock and others added 4 commits March 8, 2026 23:44
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)
@SuperSandro2000 SuperSandro2000 force-pushed the feature/machined-registration branch from bfd0f24 to 96f47e1 Compare March 9, 2026 00:58
Comment thread pkgs/microvm-command.nix Outdated
Comment thread checks/machined.nix
@SuperSandro2000 SuperSandro2000 merged commit 25ebda3 into microvm-nix:main Mar 9, 2026
@elsbrock elsbrock deleted the feature/machined-registration branch March 9, 2026 20:56
text = lib.replaceString "-" "" config.microvm.machineId + "\n";
};
# Generate hostId from machine-id like systemd would do
networking.hostId = lib.mkDefault (
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if a user sets machineId = null this will error out. should probably be guarded with mkIf machineId != null

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 =
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not have a good idea how to make this migration smooth unless we introduce a state version.

oddlama added a commit to oddlama/nixos-extra-modules that referenced this pull request Mar 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enter running machine as systemd service

5 participants