Loading nixos/modules/services/system/nix-daemon.nix +118 −2 Original line number Diff line number Diff line Loading @@ -62,6 +62,101 @@ in ]; }) (lib.mkRemovedOptionModule [ "nix" "daemonNiceLevel" ] "Consider nix.daemonCPUSchedPolicy instead.") { # Unprivileged Nix daemon config = lib.mkIf (cfg.daemonUser != "root") { assertions = [ { message = '' The Nix daemon cannot run as the root group when not running as the root user. ''; assertion = cfg.daemonGroup != "root"; } { message = '' Nix must have the `local-overlay-store` experimental feature when not running as the root user. ''; assertion = lib.elem "local-overlay-store" cfg.settings.experimental-features; } { message = '' Nix must have the `auto-allocate-uids` experimental feature when not running as the root user. ''; assertion = lib.elem "auto-allocate-uids" cfg.settings.experimental-features; } ]; nix.settings = { sandbox = true; auto-allocate-uids = true; # No such group would exist within the sandbox, so chowning to it would fail build-users-group = ""; # Default settings from Nix, we need to specify them here to use them in nix code though start-id = lib.mkDefault (832 * 1024 * 1024); id-count = lib.mkDefault (128 * 65536); }; systemd.services.nix-daemon = { # Nix assumes it should use `daemon` if it isn't root, so we have to set `NIX_REMOTE` anyway environment.NIX_REMOTE = "local?use-roots-daemon=true"; serviceConfig = { User = cfg.daemonUser; Group = cfg.daemonGroup; # Empty string needed to disable old Exec ExecStart = [ "" "${nixPackage}/libexec/nix-nswrapper ${toString cfg.settings.start-id} ${toString cfg.settings.id-count} ${nixPackage}/bin/nix-daemon --daemon" ]; }; }; # We can't remount rw while unprivileged boot.nixStoreMountOpts = [ "nodev" "nosuid" ]; users.users."${cfg.daemonUser}" = { subUidRanges = [ { startUid = cfg.settings.start-id; count = cfg.settings.id-count; } ]; subGidRanges = [ { startGid = cfg.settings.start-id; count = cfg.settings.id-count; } ]; }; systemd.tmpfiles.rules = [ "d /nix/store 0755 ${config.nix.daemonUser} ${config.nix.daemonGroup} - -" "Z /nix/var 0755 ${config.nix.daemonUser} ${config.nix.daemonGroup} - -" "d /nix/var/nix/builds 0755 ${config.nix.daemonUser} ${config.nix.daemonGroup} - 7d" "d /nix/var/nix/daemon-socket 0755 ${config.nix.daemonUser} ${config.nix.daemonGroup} - -" ]; systemd.services.nix-roots-daemon = { serviceConfig.ExecStart = "${config.nix.package.out}/bin/nix --extra-experimental-features nix-command store roots-daemon"; }; systemd.sockets.nix-roots-daemon = { wantedBy = [ "nix-daemon.service" ]; listenStreams = [ "/nix/var/nix/gc-roots-socket/socket" ]; unitConfig = { ConditionPathIsReadWrite = "/nix/var/nix/gc-roots-socket"; RequiresMountsFor = "/nix/store"; }; }; }; } ]; ###### interface Loading @@ -88,6 +183,24 @@ in ''; }; daemonUser = lib.mkOption { type = lib.types.str; default = "root"; description = '' User to use to run the Nix daemon. If this is not "root" then the Nix daemon will set several settings to preserve functionality. When setting this option, you must also set `nix.daemonGroup`. ''; }; daemonGroup = lib.mkOption { type = lib.types.str; default = "root"; description = '' Group to use to run the Nix daemon. ''; }; daemonCPUSchedPolicy = lib.mkOption { type = lib.types.enum [ "other" Loading Loading @@ -192,7 +305,8 @@ in systemd.packages = [ nixPackage ]; systemd.tmpfiles.packages = [ nixPackage ]; # The upstream Nix tmpfiles.d file assumes the daemon runs as root systemd.tmpfiles.packages = lib.mkIf (cfg.daemonUser == "root") [ nixPackage ]; systemd.sockets.nix-daemon.wantedBy = [ "sockets.target" ]; Loading @@ -200,7 +314,9 @@ in path = [ nixPackage config.programs.ssh.package ]; ] # For running "newuidmap" ++ lib.optional (cfg.daemonUser != "root") "/run/wrappers"; environment = cfg.envVars Loading Loading
nixos/modules/services/system/nix-daemon.nix +118 −2 Original line number Diff line number Diff line Loading @@ -62,6 +62,101 @@ in ]; }) (lib.mkRemovedOptionModule [ "nix" "daemonNiceLevel" ] "Consider nix.daemonCPUSchedPolicy instead.") { # Unprivileged Nix daemon config = lib.mkIf (cfg.daemonUser != "root") { assertions = [ { message = '' The Nix daemon cannot run as the root group when not running as the root user. ''; assertion = cfg.daemonGroup != "root"; } { message = '' Nix must have the `local-overlay-store` experimental feature when not running as the root user. ''; assertion = lib.elem "local-overlay-store" cfg.settings.experimental-features; } { message = '' Nix must have the `auto-allocate-uids` experimental feature when not running as the root user. ''; assertion = lib.elem "auto-allocate-uids" cfg.settings.experimental-features; } ]; nix.settings = { sandbox = true; auto-allocate-uids = true; # No such group would exist within the sandbox, so chowning to it would fail build-users-group = ""; # Default settings from Nix, we need to specify them here to use them in nix code though start-id = lib.mkDefault (832 * 1024 * 1024); id-count = lib.mkDefault (128 * 65536); }; systemd.services.nix-daemon = { # Nix assumes it should use `daemon` if it isn't root, so we have to set `NIX_REMOTE` anyway environment.NIX_REMOTE = "local?use-roots-daemon=true"; serviceConfig = { User = cfg.daemonUser; Group = cfg.daemonGroup; # Empty string needed to disable old Exec ExecStart = [ "" "${nixPackage}/libexec/nix-nswrapper ${toString cfg.settings.start-id} ${toString cfg.settings.id-count} ${nixPackage}/bin/nix-daemon --daemon" ]; }; }; # We can't remount rw while unprivileged boot.nixStoreMountOpts = [ "nodev" "nosuid" ]; users.users."${cfg.daemonUser}" = { subUidRanges = [ { startUid = cfg.settings.start-id; count = cfg.settings.id-count; } ]; subGidRanges = [ { startGid = cfg.settings.start-id; count = cfg.settings.id-count; } ]; }; systemd.tmpfiles.rules = [ "d /nix/store 0755 ${config.nix.daemonUser} ${config.nix.daemonGroup} - -" "Z /nix/var 0755 ${config.nix.daemonUser} ${config.nix.daemonGroup} - -" "d /nix/var/nix/builds 0755 ${config.nix.daemonUser} ${config.nix.daemonGroup} - 7d" "d /nix/var/nix/daemon-socket 0755 ${config.nix.daemonUser} ${config.nix.daemonGroup} - -" ]; systemd.services.nix-roots-daemon = { serviceConfig.ExecStart = "${config.nix.package.out}/bin/nix --extra-experimental-features nix-command store roots-daemon"; }; systemd.sockets.nix-roots-daemon = { wantedBy = [ "nix-daemon.service" ]; listenStreams = [ "/nix/var/nix/gc-roots-socket/socket" ]; unitConfig = { ConditionPathIsReadWrite = "/nix/var/nix/gc-roots-socket"; RequiresMountsFor = "/nix/store"; }; }; }; } ]; ###### interface Loading @@ -88,6 +183,24 @@ in ''; }; daemonUser = lib.mkOption { type = lib.types.str; default = "root"; description = '' User to use to run the Nix daemon. If this is not "root" then the Nix daemon will set several settings to preserve functionality. When setting this option, you must also set `nix.daemonGroup`. ''; }; daemonGroup = lib.mkOption { type = lib.types.str; default = "root"; description = '' Group to use to run the Nix daemon. ''; }; daemonCPUSchedPolicy = lib.mkOption { type = lib.types.enum [ "other" Loading Loading @@ -192,7 +305,8 @@ in systemd.packages = [ nixPackage ]; systemd.tmpfiles.packages = [ nixPackage ]; # The upstream Nix tmpfiles.d file assumes the daemon runs as root systemd.tmpfiles.packages = lib.mkIf (cfg.daemonUser == "root") [ nixPackage ]; systemd.sockets.nix-daemon.wantedBy = [ "sockets.target" ]; Loading @@ -200,7 +314,9 @@ in path = [ nixPackage config.programs.ssh.package ]; ] # For running "newuidmap" ++ lib.optional (cfg.daemonUser != "root") "/run/wrappers"; environment = cfg.envVars Loading