Nixos-vm-examples: A collection of examples on how to build NixOS VMs

New project I just made because I got annoyed that I can never remember how to build NixOS VMs well:

Please contribute your VMs :slight_smile:

8 Likes

:+1:

How does it compare to the nixos-generators project?

1 Like

I think the main difference is that it’s not a tool to turn your config into something that works against a specific target, but instead a collection of examples.

E.g. the example I’ve added so far show specifically how to make a VM that tests the effect of my GRUB PR grub: Add `boot.loader.grub.extraGrubInstallArgs` option by nh2 · Pull Request #85895 · NixOS/nixpkgs · GitHub (or other such changes to the bootloader), and recently I helped building a VM for a friend to make a reproducible environment for building the code coming with his scientific paper publication, which could also be added.

In other words, it tries to solve the problem of “to see how can I use NixOS VMs to solve my problem, I first want to look at some existing examples”.

2 Likes

Thanks for this :slight_smile:
I’m wondering, is there a way to SSH into the VM without port forwarding?

1 Like

@balint To connect via SSH, you need to be able to talk to its SSH port. So either by letting QEMU do the port forwarding to a port that’s not already occupied (because your host machine’s SSH port 22 is likely already occupied by you host machine’s SSH server), or by exposing the guest’s network interface in a way that makes it directly connectable from the host.

1 Like

@nh2 I tried to set a different IP address for the VM with the default port and I couldn’t get it to work. I generally have so much trouble with these VMs that it’s easier to just deploy a server to play around with. The port forwarding for SSH is one thing but I couldn’t get impermanence to work either, for example.

I recently started using a similar workflow. I added this to my flake:

      packages.${system} = {
        closureInfo = pkgs.closureInfo {
          rootPaths = [self.devShells.${system}.default] ++
       (builtins.attrValues (builtins.mapAttrs (name: value: value.outPath) inputs));};
        registerClosureScript = (
        pkgs.writeShellScriptBin "register-dev-closure" ''
          #!/usr/bin/env bash
          echo "Registering development environment closure..."
          sudo nix-store --load-db < ${self.packages.${system}.closureInfo}/registration
          '');
        };
  1. build on the host with nix build .#registerClosureScript
  2. copy the output path (ls -l result)
  3. (re)start the guest vm to see the new path in the host store
  4. run on the guest vm with <output path>/bin/register-dev-closure. It will ask for sudo access to run the nix-store data base load.

Here is some more info on the behavior of nix-store --load-db that I found helpful.