Use specific `unifi` release through overlay

My goal is to be able to define a specific version of pkgs.unifi, as I’m dealing with a weird issue on my UniFi controller, not being able to migrate its DB (We do not support upgrading from 5.6.42), so I need to further debug things by testing a few things using specific versions.

According to pkgs/top-level/all-packages.nix, pkgs.unifi is an alias to pkgs.unifiStable:

inherit (callPackages ../servers/unifi { })
    unifiLTS
    unifiStable
    unifiTesting;
unifi = unifiStable;

So I have this in my configuration.nix

  • for enabling unifi:
    nixpkgs.config.allowUnfree = true;
    services.unifi.enable = true;
    services.unifi.openPorts = true;
    
  • for pulling in the overlay:
    nixpkgs.overlays = [ (import /etc/nixos/overlays/unifi.nix) ];
    

And in the overlay (/etc/nixos/overlays/unifi.nix):

self: super:
{
  unifiStable = super.unifiStable.overrideAttrs(oldAttrs: rec {
    version = "5.7.23";
    sha256 = "e7b60814c27d85c13e54fc3041da721cc38ad21bb0a932bdfe810c2ad3855392"
  });
}

While any change to this expression (e.g. inserting a random char in the value of sha256 triggers the build of a new derivation, the original version of pkgs.unifiStable is still being used (even using invalid values doesn’t cause the expected failures on nixos-rebuild build):

nixos-rebuild dry-build
building the system configuration...
these derivations will be built:
  /nix/store/vbbpn9lk9f3qsnx98rzpyknvwmd2jq33-unifi-controller-5.10.23.drv
  /nix/store/2pi4394vl72m3lnpzxdpk86s52smjaqk-unit-script-unifi-pre-start.drv
  /nix/store/9fhnrirplkjb0s3qnqmzwzf37f9q20vv-unit-var-lib-unifi-lib.mount.drv
  /nix/store/ppab6sj3drskk3ipb2fgj7bli6p8ndh1-unit-unifi.service.drv
  /nix/store/yppnjdzica1c4nsy4x09hyk01c99a7mn-unit-var-lib-unifi-dl.mount.drv
  /nix/store/sg46ls76nphl1928qqrcjm36vy4bbkj2-system-units.drv
  /nix/store/wadjbw4v318rlmkh61v1xgscpw2sc8g0-etc.drv
  /nix/store/gq9hxynxv706pch6lkxrzjypkyrxpcmw-nixos-system-cwg-sdn-unifi-a52f-19.03.172852.5121b483edc.drv

Things I’ve tried:

  • Setting unifi = self.unifiStable in my overlay
  • Using unifi = super.unifi… (or any other combination like unifi = super.unifiStable…) instead of unifiStable = super.unifiStable… in my overlay
  • Explicitly defining services.unifi.unifiPackage = pkgs.unifiStable in my configuration.nix

I’m running out of ideas and I have no idea at this point, how to dig into this, as all the evaluation happening when running nixos-rebuild feels very opaque to me and I fail to get some insight what is how and when evaluated to get a better understanding of what I’m doing (wrong).

The problem is that the generic function to generate the mkDerivation call is not exposed so you can’t just override parameters to that function. See https://github.com/NixOS/nixpkgs/blob/0d00b0b646b7a3c909631354adc16ae07be44bc8/pkgs/servers/unifi/default.nix#L4.

You need to override the regular mkDerivation attrs of unifi like this:

self: super:

{
  unifi = super.unifi.overrideAttrs (attrs: {
    name = "unifi-controller-1.0.0";
    src = self.fetchurl {
      url = "https://dl.ubnt.com/unifi/1.0.0/unifi_sysvinit_all.deb";
      sha256 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    };
  });
}
1 Like

Thanks a lot!
This sounds like it makes sense (although I don’t fully grok those internals yet), but applying this here has basically zero effect:

# nixos-rebuild build && ls -ld /nix/store/*unifi-controller-5.7.23*
building Nix...
building the system configuration...
ls: cannot access '/nix/store/*unifi-controller-5.7.23*': No such file or directory

My /etc/nixos/overlays/unifi.nix:

self: super:
let
  unifiVersion = "5.7.23";
  unifiHash = "e7b60814c27d85c13e54fc3041da721cc38ad21bb0a932bdfe810c2ad3855392";
in
{
  unifi = super.unifi.overrideAttrs (attrs: {
    name = "unifi-controller-${unifiVersion}";
    src = self.fetchurl {
      url = "https://dl.ubnt.com/unifi/${unifiVersion}/unifi_sysvinit_all.deb";
      sha256 = unifiHash;
    };
  });
}

I would suggest setting services.unifi.unifiPackage to your overridden package directly, just to make sure there’s no confusion over whether you’re actually referencing your overridden package or not. You could have your overlay define something like unifi-5_7_23 as an attribute name and then reference that for services.unifi.unifiPackage.

I would also suggest running something like nix show-derivation to print out your overridden package and make sure it looks correct.

2 Likes

Ok, so this actually worked:

In configuration.nix:

services.unifi.unifiPackage = pkgs.unifiCustom;

In overlays/unifi.nix:

self: super:
let
  unifiVersion = "5.10.24";
  unifiHash = "5d9022a71a1f35820fa578706caacfcf8a3c17601d2ee556252d74881bff6856";
in
{
  unifiCustom = super.unifi.overrideAttrs (attrs: {
    name = "unifi-controller-${unifiVersion}";
    src = self.fetchurl {
      url = "https://dl.ubnt.com/unifi/${unifiVersion}/unifi_sysvinit_all.deb";
      sha256 = unifiHash;
    };
  });
}

Although I see, that using another name avoids the collision, but I don’t really understand why there’s a collision in this case what should work just fine in other scenarios. Can anyone explain what’s going on here?

Nevertheless - thanks a lot to @fpletz and @lilyball

Glad to hear you got it working! Overwriting the previous name should have worked as well, but I can’t tell you precisely what went wrong without seeing the full setup.