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