Custom distro source with vmTools

So in my previous avenue in building a custom distro image I stumbled upon the vmTools builder which does pretty much exactly what I need logic-wise, but it has hardcoded distro versions and sources.

Basically I would like to “add” my distro specs to the debDistros set (or replace it with just my own) but so far I was spectacularly unsuccessful.

I tried these few things

let
  _vmTools = pkgs.vmTools // { debDistros = { my-debian = {...}; }; };
in
_vmTools.diskImageFuns.my-debian {};

which resulted in error: attribute 'my-debian' missing when calling the diskImageFuns function. I really thought this would work and honestly don’t understand why it doesn’t (probably one can’t do // with functions?)

Also tried

let
  _vmTools = pkgs.vmTools.override { debDistros = { my-debian = {...}; }; };
in
_vmTools.diskImageFuns.my-debian {};

which obviously resulted in error: function 'anonymous lambda' called with unexpected argument 'debDistros' because as I now (probably) understand, the .override patterns works with function inputs only, not the function itself.

I tried .overrideAttrs as well but since vmTools this is not a “package”, again, to my current understanding, it doesn’t have overrideAttrs.

Is there a simple Nix way to somehow “inject” my preferred values to debDistros inside the function without having to cherry-pick most of the logic to my own function?

The attribute sets in debDistros are simply passed to the makeImageFromDebDist function (nixpkgs/pkgs/build-support/vm/default.nix at e7d1fdf16a3978dfd7e78f2c260afa224fb2136d · NixOS/nixpkgs · GitHub)

So if you want your custom distro, you can call that function yourself, e.g (I copy-pasted the first distro in debDistros):

let
  fetchurl = pkgs.fetchurl;
  commonDebPackages = pkgs.vmTools.commonDebPackages;
in pkgs.vmTools.makeImageFromDebDist {
  name = "ubuntu-14.04-trusty-i386";
  fullName = "Ubuntu 14.04 Trusty (i386)";
  packagesLists =
    [ (fetchurl {
        url = "mirror://ubuntu/dists/trusty/main/binary-i386/Packages.bz2";
        sha256 = "1d5y3v3v079gdq45hc07ja0bjlmzqfwdwwlq0brwxi8m75k3iz7x";
      })
      (fetchurl {
        url = "mirror://ubuntu/dists/trusty/universe/binary-i386/Packages.bz2";
        sha256 = "03x9w92by320rfklrqhcl3qpwmnxds9c8ijl5zhcb21d6dcz5z1a";
      })
    ];
  urlPrefix = "mirror://ubuntu";
  packages = commonDebPackages ++ [ "diffutils" "libc-bin" ];
}

BTW there is this good blog post about this: Building Ubuntu images in Nix - Linus's blog

thanks for the blog link! Found an unrelated piece of information there which was troubling me as well :slight_smile:

In the mean time, I figured about as much, but since makeImageFromDebDists is called a “helper” function, I consider it an internal api and prefer not to call it directly if I can avoid it. But I probably can’t so I will.

I also tried an experiment, “overriding” the diskImageFuns function as well:

      let
          _vmTools = pkgs.vmTools // rec {
            debDistros = {
              debian-latest = {...}
            diskImageFuns =
              (pkgs.lib.mapAttrs (name: as: as2: pkgs.vmTools.makeImageFromDebDist (as // as2)) debDistros);
          };
      in _vmTools.diskImageFuns.debian-latest {...};

and that also works. Why tho, I’m not sure. Feels like lazy evaluation isn’t lazy enough. It almost feels like a bug in Nix but I’m far from understanding whether this is actually expected or not.

Your override works because you now reference your own version debDistros in the diskIpageFuns function/closure.

Nix variables are not passed by reference (they have ‘by value’ semantics), if you use ‘debDistros’, you cannot change that value anymore. The override mechanism is something implemented in nixpkgs which allows to do that, but in truth it works on functions and not variables/attribute sets.