diff --git a/nixos/modules/system/boot/luksroot.nix b/nixos/modules/system/boot/luksroot.nix index 31f1e22cda32c..92ba79b2bed33 100644 --- a/nixos/modules/system/boot/luksroot.nix +++ b/nixos/modules/system/boot/luksroot.nix @@ -157,19 +157,15 @@ let local passphrase while true; do - echo -n "Passphrase for ${device}: " passphrase= while true; do if [ -e /crypt-ramfs/passphrase ]; then - echo "reused" + echo "Passphrase for ${device}: reused" passphrase=$(cat /crypt-ramfs/passphrase) break else - # ask cryptsetup-askpass echo -n "${device}" > /crypt-ramfs/device - - # and try reading it from /dev/console with a timeout - IFS= read -t 1 -r passphrase + passphrase="$(askPassword "Passphrase for ${device}: ")" if [ -n "$passphrase" ]; then ${if luks.reusePassphrases then '' # remember it for the next device @@ -253,9 +249,7 @@ let for try in $(seq 3); do ${optionalString yubikey.twoFactor '' - echo -n "Enter two-factor passphrase: " - read -r k_user - echo + k_user="$(askPassword "Enter two-factor passphrase: ")" ''} if [ ! -z "$k_user" ]; then @@ -336,16 +330,15 @@ let gpg --card-status > /dev/null 2> /dev/null for try in $(seq 3); do - echo -n "PIN for GPG Card associated with device ${device}: " pin= while true; do if [ -e /crypt-ramfs/passphrase ]; then - echo "reused" + echo "PIN for GPG Card associated with device ${device}: reused" pin=$(cat /crypt-ramfs/passphrase) break else # and try reading it from /dev/console with a timeout - IFS= read -t 1 -r pin + pin="$(askPassword "PIN for GPG Card associated with device ${device}: ")" if [ -n "$pin" ]; then ${if luks.reusePassphrases then '' # remember it for the next device @@ -396,8 +389,7 @@ let ${if fido2.passwordLess then '' export passphrase="" '' else '' - read -rsp "FIDO2 salt for ${device}: " passphrase - echo + passphrase="$(askPassword "FIDO2 salt for ${device}: ")" ''} ${optionalString (lib.versionOlder kernelPackages.kernel.version "5.4") '' echo "On systems with Linux Kernel < 5.4, it might take a while to initialize the CRNG, you might want to use linuxPackages_latest." @@ -419,24 +411,6 @@ let ''} ''; - askPass = pkgs.writeScriptBin "cryptsetup-askpass" '' - #!/bin/sh - - ${commonFunctions} - - while true; do - wait_target "luks" /crypt-ramfs/device 10 "LUKS to request a passphrase" || die "Passphrase is not requested now" - device=$(cat /crypt-ramfs/device) - - echo -n "Passphrase for $device: " - IFS= read -rs passphrase - echo - - rm /crypt-ramfs/device - echo -n "$passphrase" > /crypt-ramfs/passphrase - done - ''; - preLVM = filterAttrs (n: v: v.preLVM) luks.devices; postLVM = filterAttrs (n: v: !v.preLVM) luks.devices; @@ -797,8 +771,6 @@ in # copy the cryptsetup binary and it's dependencies boot.initrd.extraUtilsCommands = '' copy_bin_and_libs ${pkgs.cryptsetup}/bin/cryptsetup - copy_bin_and_libs ${askPass}/bin/cryptsetup-askpass - sed -i s,/bin/sh,$out/bin/sh, $out/bin/cryptsetup-askpass ${optionalString luks.yubikeySupport '' copy_bin_and_libs ${pkgs.yubikey-personalization}/bin/ykchalresp diff --git a/nixos/modules/system/boot/plymouth.nix b/nixos/modules/system/boot/plymouth.nix index 23fce22366d8e..d748cab1c463b 100644 --- a/nixos/modules/system/boot/plymouth.nix +++ b/nixos/modules/system/boot/plymouth.nix @@ -111,7 +111,7 @@ in mkdir -p $out/lib/plymouth/renderers # module might come from a theme - cp ${themesEnv}/lib/plymouth/{text,details,$moduleName}.so $out/lib/plymouth + cp ${themesEnv}/lib/plymouth/{text,details,label,$moduleName}.so $out/lib/plymouth cp ${plymouth}/lib/plymouth/renderers/{drm,frame-buffer}.so $out/lib/plymouth/renderers mkdir -p $out/share/plymouth/themes @@ -120,7 +120,7 @@ in # copy themes into working directory for patching mkdir themes # use -L to copy the directories proper, not the symlinks to them - cp -r -L ${themesEnv}/share/plymouth/themes/{text,details,${cfg.theme}} themes + cp -r -L ${themesEnv}/share/plymouth/themes/{text,details,spinner,${cfg.theme}} themes # patch out any attempted references to the theme or plymouth's themes directory chmod -R +w themes @@ -131,6 +131,15 @@ in cp -r themes/* $out/share/plymouth/themes cp ${cfg.logo} $out/share/plymouth/logo.png + + mkdir -p $out/usr/share/fonts/truetype + mkdir -p $out/etc/fonts/2.11/conf.d + cp -r ${pkgs.cantarell-fonts}/share/fonts/cantarell/Cantarell-{Thin,Regular}.otf $out/usr/share/fonts/truetype + cp -r ${pkgs.dejavu_fonts.minimal}/share/fonts/truetype/DejaVuSans.ttf $out/usr/share/fonts/truetype + + cp ${pkgs.fontconfig.out}/share/fontconfig/conf.avail/60-latin.conf $out/etc/fonts/2.11/conf.d + cp ${pkgs.fontconfig.out}/etc/fonts/fonts.conf $out/etc/fonts/2.11 + sed -i 's@${pkgs.dejavu_fonts.minimal}@/usr/share/fonts@g' $out/etc/fonts/2.11/fonts.conf ''; boot.initrd.extraUtilsCommandsTest = '' @@ -143,17 +152,22 @@ in sed -i '/loginctl/d' $out/71-seat.rules ''; - # We use `mkAfter` to ensure that LUKS password prompt would be shown earlier than the splash screen. - boot.initrd.preLVMCommands = mkAfter '' - mkdir -p /etc/plymouth + boot.initrd.preLogCommands = '' + mkdir -p /etc/plymouth /usr/share ln -s ${configFile} /etc/plymouth/plymouthd.conf ln -s $extraUtils/share/plymouth/plymouthd.defaults /etc/plymouth/plymouthd.defaults ln -s $extraUtils/share/plymouth/logo.png /etc/plymouth/logo.png ln -s $extraUtils/share/plymouth/themes /etc/plymouth/themes ln -s $extraUtils/lib/plymouth /etc/plymouth/plugins + ln -s $extraUtils/etc/fonts /etc/fonts + ln -s $extraUtils/usr/share/fonts /usr/share/fonts plymouthd --mode=boot --pid-file=/run/plymouth/pid --attach-to-session plymouth show-splash + + askPassword() { + plymouth ask-for-password --prompt="$1" + } ''; boot.initrd.postMountCommands = '' diff --git a/nixos/modules/system/boot/stage-1-init.sh b/nixos/modules/system/boot/stage-1-init.sh index 607aec87f01e5..b97a5035f41a7 100644 --- a/nixos/modules/system/boot/stage-1-init.sh +++ b/nixos/modules/system/boot/stage-1-init.sh @@ -62,11 +62,6 @@ EOF trap 'fail' 0 -# Print a greeting. -echo -echo "<<< NixOS Stage 1 >>>" -echo - # Make several required directories. mkdir -p /etc/udev touch /etc/fstab # to shut up mount @@ -116,6 +111,23 @@ source @earlyMountScript@ mkdir -p /tmp mkfifo /tmp/stage-1-init.log.fifo logOutFd=8 && logErrFd=9 + +# askPassword +askPassword() { + # Ensure that we don't reset the echo flag. + curStatus=$(stty -g) + stty -echo + + printf "%s" "$1" >&2 + IFS= read -r password + printf "\n" >&2 + + stty "$curStatus" + printf "%s" "$password" +} + +@preLogCommands@ + eval "exec $logOutFd>&1 $logErrFd>&2" if test -w /dev/kmsg; then tee -i < /tmp/stage-1-init.log.fifo /proc/self/fd/"$logOutFd" | while read -r line; do @@ -129,6 +141,10 @@ else fi exec > /tmp/stage-1-init.log.fifo 2>&1 +# Print a greeting. +echo +echo -e "\e[1;3m<<< NixOS Stage 1 >>>\e[0m" +echo # Process the kernel command line. export stage2Init=/init diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix index dfd158e2d75f4..dbc757dcea73a 100644 --- a/nixos/modules/system/boot/stage-1.nix +++ b/nixos/modules/system/boot/stage-1.nix @@ -280,7 +280,7 @@ let inherit (config.system.build) earlyMountScript; inherit (config.boot.initrd) checkJournalingFS - preLVMCommands preDeviceCommands postDeviceCommands postMountCommands preFailCommands kernelModules; + preLVMCommands preLogCommands preDeviceCommands postDeviceCommands postMountCommands preFailCommands kernelModules; resumeDevices = map (sd: if sd ? device then sd.device else "/dev/disk/by-label/${sd.label}") (filter (sd: hasPrefix "/dev/" sd.device && !sd.randomEncryption.enable @@ -438,6 +438,14 @@ in ''; }; + boot.initrd.preLogCommands = mkOption { + default = ""; + type = types.lines; + description = '' + Shell commands to be executed immediately before setting up logging. + ''; + }; + boot.initrd.preDeviceCommands = mkOption { default = ""; type = types.lines; diff --git a/nixos/modules/tasks/filesystems/bcachefs.nix b/nixos/modules/tasks/filesystems/bcachefs.nix index 5fda24adb9782..806d2c25a5b63 100644 --- a/nixos/modules/tasks/filesystems/bcachefs.nix +++ b/nixos/modules/tasks/filesystems/bcachefs.nix @@ -7,18 +7,13 @@ let bootFs = filterAttrs (n: fs: (fs.fsType == "bcachefs") && (utils.fsNeededForBoot fs)) config.fileSystems; commonFunctions = '' - prompt() { - local name="$1" - printf "enter passphrase for $name: " - } tryUnlock() { local name="$1" local path="$2" if bcachefs unlock -c $path > /dev/null 2> /dev/null; then # test for encryption - prompt $name - until bcachefs unlock $path 2> /dev/null; do # repeat until sucessfully unlocked + # repeat until sucessfully unlocked + until askPassword "Enter passphrase for $name: " | bcachefs unlock $path; do printf "unlocking failed!\n" - prompt $name done printf "unlocking successful.\n" fi diff --git a/nixos/modules/tasks/filesystems/zfs.nix b/nixos/modules/tasks/filesystems/zfs.nix index 43347161a84c6..bfa9b10077a0f 100644 --- a/nixos/modules/tasks/filesystems/zfs.nix +++ b/nixos/modules/tasks/filesystems/zfs.nix @@ -421,8 +421,29 @@ in fi poolImported "${pool}" || poolImport "${pool}" # Try one last time, e.g. to import a degraded pool. fi - ${lib.optionalString cfgZfs.requestEncryptionCredentials '' - zfs load-key -a + ${optionalString cfgZfs.requestEncryptionCredentials '' + zfs list -r -H -o encryptionroot,keystatus,keylocation "${pool}" | sort | uniq | while IFS=" " read encryptionroot keystatus keylocation; do + if [ "$keystatus" != "unavailable" -o "$keylocation" == "none" ]; then + continue + fi + + if [ "$keylocation" != "prompt" ]; then + "${packages.zfsUser}/bin/zfs" load-key "$encryptionroot" || die "Failed to load key for $encryptionroot" + continue + fi + + success= + for i in $(seq 1 3); do + if askPassword "Enter key for $encryptionroot: " | zfs load-key "$encryptionroot"; then + success=1 + break + fi + done + + if [ -z "$success" ]; then + die "Failed to load key for $encryptionroot" + fi + done ''} '') rootPools)); };