From 5620d245adf03c58b74f803031ba2a85d204db31 Mon Sep 17 00:00:00 2001 From: Will Fancher Date: Fri, 15 Aug 2025 15:43:01 -0400 Subject: [PATCH] nixos/systemd-stage-1: Enable by default --- .../administration/boot-problems.section.md | 84 ++++++++++++------- .../installing-from-other-distro.section.md | 9 +- nixos/doc/manual/redirects.json | 3 + .../manual/release-notes/rl-2605.section.md | 10 +++ nixos/modules/system/boot/stage-1.nix | 4 + nixos/modules/system/boot/systemd/initrd.nix | 84 +++++++++++-------- nixos/release-combined.nix | 20 +++++ 7 files changed, 143 insertions(+), 71 deletions(-) diff --git a/nixos/doc/manual/administration/boot-problems.section.md b/nixos/doc/manual/administration/boot-problems.section.md index bca4fdc3fb38..357c6e5ea0ef 100644 --- a/nixos/doc/manual/administration/boot-problems.section.md +++ b/nixos/doc/manual/administration/boot-problems.section.md @@ -1,41 +1,61 @@ # Boot Problems {#sec-boot-problems} -If NixOS fails to boot, there are a number of kernel command line parameters that may help you to identify or fix the issue. You can add these parameters in the GRUB boot menu by pressing “e” to modify the selected boot entry and editing the line starting with `linux`. The following are some useful kernel command line parameters that are recognised by the NixOS boot scripts or by systemd: +If NixOS fails to boot, there are a number of kernel command line parameters that may help you to identify or fix the issue. You can add these parameters in the GRUB boot menu by pressing “e” to modify the selected boot entry and editing the line starting with `linux`. -`boot.shell_on_fail` - -: Allows the user to start a root shell if something goes wrong in stage 1 of the boot process (the initial ramdisk). This is disabled by default because there is no authentication for the root shell. - -`boot.debug1` - -: Start an interactive shell in stage 1 before anything useful has been done. That is, no modules have been loaded and no file systems have been mounted, except for `/proc` and `/sys`. - -`boot.debug1devices` - -: Like `boot.debug1`, but runs stage1 until kernel modules are loaded and device nodes are created. This may help with e.g. making the keyboard work. - -`boot.debug1mounts` - -: Like `boot.debug1` or `boot.debug1devices`, but runs stage1 until all filesystems that are mounted during initrd are mounted (see [neededForBoot](#opt-fileSystems._name_.neededForBoot)). As a motivating example, this could be useful if you've forgotten to set [neededForBoot](#opt-fileSystems._name_.neededForBoot) on a file system. - -`boot.trace` - -: Print every shell command executed by the stage 1 and 2 boot scripts. - -`single` - -: Boot into rescue mode (a.k.a. single user mode). This will cause systemd to start nothing but the unit `rescue.target`, which runs `sulogin` to prompt for the root password and start a root login shell. Exiting the shell causes the system to continue with the normal boot process. - -`systemd.log_level=debug` `systemd.log_target=console` - -: Make systemd very verbose and send log messages to the console instead of the journal. For more parameters recognised by systemd, see systemd(1). - -In addition, these arguments are recognised by the live image only: +{manpage}`kernel-command-line(7)` documents the kernel parameters accepted by systemd. Those include many that are helpful for debugging boot issues, such as `systemd.debug_shell` and `rescue`. Some also have `rd.`‐prefixed variants that apply to stage 1. `live.nixos.passwd=password` : Set the password for the `nixos` live user. This can be used for SSH access if there are issues using the terminal. -Notice that for `boot.shell_on_fail`, `boot.debug1`, `boot.debug1devices`, and `boot.debug1mounts`, if you did **not** select "start the new shell as pid 1", and you `exit` from the new shell, boot will proceed normally from the point where it failed, as if you'd chosen "ignore the error and continue". +If no login prompts or X11 login screens appear (e.g. due to hanging dependencies), you can press Alt+ArrowUp. If you’re lucky, this will start `rescue.target` (described in {manpage}`systemd.special(7)`). (Also note that since most units have a 90-second timeout before systemd gives up on them, the `agetty` login prompts should appear eventually unless something is very wrong.) -If no login prompts or X11 login screens appear (e.g. due to hanging dependencies), you can press Alt+ArrowUp. If you’re lucky, this will start rescue mode (described above). (Also note that since most units have a 90-second timeout before systemd gives up on them, the `agetty` login prompts should appear eventually unless something is very wrong.) +## Scripted stage 1 {#sec-boot-problems-scripted-stage-1} + +The scripted implementation of stage 1 also understands these boot parameters. + +::: {.warning} +The scripted implementation of stage 1 is disabled by default and deprecated. These parameters have no effect, unless systemd stage 1 is explicitly disabled with `boot.initrd.systemd.enable = false;`. +::: + +`boot.shell_on_fail` + +: Allows the user to start a root shell if something goes wrong in stage 1 of the boot process (the initial ramdisk). This is disabled by default because there is no authentication for the root shell. + + ::: {.note} + systemd stage 1 alternative: `SYSTEMD_SULOGIN_FORCE=1` for rescue mode, or `rd.systemd.debug_shell` for shell on tty9. + ::: + +`boot.debug1` + +: Start an interactive shell in stage 1 before anything useful has been done. That is, no modules have been loaded and no file systems have been mounted, except for `/proc` and `/sys`. + + ::: {.note} + systemd stage 1 alternative: `rd.systemd.break=pre-udev` + ::: + +`boot.debug1devices` + +: Like `boot.debug1`, but runs stage1 until kernel modules are loaded and device nodes are created. This may help with e.g. making the keyboard work. + + ::: {.note} + systemd stage 1 alternative: `rd.systemd.break=pre-mount` + ::: + +`boot.debug1mounts` + +: Like `boot.debug1` or `boot.debug1devices`, but runs stage1 until all filesystems that are mounted during initrd are mounted (see [neededForBoot](#opt-fileSystems._name_.neededForBoot)). As a motivating example, this could be useful if you've forgotten to set [neededForBoot](#opt-fileSystems._name_.neededForBoot) on a file system. + + ::: {.note} + systemd stage 1 alternative: `rd.systemd.break=pre-switch-root` + ::: + +`boot.trace` + +: Print every shell command executed by the stage 1 and 2 boot scripts. + + ::: {.note} + systemd stage 1 alternative: `rd.systemd.log_level=debug` + ::: + +Notice that for `boot.shell_on_fail`, `boot.debug1`, `boot.debug1devices`, and `boot.debug1mounts`, if you did **not** select "start the new shell as pid 1", and you `exit` from the new shell, boot will proceed normally from the point where it failed, as if you'd chosen "ignore the error and continue". diff --git a/nixos/doc/manual/installation/installing-from-other-distro.section.md b/nixos/doc/manual/installation/installing-from-other-distro.section.md index 56b1cca00e05..2b9d3171264a 100644 --- a/nixos/doc/manual/installation/installing-from-other-distro.section.md +++ b/nixos/doc/manual/installation/installing-from-other-distro.section.md @@ -149,6 +149,10 @@ The first steps to all these are the same: `NIXOS_LUSTRATE`: ::: + ::: {.warning} + The lustrate process will not work if the [](#opt-boot.initrd.systemd.enable) option is set to `true`, which is now the default. Setting this to `false` is deprecated and scheduled for removal in NixOS 26.11, along with `NIXOS_LUSTRATE`. Other installation methods, such as the one outlined above, or installing from [kexec](#sec-booting-via-kexec), are recommended instead. + ::: + Generate your NixOS configuration: ```ShellSession @@ -167,11 +171,6 @@ The first steps to all these are the same: If the current system and NixOS's bootloader configuration don't agree on where the [EFI System Partition](https://en.wikipedia.org/wiki/EFI_system_partition) is to be mounted, you'll need to manually alter the mount point in `hardware-configuration.nix` before building the system closure. ::: - ::: {.note} - The lustrate process will not work if the [](#opt-boot.initrd.systemd.enable) option is set to `true`. - If you want to use this option, wait until after the first boot into the NixOS system to enable it and rebuild. - ::: - You'll likely want to set a root password for your first boot using the configuration files because you won't have a chance to enter a password until after you reboot. You can initialize the root password diff --git a/nixos/doc/manual/redirects.json b/nixos/doc/manual/redirects.json index 7bf88472148e..feb535c2142c 100644 --- a/nixos/doc/manual/redirects.json +++ b/nixos/doc/manual/redirects.json @@ -151,6 +151,9 @@ "module-virtualisation-xen-introduction": [ "index.html#module-virtualisation-xen-introduction" ], + "sec-boot-problems-scripted-stage-1": [ + "index.html#sec-boot-problems-scripted-stage-1" + ], "sec-nixos-test-vms-vs-containers": [ "index.html#sec-nixos-test-vms-vs-containers" ], diff --git a/nixos/doc/manual/release-notes/rl-2605.section.md b/nixos/doc/manual/release-notes/rl-2605.section.md index 5220d49e71e2..c0caa51bd18f 100644 --- a/nixos/doc/manual/release-notes/rl-2605.section.md +++ b/nixos/doc/manual/release-notes/rl-2605.section.md @@ -4,6 +4,16 @@ +- Stage 1 (a.k.a. initrd) is now based on systemd by default, and the old scripted implementation is deprecated and scheduled for removal in 26.11. If you run into issues migrating, you can [get help from the community](https://nixos.org/community/) or report an issue on GitHub. + + You can temporarily revert to the scripted stage 1 implementation by disabling [](#opt-boot.initrd.systemd.enable), but this is discouraged. + + Most incompatibilities will be explained with assertions during configuration evaluation, but be aware of the following that can't be automatically detected: + + - If you use LUKS disk encryption, ensure that `fileSystems."/".device` is set to `"/dev/mapper/"`, where `` matches the name in your `boot.initrd.luks.devices.` definition, to avoid systemd timing out while prompting for a passphrase. If you have a more complex setup, e.g. with LVM on top of LUKS, you may need to add `"x-systemd.device-timeout=infinity"` to `fileSystems."/".options` instead. If you need to disable the timeout before you can boot into the system, pass `systemd.default_device_timeout_sec=infinity` on the kernel command line. + - The `cryptsetup-askpass` program is not available; use `systemctl default` instead, which will prompt for passphrases as necessary. If you pipe password responses into SSH over stdin, use `ssh -o RequestTTY=force` to ensure `systemctl default` gets a TTY to prompt on. + - Many kernel parameters have been replaced with native systemd versions; see [](#sec-boot-problems). + - The system.nix file has been added has an alternative entry point to configuration.nix (and flake.nix) that allows to configure NixOS without using `nix-channel`. This file must evaluate to a NixOS system derivation or an attribute set of such derivations, in which case the attribute to build has to be selected with the `--attr` option of `nixos-rebuild` or `nixos-install`. For example, diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix index 343777d05c3a..a2594b3e9ab3 100644 --- a/nixos/modules/system/boot/stage-1.nix +++ b/nixos/modules/system/boot/stage-1.nix @@ -727,6 +727,10 @@ in }; config = mkIf config.boot.initrd.enable { + warnings = lib.optional (!config.boot.initrd.systemd.enable) '' + Scripted initrd is deprecated and scheduled for removal in 26.11. See the NixOS 26.05 release notes. + ''; + assertions = [ { assertion = !config.boot.initrd.systemd.enable -> any (fs: fs.mountPoint == "/") fileSystems; diff --git a/nixos/modules/system/boot/systemd/initrd.nix b/nixos/modules/system/boot/systemd/initrd.nix index f61d94b7851a..c3713c026b0e 100644 --- a/nixos/modules/system/boot/systemd/initrd.nix +++ b/nixos/modules/system/boot/systemd/initrd.nix @@ -157,6 +157,7 @@ in options.boot.initrd.systemd = { enable = mkEnableOption "systemd in initrd" // { + default = true; description = '' Whether to enable systemd in initrd. The unit options such as {option}`boot.initrd.systemd.services` are the same as their @@ -427,42 +428,57 @@ in }; config = mkIf (config.boot.initrd.enable && cfg.enable) { - assertions = [ - { - assertion = - cfg.root == "fstab" -> any (fs: fs.mountPoint == "/") (builtins.attrValues config.fileSystems); - message = "The ‘fileSystems’ option does not specify your root file system."; - } - ] - ++ - map - (name: { - assertion = lib.attrByPath name (throw "impossible") config.boot.initrd == ""; - message = '' - systemd stage 1 does not support 'boot.initrd.${lib.concatStringsSep "." name}'. Please - convert it to analogous systemd units in 'boot.initrd.systemd'. - - Definitions: - ${lib.concatMapStringsSep "\n" ({ file, ... }: " - ${file}") - (lib.attrByPath name (throw "impossible") options.boot.initrd).definitionsWithLocations - } - ''; - }) - [ - [ "preFailCommands" ] - [ "preDeviceCommands" ] - [ "preLVMCommands" ] - [ "postDeviceCommands" ] - [ "postResumeCommands" ] - [ "postMountCommands" ] - [ "extraUdevRulesCommands" ] - [ "extraUtilsCommands" ] - [ "extraUtilsCommandsTest" ] + assertions = + let + obsoleteOpt = + opts: msgFn: + lib.flip map opts (opt: { + assertion = lib.attrByPath opt (throw "impossible") config.boot.initrd == ""; + message = '' + ${msgFn (lib.concatStringsSep "." opt)} + Definitions: + ${lib.concatMapStringsSep "\n" ({ file, ... }: " - ${file}") + (lib.attrByPath opt (throw "impossible") options.boot.initrd).definitionsWithLocations + } + ''; + }); + in + [ + { + assertion = + cfg.root == "fstab" -> any (fs: fs.mountPoint == "/") (builtins.attrValues config.fileSystems); + message = "The ‘fileSystems’ option does not specify your root file system."; + } + ] + ++ + obsoleteOpt [ - "network" - "postCommands" + [ "preFailCommands" ] + [ "preDeviceCommands" ] + [ "preLVMCommands" ] + [ "postDeviceCommands" ] + [ "postResumeCommands" ] + [ "postMountCommands" ] + [ + "network" + "postCommands" + ] ] - ]; + (name: '' + systemd stage 1 does not support `boot.initrd.${name}`. Instead, create systemd services using the `boot.initrd.systemd.services` options, which has an API matching the stage 2 `systemd.services` options. Refer to `bootup(7)`, specifically the sections on "Bootup in the Initrd" and "System Manager Bootup", for information about when various units happen, and order services accordingly. + '') + ++ + obsoleteOpt + [ + [ "extraUtilsCommands" ] + [ "extraUtilsCommandsTest" ] + ] + (name: '' + systemd stage 1 does not support `boot.initrd.${name}`. Instead, use `boot.initrd.systemd.initrdBin`, `boot.initrd.systemd.extraBin`, `boot.initrd.systemd.contents`, or `boot.initrd.systemd.storePaths` to add files to the initrd. + '') + ++ obsoleteOpt [ [ "extraUdevRulesCommands" ] ] (name: '' + systemd stage 1 does not support `boot.initrd.${name}`. Instead, use `boot.initrd.services.udev` to configure udev. + ''); system.build = { inherit initialRamdisk; }; diff --git a/nixos/release-combined.nix b/nixos/release-combined.nix index d299ead82a1b..40eb4a0d34ae 100644 --- a/nixos/release-combined.nix +++ b/nixos/release-combined.nix @@ -103,6 +103,24 @@ rec { (onFullSupported "nixos.tests.gnome") (onSystems [ "x86_64-linux" ] "nixos.tests.hibernate") (onFullSupported "nixos.tests.i3wm") + (onSystems [ "aarch64-linux" ] "nixos.tests.installer-systemd-stage-1.simpleUefiSystemdBoot") + (onSystems [ "x86_64-linux" ] "nixos.tests.installer-systemd-stage-1.btrfsSimple") + (onSystems [ "x86_64-linux" ] "nixos.tests.installer-systemd-stage-1.btrfsSubvolDefault") + (onSystems [ "x86_64-linux" ] "nixos.tests.installer-systemd-stage-1.btrfsSubvolEscape") + (onSystems [ "x86_64-linux" ] "nixos.tests.installer-systemd-stage-1.btrfsSubvols") + (onSystems [ "x86_64-linux" ] "nixos.tests.installer-systemd-stage-1.luksroot") + (onSystems [ "x86_64-linux" ] "nixos.tests.installer-systemd-stage-1.lvm") + (onSystems [ "x86_64-linux" ] "nixos.tests.installer-systemd-stage-1.separateBootZfs") + (onSystems [ "x86_64-linux" ] "nixos.tests.installer-systemd-stage-1.separateBootFat") + (onSystems [ "x86_64-linux" ] "nixos.tests.installer-systemd-stage-1.separateBoot") + (onSystems [ "x86_64-linux" ] "nixos.tests.installer-systemd-stage-1.simpleLabels") + (onSystems [ "x86_64-linux" ] "nixos.tests.installer-systemd-stage-1.simpleProvided") + (onSystems [ "x86_64-linux" ] "nixos.tests.installer-systemd-stage-1.simpleUefiSystemdBoot") + (onSystems [ "x86_64-linux" ] "nixos.tests.installer-systemd-stage-1.simple") + (onSystems [ "x86_64-linux" ] "nixos.tests.installer-systemd-stage-1.swraid") + (onSystems [ "x86_64-linux" ] "nixos.tests.installer-systemd-stage-1.zfsroot") + (onSystems [ "x86_64-linux" ] "nixos.tests.nixos-rebuild-specialisations") + # Scripted stage 1 installer tests, remove in 26.11 (onSystems [ "aarch64-linux" ] "nixos.tests.installer.simpleUefiSystemdBoot") (onSystems [ "x86_64-linux" ] "nixos.tests.installer.btrfsSimple") (onSystems [ "x86_64-linux" ] "nixos.tests.installer.btrfsSubvolDefault") @@ -166,6 +184,8 @@ rec { (onFullSupported "nixos.tests.nfs4.simple") (onSystems [ "x86_64-linux" ] "nixos.tests.oci-containers.podman") (onFullSupported "nixos.tests.openssh") + (onFullSupported "nixos.tests.systemd-initrd-networkd-ssh") + # Scripted stage 1 SSH test, remove in 26.11 (onFullSupported "nixos.tests.initrd-network-ssh") (onFullSupported "nixos.tests.pantheon") (onFullSupported "nixos.tests.php.fpm")