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