astro / microvm.nix

NixOS MicroVMs
https://astro.github.io/microvm.nix/
MIT License
1.25k stars 94 forks source link

[FR] option to populate profile channel during VM creation #175

Closed thkoch2001 closed 8 months ago

thkoch2001 commented 8 months ago

Copied from this SO question, with addtions at the end: https://stackoverflow.com/questions/77728179/how-to-install-a-nix-channel-in-a-nixos-vm

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?

I need channels, because I want to use the nix integration of the Haskell tool "stack", which seems to rely on channels. When I use emacs' eglot on Haskell code inside the VM, stack setup gets called and fails with:

file 'nixpkgs' was not found in the Nix search path (add it using $NIX_PATH or -I)

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 = {};
            })
          ];
        };
      };
    };
}
astro commented 8 months ago

How about

nix-channel --add  https://nixos.org/channels/nixpkgs-unstable nixpkgs

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?

I use flakes but you can get a channel with the <nixpkgs> syntax. So maybe try that in your MicroVM NixOS configuration:

nix.nixPath = builtins.storePath <nixpkgs>;
thkoch2001 commented 8 months ago

Thx for the hint, but unfortunately it gives:

error: 'builtins.storePath' is not allowed in pure evaluation mode

After reading way too much about nix path, nix profiles and the whole mess this seems to be, I'm not sure whether I want to dive into this topic right now.

Just for reference, these are the ideas I still have:

UPDATE

The following did the trick:

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

together with running the flake with nix run --impure.

astro commented 8 months ago

Thank you for your investigation and write-up. I added that as an FAQ section.