How to override set isoImage.contents?

# image.nix
{ config, lib, pkgs, ... }:

with lib;

{
  imports =
    [ <nixpkgs/nixos/modules/installer/cd-dvd/channel.nix>
      ./machine-config.nix
    ];

  system.build.qemuvmImage = import <nixpkgs/nixos/lib/make-disk-image.nix> {
    inherit lib config;
    pkgs = import <nixpkgs/nixos> { inherit (pkgs) system; }; # ensure we use the regular qemu-kvm package
    diskSize = 8192;
    format = "qcow2";
    configFile = pkgs.writeText "configuration.nix"
      ''
        {
          imports = [ <./machine-config.nix> ];
        }
      '';
  };
}
# machine-config.nix
{ pkgs, lib, ... }:

with lib;

{
  imports = [
    <nixpkgs/nixos/modules/profiles/qemu-guest.nix>
  ];

  config = {
# ...
    isoImage.contents = ''
        [ { source = "/home/my/thisfolder";
            target = "/thisfolder";
          }
        ]
      '';
  };
}

I am using nixos-generate -f iso -c image.nix to generate a custom nixos.iso file.

I want to add a directory to the generated iso though. My first thought was using an override of isoImage.contents as hinted at iso-image.nix, but now I am stuck, the nixos-generate telling me:

error: Cannot merge definitions of isoImage.contents' given in /home/me/nixos2qemuvm/machine-config.nix’ and `/home/me/.nix-defexpr/channels/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix’.

3 Likes

I haven’t tried this, but I think the ‘’ is wrong here. isoImage.contents appears to be a list of objects. You’re providing a string.
Something like this will probably work better:

isoImage.contents = [ { source = "/home/my/thisfolder"; target = "/thisfolder"; } ];

However there is probably another catch: The builder is probably run in a sandbox and will probably be unable to access anything not referenced by a derivation.
A workaround for that could be to use a path instead of a string as the source. This will copy /home/my/thisfolder to the nix store for the build (think about if that’s actually ok for you).
So i suggest something like this:

isoImage.contents = [ { source = /home/my/thisfolder; target = "/thisfolder"; } ];

You could also use source = ./thisfolder; instead.

2 Likes

Thanks @tokudan, this absolutely works, using your last suggestion (isoImage.contents = [ { source = /home/my/thisfolder; target = "/thisfolder"; } ];)!

Circumvented the impassing need to figure out mkmerge workings.

I need to correct some of my assumptions in the examples I gave above as those were wrong.

First the nixos-generate -f iso -c image.nix call given with the image.nix listed would generate an iso file indeed and still would be possible to boot from using qemu but - and this is the error i guess - writing it to an usbstick and trying to boot it will lead to an endless Booting kernel message best case.

What to do instead ?

Take the following iso.nix and iso-config.nix files to actually create correct iso file (I’ll provide vm.nix and vm-config.nix further below):

# iso.nix
# nix-build '<nixpkgs/nixos>' -A config.system.build.isoImage --arg configuration "{ imports = [ ./iso.nix ]; }"
# or nixos-generate -f iso -c iso.nix
# This module defines a small NixOS installation CD.  It does not
# contain any graphical stuff.
{config, pkgs, ...}:
{
  imports = [
    <nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-minimal.nix>
    ./iso-config.nix
    # Provide an initial copy of the NixOS channel so that the user
    # doesn't need to run "nix-channel --update" first.
    <nixpkgs/nixos/modules/installer/cd-dvd/channel.nix>
  ];
}
# iso-config.nix
{ pkgs, lib, ... }:

with lib;

{
  config = {
    i18n.defaultLocale = "de_DE.UTF-8";
    time.timeZone = "Europe/Paris";

    services = {
      timesyncd.enable = lib.mkDefault true;
      openssh = {
        enable = true;
        permitRootLogin = "yes";
      };
    };

    environment.systemPackages = with pkgs; [
      dosfstools vim netcat curl openjdk8
    ];

    users.extraUsers.root.password = "";
    users.mutableUsers = false;

    users.users.root = {
      extraGroups = [ "wheel" ];
      openssh.authorizedKeys.keys = [
        "ssh-rsa ... "
      ];
    };

    isoImage.contents =
        [ { source = /home/me/somefolder;
            target = "/folderiniso";
          }
        ];
  };
}

For comprehension the vm-files again:

# vm.nix
# nix-build '<nixpkgs/nixos>' -A vm --arg configuration "{ imports = [ ./vm.nix ]; }"
# nix-build '<nixpkgs/nixos>' -A vm -I nixos-config=vm.nix
# ./result/bin/run-nixos-vm
# or nixos-generate -f vm -c vm.nix --run
# nixos-generate --help
# nixos-generate --list
{ config, lib, pkgs, ... }:

with lib;

{
  imports =
    [ <nixpkgs/nixos/modules/installer/cd-dvd/channel.nix>
      ./vm-config.nix
    ];

  system.build.qemuvmImage = import <nixpkgs/nixos/lib/make-disk-image.nix> {
    inherit lib config;
    pkgs = import <nixpkgs/nixos> { inherit (pkgs) system; }; # ensure we use the regular qemu-kvm package
    diskSize = 8192;
    format = "qcow2";
    configFile = pkgs.writeText "configuration.nix"
      ''
        {
          imports = [ <./machine-config.nix> ];
        }
      '';
    };
}
# vm-config.nix
{ pkgs, lib, ... }:

with lib;

{
  imports = [
    <nixpkgs/nixos/modules/profiles/qemu-guest.nix>
  ];

  config = {
    fileSystems."/" = {
      device = "/dev/disk/by-label/nixos";
      fsType = "ext4";
      autoResize = true;
    };

    # Set VM disk size (in MB)
    virtualisation.diskSize = 1024 * 2048;

    boot.growPartition = true;
    boot.kernelParams = [ "console=ttyS0" ];
    boot.loader.grub.device = "/dev/vda";
    boot.loader.timeout = 0;

    i18n.defaultLocale = "de_DE.UTF-8";
    time.timeZone = "Europe/Paris";

    services = {
      timesyncd.enable = lib.mkDefault true;
      openssh = {
        enable = true;
        permitRootLogin = "yes";
      };
    };

    environment.systemPackages = with pkgs; [
      dosfstools vim netcat curl openjdk8
    ];

    users.extraUsers.root.password = "";
    users.mutableUsers = false;

    users.users.root = {
      extraGroups = [ "wheel" ];
      openssh.authorizedKeys.keys = [
        "ssh-rsa ... "
      ];
    };
  };
}

Thank you and sorry for the fuzz!