Tiny NixOS VirtualBox appliance

I am trying to build a minimal as possible nixos in a virtualbox. I halfway succeeded by just using the minimal install and adding the packages I needed. I then added the iso manually to an otherwise barren virtualbox and exported the appliance with the iso attached.

I am pretty sure it can be done better, but my attempts are being met with much frustration.

I have taken several attempts at making the flake/configuration, but it seems like when I get the closest to getting something to work I always get thwarted by bashInteractive, with this error:

$ nix flake show
warning: Git tree '/home/kt/work/nix-appliance' is dirty
git+file:///home/kt/work/nix-appliance
└───packages
    └───x86_64-linux
        └───default: package 'nixos-ova-23.11.20231129.057f9ae-x86_64-linux'
$ nix build .#
warning: Git tree '/home/kt/work/nix-appliance' is dirty
error: path '/nix/store/svs265fwvyf7dbs6w1zkvzkk91vv0s5q-bash-interactive-5.2-p15-info' is not valid

This build is being done in WSL Ubuntu 22.04 using the nix command.
I will try to make this as minimal as possible, but my flake.nix and iso.nix are:

flake.nix:

{
  description = "Minimal NixOS appliance";
  inputs = {
    nixos.url = "nixpkgs/23.11";
    nixos-generators = {
      url = "github:nix-community/nixos-generators";
      inputs.nixpkgs.follows = "nixos";
    };
  };

  outputs =  { self, nixos, nixos-generators }: 
  let
    system = "x86_64-linux";
  in
  {
    # nixosConfigurations = 
    # {
    #   exampleIso = nixos.lib.nixosSystem {
    #     inherit system;
    #     modules = [
    #       "${nixos}/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix"
    #       ./iso.nix
    #     ];
    #   };
    # };
    packages.${system} = {
      default = nixos-generators.nixosGenerate {
        inherit system;
        modules = [
          # "${nixos}/nixos/modules/profiles/headless.nix"
          # "${nixos}/nixos/modules/profiles/minimal.nix"
          "${nixos}/nixos/modules/image/repart.nix"
          ./iso.nix
        ];

        format = "virtualbox";
      };
    };
  };
}

iso.nix:

{ config, pkgs, modulesPath, ... }:
let
  lib = pkgs.lib;
in
{

  boot.loader.grub.device = "/dev/sda";
  boot.initrd.checkJournalingFS = false;

  fonts.fontconfig.enable = lib.mkForce false;

  disabledModules = [ 
      "${modulesPath}/nixos/modules/profiles/all-hardware.nix"
      "${modulesPath}/nixos/modules/profiles/base.nix"
  ];

  # only add strictly necessary modules
  boot.initrd.includeDefaultModules = false;
  
  fileSystems."/".device = "/dev/disk/by-label/nixos";
  fileSystems."/nix/store".device = "/dev/disk/by-partlabel/nix-store";

  boot.initrd.availableKernelModules = [ "squashfs" "ext4" "overlay" ];

  # See here for documentation:
  #
  # https://github.com/NixOS/nixpkgs/blob/f489e99576900d96aa7fad0780f4e5957e1ab8c0/nixos/modules/image/repart.md
  image.repart = {
    name = "image";
    partitions = {
      # "esp" = {
      #   contents = {
      #     "/EFI/BOOT/BOOT${lib.toUpper efiArch}.EFI".source =
      #       "${pkgs.systemd}/lib/systemd/boot/efi/systemd-boot${efiArch}.efi";

      #     "/loader/entries/nixos.conf".source = pkgs.writeText "nixos.conf" ''
      #         title NixOS
      #         linux /EFI/nixos/kernel.efi
      #         initrd /EFI/nixos/initrd.efi
      #         options init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
      #       '';

      #     "/EFI/nixos/kernel.efi".source =
      #       "${config.boot.kernelPackages.kernel}/${config.system.boot.loader.kernelFile}";

      #     "/EFI/nixos/initrd.efi".source =
      #       "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}";
      #   };
      #   repartConfig = {
      #     Type = "esp";
      #     Format = "vfat";
      #     SizeMinBytes = "96M";
      #   };
      # };

      "store" = {
        storePaths = [ config.system.build.toplevel ];
        stripNixStorePrefix = true;
        repartConfig = {
          Type = "linux-generic";
          Label = "nix-store";

          Format = "squashfs";
          Minimize = "best";
        };
      };

      "root" = {
        repartConfig = {
          Type = "root";
          Format = "ext4";
          Label = "nixos";
          SizeMinBytes = "512M";
        };
      };
    };
  };

  # Enable SSH in the boot process.
  systemd.services.sshd.wantedBy = pkgs.lib.mkForce [ "multi-user.target" ];
  users.users.root = {
    password = "test1234";
    # openssh.authorizedKeys.keys = [
    #   "ssh-ed25519 AaAeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee username@host"
    # ];
  };

  virtualisation.virtualbox.guest.enable = true;

  system.stateVersion = "23.11";
}

If anyone has information that could help me back on the right track, it would be much appreciated. It would surprise me if someone doesn’t already have this exact thing done, but my searches always seem to find something just enough different that I can’t seem to make the adjustments.

2 Likes

This also fails (but succeeds on a nixos machine):
(I had to edit … for some reason I thought it actually worked, but it had the same problem)

{
  description = "Minimal NixOS appliance";
  inputs = {
    nixpkgs.url = "nixpkgs/23.11";
    nixos-generators = {
      url = "github:nix-community/nixos-generators";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs =  { self, nixpkgs, nixos-generators }: 
  let
    system = "x86_64-linux";
  in
  {
    packages.${system} = {
      default = nixos-generators.nixosGenerate {
        inherit system;

        format = "virtualbox";
      };
    };
  };
}
1 Like

which nix version do you use?
most likely you hit this problem:
https://github.com/NixOS/nix/issues/9052
maybe downgrade nix to < 2.18

2 Likes

It turns out it was this problem and one other problem. I am running nix 2.18.0. I have been making so many changes trying to get things to work that I didn’t realize that some of the time it was complaining about not having the “kvm” feature. Since I am running it in WSL on Windows 10, there is no nested vm support.

This was easy enough to work around by generating an iso instead and then using VirtualBox to create the ova from the iso. Thanks for pointing this out. Using the nix-store --repair-path is easy enough if that problem returns.

1 Like