at master 24 kB view raw
1{ 2 lib, 3 options, 4 config, 5 utils, 6 pkgs, 7 ... 8}: 9 10with lib; 11 12let 13 inherit (utils) systemdUtils escapeSystemdPath; 14 inherit (systemdUtils.unitOptions) unitOption; 15 inherit (systemdUtils.lib) 16 generateUnits 17 pathToUnit 18 serviceToUnit 19 sliceToUnit 20 socketToUnit 21 targetToUnit 22 timerToUnit 23 mountToUnit 24 automountToUnit 25 attrsToSection 26 ; 27 28 cfg = config.boot.initrd.systemd; 29 30 upstreamUnits = [ 31 "basic.target" 32 "ctrl-alt-del.target" 33 "debug-shell.service" 34 "emergency.service" 35 "emergency.target" 36 "final.target" 37 "halt.target" 38 "initrd-cleanup.service" 39 "initrd-fs.target" 40 "initrd-parse-etc.service" 41 "initrd-root-device.target" 42 "initrd-root-fs.target" 43 "initrd-switch-root.service" 44 "initrd-switch-root.target" 45 "initrd.target" 46 "kexec.target" 47 "kmod-static-nodes.service" 48 "local-fs-pre.target" 49 "local-fs.target" 50 "modprobe@.service" 51 "multi-user.target" 52 "paths.target" 53 "poweroff.target" 54 "reboot.target" 55 "rescue.service" 56 "rescue.target" 57 "rpcbind.target" 58 "shutdown.target" 59 "sigpwr.target" 60 "slices.target" 61 "sockets.target" 62 "swap.target" 63 "sysinit.target" 64 "sys-kernel-config.mount" 65 "syslog.socket" 66 "systemd-ask-password-console.path" 67 "systemd-ask-password-console.service" 68 "systemd-fsck@.service" 69 "systemd-halt.service" 70 "systemd-hibernate-resume.service" 71 "systemd-journald-audit.socket" 72 "systemd-journald-dev-log.socket" 73 "systemd-journald.service" 74 "systemd-journald.socket" 75 "systemd-kexec.service" 76 "systemd-modules-load.service" 77 "systemd-poweroff.service" 78 "systemd-reboot.service" 79 "systemd-sysctl.service" 80 "timers.target" 81 "umount.target" 82 "systemd-bsod.service" 83 ] 84 ++ cfg.additionalUpstreamUnits; 85 86 upstreamWants = [ 87 "sysinit.target.wants" 88 ]; 89 90 enabledUpstreamUnits = filter (n: !elem n cfg.suppressedUnits) upstreamUnits; 91 enabledUnits = filterAttrs (n: v: !elem n cfg.suppressedUnits) cfg.units; 92 jobScripts = concatLists ( 93 mapAttrsToList (_: unit: unit.jobScripts or [ ]) (filterAttrs (_: v: v.enable) cfg.services) 94 ); 95 96 stage1Units = generateUnits { 97 type = "initrd"; 98 units = enabledUnits; 99 upstreamUnits = enabledUpstreamUnits; 100 inherit upstreamWants; 101 inherit (cfg) packages package; 102 }; 103 104 kernel-name = config.boot.kernelPackages.kernel.name or "kernel"; 105 106 initrdBinEnv = pkgs.buildEnv { 107 name = "initrd-bin-env"; 108 paths = map getBin cfg.initrdBin; 109 pathsToLink = [ 110 "/bin" 111 "/sbin" 112 ]; 113 114 # Make sure sbin and bin have the same contents, and add extraBin 115 postBuild = '' 116 find $out/bin -maxdepth 1 -type l -print0 | xargs --null cp --no-dereference --no-clobber -t $out/sbin/ 117 find $out/sbin -maxdepth 1 -type l -print0 | xargs --null cp --no-dereference --no-clobber -t $out/bin/ 118 ${concatStringsSep "\n" ( 119 mapAttrsToList (n: v: '' 120 ln -sf '${v}' $out/bin/'${n}' 121 ln -sf '${v}' $out/sbin/'${n}' 122 '') cfg.extraBin 123 )} 124 ''; 125 }; 126 127 initialRamdisk = pkgs.makeInitrdNG { 128 name = "initrd-${kernel-name}"; 129 inherit (config.boot.initrd) compressor compressorArgs prepend; 130 131 contents = lib.filter ( 132 { source, enable, ... }: (!lib.elem source cfg.suppressedStorePaths) && enable 133 ) cfg.storePaths; 134 }; 135 136in 137{ 138 imports = [ 139 (lib.mkRemovedOptionModule [ "boot" "initrd" "systemd" "strip" ] '' 140 The option to strip ELF files in initrd has been removed. 141 It only saved ~1MiB of initramfs size, but caused a few issues 142 like unloadable kernel modules. 143 '') 144 (lib.mkRemovedOptionModule [ 145 "boot" 146 "initrd" 147 "systemd" 148 "extraConfig" 149 ] "Use boot.initrd.systemd.settings.Manager instead.") 150 ]; 151 152 options.boot.initrd.systemd = { 153 enable = mkEnableOption "systemd in initrd" // { 154 description = '' 155 Whether to enable systemd in initrd. The unit options such as 156 {option}`boot.initrd.systemd.services` are the same as their 157 stage 2 counterparts such as {option}`systemd.services`, 158 except that `restartTriggers` and `reloadTriggers` are not 159 supported. 160 ''; 161 }; 162 163 package = lib.mkOption { 164 type = lib.types.package; 165 default = config.systemd.package; 166 defaultText = lib.literalExpression "config.systemd.package"; 167 description = '' 168 The systemd package to use. 169 ''; 170 }; 171 172 settings.Manager = mkOption { 173 default = { }; 174 defaultText = lib.literalExpression '' 175 { 176 DefaultEnvironment = "PATH=/bin:/sbin"; 177 } 178 ''; 179 type = lib.types.submodule { 180 freeformType = types.attrsOf unitOption; 181 }; 182 example = { 183 WatchdogDevice = "/dev/watchdog"; 184 RuntimeWatchdogSec = "30s"; 185 RebootWatchdogSec = "10min"; 186 KExecWatchdogSec = "5min"; 187 }; 188 description = '' 189 Options for the global systemd service manager used in initrd. See {manpage}`systemd-system.conf(5)` man page 190 for available options. 191 ''; 192 }; 193 194 managerEnvironment = mkOption { 195 type = 196 with types; 197 attrsOf ( 198 nullOr (oneOf [ 199 str 200 path 201 package 202 ]) 203 ); 204 default = { }; 205 defaultText = '' 206 { 207 PATH = "/bin:/sbin"; 208 } 209 ''; 210 example = { 211 SYSTEMD_LOG_LEVEL = "debug"; 212 }; 213 description = '' 214 Environment variables of PID 1. These variables are 215 *not* passed to started units. 216 ''; 217 }; 218 219 contents = mkOption { 220 description = "Set of files that have to be linked into the initrd"; 221 example = literalExpression '' 222 { 223 "/etc/machine-id".source = /etc/machine-id; 224 } 225 ''; 226 default = { }; 227 type = utils.systemdUtils.types.initrdContents; 228 }; 229 230 storePaths = mkOption { 231 description = '' 232 Store paths to copy into the initrd as well. 233 ''; 234 type = utils.systemdUtils.types.initrdStorePath; 235 default = [ ]; 236 }; 237 238 extraBin = mkOption { 239 description = '' 240 Tools to add to /bin 241 ''; 242 example = literalExpression '' 243 { 244 umount = ''${pkgs.util-linux}/bin/umount; 245 } 246 ''; 247 type = types.attrsOf types.path; 248 default = { }; 249 }; 250 251 suppressedStorePaths = mkOption { 252 description = '' 253 Store paths specified in the storePaths option that 254 should not be copied. 255 ''; 256 type = types.listOf types.singleLineStr; 257 default = [ ]; 258 }; 259 260 root = lib.mkOption { 261 type = lib.types.enum [ 262 "fstab" 263 "gpt-auto" 264 ]; 265 default = "fstab"; 266 example = "gpt-auto"; 267 description = '' 268 Controls how systemd will interpret the root FS in initrd. See 269 {manpage}`kernel-command-line(7)`. NixOS currently does not 270 allow specifying the root file system itself this 271 way. Instead, the `fstab` value is used in order to interpret 272 the root file system specified with the `fileSystems` option. 273 ''; 274 }; 275 276 emergencyAccess = mkOption { 277 type = 278 with types; 279 oneOf [ 280 bool 281 (nullOr (passwdEntry str)) 282 ]; 283 description = '' 284 Set to true for unauthenticated emergency access, and false or 285 null for no emergency access. 286 287 Can also be set to a hashed super user password to allow 288 authenticated access to the emergency mode. 289 290 For emergency access after initrd, use `${options.systemd.enableEmergencyMode}` instead. 291 ''; 292 default = false; 293 }; 294 295 initrdBin = mkOption { 296 type = types.listOf types.package; 297 default = [ ]; 298 description = '' 299 Packages to include in /bin for the stage 1 emergency shell. 300 ''; 301 }; 302 303 additionalUpstreamUnits = mkOption { 304 default = [ ]; 305 type = types.listOf types.str; 306 example = [ 307 "debug-shell.service" 308 "systemd-quotacheck.service" 309 ]; 310 description = '' 311 Additional units shipped with systemd that shall be enabled. 312 ''; 313 }; 314 315 suppressedUnits = mkOption { 316 default = [ ]; 317 type = types.listOf types.str; 318 example = [ "systemd-backlight@.service" ]; 319 description = '' 320 A list of units to skip when generating system systemd configuration directory. This has 321 priority over upstream units, {option}`boot.initrd.systemd.units`, and 322 {option}`boot.initrd.systemd.additionalUpstreamUnits`. The main purpose of this is to 323 prevent a upstream systemd unit from being added to the initrd with any modifications made to it 324 by other NixOS modules. 325 ''; 326 }; 327 328 units = mkOption { 329 description = "Definition of systemd units."; 330 default = { }; 331 visible = "shallow"; 332 type = systemdUtils.types.units; 333 }; 334 335 packages = mkOption { 336 default = [ ]; 337 type = types.listOf types.package; 338 example = literalExpression "[ pkgs.systemd-cryptsetup-generator ]"; 339 description = "Packages providing systemd units and hooks."; 340 }; 341 342 targets = mkOption { 343 default = { }; 344 visible = "shallow"; 345 type = systemdUtils.types.initrdTargets; 346 description = "Definition of systemd target units."; 347 }; 348 349 services = mkOption { 350 default = { }; 351 type = systemdUtils.types.initrdServices; 352 visible = "shallow"; 353 description = "Definition of systemd service units."; 354 }; 355 356 sockets = mkOption { 357 default = { }; 358 type = systemdUtils.types.initrdSockets; 359 visible = "shallow"; 360 description = "Definition of systemd socket units."; 361 }; 362 363 timers = mkOption { 364 default = { }; 365 type = systemdUtils.types.initrdTimers; 366 visible = "shallow"; 367 description = "Definition of systemd timer units."; 368 }; 369 370 paths = mkOption { 371 default = { }; 372 type = systemdUtils.types.initrdPaths; 373 visible = "shallow"; 374 description = "Definition of systemd path units."; 375 }; 376 377 mounts = mkOption { 378 default = [ ]; 379 type = systemdUtils.types.initrdMounts; 380 visible = "shallow"; 381 description = '' 382 Definition of systemd mount units. 383 This is a list instead of an attrSet, because systemd mandates the names to be derived from 384 the 'where' attribute. 385 ''; 386 }; 387 388 automounts = mkOption { 389 default = [ ]; 390 type = systemdUtils.types.automounts; 391 visible = "shallow"; 392 description = '' 393 Definition of systemd automount units. 394 This is a list instead of an attrSet, because systemd mandates the names to be derived from 395 the 'where' attribute. 396 ''; 397 }; 398 399 slices = mkOption { 400 default = { }; 401 type = systemdUtils.types.slices; 402 visible = "shallow"; 403 description = "Definition of slice configurations."; 404 }; 405 }; 406 407 config = mkIf (config.boot.initrd.enable && cfg.enable) { 408 assertions = [ 409 { 410 assertion = 411 cfg.root == "fstab" -> any (fs: fs.mountPoint == "/") (builtins.attrValues config.fileSystems); 412 message = "The fileSystems option does not specify your root file system."; 413 } 414 ] 415 ++ 416 map 417 (name: { 418 assertion = lib.attrByPath name (throw "impossible") config.boot.initrd == ""; 419 message = '' 420 systemd stage 1 does not support 'boot.initrd.${lib.concatStringsSep "." name}'. Please 421 convert it to analogous systemd units in 'boot.initrd.systemd'. 422 423 Definitions: 424 ${lib.concatMapStringsSep "\n" ({ file, ... }: " - ${file}") 425 (lib.attrByPath name (throw "impossible") options.boot.initrd).definitionsWithLocations 426 } 427 ''; 428 }) 429 [ 430 [ "preFailCommands" ] 431 [ "preDeviceCommands" ] 432 [ "preLVMCommands" ] 433 [ "postDeviceCommands" ] 434 [ "postResumeCommands" ] 435 [ "postMountCommands" ] 436 [ "extraUdevRulesCommands" ] 437 [ "extraUtilsCommands" ] 438 [ "extraUtilsCommandsTest" ] 439 [ 440 "network" 441 "postCommands" 442 ] 443 ]; 444 445 system.build = { inherit initialRamdisk; }; 446 447 boot.initrd.availableKernelModules = [ 448 # systemd needs this for some features 449 "autofs" 450 # systemd-cryptenroll 451 ] 452 ++ lib.optional cfg.package.withEfi "efivarfs"; 453 454 boot.kernelParams = [ 455 "root=${config.boot.initrd.systemd.root}" 456 ] 457 ++ lib.optional (config.boot.resumeDevice != "") "resume=${config.boot.resumeDevice}" 458 # `systemd` mounts root in initrd as read-only unless "rw" is on the kernel command line. 459 # For NixOS activation to succeed, we need to have root writable in initrd. 460 ++ lib.optional (config.boot.initrd.systemd.root == "gpt-auto") "rw"; 461 462 boot.initrd.systemd = { 463 # bashInteractive is easier to use and also required by debug-shell.service 464 initrdBin = [ 465 pkgs.bashInteractive 466 pkgs.coreutils 467 cfg.package 468 ] 469 ++ lib.optional (config.system.build.kernel.config.isYes "MODULES") cfg.package.kmod; 470 extraBin = { 471 less = "${pkgs.less}/bin/less"; 472 mount = "${cfg.package.util-linux}/bin/mount"; 473 umount = "${cfg.package.util-linux}/bin/umount"; 474 fsck = "${cfg.package.util-linux}/bin/fsck"; 475 }; 476 477 managerEnvironment.PATH = "/bin:/sbin"; 478 settings.Manager.ManagerEnvironment = lib.concatStringsSep " " ( 479 lib.mapAttrsToList (n: v: "${n}=${lib.escapeShellArg v}") cfg.managerEnvironment 480 ); 481 settings.Manager.DefaultEnvironment = "PATH=/bin:/sbin"; 482 483 contents = { 484 "/init".source = "${cfg.package}/lib/systemd/systemd"; 485 "/etc/systemd/system".source = stage1Units; 486 487 "/etc/systemd/system.conf".text = '' 488 [Manager] 489 ${attrsToSection cfg.settings.Manager} 490 ''; 491 492 # We can use either ! or * to lock the root account in the 493 # console, but some software like OpenSSH won't even allow you 494 # to log in with an SSH key if you use ! so we use * instead 495 "/etc/shadow".text = 496 let 497 ea = cfg.emergencyAccess; 498 access = ea != null && !(isBool ea && !ea); 499 passwd = if isString ea then ea else ""; 500 in 501 "root:${if access then passwd else "*"}:::::::"; 502 503 "/bin".source = "${initrdBinEnv}/bin"; 504 "/sbin".source = "${initrdBinEnv}/sbin"; 505 "/usr/bin".source = "${initrdBinEnv}/bin"; 506 "/usr/sbin".source = "${initrdBinEnv}/sbin"; 507 508 "/etc/os-release".source = config.boot.initrd.osRelease; 509 "/etc/initrd-release".source = config.boot.initrd.osRelease; 510 511 # For systemd-journald's _HOSTNAME field; needs to be set early, cannot be backfilled. 512 "/etc/hostname".text = config.networking.hostName; 513 514 } 515 // optionalAttrs (config.environment.etc ? "modprobe.d/nixos.conf") { 516 "/etc/modprobe.d/nixos.conf".source = config.environment.etc."modprobe.d/nixos.conf".source; 517 } 518 // optionalAttrs (with config.system.build.kernel.config; isSet "MODULES" -> isYes "MODULES") { 519 "/lib".source = "${config.system.build.modulesClosure}/lib"; 520 521 "/etc/modules-load.d/nixos.conf".text = concatStringsSep "\n" config.boot.initrd.kernelModules; 522 523 "/etc/sysctl.d/nixos.conf".text = "kernel.modprobe = /sbin/modprobe"; 524 "/etc/modprobe.d/systemd.conf".source = "${cfg.package}/lib/modprobe.d/systemd.conf"; 525 "/etc/modprobe.d/ubuntu.conf".source = "${pkgs.kmod-blacklist-ubuntu}/modprobe.conf"; 526 "/etc/modprobe.d/debian.conf".source = pkgs.kmod-debian-aliases; 527 }; 528 529 storePaths = [ 530 # systemd tooling 531 "${cfg.package}/lib/systemd/systemd-executor" 532 "${cfg.package}/lib/systemd/systemd-fsck" 533 "${cfg.package}/lib/systemd/systemd-hibernate-resume" 534 "${cfg.package}/lib/systemd/systemd-journald" 535 "${cfg.package}/lib/systemd/systemd-makefs" 536 "${cfg.package}/lib/systemd/systemd-modules-load" 537 "${cfg.package}/lib/systemd/systemd-remount-fs" 538 "${cfg.package}/lib/systemd/systemd-shutdown" 539 "${cfg.package}/lib/systemd/systemd-sulogin-shell" 540 "${cfg.package}/lib/systemd/systemd-sysctl" 541 "${cfg.package}/lib/systemd/systemd-bsod" 542 "${cfg.package}/lib/systemd/systemd-sysroot-fstab-check" 543 544 # generators 545 "${cfg.package}/lib/systemd/system-generators/systemd-debug-generator" 546 "${cfg.package}/lib/systemd/system-generators/systemd-fstab-generator" 547 "${cfg.package}/lib/systemd/system-generators/systemd-gpt-auto-generator" 548 "${cfg.package}/lib/systemd/system-generators/systemd-hibernate-resume-generator" 549 "${cfg.package}/lib/systemd/system-generators/systemd-run-generator" 550 551 # utilities needed by systemd 552 "${cfg.package.util-linux}/bin/mount" 553 "${cfg.package.util-linux}/bin/umount" 554 "${cfg.package.util-linux}/bin/sulogin" 555 556 # required for services generated with writeShellScript and friends 557 pkgs.runtimeShell 558 # some tools like xfs still want the sh symlink 559 "${pkgs.bashNonInteractive}/bin" 560 561 # so NSS can look up usernames 562 "${pkgs.glibc}/lib/libnss_files.so.2" 563 564 # Resolving sysroot symlinks without code exec 565 "${config.system.nixos-init.package}/bin/chroot-realpath" 566 # Find the etc paths 567 "${config.system.nixos-init.package}/bin/find-etc" 568 ] 569 ++ lib.optionals config.system.nixos-init.enable [ 570 "${config.system.nixos-init.package}/bin/initrd-init" 571 ] 572 ++ jobScripts 573 ++ map (c: builtins.removeAttrs c [ "text" ]) (builtins.attrValues cfg.contents); 574 575 targets.initrd.aliases = [ "default.target" ]; 576 units = 577 mapAttrs' (n: v: nameValuePair "${n}.path" (pathToUnit v)) cfg.paths 578 // mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit v)) cfg.services 579 // mapAttrs' (n: v: nameValuePair "${n}.slice" (sliceToUnit v)) cfg.slices 580 // mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit v)) cfg.sockets 581 // mapAttrs' (n: v: nameValuePair "${n}.target" (targetToUnit v)) cfg.targets 582 // mapAttrs' (n: v: nameValuePair "${n}.timer" (timerToUnit v)) cfg.timers 583 // listToAttrs ( 584 map ( 585 v: 586 let 587 n = escapeSystemdPath v.where; 588 in 589 nameValuePair "${n}.mount" (mountToUnit v) 590 ) cfg.mounts 591 ) 592 // listToAttrs ( 593 map ( 594 v: 595 let 596 n = escapeSystemdPath v.where; 597 in 598 nameValuePair "${n}.automount" (automountToUnit v) 599 ) cfg.automounts 600 ); 601 602 services.initrd-find-nixos-closure = lib.mkIf (!config.system.nixos-init.enable) { 603 description = "Find NixOS closure"; 604 605 unitConfig = { 606 RequiresMountsFor = "/sysroot/nix/store"; 607 DefaultDependencies = false; 608 }; 609 before = [ 610 "initrd.target" 611 "shutdown.target" 612 ]; 613 conflicts = [ "shutdown.target" ]; 614 requiredBy = [ "initrd.target" ]; 615 serviceConfig = { 616 Type = "oneshot"; 617 RemainAfterExit = true; 618 }; 619 620 script = # bash 621 '' 622 set -uo pipefail 623 export PATH="/bin:${ 624 lib.makeBinPath [ 625 cfg.package.util-linux 626 config.system.nixos-init.package 627 ] 628 }" 629 630 # Figure out what closure to boot 631 closure= 632 for o in $(< /proc/cmdline); do 633 case $o in 634 init=*) 635 IFS="=" read -r -a initParam <<< "$o" 636 closure="''${initParam[1]}" 637 ;; 638 esac 639 done 640 641 # Sanity check 642 if [ -z "''${closure:-}" ]; then 643 echo 'No init= parameter on the kernel command line' >&2 644 exit 1 645 fi 646 647 # Resolve symlinks in the init parameter. We need this for some boot loaders 648 # (e.g. boot.loader.generationsDir). 649 closure="$(chroot-realpath /sysroot "$closure")" 650 651 # Assume the directory containing the init script is the closure. 652 closure="$(dirname "$closure")" 653 654 ln --symbolic "$closure" /nixos-closure 655 656 # If we are not booting a NixOS closure (e.g. init=/bin/sh), 657 # we don't know what root to prepare so we don't do anything 658 if ! [ -x "/sysroot$(readlink "/sysroot$closure/prepare-root" || echo "$closure/prepare-root")" ]; then 659 echo "NEW_INIT=''${initParam[1]}" > /etc/switch-root.conf 660 echo "$closure does not look like a NixOS installation - not activating" 661 exit 0 662 fi 663 echo 'NEW_INIT=' > /etc/switch-root.conf 664 ''; 665 }; 666 667 # We need to propagate /run for things like /run/booted-system 668 # and /run/current-system. 669 mounts = [ 670 { 671 where = "/sysroot/run"; 672 what = "/run"; 673 options = "rbind"; 674 unitConfig = { 675 # See the comment on the mount unit for /run/etc-metadata 676 DefaultDependencies = false; 677 }; 678 requiredBy = [ "initrd-fs.target" ]; 679 before = [ "initrd-fs.target" ]; 680 } 681 ]; 682 683 services.initrd-nixos-activation = lib.mkIf (!config.system.nixos-init.enable) { 684 after = [ "initrd-switch-root.target" ]; 685 requiredBy = [ "initrd-switch-root.service" ]; 686 before = [ "initrd-switch-root.service" ]; 687 unitConfig.DefaultDependencies = false; 688 unitConfig = { 689 AssertPathExists = "/etc/initrd-release"; 690 RequiresMountsFor = [ 691 "/sysroot/run" 692 ]; 693 }; 694 serviceConfig.Type = "oneshot"; 695 description = "NixOS Activation"; 696 697 script = # bash 698 '' 699 set -uo pipefail 700 export PATH="/bin:${cfg.package.util-linux}/bin" 701 702 closure="$(realpath /nixos-closure)" 703 704 # Initialize the system 705 export IN_NIXOS_SYSTEMD_STAGE1=true 706 exec chroot /sysroot "$closure/prepare-root" 707 ''; 708 }; 709 710 services.initrd-switch-root = 711 if config.system.nixos-init.enable then 712 { 713 path = [ 714 cfg.package 715 cfg.package.util-linux 716 config.system.nixos-init.package 717 ]; 718 environment = { 719 FIRMWARE = "${config.hardware.firmware}/lib/firmware"; 720 MODPROBE_BINARY = "${pkgs.kmod}/bin/modprobe"; 721 NIX_STORE_MOUNT_OPTS = lib.concatStringsSep "," config.boot.nixStoreMountOpts; 722 } 723 // lib.optionalAttrs (config.environment.usrbinenv != null) { 724 ENV_BINARY = config.environment.usrbinenv; 725 } 726 // lib.optionalAttrs (config.environment.binsh != null) { 727 SH_BINARY = config.environment.binsh; 728 }; 729 serviceConfig = { 730 ExecStart = [ 731 "" 732 "${config.system.nixos-init.package}/bin/initrd-init" 733 ]; 734 }; 735 } 736 else 737 # This will either call systemctl with the new init as the last parameter (which 738 # is the case when not booting a NixOS system) or with an empty string, causing 739 # systemd to bypass its verification code that checks whether the next file is a systemd 740 # and using its compiled-in value 741 { 742 serviceConfig = { 743 EnvironmentFile = "-/etc/switch-root.conf"; 744 ExecStart = [ 745 "" 746 ''systemctl --no-block switch-root /sysroot "''${NEW_INIT}"'' 747 ]; 748 }; 749 }; 750 751 services.panic-on-fail = { 752 wantedBy = [ "emergency.target" ]; 753 unitConfig = { 754 DefaultDependencies = false; 755 ConditionKernelCommandLine = [ 756 "|boot.panic_on_fail" 757 "|stage1panic" 758 ]; 759 }; 760 serviceConfig = { 761 Type = "oneshot"; 762 ExecStart = "${pkgs.coreutils}/bin/echo c"; 763 StandardOutput = "file:/proc/sysrq-trigger"; 764 }; 765 }; 766 }; 767 }; 768}