{ config, lib, pkgs, ... }: let cfg = config.nix; nixPackage = cfg.package.out; commonNixDaemonConfig = { path = [ nixPackage config.programs.ssh.package ]; environment = cfg.envVars // { CURL_CA_BUNDLE = config.security.pki.caBundle; } // config.networking.proxy.envVars; serviceConfig = { CPUSchedulingPolicy = cfg.daemonCPUSchedPolicy; IOSchedulingClass = cfg.daemonIOSchedClass; IOSchedulingPriority = cfg.daemonIOSchedPriority; }; }; makeNixBuildUser = nr: { name = "nixbld${toString nr}"; value = { description = "Lix build user ${toString nr}"; uid = builtins.add config.ids.uids.nixbld nr; isSystemUser = true; group = "nixbld"; extraGroups = [ "nixbld" ]; }; }; nixbldUsers = lib.listToAttrs (map makeNixBuildUser (lib.range 1 cfg.nrBuildUsers)); in { config = lib.mkIf (cfg.enable && nixPackage.pname == "lix") { # Require the tun kernel module for pasta, can be disabled if pasta is not used. boot.kernelModules.tun = lib.mkDefault true; environment.systemPackages = [ nixPackage pkgs.nix-info ] ++ lib.optional (config.programs.bash.completion.enable) pkgs.nix-bash-completions; systemd.packages = [ nixPackage ]; systemd.tmpfiles.packages = [ nixPackage ]; systemd.sockets.nix-daemon.wantedBy = [ "sockets.target" ]; systemd.services."nix-daemon@" = lib.mkMerge [ commonNixDaemonConfig { # Do not kill connections serving established connections on upgrade. restartIfChanged = false; } ]; systemd.services.nix-daemon = lib.mkMerge [ commonNixDaemonConfig { restartTriggers = [ config.environment.etc."nix/nix.conf".source ]; # `stopIfChanged = false` changes to switch behavior # from stop -> update units -> start # to update units -> restart # # The `stopIfChanged` setting therefore controls a trade-off between a # more predictable lifecycle, which runs the correct "version" of # the `ExecStop` line, and on the other hand the availability of # sockets during the switch, as the effectiveness of the stop operation # depends on the socket being stopped as well. # # As `nix-daemon.service` does not make use of `ExecStop`, we prefer # to keep the socket up and available. This is important for machines # that run Nix-based services, such as automated build, test, and deploy # services, that expect the daemon socket to be available at all times. # # Notably, the Nix client does not retry on failure to connect to the # daemon socket, and the in-process RemoteStore instance will disable # itself. This makes retries infeasible even for services that are # aware of the issue. Failure to connect can affect not only new client # processes, but also new RemoteStore instances in existing processes, # as well as existing RemoteStore instances that have not saturated # their connection pool. # # Also note that `stopIfChanged = true` does not kill existing # connection handling daemons, as one might wish to happen before a # breaking Nix upgrade (which is rare). The daemon forks that handle # the individual connections split off into their own sessions, causing # them not to be stopped by systemd. # If a Nix upgrade does require all existing daemon processes to stop, # nix-daemon must do so on its own accord, and only when the new version # starts and detects that Nix's persistent state needs an upgrade. stopIfChanged = false; } ]; # Set up the environment variables for running Nix. environment.sessionVariables = cfg.envVars; nix.nrBuildUsers = lib.mkDefault ( if cfg.settings.auto-allocate-uids or false then 0 else lib.max 32 (if cfg.settings.max-jobs == "auto" then 0 else cfg.settings.max-jobs) ); users.users = nixbldUsers; services.displayManager.hiddenUsers = lib.attrNames nixbldUsers; # Legacy configuration conversion. nix.settings.sandbox-fallback = false; }; }