1{
2 config,
3 lib,
4 pkgs,
5 utils,
6 ...
7}:
8
9with utils;
10with systemdUtils.unitOptions;
11with lib;
12
13let
14
15 cfg = config.systemd;
16
17 inherit (systemdUtils.lib)
18 generateUnits
19 targetToUnit
20 serviceToUnit
21 socketToUnit
22 timerToUnit
23 pathToUnit
24 mountToUnit
25 automountToUnit
26 sliceToUnit
27 attrsToSection
28 ;
29
30 upstreamSystemUnits = [
31 # Targets.
32 "basic.target"
33 "sysinit.target"
34 "sockets.target"
35 "exit.target"
36 "graphical.target"
37 "multi-user.target"
38 "network.target"
39 "network-pre.target"
40 "network-online.target"
41 "nss-lookup.target"
42 "nss-user-lookup.target"
43 "time-sync.target"
44 "first-boot-complete.target"
45 ]
46 ++ optionals cfg.package.withCryptsetup [
47 "cryptsetup.target"
48 "cryptsetup-pre.target"
49 "remote-cryptsetup.target"
50 ]
51 ++ [
52 "sigpwr.target"
53 "timers.target"
54 "paths.target"
55 "rpcbind.target"
56
57 # Rescue mode.
58 "rescue.target"
59 "rescue.service"
60
61 # systemd-debug-generator
62 "debug-shell.service"
63
64 # Udev.
65 "systemd-udevd-control.socket"
66 "systemd-udevd-kernel.socket"
67 "systemd-udevd.service"
68 "systemd-udev-settle.service"
69 ]
70 ++ (optional (!config.boot.isContainer) "systemd-udev-trigger.service")
71 ++ [
72 # hwdb.bin is managed by NixOS
73 # "systemd-hwdb-update.service"
74
75 # Hardware (started by udev when a relevant device is plugged in).
76 "sound.target"
77 "bluetooth.target"
78 "printer.target"
79 "smartcard.target"
80
81 # Kernel module loading.
82 "systemd-modules-load.service"
83 "kmod-static-nodes.service"
84 "modprobe@.service"
85
86 # Filesystems.
87 "systemd-fsck@.service"
88 "systemd-fsck-root.service"
89 "systemd-growfs@.service"
90 "systemd-growfs-root.service"
91 "systemd-remount-fs.service"
92 "systemd-pstore.service"
93 "local-fs.target"
94 "local-fs-pre.target"
95 "remote-fs.target"
96 "remote-fs-pre.target"
97 "swap.target"
98 "dev-hugepages.mount"
99 "dev-mqueue.mount"
100 "sys-fs-fuse-connections.mount"
101 ]
102 ++ (optional (!config.boot.isContainer) "sys-kernel-config.mount")
103 ++ [
104 "sys-kernel-debug.mount"
105 "sys-kernel-tracing.mount"
106
107 # Maintaining state across reboots.
108 "systemd-random-seed.service"
109 ]
110 ++ optionals cfg.package.withBootloader [
111 "systemd-boot-random-seed.service"
112 "systemd-bless-boot.service"
113 ]
114 ++ [
115 "systemd-backlight@.service"
116 "systemd-rfkill.service"
117 "systemd-rfkill.socket"
118
119 "boot-complete.target"
120
121 # Hibernate / suspend.
122 "hibernate.target"
123 "suspend.target"
124 "suspend-then-hibernate.target"
125 "sleep.target"
126 "hybrid-sleep.target"
127 "systemd-hibernate.service"
128 ]
129 ++ (lib.optional cfg.package.withEfi "systemd-hibernate-clear.service")
130 ++ [
131 "systemd-hybrid-sleep.service"
132 "systemd-suspend.service"
133 "systemd-suspend-then-hibernate.service"
134
135 # Reboot stuff.
136 "reboot.target"
137 "systemd-reboot.service"
138 "poweroff.target"
139 "systemd-poweroff.service"
140 "halt.target"
141 "systemd-halt.service"
142 "shutdown.target"
143 "umount.target"
144 "final.target"
145 "kexec.target"
146 "systemd-kexec.service"
147 ]
148 ++ lib.optional cfg.package.withUtmp "systemd-update-utmp.service"
149 ++ [
150
151 # Password entry.
152 "systemd-ask-password-console.path"
153 "systemd-ask-password-console.service"
154 "systemd-ask-password-wall.path"
155 "systemd-ask-password-wall.service"
156
157 # Varlink APIs
158 ]
159 ++ lib.optionals cfg.package.withBootloader [
160 "systemd-bootctl@.service"
161 "systemd-bootctl.socket"
162 ]
163 ++ [
164 "systemd-creds@.service"
165 "systemd-creds.socket"
166 ]
167 ++ lib.optional cfg.package.withTpm2Units [
168 "systemd-pcrlock@.service"
169 "systemd-pcrlock.socket"
170 ]
171 ++ [
172
173 # Slices / containers.
174 "slices.target"
175 ]
176 ++ optionals cfg.package.withImportd [
177 "systemd-importd.service"
178 ]
179 ++ optionals cfg.package.withMachined [
180 "machine.slice"
181 "machines.target"
182 "systemd-machined.service"
183 ]
184 ++ [
185 "systemd-nspawn@.service"
186
187 # Misc.
188 "systemd-sysctl.service"
189 "systemd-machine-id-commit.service"
190 ]
191 ++ optionals cfg.package.withTimedated [
192 "dbus-org.freedesktop.timedate1.service"
193 "systemd-timedated.service"
194 ]
195 ++ optionals cfg.package.withLocaled [
196 "dbus-org.freedesktop.locale1.service"
197 "systemd-localed.service"
198 ]
199 ++ optionals cfg.package.withHostnamed [
200 "dbus-org.freedesktop.hostname1.service"
201 "systemd-hostnamed.service"
202 "systemd-hostnamed.socket"
203 ]
204 ++ optionals cfg.package.withPortabled [
205 "dbus-org.freedesktop.portable1.service"
206 "systemd-portabled.service"
207 ]
208 ++ [
209 "systemd-exit.service"
210 "systemd-update-done.service"
211
212 # Capsule support
213 "capsule@.service"
214 "capsule.slice"
215 ]
216 ++ cfg.additionalUpstreamSystemUnits;
217
218 upstreamSystemWants = [
219 "sysinit.target.wants"
220 "sockets.target.wants"
221 "local-fs.target.wants"
222 "multi-user.target.wants"
223 "timers.target.wants"
224 ];
225
226 proxy_env = config.networking.proxy.envVars;
227
228in
229
230{
231 ###### interface
232
233 options.systemd = {
234
235 package = mkPackageOption pkgs "systemd" { };
236
237 enableStrictShellChecks = mkEnableOption "" // {
238 description = ''
239 Whether to run `shellcheck` on the generated scripts for systemd
240 units.
241
242 When enabled, all systemd scripts generated by NixOS will be checked
243 with `shellcheck` and any errors or warnings will cause the build to
244 fail.
245
246 This affects all scripts that have been created through the `script`,
247 `reload`, `preStart`, `postStart`, `preStop` and `postStop` options for
248 systemd services. This does not affect command lines passed directly
249 to `ExecStart`, `ExecReload`, `ExecStartPre`, `ExecStartPost`,
250 `ExecStop` or `ExecStopPost`.
251
252 It therefore also does not affect systemd units that are coming from
253 packages and that are not defined through the NixOS config. This option
254 is disabled by default, and although some services have already been
255 fixed, it is still likely that you will encounter build failures when
256 enabling this.
257
258 We encourage people to enable this option when they are willing and
259 able to submit fixes for potential build failures to Nixpkgs. The
260 option can also be enabled or disabled for individual services using
261 the `enableStrictShellChecks` option on the service itself, which will
262 take precedence over the global setting.
263 '';
264 };
265
266 units = mkOption {
267 description = "Definition of systemd units; see {manpage}`systemd.unit(5)`.";
268 default = { };
269 type = systemdUtils.types.units;
270 };
271
272 packages = mkOption {
273 default = [ ];
274 type = types.listOf types.package;
275 example = literalExpression "[ pkgs.systemd-cryptsetup-generator ]";
276 description = "Packages providing systemd units and hooks.";
277 };
278
279 targets = mkOption {
280 default = { };
281 type = systemdUtils.types.targets;
282 description = "Definition of systemd target units; see {manpage}`systemd.target(5)`";
283 };
284
285 services = mkOption {
286 default = { };
287 type = systemdUtils.types.services;
288 description = "Definition of systemd service units; see {manpage}`systemd.service(5)`.";
289 };
290
291 sockets = mkOption {
292 default = { };
293 type = systemdUtils.types.sockets;
294 description = "Definition of systemd socket units; see {manpage}`systemd.socket(5)`.";
295 };
296
297 timers = mkOption {
298 default = { };
299 type = systemdUtils.types.timers;
300 description = "Definition of systemd timer units; see {manpage}`systemd.timer(5)`.";
301 };
302
303 paths = mkOption {
304 default = { };
305 type = systemdUtils.types.paths;
306 description = "Definition of systemd path units; see {manpage}`systemd.path(5)`.";
307 };
308
309 mounts = mkOption {
310 default = [ ];
311 type = systemdUtils.types.mounts;
312 description = ''
313 Definition of systemd mount units; see {manpage}`systemd.mount(5)`.
314
315 This is a list instead of an attrSet, because systemd mandates
316 the names to be derived from the `where` attribute.
317 '';
318 };
319
320 automounts = mkOption {
321 default = [ ];
322 type = systemdUtils.types.automounts;
323 description = ''
324 Definition of systemd automount units; see {manpage}`systemd.automount(5)`.
325
326 This is a list instead of an attrSet, because systemd mandates
327 the names to be derived from the `where` attribute.
328 '';
329 };
330
331 slices = mkOption {
332 default = { };
333 type = systemdUtils.types.slices;
334 description = "Definition of slice configurations; see {manpage}`systemd.slice(5)`.";
335 };
336
337 generators = mkOption {
338 type = types.attrsOf types.path;
339 default = { };
340 example = {
341 systemd-gpt-auto-generator = "/dev/null";
342 };
343 description = ''
344 Definition of systemd generators; see {manpage}`systemd.generator(5)`.
345
346 For each `NAME = VALUE` pair of the attrSet, a link is generated from
347 `/etc/systemd/system-generators/NAME` to `VALUE`.
348 '';
349 };
350
351 shutdown = mkOption {
352 type = types.attrsOf types.path;
353 default = { };
354 description = ''
355 Definition of systemd shutdown executables.
356 For each `NAME = VALUE` pair of the attrSet, a link is generated from
357 `/etc/systemd/system-shutdown/NAME` to `VALUE`.
358 '';
359 };
360
361 defaultUnit = mkOption {
362 default = "multi-user.target";
363 type = types.str;
364 description = ''
365 Default unit started when the system boots; see {manpage}`systemd.special(7)`.
366 '';
367 };
368
369 ctrlAltDelUnit = mkOption {
370 default = "reboot.target";
371 type = types.str;
372 example = "poweroff.target";
373 description = ''
374 Target that should be started when Ctrl-Alt-Delete is pressed;
375 see {manpage}`systemd.special(7)`.
376 '';
377 };
378
379 globalEnvironment = mkOption {
380 type =
381 with types;
382 attrsOf (
383 nullOr (oneOf [
384 str
385 path
386 package
387 ])
388 );
389 default = { };
390 example = {
391 TZ = "CET";
392 };
393 description = ''
394 Environment variables passed to *all* systemd units.
395 '';
396 };
397
398 managerEnvironment = mkOption {
399 type =
400 with types;
401 attrsOf (
402 nullOr (oneOf [
403 str
404 path
405 package
406 ])
407 );
408 default = { };
409 example = {
410 SYSTEMD_LOG_LEVEL = "debug";
411 };
412 description = ''
413 Environment variables of PID 1. These variables are
414 *not* passed to started units.
415 '';
416 };
417
418 settings.Manager = mkOption {
419 default = { };
420 defaultText = lib.literalExpression ''
421 {
422 DefaultIOAccounting = true;
423 DefaultIPAccounting = true;
424 }
425 '';
426 type = lib.types.submodule {
427 freeformType = types.attrsOf unitOption;
428 };
429 example = {
430 WatchdogDevice = "/dev/watchdog";
431 RuntimeWatchdogSec = "30s";
432 RebootWatchdogSec = "10min";
433 KExecWatchdogSec = "5min";
434 };
435 description = ''
436 Options for the global systemd service manager. See {manpage}`systemd-system.conf(5)` man page
437 for available options.
438 '';
439 };
440
441 sleep.extraConfig = mkOption {
442 default = "";
443 type = types.lines;
444 example = "HibernateDelaySec=1h";
445 description = ''
446 Extra config options for systemd sleep state logic.
447 See {manpage}`sleep.conf.d(5)` man page for available options.
448 '';
449 };
450
451 additionalUpstreamSystemUnits = mkOption {
452 default = [ ];
453 type = types.listOf types.str;
454 example = [
455 "debug-shell.service"
456 "systemd-quotacheck.service"
457 ];
458 description = ''
459 Additional units shipped with systemd that shall be enabled.
460 '';
461 };
462
463 suppressedSystemUnits = mkOption {
464 default = [ ];
465 type = types.listOf types.str;
466 example = [ "systemd-backlight@.service" ];
467 description = ''
468 A list of units to skip when generating system systemd configuration directory. This has
469 priority over upstream units, {option}`systemd.units`, and
470 {option}`systemd.additionalUpstreamSystemUnits`. The main purpose of this is to
471 prevent a upstream systemd unit from being added to the initrd with any modifications made to it
472 by other NixOS modules.
473 '';
474 };
475 };
476
477 ###### implementation
478
479 config = {
480
481 warnings =
482 let
483 mkOneNetOnlineWarn =
484 typeStr: name: def:
485 lib.optional (
486 lib.elem "network-online.target" def.after
487 && !(lib.elem "network-online.target" (def.wants ++ def.requires ++ def.bindsTo))
488 ) "${name}.${typeStr} is ordered after 'network-online.target' but doesn't depend on it";
489 mkNetOnlineWarns =
490 typeStr: defs: lib.concatLists (lib.mapAttrsToList (mkOneNetOnlineWarn typeStr) defs);
491 mkMountNetOnlineWarns =
492 typeStr: defs: lib.concatLists (map (m: mkOneNetOnlineWarn typeStr m.what m) defs);
493 in
494 concatLists (
495 mapAttrsToList (
496 name: service:
497 let
498 type = service.serviceConfig.Type or "";
499 restart = service.serviceConfig.Restart or "no";
500 hasDeprecated = builtins.hasAttr "StartLimitInterval" service.serviceConfig;
501 in
502 concatLists [
503 (optional (type == "oneshot" && (restart == "always" || restart == "on-success"))
504 "Service '${name}.service' with 'Type=oneshot' cannot have 'Restart=always' or 'Restart=on-success'"
505 )
506 (optional hasDeprecated "Service '${name}.service' uses the attribute 'StartLimitInterval' in the Service section, which is deprecated. See https://github.com/NixOS/nixpkgs/issues/45786.")
507 (optional (service.reloadIfChanged && service.reloadTriggers != [ ])
508 "Service '${name}.service' has both 'reloadIfChanged' and 'reloadTriggers' set. This is probably not what you want, because 'reloadTriggers' behave the same whay as 'restartTriggers' if 'reloadIfChanged' is set."
509 )
510 ]
511 ) cfg.services
512 )
513 ++ (mkNetOnlineWarns "target" cfg.targets)
514 ++ (mkNetOnlineWarns "service" cfg.services)
515 ++ (mkNetOnlineWarns "socket" cfg.sockets)
516 ++ (mkNetOnlineWarns "timer" cfg.timers)
517 ++ (mkNetOnlineWarns "path" cfg.paths)
518 ++ (mkMountNetOnlineWarns "mount" cfg.mounts)
519 ++ (mkMountNetOnlineWarns "automount" cfg.automounts)
520 ++ (mkNetOnlineWarns "slice" cfg.slices);
521
522 assertions = concatLists (
523 mapAttrsToList (
524 name: service:
525 map
526 (message: {
527 assertion = false;
528 inherit message;
529 })
530 (concatLists [
531 (optional
532 (
533 (builtins.elem "network-interfaces.target" service.after)
534 || (builtins.elem "network-interfaces.target" service.wants)
535 )
536 "Service '${name}.service' is using the deprecated target network-interfaces.target, which no longer exists. Using network.target is recommended instead."
537 )
538 ])
539 ) cfg.services
540 );
541
542 system.build.units = cfg.units;
543
544 system.nssModules = [ cfg.package.out ];
545 system.nssDatabases = {
546 hosts = (
547 mkMerge [
548 (mkOrder 400 [ "mymachines" ]) # 400 to ensure it comes before resolve (which is 501)
549 (mkOrder 999 [ "myhostname" ]) # after files (which is 998), but before regular nss modules
550 ]
551 );
552 passwd = (
553 mkMerge [
554 (mkAfter [ "systemd" ])
555 ]
556 );
557 group = (
558 mkMerge [
559 (mkAfter [ "[success=merge] systemd" ]) # need merge so that NSS won't stop at file-based groups
560 ]
561 );
562 shadow = (
563 mkMerge [
564 (mkAfter [ "systemd" ])
565 ]
566 );
567 };
568
569 environment.systemPackages = [ cfg.package ];
570
571 environment.etc =
572 let
573 # generate contents for /etc/systemd/${dir} from attrset of links and packages
574 hooks =
575 dir: links:
576 pkgs.runCommand "${dir}"
577 {
578 preferLocalBuild = true;
579 packages = cfg.packages;
580 }
581 ''
582 set -e
583 mkdir -p $out
584 for package in $packages
585 do
586 for hook in $package/lib/systemd/${dir}/*
587 do
588 ln -s $hook $out/
589 done
590 done
591 ${concatStrings (mapAttrsToList (exec: target: "ln -s ${target} $out/${exec};\n") links)}
592 '';
593
594 enabledUpstreamSystemUnits = filter (n: !elem n cfg.suppressedSystemUnits) upstreamSystemUnits;
595 enabledUnits = filterAttrs (n: v: !elem n cfg.suppressedSystemUnits) cfg.units;
596
597 in
598 ({
599 "systemd/system".source = generateUnits {
600 type = "system";
601 units = enabledUnits;
602 upstreamUnits = enabledUpstreamSystemUnits;
603 upstreamWants = upstreamSystemWants;
604 };
605
606 "systemd/system.conf".text = ''
607 [Manager]
608 ${attrsToSection cfg.settings.Manager}
609 '';
610
611 "systemd/sleep.conf".text = ''
612 [Sleep]
613 ${cfg.sleep.extraConfig}
614 '';
615
616 "systemd/user-generators" = {
617 source = hooks "user-generators" cfg.user.generators;
618 };
619 "systemd/system-generators" = {
620 source = hooks "system-generators" cfg.generators;
621 };
622 "systemd/system-shutdown" = {
623 source = hooks "system-shutdown" cfg.shutdown;
624 };
625
626 # Ignore all other preset files so systemd doesn't try to enable/disable
627 # units during runtime.
628 "systemd/system-preset/00-nixos.preset".text = ''
629 ignore *
630 '';
631 "systemd/user-preset/00-nixos.preset".text = ''
632 ignore *
633 '';
634 });
635
636 services.dbus.enable = true;
637
638 users.users.systemd-network = {
639 uid = config.ids.uids.systemd-network;
640 group = "systemd-network";
641 };
642 users.groups.systemd-network.gid = config.ids.gids.systemd-network;
643 users.users.systemd-resolve = {
644 uid = config.ids.uids.systemd-resolve;
645 group = "systemd-resolve";
646 };
647 users.groups.systemd-resolve.gid = config.ids.gids.systemd-resolve;
648
649 # Target for ‘charon send-keys’ to hook into.
650 users.groups.keys.gid = config.ids.gids.keys;
651
652 systemd.targets.keys = {
653 description = "Security Keys";
654 unitConfig.X-StopOnReconfiguration = true;
655 };
656
657 # This target only exists so that services ordered before sysinit.target
658 # are restarted in the correct order, notably BEFORE the other services,
659 # when switching configurations.
660 systemd.targets.sysinit-reactivation = {
661 description = "Reactivate sysinit units";
662 };
663
664 systemd.units =
665 let
666 withName = cfgToUnit: cfg: lib.nameValuePair cfg.name (cfgToUnit cfg);
667 in
668 mapAttrs' (_: withName pathToUnit) cfg.paths
669 // mapAttrs' (_: withName serviceToUnit) cfg.services
670 // mapAttrs' (_: withName sliceToUnit) cfg.slices
671 // mapAttrs' (_: withName socketToUnit) cfg.sockets
672 // mapAttrs' (_: withName targetToUnit) cfg.targets
673 // mapAttrs' (_: withName timerToUnit) cfg.timers
674 // listToAttrs (map (withName mountToUnit) cfg.mounts)
675 // listToAttrs (map (withName automountToUnit) cfg.automounts);
676
677 # Environment of PID 1
678 systemd.managerEnvironment = {
679 # Doesn't contain systemd itself - everything works so it seems to use the compiled-in value for its tools
680 # util-linux is needed for the main fsck utility wrapping the fs-specific ones
681 PATH = lib.makeBinPath (
682 config.system.fsPackages
683 ++ [ cfg.package.util-linux ]
684 # systemd-ssh-generator needs sshd in PATH
685 ++ lib.optional config.services.openssh.enable config.services.openssh.package
686 );
687 LOCALE_ARCHIVE = "/run/current-system/sw/lib/locale/locale-archive";
688 TZDIR = "/etc/zoneinfo";
689 # If SYSTEMD_UNIT_PATH ends with an empty component (":"), the usual unit load path will be appended to the contents of the variable
690 SYSTEMD_UNIT_PATH = lib.mkIf (
691 config.boot.extraSystemdUnitPaths != [ ]
692 ) "${builtins.concatStringsSep ":" config.boot.extraSystemdUnitPaths}:";
693 };
694 systemd.settings.Manager = {
695 ManagerEnvironment = lib.concatStringsSep " " (
696 lib.mapAttrsToList (n: v: "${n}=${lib.escapeShellArg v}") cfg.managerEnvironment
697 );
698 DefaultIOAccounting = lib.mkDefault true;
699 DefaultIPAccounting = lib.mkDefault true;
700 };
701
702 system.requiredKernelConfig = map config.lib.kernelConfig.isEnabled [
703 "DEVTMPFS"
704 "CGROUPS"
705 "INOTIFY_USER"
706 "SIGNALFD"
707 "TIMERFD"
708 "EPOLL"
709 "NET"
710 "SYSFS"
711 "PROC_FS"
712 "FHANDLE"
713 "CRYPTO_USER_API_HASH"
714 "CRYPTO_HMAC"
715 "CRYPTO_SHA256"
716 "DMIID"
717 "AUTOFS_FS"
718 "TMPFS_POSIX_ACL"
719 "TMPFS_XATTR"
720 "SECCOMP"
721 ];
722
723 # Generate timer units for all services that have a ‘startAt’ value.
724 systemd.timers = mapAttrs (name: service: {
725 wantedBy = [ "timers.target" ];
726 timerConfig.OnCalendar = service.startAt;
727 }) (filterAttrs (name: service: service.enable && service.startAt != [ ]) cfg.services);
728
729 # Some overrides to upstream units.
730 systemd.services."systemd-backlight@".restartIfChanged = false;
731 systemd.services."systemd-fsck@".restartIfChanged = false;
732 systemd.services."systemd-fsck@".path = [ pkgs.util-linux ] ++ config.system.fsPackages;
733 systemd.services."systemd-makefs@" = {
734 restartIfChanged = false;
735 path = [ pkgs.util-linux ] ++ config.system.fsPackages;
736 # Since there is no /etc/systemd/system/systemd-makefs@.service
737 # file, the units generated in /run/systemd/generator would
738 # override anything we put here. But by forcing the use of a
739 # drop-in in /etc, it does apply.
740 overrideStrategy = "asDropin";
741 };
742 systemd.services."systemd-mkswap@" = {
743 restartIfChanged = false;
744 path = [ pkgs.util-linux ];
745 overrideStrategy = "asDropin";
746 };
747 systemd.services.systemd-random-seed.restartIfChanged = false;
748 systemd.services.systemd-remount-fs.restartIfChanged = false;
749 systemd.services.systemd-update-utmp.restartIfChanged = false;
750 systemd.services.systemd-udev-settle.restartIfChanged = false; # Causes long delays in nixos-rebuild
751 systemd.targets.local-fs.unitConfig.X-StopOnReconfiguration = true;
752 systemd.targets.remote-fs.unitConfig.X-StopOnReconfiguration = true;
753 systemd.services.systemd-importd.environment = proxy_env;
754 systemd.services.systemd-pstore.wantedBy = [ "sysinit.target" ]; # see #81138
755
756 # NixOS has kernel modules in a different location, so override that here.
757 systemd.services.kmod-static-nodes.unitConfig.ConditionFileNotEmpty = [
758 "" # required to unset the previous value!
759 "/run/booted-system/kernel-modules/lib/modules/%v/modules.devname"
760 ];
761
762 # Don't bother with certain units in containers.
763 systemd.services.systemd-remount-fs.unitConfig.ConditionVirtualization = "!container";
764
765 # Increase numeric PID range (set directly instead of copying a one-line file from systemd)
766 # https://github.com/systemd/systemd/pull/12226
767 boot.kernel.sysctl."kernel.pid_max" = mkIf pkgs.stdenv.hostPlatform.is64bit (lib.mkDefault 4194304);
768
769 services.logrotate.settings = {
770 "/var/log/btmp" = mapAttrs (_: mkDefault) {
771 frequency = "monthly";
772 rotate = 1;
773 create = "0660 root ${config.users.groups.utmp.name}";
774 minsize = "1M";
775 };
776 "/var/log/wtmp" = mapAttrs (_: mkDefault) {
777 frequency = "monthly";
778 rotate = 1;
779 create = "0664 root ${config.users.groups.utmp.name}";
780 minsize = "1M";
781 };
782 };
783
784 # run0 is supposed to authenticate the user via polkit and then run a command. Without this next
785 # part, run0 would fail to run the command even if authentication is successful and the user has
786 # permission to run the command. This next part is only enabled if polkit is enabled because the
787 # error that we’re trying to avoid can’t possibly happen if polkit isn’t enabled. When polkit isn’t
788 # enabled, run0 will fail before it even tries to run the command.
789 security.pam.services = mkIf config.security.polkit.enable {
790 systemd-run0 = {
791 # Upstream config: https://github.com/systemd/systemd/blob/main/src/run/systemd-run0.in
792 setLoginUid = true;
793 pamMount = false;
794 };
795 };
796 };
797
798 # FIXME: Remove these eventually.
799 imports = [
800 (mkRenamedOptionModule [ "boot" "systemd" "sockets" ] [ "systemd" "sockets" ])
801 (mkRenamedOptionModule [ "boot" "systemd" "targets" ] [ "systemd" "targets" ])
802 (mkRenamedOptionModule [ "boot" "systemd" "services" ] [ "systemd" "services" ])
803 (mkRenamedOptionModule [ "jobs" ] [ "systemd" "services" ])
804 (mkRemovedOptionModule [ "systemd" "generator-packages" ] "Use systemd.packages instead.")
805 (mkRemovedOptionModule [ "systemd" "enableUnifiedCgroupHierarchy" ] ''
806 In 256 support for cgroup v1 ('legacy' and 'hybrid' hierarchies) is now considered obsolete and systemd by default will refuse to boot under it.
807 To forcibly reenable cgroup v1 support, you can set boot.kernelParams = [ "systemd.unified_cgroup_hierarchy=0" "SYSTEMD_CGROUP_ENABLE_LEGACY_FORCE=1" ].
808 NixOS does not officially support this configuration and might cause your system to be unbootable in future versions. You are on your own.
809 '')
810 (mkRemovedOptionModule [ "systemd" "extraConfig" ] "Use systemd.settings.Manager instead.")
811 (lib.mkRenamedOptionModule
812 [ "systemd" "watchdog" "device" ]
813 [ "systemd" "settings" "Manager" "WatchdogDevice" ]
814 )
815 (lib.mkRenamedOptionModule
816 [ "systemd" "watchdog" "runtimeTime" ]
817 [ "systemd" "settings" "Manager" "RuntimeWatchdogSec" ]
818 )
819 (lib.mkRenamedOptionModule
820 [ "systemd" "watchdog" "rebootTime" ]
821 [ "systemd" "settings" "Manager" "RebootWatchdogSec" ]
822 )
823 (lib.mkRenamedOptionModule
824 [ "systemd" "watchdog" "kexecTime" ]
825 [ "systemd" "settings" "Manager" "KExecWatchdogSec" ]
826 )
827 (mkRemovedOptionModule [
828 "systemd"
829 "enableCgroupAccounting"
830 ] "To disable cgroup accounting, disable systemd.settings.Manager.*Accounting directly.")
831 ];
832}