Ok, I finally found the answer… So it is a bit more complicated than expected: to get the configuration.qemu
function I need to use:
imports = [
# We need to import that to make it work.
"${nixpkgs}/nixos/modules/virtualisation/qemu-vm.nix"
];
and then we need to configure qemu to start a spice server. With spice qemu is not anymore in charge of displaying the screen but it is delegated to a client on the host. Qemu is just a gateway between vdagent in the host and the spice client. Note that qemu will open a socket (and will appear frozen since it is just a server) and the client will connect to it. To start it automatically see the dirty trick below. You can use different clients (see Aarch linux page).
So the configuration looks like
services.spice-vdagentd.enable = true;
virtualisation.qemu.options = [
"-vga qxl -device virtio-serial-pci -spice port=5930,disable-ticketing=on -device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 -chardev spicevmc,id=spicechannel0,name=vdagent"
];
And after you start the vm (qemu will hang), you need to start: remote-viewer spice://127.0.0.1:5930
and it will start to display the vm.
I also created a script to automatically call the script (you also have qemu -display spice-app
but it is harder to pack it into a derivation since it relies on mime) but I need to create a new derivation for that. The whole flake is now:
{
description = "Configuration";
# To easily generate a derivation per architecture
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, flake-utils }: flake-utils.lib.eachDefaultSystem (system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
{
packages.nixosConfigurations.demo = nixpkgs.lib.nixosSystem {
system = system; # flake needs to know the architecture of the OS
modules = [
(
{config, lib, pkgs, ...}:
{
imports = [
# We need to import that to make it work.
"${nixpkgs}/nixos/modules/virtualisation/qemu-vm.nix"
];
# Trying to get copy/paste working
# virtualisation.qemu.guestAgent.enable = true;
# services.qemuGuest.enable = true;
## With spice qemu is not anymore in charge of displaying the screen but it is delegated
## to a client on the host. Qemu is just a gateway between vdagent in the host and the spice client.
## Note that qemu will open a socket (and will appear frozen since it is
## just a server) and the client will connect to it.
## To start it automatically see the dirty trick below
## You can use different clients (see arch linux page).
services.spice-vdagentd.enable = true;
virtualisation.qemu.options = [
"-vga qxl -device virtio-serial-pci -spice port=5930,disable-ticketing=on -device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0 -chardev spicevmc,id=spicechannel0,name=vdagent"
];
# GUI
services.xserver = {
enable = true;
desktopManager.xfce = {
enable = true;
enableScreensaver = false;
};
displayManager = {
defaultSession = "xfce";
autoLogin = {
enable = true;
user = "me";
};
};
};
users.users.me = {
isNormalUser = true;
# In theory one should use hashedPassword but who care, the password is public anyway
password = "me";
extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
};
system.stateVersion = "22.11"; # Did you read the comment?
}
)
];
};
## Build it with "nix build .#demo-with-automatic-vm-integration" and run the script in `result/bin/run-nixos-vm`.
packages.demo-with-automatic-vm-integration = pkgs.writeShellApplication {
name = "run-nixos-vm";
runtimeInputs = [ pkgs.virt-viewer ];
text = ''
${self.packages.${system}.nixosConfigurations.demo.config.system.build.vm}/bin/run-nixos-vm & PID_QEMU="$!"
sleep 1 # I think some tools have an option to wait like -w
remote-viewer spice://127.0.0.1:5930
kill $PID_QEMU
'';
};
});
}
and the above gist contains the latest version. To compile the VM with autostart of the client:
$ nix build .#demo-with-automatic-vm-integration
$ ./result/bin/run-nixos-vm
I would love to see directly an option in nixpkgs, this is not really an “easy” approach…
Or with the gist
$ nix build 'git+https://gist.github.com/tobiasBora/c9ec77de0c3c50d433707d3323720cd6?ref=main#demo-with-automatic-vm-integration' --refresh
$ ./result/bin/run-nixos-vm