at v192 24 kB view raw
1{ config, lib, pkgs, utils, ... }: 2 3with utils; 4with lib; 5with import ./systemd-unit-options.nix { inherit config lib; }; 6with import ./systemd-lib.nix { inherit config lib pkgs; }; 7 8let 9 10 cfg = config.systemd; 11 12 systemd = cfg.package; 13 14 upstreamSystemUnits = 15 [ # Targets. 16 "basic.target" 17 "sysinit.target" 18 "sockets.target" 19 "graphical.target" 20 "multi-user.target" 21 "network.target" 22 "network-pre.target" 23 "network-online.target" 24 "nss-lookup.target" 25 "nss-user-lookup.target" 26 "time-sync.target" 27 #"cryptsetup.target" 28 "sigpwr.target" 29 "timers.target" 30 "paths.target" 31 "rpcbind.target" 32 33 # Rescue mode. 34 "rescue.target" 35 "rescue.service" 36 37 # Udev. 38 "systemd-udevd-control.socket" 39 "systemd-udevd-kernel.socket" 40 "systemd-udevd.service" 41 "systemd-udev-settle.service" 42 "systemd-udev-trigger.service" 43 44 # Consoles. 45 "getty.target" 46 "getty@.service" 47 "serial-getty@.service" 48 "container-getty@.service" 49 "systemd-vconsole-setup.service" 50 51 # Hardware (started by udev when a relevant device is plugged in). 52 "sound.target" 53 "bluetooth.target" 54 "printer.target" 55 "smartcard.target" 56 57 # Login stuff. 58 "systemd-logind.service" 59 "autovt@.service" 60 #"systemd-vconsole-setup.service" 61 "systemd-user-sessions.service" 62 "dbus-org.freedesktop.login1.service" 63 "dbus-org.freedesktop.machine1.service" 64 "user@.service" 65 66 # Journal. 67 "systemd-journald.socket" 68 "systemd-journald.service" 69 "systemd-journal-flush.service" 70 "systemd-journal-gatewayd.socket" 71 "systemd-journal-gatewayd.service" 72 "systemd-journald-dev-log.socket" 73 "syslog.socket" 74 75 # SysV init compatibility. 76 "systemd-initctl.socket" 77 "systemd-initctl.service" 78 79 # Kernel module loading. 80 "systemd-modules-load.service" 81 "kmod-static-nodes.service" 82 83 # Filesystems. 84 "systemd-fsck@.service" 85 "systemd-fsck-root.service" 86 "systemd-remount-fs.service" 87 "local-fs.target" 88 "local-fs-pre.target" 89 "remote-fs.target" 90 "remote-fs-pre.target" 91 "swap.target" 92 "dev-hugepages.mount" 93 "dev-mqueue.mount" 94 "proc-sys-fs-binfmt_misc.mount" 95 "sys-fs-fuse-connections.mount" 96 "sys-kernel-config.mount" 97 "sys-kernel-debug.mount" 98 99 # Maintaining state across reboots. 100 "systemd-random-seed.service" 101 "systemd-backlight@.service" 102 "systemd-rfkill@.service" 103 104 # Hibernate / suspend. 105 "hibernate.target" 106 "suspend.target" 107 "sleep.target" 108 "hybrid-sleep.target" 109 "systemd-hibernate.service" 110 "systemd-suspend.service" 111 "systemd-hybrid-sleep.service" 112 "systemd-shutdownd.socket" 113 "systemd-shutdownd.service" 114 115 # Reboot stuff. 116 "reboot.target" 117 "systemd-reboot.service" 118 "poweroff.target" 119 "systemd-poweroff.service" 120 "halt.target" 121 "systemd-halt.service" 122 "ctrl-alt-del.target" 123 "shutdown.target" 124 "umount.target" 125 "final.target" 126 "kexec.target" 127 "systemd-kexec.service" 128 "systemd-update-utmp.service" 129 130 # Password entry. 131 "systemd-ask-password-console.path" 132 "systemd-ask-password-console.service" 133 "systemd-ask-password-wall.path" 134 "systemd-ask-password-wall.service" 135 136 # Slices / containers. 137 "slices.target" 138 "-.slice" 139 "system.slice" 140 "user.slice" 141 "machine.slice" 142 "systemd-machined.service" 143 144 # Temporary file creation / cleanup. 145 "systemd-tmpfiles-clean.service" 146 "systemd-tmpfiles-clean.timer" 147 "systemd-tmpfiles-setup.service" 148 "systemd-tmpfiles-setup-dev.service" 149 150 # Misc. 151 "systemd-sysctl.service" 152 ] 153 154 ++ cfg.additionalUpstreamSystemUnits; 155 156 upstreamSystemWants = 157 [ #"basic.target.wants" 158 "sysinit.target.wants" 159 "sockets.target.wants" 160 "local-fs.target.wants" 161 "multi-user.target.wants" 162 "timers.target.wants" 163 ]; 164 165 upstreamUserUnits = 166 [ "basic.target" 167 "default.target" 168 "exit.target" 169 "paths.target" 170 "shutdown.target" 171 "sockets.target" 172 "systemd-exit.service" 173 "timers.target" 174 ]; 175 176 makeJobScript = name: text: 177 let x = pkgs.writeTextFile { name = "unit-script"; executable = true; destination = "/bin/${shellEscape name}"; inherit text; }; 178 in "${x}/bin/${shellEscape name}"; 179 180 unitConfig = { name, config, ... }: { 181 config = { 182 unitConfig = 183 optionalAttrs (config.requires != []) 184 { Requires = toString config.requires; } 185 // optionalAttrs (config.wants != []) 186 { Wants = toString config.wants; } 187 // optionalAttrs (config.after != []) 188 { After = toString config.after; } 189 // optionalAttrs (config.before != []) 190 { Before = toString config.before; } 191 // optionalAttrs (config.bindsTo != []) 192 { BindsTo = toString config.bindsTo; } 193 // optionalAttrs (config.partOf != []) 194 { PartOf = toString config.partOf; } 195 // optionalAttrs (config.conflicts != []) 196 { Conflicts = toString config.conflicts; } 197 // optionalAttrs (config.requisite != []) 198 { Requisite = toString config.requisite; } 199 // optionalAttrs (config.restartTriggers != []) 200 { X-Restart-Triggers = toString config.restartTriggers; } 201 // optionalAttrs (config.description != "") { 202 Description = config.description; 203 }; 204 }; 205 }; 206 207 serviceConfig = { name, config, ... }: { 208 config = mkMerge 209 [ { # Default path for systemd services. Should be quite minimal. 210 path = 211 [ pkgs.coreutils 212 pkgs.findutils 213 pkgs.gnugrep 214 pkgs.gnused 215 systemd 216 ]; 217 environment.PATH = config.path; 218 } 219 (mkIf (config.preStart != "") 220 { serviceConfig.ExecStartPre = makeJobScript "${name}-pre-start" '' 221 #! ${pkgs.stdenv.shell} -e 222 ${config.preStart} 223 ''; 224 }) 225 (mkIf (config.script != "") 226 { serviceConfig.ExecStart = makeJobScript "${name}-start" '' 227 #! ${pkgs.stdenv.shell} -e 228 ${config.script} 229 '' + " " + config.scriptArgs; 230 }) 231 (mkIf (config.postStart != "") 232 { serviceConfig.ExecStartPost = makeJobScript "${name}-post-start" '' 233 #! ${pkgs.stdenv.shell} -e 234 ${config.postStart} 235 ''; 236 }) 237 (mkIf (config.reload != "") 238 { serviceConfig.ExecReload = makeJobScript "${name}-reload" '' 239 #! ${pkgs.stdenv.shell} -e 240 ${config.reload} 241 ''; 242 }) 243 (mkIf (config.preStop != "") 244 { serviceConfig.ExecStop = makeJobScript "${name}-pre-stop" '' 245 #! ${pkgs.stdenv.shell} -e 246 ${config.preStop} 247 ''; 248 }) 249 (mkIf (config.postStop != "") 250 { serviceConfig.ExecStopPost = makeJobScript "${name}-post-stop" '' 251 #! ${pkgs.stdenv.shell} -e 252 ${config.postStop} 253 ''; 254 }) 255 ]; 256 }; 257 258 mountConfig = { name, config, ... }: { 259 config = { 260 mountConfig = 261 { What = config.what; 262 Where = config.where; 263 } // optionalAttrs (config.type != "") { 264 Type = config.type; 265 } // optionalAttrs (config.options != "") { 266 Options = config.options; 267 }; 268 }; 269 }; 270 271 automountConfig = { name, config, ... }: { 272 config = { 273 automountConfig = 274 { Where = config.where; 275 }; 276 }; 277 }; 278 279 commonUnitText = def: '' 280 [Unit] 281 ${attrsToSection def.unitConfig} 282 ''; 283 284 targetToUnit = name: def: 285 { inherit (def) wantedBy requiredBy enable; 286 text = 287 '' 288 [Unit] 289 ${attrsToSection def.unitConfig} 290 ''; 291 }; 292 293 serviceToUnit = name: def: 294 { inherit (def) wantedBy requiredBy enable; 295 text = commonUnitText def + 296 '' 297 [Service] 298 ${let env = cfg.globalEnvironment // def.environment; 299 in concatMapStrings (n: 300 let s = optionalString (env."${n}" != null) 301 "Environment=\"${n}=${env.${n}}\"\n"; 302 in if stringLength s >= 2048 then throw "The value of the environment variable ${n} in systemd service ${name}.service is too long." else s) (attrNames env)} 303 ${if def.reloadIfChanged then '' 304 X-ReloadIfChanged=true 305 '' else if !def.restartIfChanged then '' 306 X-RestartIfChanged=false 307 '' else ""} 308 ${optionalString (!def.stopIfChanged) "X-StopIfChanged=false"} 309 ${attrsToSection def.serviceConfig} 310 ''; 311 }; 312 313 socketToUnit = name: def: 314 { inherit (def) wantedBy requiredBy enable; 315 text = commonUnitText def + 316 '' 317 [Socket] 318 ${attrsToSection def.socketConfig} 319 ${concatStringsSep "\n" (map (s: "ListenStream=${s}") def.listenStreams)} 320 ''; 321 }; 322 323 timerToUnit = name: def: 324 { inherit (def) wantedBy requiredBy enable; 325 text = commonUnitText def + 326 '' 327 [Timer] 328 ${attrsToSection def.timerConfig} 329 ''; 330 }; 331 332 pathToUnit = name: def: 333 { inherit (def) wantedBy requiredBy enable; 334 text = commonUnitText def + 335 '' 336 [Path] 337 ${attrsToSection def.pathConfig} 338 ''; 339 }; 340 341 mountToUnit = name: def: 342 { inherit (def) wantedBy requiredBy enable; 343 text = commonUnitText def + 344 '' 345 [Mount] 346 ${attrsToSection def.mountConfig} 347 ''; 348 }; 349 350 automountToUnit = name: def: 351 { inherit (def) wantedBy requiredBy enable; 352 text = commonUnitText def + 353 '' 354 [Automount] 355 ${attrsToSection def.automountConfig} 356 ''; 357 }; 358 359in 360 361{ 362 363 ###### interface 364 365 options = { 366 367 systemd.package = mkOption { 368 default = pkgs.systemd; 369 type = types.package; 370 description = "The systemd package."; 371 }; 372 373 systemd.units = mkOption { 374 description = "Definition of systemd units."; 375 default = {}; 376 type = types.attrsOf types.optionSet; 377 options = { name, config, ... }: 378 { options = concreteUnitOptions; 379 config = { 380 unit = mkDefault (makeUnit name config); 381 }; 382 }; 383 }; 384 385 systemd.packages = mkOption { 386 default = []; 387 type = types.listOf types.package; 388 description = "Packages providing systemd units."; 389 }; 390 391 systemd.targets = mkOption { 392 default = {}; 393 type = types.attrsOf types.optionSet; 394 options = [ targetOptions unitConfig ]; 395 description = "Definition of systemd target units."; 396 }; 397 398 systemd.services = mkOption { 399 default = {}; 400 type = types.attrsOf types.optionSet; 401 options = [ serviceOptions unitConfig serviceConfig ]; 402 description = "Definition of systemd service units."; 403 }; 404 405 systemd.sockets = mkOption { 406 default = {}; 407 type = types.attrsOf types.optionSet; 408 options = [ socketOptions unitConfig ]; 409 description = "Definition of systemd socket units."; 410 }; 411 412 systemd.timers = mkOption { 413 default = {}; 414 type = types.attrsOf types.optionSet; 415 options = [ timerOptions unitConfig ]; 416 description = "Definition of systemd timer units."; 417 }; 418 419 systemd.paths = mkOption { 420 default = {}; 421 type = types.attrsOf types.optionSet; 422 options = [ pathOptions unitConfig ]; 423 description = "Definition of systemd path units."; 424 }; 425 426 systemd.mounts = mkOption { 427 default = []; 428 type = types.listOf types.optionSet; 429 options = [ mountOptions unitConfig mountConfig ]; 430 description = '' 431 Definition of systemd mount units. 432 This is a list instead of an attrSet, because systemd mandates the names to be derived from 433 the 'where' attribute. 434 ''; 435 }; 436 437 systemd.automounts = mkOption { 438 default = []; 439 type = types.listOf types.optionSet; 440 options = [ automountOptions unitConfig automountConfig ]; 441 description = '' 442 Definition of systemd automount units. 443 This is a list instead of an attrSet, because systemd mandates the names to be derived from 444 the 'where' attribute. 445 ''; 446 }; 447 448 systemd.defaultUnit = mkOption { 449 default = "multi-user.target"; 450 type = types.str; 451 description = "Default unit started when the system boots."; 452 }; 453 454 systemd.globalEnvironment = mkOption { 455 type = types.attrs; 456 default = {}; 457 example = { TZ = "CET"; }; 458 description = '' 459 Environment variables passed to <emphasis>all</emphasis> systemd units. 460 ''; 461 }; 462 463 systemd.extraConfig = mkOption { 464 default = ""; 465 type = types.lines; 466 example = "DefaultLimitCORE=infinity"; 467 description = '' 468 Extra config options for systemd. See man systemd-system.conf for 469 available options. 470 ''; 471 }; 472 473 services.journald.console = mkOption { 474 default = ""; 475 type = types.str; 476 description = "If non-empty, write log messages to the specified TTY device."; 477 }; 478 479 services.journald.rateLimitInterval = mkOption { 480 default = "10s"; 481 type = types.str; 482 description = '' 483 Configures the rate limiting interval that is applied to all 484 messages generated on the system. This rate limiting is applied 485 per-service, so that two services which log do not interfere with 486 each other's limit. The value may be specified in the following 487 units: s, min, h, ms, us. To turn off any kind of rate limiting, 488 set either value to 0. 489 ''; 490 }; 491 492 services.journald.rateLimitBurst = mkOption { 493 default = 100; 494 type = types.int; 495 description = '' 496 Configures the rate limiting burst limit (number of messages per 497 interval) that is applied to all messages generated on the system. 498 This rate limiting is applied per-service, so that two services 499 which log do not interfere with each other's limit. 500 ''; 501 }; 502 503 services.journald.extraConfig = mkOption { 504 default = ""; 505 type = types.lines; 506 example = "Storage=volatile"; 507 description = '' 508 Extra config options for systemd-journald. See man journald.conf 509 for available options. 510 ''; 511 }; 512 513 services.journald.enableHttpGateway = mkOption { 514 default = false; 515 type = types.bool; 516 description = '' 517 Whether to enable the HTTP gateway to the journal. 518 ''; 519 }; 520 521 services.logind.extraConfig = mkOption { 522 default = ""; 523 type = types.lines; 524 example = "HandleLidSwitch=ignore"; 525 description = '' 526 Extra config options for systemd-logind. See man logind.conf for 527 available options. 528 ''; 529 }; 530 531 systemd.tmpfiles.rules = mkOption { 532 type = types.listOf types.str; 533 default = []; 534 example = [ "d /tmp 1777 root root 10d" ]; 535 description = '' 536 Rules for creating and cleaning up temporary files 537 automatically. See 538 <citerefentry><refentrytitle>tmpfiles.d</refentrytitle><manvolnum>5</manvolnum></citerefentry> 539 for the exact format. You should not use this option to create 540 files required by systemd services, since there is no 541 guarantee that <command>systemd-tmpfiles</command> runs when 542 the system is reconfigured using 543 <command>nixos-rebuild</command>. 544 ''; 545 }; 546 547 systemd.user.units = mkOption { 548 description = "Definition of systemd per-user units."; 549 default = {}; 550 type = types.attrsOf types.optionSet; 551 options = { name, config, ... }: 552 { options = concreteUnitOptions; 553 config = { 554 unit = mkDefault (makeUnit name config); 555 }; 556 }; 557 }; 558 559 systemd.user.services = mkOption { 560 default = {}; 561 type = types.attrsOf types.optionSet; 562 options = [ serviceOptions unitConfig serviceConfig ]; 563 description = "Definition of systemd per-user service units."; 564 }; 565 566 systemd.user.timers = mkOption { 567 default = {}; 568 type = types.attrsOf types.optionSet; 569 options = [ timerOptions unitConfig ]; 570 description = "Definition of systemd per-user timer units."; 571 }; 572 573 systemd.user.sockets = mkOption { 574 default = {}; 575 type = types.attrsOf types.optionSet; 576 options = [ socketOptions unitConfig ]; 577 description = "Definition of systemd per-user socket units."; 578 }; 579 580 systemd.additionalUpstreamSystemUnits = mkOption { 581 default = [ ]; 582 type = types.listOf types.str; 583 example = [ "debug-shell.service" "systemd-quotacheck.service" ]; 584 description = '' 585 Additional units shipped with systemd that shall be enabled. 586 ''; 587 }; 588 589 }; 590 591 592 ###### implementation 593 594 config = { 595 596 warnings = concatLists (mapAttrsToList (name: service: 597 optional (service.serviceConfig.Type or "" == "oneshot" && service.serviceConfig.Restart or "no" != "no") 598 "Service ${name}.service with Type=oneshot must have Restart=no") cfg.services); 599 600 system.build.units = cfg.units; 601 602 environment.systemPackages = [ systemd ]; 603 604 environment.etc."systemd/system".source = 605 generateUnits "system" cfg.units upstreamSystemUnits upstreamSystemWants; 606 607 environment.etc."systemd/user".source = 608 generateUnits "user" cfg.user.units upstreamUserUnits []; 609 610 environment.etc."systemd/system.conf".text = 611 '' 612 [Manager] 613 ${config.systemd.extraConfig} 614 ''; 615 616 environment.etc."systemd/journald.conf".text = 617 '' 618 [Journal] 619 RateLimitInterval=${config.services.journald.rateLimitInterval} 620 RateLimitBurst=${toString config.services.journald.rateLimitBurst} 621 ${optionalString (config.services.journald.console != "") '' 622 ForwardToConsole=yes 623 TTYPath=${config.services.journald.console} 624 ''} 625 ${config.services.journald.extraConfig} 626 ''; 627 628 environment.etc."systemd/logind.conf".text = 629 '' 630 [Login] 631 ${config.services.logind.extraConfig} 632 ''; 633 634 environment.etc."systemd/sleep.conf".text = 635 '' 636 [Sleep] 637 ''; 638 639 system.activationScripts.systemd = stringAfter [ "groups" ] 640 '' 641 mkdir -m 0755 -p /var/lib/udev 642 643 if ! [ -e /etc/machine-id ]; then 644 ${systemd}/bin/systemd-machine-id-setup 645 fi 646 647 # Keep a persistent journal. Note that systemd-tmpfiles will 648 # set proper ownership/permissions. 649 mkdir -m 0700 -p /var/log/journal 650 ''; 651 652 users.extraUsers.systemd-network.uid = config.ids.uids.systemd-network; 653 users.extraGroups.systemd-network.gid = config.ids.gids.systemd-network; 654 users.extraUsers.systemd-resolve.uid = config.ids.uids.systemd-resolve; 655 users.extraGroups.systemd-resolve.gid = config.ids.gids.systemd-resolve; 656 657 # Target for ‘charon send-keys’ to hook into. 658 users.extraGroups.keys.gid = config.ids.gids.keys; 659 660 systemd.targets.keys = 661 { description = "Security Keys"; 662 unitConfig.X-StopOnReconfiguration = true; 663 }; 664 665 systemd.targets.network-online.after = [ "ip-up.target" ]; 666 667 systemd.targets.network-pre = { 668 wantedBy = [ "network.target" ]; 669 before = [ "network.target" ]; 670 }; 671 672 systemd.targets.remote-fs-pre = { 673 wantedBy = [ "remote-fs.target" ]; 674 before = [ "remote-fs.target" ]; 675 }; 676 677 systemd.units = 678 mapAttrs' (n: v: nameValuePair "${n}.target" (targetToUnit n v)) cfg.targets 679 // mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.services 680 // mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit n v)) cfg.sockets 681 // mapAttrs' (n: v: nameValuePair "${n}.timer" (timerToUnit n v)) cfg.timers 682 // mapAttrs' (n: v: nameValuePair "${n}.path" (pathToUnit n v)) cfg.paths 683 // listToAttrs (map 684 (v: let n = escapeSystemdPath v.where; 685 in nameValuePair "${n}.mount" (mountToUnit n v)) cfg.mounts) 686 // listToAttrs (map 687 (v: let n = escapeSystemdPath v.where; 688 in nameValuePair "${n}.automount" (automountToUnit n v)) cfg.automounts); 689 690 systemd.user.units = 691 mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.user.services 692 // mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit n v)) cfg.user.sockets 693 // mapAttrs' (n: v: nameValuePair "${n}.timer" (timerToUnit n v)) cfg.user.timers; 694 695 system.requiredKernelConfig = map config.lib.kernelConfig.isEnabled 696 [ "DEVTMPFS" "CGROUPS" "INOTIFY_USER" "SIGNALFD" "TIMERFD" "EPOLL" "NET" 697 "SYSFS" "PROC_FS" "FHANDLE" "DMIID" "AUTOFS4_FS" "TMPFS_POSIX_ACL" 698 "TMPFS_XATTR" "SECCOMP" 699 ]; 700 701 environment.shellAliases = 702 { start = "systemctl start"; 703 stop = "systemctl stop"; 704 restart = "systemctl restart"; 705 status = "systemctl status"; 706 }; 707 708 users.extraGroups.systemd-journal.gid = config.ids.gids.systemd-journal; 709 users.extraUsers.systemd-journal-gateway.uid = config.ids.uids.systemd-journal-gateway; 710 users.extraGroups.systemd-journal-gateway.gid = config.ids.gids.systemd-journal-gateway; 711 712 # Generate timer units for all services that have a ‘startAt’ value. 713 systemd.timers = 714 mapAttrs (name: service: 715 { wantedBy = [ "timers.target" ]; 716 timerConfig.OnCalendar = service.startAt; 717 }) 718 (filterAttrs (name: service: service.startAt != "") cfg.services); 719 720 # Generate timer units for all services that have a ‘startAt’ value. 721 systemd.user.timers = 722 mapAttrs (name: service: 723 { wantedBy = [ "timers.target" ]; 724 timerConfig.OnCalendar = service.startAt; 725 }) 726 (filterAttrs (name: service: service.startAt != "") cfg.user.services); 727 728 systemd.sockets.systemd-journal-gatewayd.wantedBy = 729 optional config.services.journald.enableHttpGateway "sockets.target"; 730 731 # Provide the systemd-user PAM service, required to run systemd 732 # user instances. 733 security.pam.services.systemd-user = 734 { # Ensure that pam_systemd gets included. This is special-cased 735 # in systemd to provide XDG_RUNTIME_DIR. 736 startSession = true; 737 }; 738 739 environment.etc."tmpfiles.d/systemd.conf".source = "${systemd}/example/tmpfiles.d/systemd.conf"; 740 environment.etc."tmpfiles.d/x11.conf".source = "${systemd}/example/tmpfiles.d/x11.conf"; 741 742 environment.etc."tmpfiles.d/nixos.conf".text = 743 '' 744 # This file is created automatically and should not be modified. 745 # Please change the option systemd.tmpfiles.rules instead. 746 747 ${concatStringsSep "\n" cfg.tmpfiles.rules} 748 ''; 749 750 # Some overrides to upstream units. 751 systemd.services."systemd-backlight@".restartIfChanged = false; 752 systemd.services."systemd-rfkill@".restartIfChanged = false; 753 systemd.services."user@".restartIfChanged = false; 754 systemd.services.systemd-journal-flush.restartIfChanged = false; 755 systemd.services.systemd-journald.restartIfChanged = false; # FIXME: shouldn't be necessary with systemd 219 756 systemd.services.systemd-random-seed.restartIfChanged = false; 757 systemd.services.systemd-remount-fs.restartIfChanged = false; 758 systemd.services.systemd-update-utmp.restartIfChanged = false; 759 systemd.services.systemd-user-sessions.restartIfChanged = false; # Restart kills all active sessions. 760 systemd.targets.local-fs.unitConfig.X-StopOnReconfiguration = true; 761 systemd.targets.remote-fs.unitConfig.X-StopOnReconfiguration = true; 762 763 # Don't bother with certain units in containers. 764 systemd.services.systemd-remount-fs.unitConfig.ConditionVirtualization = "!container"; 765 systemd.services.systemd-random-seed.unitConfig.ConditionVirtualization = "!container"; 766 767 }; 768 769}