Use one service from the unstable branch with flakes

I’m trying to use a service from unstable. In this case tailscale but I’d like to get the procedure nailed down so I can use it for others if I choose.

I found some advice at Configuring programs and services from unstable channel in NixOS - Unix & Linux Stack Exchange but I can’t get it to work so I’m probably missing something.

In my flake.nix I have the unstable branch as an input

nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";

And create my system as follows

"laptop" = nixpkgs.lib.nixosSystem {
          system = "x86_64-linux";
          modules = [
            (
              self.lib.createSystem "laptop" {
                hardwareConfig = ./hardware/laptop.nix;
                config = ./hosts/laptop.nix;
              }
            )
          ];
          specialArgs = { inherit inputs; };
        };

And in my hosts/laptop.nix I import the tailscale.nix from the unstable branch and disable the regular one

imports =
    [ 
      "${nixpkgs-unstable}/nixos/modules/services/networking/tailscale.nix"
    ];

  disabledModules = [
    "services/networking/tailscale.nix"
  ];

And I enable the service as follows

services.tailscale.enable = true;

However I’m getting an infitnite recursion error when I try to build it. Any ideas where I’m going wrong?

I think you just need to set the tailscale package to the unstable package as well:

services.tailscale = {
    enable= true;
    package = nixos-unstable.tailscale;
    <any other options>
};

Always, share the error, we’re not mindreaders.

But as said above, setting the .package option makes more sense unless the module itself changed.

1 Like

Unfortunately this did not seem to make a difference.

I changed the code to

  services.tailscale = {
    enable = true;
    package = nixpkgs-unstable.tailscale;
  };

Sorry, I forgot that just because it makes not sense to me that it might make loads of sense to someone else

error:
       … while calling the 'seq' builtin

         at /nix/store/wdk3xa0vwx7swjdl1samf1bccvyyzfc1-source/lib/modules.nix:322:18:

          321|         options = checked options;
          322|         config = checked (removeAttrs config [ "_module" ]);
             |                  ^
          323|         _module = checked (config._module);

       … while evaluating a branch condition

         at /nix/store/wdk3xa0vwx7swjdl1samf1bccvyyzfc1-source/lib/modules.nix:261:9:

          260|       checkUnmatched =
          261|         if config._module.check && config._module.freeformType == null && merged.unmatchedDefns != [] then
             |         ^
          262|           let

       (stack trace truncated; use '--show-trace' to show the full trace)

       error: infinite recursion encountered

       at /nix/store/wdk3xa0vwx7swjdl1samf1bccvyyzfc1-source/lib/modules.nix:508:28:

          507|         builtins.addErrorContext (context name)
          508|           (args.${name} or config._module.args.${name})
             |                            ^
          509|       ) (lib.functionArgs f);

If I show trace it’s actually a bit more revealing. I think it’s something to do with the way I’m passing nixpks-unstable

        at /nix/store/wdk3xa0vwx7swjdl1samf1bccvyyzfc1-source/lib/modules.nix:506:44:

          505|       context = name: ''while evaluating the module argument `${name}' in "${key}":'';
          506|       extraArgs = builtins.mapAttrs (name: _:
             |                                            ^
          507|         builtins.addErrorContext (context name)

       … while evaluating the module argument `nixpkgs-unstable' in "/nix/store/hcfc9iin20pjdw0fvjayjggvbfxjlgsk-source/hosts/framework.nix":

       error: infinite recursion encountered

       at /nix/store/wdk3xa0vwx7swjdl1samf1bccvyyzfc1-source/lib/modules.nix:508:28:

          507|         builtins.addErrorContext (context name)
          508|           (args.${name} or config._module.args.${name})
             |                            ^
          509|       ) (lib.functionArgs f);

The declaration on the first line of my module is

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

Yep this indicates trying to use a module arg that wasn’t passed into the module system, and you found it yourself here. (I probably should’ve caught it too but the error really helps.)

Since you only passed inputs into the module system via specialArgs, you need to write

{ config, pkgs, inputs, ... }:
{
  imports =
    [ 
      "${inputs.nixpkgs-unstable}/nixos/modules/services/networking/tailscale.nix"
    ];

  disabledModules = [
    "services/networking/tailscale.nix"
  ];

  # etc.
}

Also I’m surprised this works for you without --impure, I thought you had to write "${modulesPath}/services/networking/tailscale.nix" (at least I tried with your syntax before and had issues with pure eval)

I have got a step further now but it’s having trouble with the package element in the services part.

services.tailscale = {
    enable = true;
    package = inputs.nixpkgs-unstable.tailscale;
    useRoutingFeatures = "client";
  };

The error is

    error: attribute 'tailscale' missing

       at /nix/store/mmp8knakxia6jznwg44g46h69kml33s6-source/hosts/laptop.nix:75:15:

           74|     enable = true;
           75|     package = inputs.nixpkgs-unstable.tailscale;
             |               ^
           76|     useRoutingFeatures = "client";

I actually started this in order to have a more up to date tailscale as 24.05 was behind somewhat. It’s now up to date with unstable so I’m not exactly sure how to tell if this actually works.

Removing the package line compiles but I don’t know if it’s the result I want

Use inputs.nixpkgs-unstable.legacyPackages.${pkgs.system}.tailscale

That did the job. I have to say I would not have worked that out. Thanks very much for your help, I’ll need to monitor for a divergence in the tailscale version between stable and unstable to see if it’s working but looking good for now and I have an example of using a package from another flake input which I’m sure will come in handy at some point.