Install an unstable package in stable home manager using flakes

I’ve looked in several places and have read multiple ways to do this, but I just can’t get this to work.

Here is my flake.nix

{
  description = "Nixos config flake";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/24.05";
    nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";

    home-manager = {
      url = "github:nix-community/home-manager/release-24.05";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { self, nixpkgs, nixpkgs-unstable, ... }@inputs:
    let
      system = "x86_64-linux";
      pkgs = nixpkgs.legacyPackages.${system};
      unstable = nixpkgs.legacyPackages.${system};
    in
    {
      nixosConfigurations = {
        samara = nixpkgs.lib.nixosSystem {
          specialArgs = {inherit inputs;};
          modules = [
            ./hosts/samara/configuration.nix
            inputs.home-manager.nixosModules.default
          ];
        };
        oak = nixpkgs.lib.nixosSystem {
          specialArgs = {inherit inputs;};
          modules = [
            ./hosts/oak/configuration.nix
            inputs.home-manager.nixosModules.default
          ];
        };
      };
    };
}

I’ve added this to the home.nix file:
{ config, pkgs, pkgs-unstable, ... }:

But how do I add the Amarok unstable package?

You need to overlay nixpkgs with unstable

    nixpkgs.overlays=[ final: prev: {
      unstable = import nixpkgs-unstable {
        system = final.system;
      };
    }];

Then you can add unstable packages like so:

environment.systemPackages = [pkgs.unstable.amarok]

this should also work when installing packages via home-manager.

2 Likes

Basically you have some errors there:

  • for the unstable binding you should set it to use the nixpkgs-unstable input instead of nixpkgs
  • if you really want to make it available via pkgs-unstable, you should add it to specialArgs, i.e. specialArgs = { inherit inputs; pkgs-unstable = unstable; };
  • you need to do the same with HM, but using extraSpecialArgs instead of specialArgs, i.e. put ({ home-manager.extraSpecialArgs = { ... }; }) in the modules list for the respective system configs

Overlay is unnecessary, I would not use overlays as they will slow down eval and it’s a misuse to use them for something like this.

Done:
Also changed unstable to pkgs-unstable, is that what you meant from your second point?

I’m not attached to how I do this as long as it’s not working against it’s intended use/configuration…
specialArgs = { inherit inputs; pkgs-unstable = unstable; }; goes on the configuration.nix file and the next point in the flake.nix

So, like this?

{
  description = "Nixos config flake";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/24.05";
    nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";

    home-manager = {
      url = "github:nix-community/home-manager/release-24.05";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { self, nixpkgs, nixpkgs-unstable, ... }@inputs:
    let
      system = "x86_64-linux";
      pkgs = nixpkgs.legacyPackages.${system};
      pkgs-unstable = nixpkgs-unstable.legacyPackages.${system};
    in
    {
      nixosConfigurations = {
        samara = nixpkgs.lib.nixosSystem {
          specialArgs = {inherit inputs;};
          modules = [
            ./hosts/samara/configuration.nix
            inputs.home-manager.nixosModules.default
            ({ home-manager.extraSpecialArgs = { ... }; })
          ];
        };
        oak = nixpkgs.lib.nixosSystem {
          specialArgs = {inherit inputs;};
          modules = [
            ./hosts/oak/configuration.nix
            inputs.home-manager.nixosModules.default
           ({ home-manager.extraSpecialArgs = { ... }; })
          ];
        };
      };
    };
}

How wold I then add the package? Sorry for the dense questions, I’m new to the nix language…

What file would that go into? Also, I keep getting a error: syntax error, unexpected ':'

This would go on the home.nix file?

Use pkgs-unstable.whatever (replace pkgs-unstable with whatever you passed into the extraSpecialArgs)

Following the example in Importing packages from multiple nixpkgs branches - Flakes - NixOS Wiki, this is what you need to have:

{
  description = "Nixos config flake";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/24.05";
    nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";

    home-manager = {
      url = "github:nix-community/home-manager/release-24.05";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs =
    {
      self,
      nixpkgs,
      nixpkgs-unstable,
      ...
    }@inputs:
    let
      system = "x86_64-linux";
      pkgs = nixpkgs.legacyPackages.${system};

      # <-- We define unstable here to re-use on both hosts -->
      unstable-overlays = {
        nixpkgs.overlays = [
          (final: prev: {
            unstable = nixpkgs-unstable.legacyPackages.${prev.system};
            # <-- use this variant instead if unfree packages are needed: -->
            # unstable = import nixpkgs-unstable {
            #   inherit system;
            #   config.allowUnfree = true;
            # };
          })
        ];
      };
    in
    {
      nixosConfigurations = {
        samara = nixpkgs.lib.nixosSystem {
          specialArgs = {
            inherit inputs;
          };
          modules = [
            ./hosts/samara/configuration.nix
            inputs.home-manager.nixosModules.default
            unstable-overlays  # <----
          ];
        };
        oak = nixpkgs.lib.nixosSystem {
          specialArgs = {
            inherit inputs;
          };
          modules = [
            ./hosts/oak/configuration.nix
            inputs.home-manager.nixosModules.default
            unstable-overlays  # <----
          ];
        };
      };
    };
}

You can then use pkgs.unstable.<package> in:

# configuration.nix
{ pkgs, ... }:
{
  environment.systemPackages = [
    pkgs.unstable.amarok
  ];
}

or

# home.nix
{ pkgs, ... }:
{
  home.packages = [
    pkgs.unstable.amarok
  ];
}

Some NixOS and home-manager modules also provide a .package option, which you can pass the unstable version to. For example:

# home.nix
{ pkgs, ... }:
{
  home = {
    programs.mpv.package = pkgs.unstable.mpv;
  };
}

Thanks for that information, I am getting an error when trying to switch.
error: undefined variable 'unstable'

Here is my home.nix

{ config, pkgs, pkgs-unstable, ... }:

{
  home.username = "sergio";
  home.homeDirectory = "/home/sergio";

  home.stateVersion = "24.05"; 

  nixpkgs = {
    config = {
      allowUnfree = true;
    };
  };

  home.packages = with pkgs; [
    unstable.amarok
    audacity
    darktable

flake.nix

{
  description = "Nixos config flake";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/24.05";
    nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable";

    home-manager = {
      url = "github:nix-community/home-manager/release-24.05";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = { self, nixpkgs, nixpkgs-unstable, ... }@inputs:
    let
      system = "x86_64-linux";
      pkgs = nixpkgs.legacyPackages.${system};
      pkgs-unstable = nixpkgs-unstable.legacyPackages.${system};
            # <-- We define unstable here to re-use on both hosts -->
      unstable-overlays = {
        nixpkgs.overlays = [
          (final: prev: {
            unstable = nixpkgs-unstable.legacyPackages.${prev.system};
            # <-- use this variant instead if unfree packages are needed: -->
            # unstable = import nixpkgs-unstable {
            #   inherit system;
            #   config.allowUnfree = true;
            # };
          })
        ];
      };
    in
    {
      nixosConfigurations = {
        samara = nixpkgs.lib.nixosSystem {
          specialArgs = {inherit inputs;};
          modules = [
            ./hosts/samara/configuration.nix
            inputs.home-manager.nixosModules.default
            unstable-overlays
          ];
        };
        oak = nixpkgs.lib.nixosSystem {
          specialArgs = {inherit inputs;};
          modules = [
            ./hosts/oak/configuration.nix
            inputs.home-manager.nixosModules.default
            unstable-overlays
          ];
        };
      };
    };
}

If I add the section you mentioned to configuration.nix instead then it seems to not give any errors while switching.

Though, it still isn’t actually working because of this error:

Got ERROR: "Can't open and lock privilege tables: Table 'mysql.servers' doesn't exist" errno: 2000

Cannot mix incompatible Qt library (5.15.12) with this library (5.15.14)

You probably have to do it like this:

    home.packages =
      (with pkgs; [
        audacity
        darktable
      ])
      ++ (with pkgs.unstable; [
        amarok
      ]);

or

    home.packages = [
      pkgs.audacity
      pkgs.darktable
      pkgs.unstable.amarok
    ];

Did it build the new version? What path does this command give?

readlink $(which amarok)

So, I don’t think pulling amarok from the unstable branch will help in this case because the QT versions are different, so the derivation will need to be build from your system.

We can easily do this by overlaying amarok with changes from unstable:

# configuration.nix
  nixpkgs.overlays = [
    (final: prev: {
      amarok = prev.amarok.overrideAttrs (finalAttrs: {
        version = "3.0.1";
        src = prev.fetchurl {
          url = "mirror://kde/stable/amarok/${finalAttrs.version}/amarok-${finalAttrs.version}.tar.xz";
          sha256 = "sha256-S+zyrp3cvoYRA+ZCFDaireIvU4yxw2ANTmZ/cb6ljys=";
        };
        nativeBuildInputs = finalAttrs.nativeBuildInputs ++ [ pkgs.libsForQt5.qt5.wrapQtAppsHook ];
      });
    })
  ];
  environment.systemPackages = [ pkgs.amarok ];

Thanks for the help with this! I’m confused though. How is it that the 2.9.71 version is being downloaded?
configuration.nix:

  nixpkgs.overlays = [
    (final: prev: {
      amarok = prev.amarok.overrideAttrs (finalAttrs: {
        version = "3.0.1";
        src = prev.fetchurl {
          url = "mirror://kde/stable/amarok/${finalAttrs.version}/amarok-${finalAttrs.version}.tar.xz";
          sha256 = "sha256-S+zyrp3cvoYRA+ZCFDaireIvU4yxw2ANTmZ/cb6ljys=";
        };
        nativeBuildInputs = finalAttrs.nativeBuildInputs ++ [ pkgs.libsForQt5.qt5.wrapQtAppsHook ];
      });
    })
  ];

  environment.systemPackages = [
    pkgs.amarok
    pkgs.devenv
error: builder for '/nix/store/rxf1chlk99qmlj2rjmvmapk8ni3bl25q-amarok-2.9.71.tar.xz.drv' failed with exit code 1;
       last 10 log lines:
       >                                  Dload  Upload   Total   Spent    Left  Speed
       >   0   150    0     0    0     0      0      0 --:--:--  0:00:02 --:--:--     0
       > curl: (56) The requested URL returned error: 404
       >
       > trying https://ftp.funet.fi/pub/mirrors/ftp.kde.org/pub/kde/stable/amarok/2.9.71/amarok-2.9.71.tar.xz
       >   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
       >                                  Dload  Upload   Total   Spent    Left  Speed
       >   0   315    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0
       > curl: (22) The requested URL returned error: 404
       > error: cannot download amarok-2.9.71.tar.xz from any mirror
       For full logs, run 'nix log /nix/store/rxf1chlk99qmlj2rjmvmapk8ni3bl25q-amarok-2.9.71.tar.xz.drv'.
error: 1 dependencies of derivation '/nix/store/mg692sq6r0j0ip9cdq3yd0ji103imbxd-amarok-3.0.1.drv' failed to build
error: 1 dependencies of derivation '/nix/store/7f24mprdai75863gf4n1lfj4airgq0jy-system-path.drv' failed to build
error: 1 dependencies of derivation '/nix/store/dxhfxrl7gdp9l0r8lknyi5kp2qpmp91n-nixos-system-oak-24.05.20240531.63dacb4.drv' failed to build

These are the only references to Amarok. Scratching my head…

My bad. It should be version not finalAttrs.version. This should work:

    (final: prev: {
      amarok = prev.amarok.overrideAttrs (finalAttrs: rec {
        version = "3.0.1";
        src = prev.fetchurl {
          url = "mirror://kde/stable/amarok/${version}/amarok-${version}.tar.xz";
          sha256 = "sha256-S+zyrp3cvoYRA+ZCFDaireIvU4yxw2ANTmZ/cb6ljys=";
        };
        nativeBuildInputs = finalAttrs.nativeBuildInputs ++ [ pkgs.libsForQt5.qt5.wrapQtAppsHook ];
      });
    })

The confusion arose because the argument is named inaccurately; if you provide single arg to overrideAttrs it refers to the oldAttrs (not finalAttrs).

2 Likes

That is quite confusing indeed. I though just having finalAttrs is enough because I’ve used one argument once to pin a version package and it worked. Looking back, I think it was just be pinning the wrong version and just using the version number I specified for the name…

In this case with amarok, it was building 2.9.71, but naming the package 3.0.1

Okay, got Amarok (unstable) loading AND with sound. Which seems to be an issue on how Amarok is being compiled…
Had to add libsForQt5.phonon-backend-gstreamer for it to output sound.

Here is the working home.nix

  nixpkgs.overlays = [
    (final: prev: {
      amarok = prev.amarok.overrideAttrs (finalAttrs: rec {
        version = "3.0.1";
        src = prev.fetchurl {
          url = "mirror://kde/stable/amarok/${version}/amarok-${version}.tar.xz";
          sha256 = "sha256-S+zyrp3cvoYRA+ZCFDaireIvU4yxw2ANTmZ/cb6ljys=";
        };
        nativeBuildInputs = finalAttrs.nativeBuildInputs ++ [ pkgs.libsForQt5.qt5.wrapQtAppsHook ];
      });
    })
  ];

  home.packages = with pkgs; [
    amarok
    libsForQt5.phonon-backend-gstreamer
  ];

I would have loved to know how to set this up without overlays, but not up to speed enough for that.

1 Like

Btw, don’t use pkgs in an overlay, prefer final whenever possible. If not possible, due to infrec, use prev.

Literally the same thing but without using overlays, just use the override directly where you want the package.blah.overrideAttrs { ... } returns another package.

home.packages = with pkgs; [
  (amarok.overrideAttrs (oldAttrs: rec {
    version = "3.0.1";
    src = fetchurl {
      url = "mirror://kde/stable/amarok/${version}/amarok-${version}.tar.xz";
      hash = "sha256-S+zyrp3cvoYRA+ZCFDaireIvU4yxw2ANTmZ/cb6ljys=";
    };
    nativeBuildInputs = (oldAttrs.nativeBuildInputs or [ ]) ++ [ libsForQt5.wrapQtAppsHook ];
  }))
  libsForQt5.phonon-backend-gstreamer
];

And this is better (if you’re overriding a leaf package) than an overlay, because it will eval faster.

1 Like

Actually on that note, I’m not sure why you’d want this package in your config, it’s certainly not doing anything…

Thanks :superhero: I got it working as I wanted, no overlay and seems fine!

I need to add libsForQt5.phonon-backend-gstreamer because if I don’t there is no audio output. Amarok won’t even play at all. Even though the rest of the system works. :person_shrugging: Mainly, this line gave me the hint I needed:
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded

This is on the stable and unstable branches…

No audio… This is the output of the amarok command with out gstreamer added:

**********************************************************************************************
** AMAROK WAS STARTED IN NORMAL MODE. IF YOU WANT TO SEE DEBUGGING INFORMATION, PLEASE USE: **
** amarok --debug                                                                           **
**********************************************************************************************
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
WARNING: Phonon::createPath: Cannot connect  Phonon::MediaObject ( no objectName ) to  Phonon::AudioOutput ( no objectName ).
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
WARNING: Phonon::createPath: Cannot connect  Phonon::MediaObject ( no objectName ) to  Phonon::AudioDataOutput ( no objectName ).
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
WARNING: bool Phonon::FactoryPrivate::createBackend() phonon backend plugin could not be loaded
Got ERROR: "Can't open and lock privilege tables: Table 'mysql.servers' doesn't exist" errno: 2000
kf.kirigami: Failed to find a Kirigami platform plugin

Working… This is the output with it added:

**********************************************************************************************
** AMAROK WAS STARTED IN NORMAL MODE. IF YOU WANT TO SEE DEBUGGING INFORMATION, PLEASE USE: **
** amarok --debug                                                                           **
**********************************************************************************************
Got ERROR: "Can't open and lock privilege tables: Table 'mysql.servers' doesn't exist" errno: 2000
kf.kirigami: Failed to find a Kirigami platform plugin
file:///nix/store/s0m9rdvp25409sq2j9nnwi4l2zx7mifm-amarok-3.0.1/share/kpackage/genericqml/org.kde.amarok.context/contents/ui/main.qml:97:25: QML Connections: Implicitly defined onFoo properties in Connections are deprecated. Use this syntax instead: function onFoo(<arguments>) { ... }
file:///nix/store/s0m9rdvp25409sq2j9nnwi4l2zx7mifm-amarok-3.0.1/share/kpackage/genericqml/org.kde.amarok.context/contents/ui/main.qml:87:25: QML Connections: Implicitly defined onFoo properties in Connections are deprecated. Use this syntax instead: function onFoo(<arguments>) { ... }
file:///nix/store/s0m9rdvp25409sq2j9nnwi4l2zx7mifm-amarok-3.0.1/share/kpackage/genericqml/org.kde.amarok.context/contents/ui/main.qml:97:25: QML Connections: Implicitly defined onFoo properties in Connections are deprecated. Use this syntax instead: function onFoo(<arguments>) { ... }
file:///nix/store/s0m9rdvp25409sq2j9nnwi4l2zx7mifm-amarok-3.0.1/share/kpackage/genericqml/org.kde.amarok.context/contents/ui/main.qml:87:25: QML Connections: Implicitly defined onFoo properties in Connections are deprecated. Use this syntax instead: function onFoo(<arguments>) { ... }
file:///nix/store/s0m9rdvp25409sq2j9nnwi4l2zx7mifm-amarok-3.0.1/share/kpackage/genericqml/org.kde.amarok.context/contents/ui/main.qml:97:25: QML Connections: Implicitly defined onFoo properties in Connections are deprecated. Use this syntax instead: function onFoo(<arguments>) { ... }
file:///nix/store/s0m9rdvp25409sq2j9nnwi4l2zx7mifm-amarok-3.0.1/share/kpackage/genericqml/org.kde.amarok.context/contents/ui/main.qml:87:25: QML Connections: Implicitly defined onFoo properties in Connections are deprecated. Use this syntax instead: function onFoo(<arguments>) { ... }
[29915:30005:0802/111326.201816:ERROR:gl_context_egl.cc(259)] eglCreateContext failed with error EGL_BAD_CONTEXT
[29915:30005:0802/111326.201828:ERROR:gpu_channel_manager.cc(753)] ContextResult::kFatalFailure: Failed to create shared context for virtualization.
[29915:30005:0802/111326.201834:ERROR:shared_image_stub.cc(470)] SharedImageStub: unable to create context
[29915:30005:0802/111326.201840:ERROR:gpu_channel.cc(449)] GpuChannel: Failed to create SharedImageStub