I have a little module that enables my remote builder, which I’ve used on a few NixOS machines to allow building on my relatively beefy server.
Today I decided to set up my M1 Mac to allow remote builds on this machine so I could hopefully have an easier time running x86_64-linux-based tests on various PRs. (I’m setting up to use nixpkgs#darwin.builder as well.) programs.ssh doesn’t exist on nix-darwin, so I need to adapt my module to only include this part of the configuration on Linux hosts.
Unfortunately I’m again running into the dreaded “infinite recursion with config” issues, of which there are many threads and SO posts.
I thought I was getting pretty good at this problem, but none of my usual tricks are working:
- I initially tried
inherit (pkgs.stdenv) isLinux, and when it didn’t work read several threads aboutpkgsdepending onconfig, so obviously I can’t change usepkgswhile definingconfig. - A common suggestion (at least for the
pkgs.stdenv.isLinuxissues in home-manager) is makingisLinux ? falsea passed in argument from the parent config, but I still get infinite recursion (orattribute missingif I changeoptionalAttrstomkIf) - As a test, I tried removing the
${config.age.secrets...line, but still get infinite recursion - I really thought it would work if I just made it a configuration option, which is the version I’m including below, but I still get infinite recursion.
- Also tried swapping out
optionalAttrsformkIf, which then gets me back toerror: The option 'programs.ssh.extraConfig' does not exist.(even if I configure as false and set the default tofalse)
I’m sure there’s some fundamental concept I’m missing here. Why am I unable to configure this module based on the host OS?
{
pkgs,
config,
lib,
...
}: let
service_name = "use_builder";
cfg = config.services.${service_name};
in
with lib; {
options.services.${service_name} = {
enable = mkEnableOption service_name;
isLinux = mkOption {
type = types.bool;
description = "Is this a Linux machine?";
default = true;
};
};
config = mkIf cfg.enable (mkMerge [
{
age.secrets.builder_id_ed25519.file = ../secrets/builder_id_ed25519.age;
nix = {
buildMachines = [
{
hostName = "builder";
systems = ["aarch64-linux" "x86_64-linux"];
maxJobs = 12;
speedFactor = 2;
}
];
distributedBuilds = true;
};
}
(optionalAttrs cfg.isLinux {
programs.ssh.extraConfig = ''
Host builder
hostName myBuilderMachine.home.arpa
User builder
Port 2222
IdentityFile = ${config.age.secrets.builder_id_ed25519.path}
'';
})
]);
Happy to include the full trace if helpful, this is the abbreviated version:
at /nix/store/k90rk91pfcfl5cajsgi5pnvxkwfi77p1-source/lib/modules.nix:483:28:
482| builtins.addErrorContext (context name)
483| (args.${name} or config._module.args.${name})
| ^
484| ) (lib.functionArgs f);