How to install a nix channel in a NixOS VM?

105 Views Asked by At

I'm using microvm to create and run a NixOS vm (on a Debian system with the nix packet manager installed).

The NIX_PATH environment variable inside the VM is set to its default value:

nixpkgs=/nix/var/nix/profiles/per-user/root/channels/nixos:nixos-config=/etc/nixos/configuration.nix:/nix/var/nix/profiles/per-user/root/channels

The nixpkgs path referenced above however does not exist on the VM, /nix/var/nix/profiles/per-user/ is empty.

How can I configure the VM so that it gets built with a working reference to the nixpkgs channel that was also used to build the VM?

These questions seem to be similar, but I'm not sure yet:

My flake.nix to build the microvm:

{
  description = "NixOS in MicroVMs";

  inputs.microvm.url = "github:astro/microvm.nix";
  inputs.microvm.inputs.nixpkgs.follows = "nixpkgs";

  outputs = { self, nixpkgs, microvm }:
    let
      system = "x86_64-linux";
      user = "REDACTED";
      vmname = "haskell";
    in {
      defaultPackage.${system} = self.packages.${system}.my-microvm;

      packages.${system} = {
        my-microvm = self.nixosConfigurations.my-microvm.config.microvm.declaredRunner;
      };

      nixosConfigurations = {
        my-microvm = nixpkgs.lib.nixosSystem {
          inherit system;
          modules = [
            microvm.nixosModules.microvm
            ({pkgs, ... }: {
              environment.systemPackages = [
                pkgs.ghc
                pkgs.git
                (pkgs.haskell-language-server.override { supportedGhcVersions = [ "94" ]; })
                pkgs.stack
              ];
              microvm = {
                forwardPorts = [
                  { from = "host"; host.port = 2222; guest.port = 22; }
                ];
                hypervisor = "qemu";
                interfaces = [
                  { type = "user"; id = "usernet"; mac = "00:00:00:00:00:02"; }
                ];
                mem = 4096;
                shares = [ {
                  proto = "9p";
                  tag = "ro-store";
                  source = "/nix/store";
                  mountPoint = "/nix/.ro-store";
                } {
                  proto = "virtiofs";
                  tag = "hometest";
                  source = "~/.local/share/microvm/vms/${vmname}/shares/home";
                  mountPoint = "/home/${user}";
                  socket = "/run/user/1000/microvm-virtiofsd_vm_home";
                }
                ];
                socket = "/run/user/1000/microvm-control.socket";
                vcpu = 3;
                volumes = [];
                writableStoreOverlay = "/home/${user}/nix-rw-store";
              };
              networking.hostName = vmname;
              nix.settings = {
                extra-experimental-features = ["nix-command" "flakes"];
                trusted-users = [user];
              };
              security.sudo = {
                enable = true;
                wheelNeedsPassword = false;
              };
              services.getty.autologinUser = user;
              services.openssh = {
                enable = true;
              };
              users.users.${user} = {
                extraGroups = [ "wheel" "video" ];
                group = "user";
                isNormalUser = true;
                openssh.authorizedKeys.keys = [
                  "ssh-rsa REDACTED"
                ];
                password = "";
              };
              users.users.root.password = "";
              users.groups.user = {};
            })
          ];
        };
      };
    };
}
1

There are 1 best solutions below

1
Thomas Koch On

It turned out, what I actually needed was to have <nixpkgs> resolve inside the VM. This I achieved by setting this option in the VM config:

nix.nixPath = ["nixpkgs=${builtins.storePath <nixpkgs>}"];

And running the flake with nix run --impure. Impure is necessary because builtins.storePath is input from outside.

I discussed this issue also here: https://github.com/astro/microvm.nix/issues/175