nixos/grub: support initrd secrets

This commit is contained in:
Ben Wolsieffer 2018-03-27 19:57:52 -04:00
parent 50a5e5597a
commit 14eceb5991
3 changed files with 58 additions and 27 deletions

View file

@ -441,6 +441,20 @@ systemd.services.nginx.serviceConfig.ReadWritePaths = [ "/var/www" ];
recommended to only use lower-case characters.
</para>
</listitem>
<listitem>
<para>
The GRUB specific option <option>boot.loader.grub.extraInitrd</option>
has been replaced with the generic option
<option>boot.initrd.secrets</option>. This option creates a secondary
initrd from the specified files, rather than using a manually created
initrd file.
Due to an existing bug with <option>boot.loader.grub.extraInitrd</option>,
it is not possible to directly boot an older generation that used that
option. It is still possible to rollback to that generation if the required
initrd file has not been deleted.
</para>
</listitem>
</itemizedlist>
</section>

View file

@ -60,7 +60,7 @@ let
inherit (efi) canTouchEfiVariables;
inherit (cfg)
version extraConfig extraPerEntryConfig extraEntries forceInstall useOSProber
extraEntriesBeforeNixOS extraPrepareConfig extraInitrd configurationLimit copyKernels
extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels
default fsIdentifier efiSupport efiInstallAsRemovable gfxmodeEfi gfxmodeBios gfxpayloadEfi gfxpayloadBios;
path = with pkgs; makeBinPath (
[ coreutils gnused gnugrep findutils diffutils btrfs-progs utillinux mdadm ]
@ -292,19 +292,6 @@ in
'';
};
extraInitrd = mkOption {
type = types.nullOr types.path;
default = null;
example = "/boot/extra_initramfs.gz";
description = ''
The path to a second initramfs to be supplied to the kernel.
This ramfs will not be copied to the store, so that it can
contain secrets such as LUKS keyfiles or ssh keys.
This implies that rolling back to a previous configuration
won't rollback the state of this file.
'';
};
useOSProber = mkOption {
default = false;
type = types.bool;
@ -608,6 +595,8 @@ in
{ path = "/boot"; inherit (cfg) devices; inherit (efi) efiSysMountPoint; }
];
boot.loader.supportsInitrdSecrets = true;
system.build.installBootLoader =
let
install-grub-pl = pkgs.substituteAll {
@ -705,6 +694,24 @@ in
(mkRenamedOptionModule [ "boot" "grubDevice" ] [ "boot" "loader" "grub" "device" ])
(mkRenamedOptionModule [ "boot" "bootMount" ] [ "boot" "loader" "grub" "bootDevice" ])
(mkRenamedOptionModule [ "boot" "grubSplashImage" ] [ "boot" "loader" "grub" "splashImage" ])
(mkRemovedOptionModule [ "boot" "loader" "grub" "extraInitrd" ] ''
This option has been replaced with the bootloader agnostic
boot.initrd.secrets option. To migrate to the initrd secrets system,
extract the extraInitrd archive into your main filesystem:
# zcat /boot/extra_initramfs.gz | cpio -idvmD /etc/secrets/initrd
/path/to/secret1
/path/to/secret2
then replace boot.loader.grub.extraInitrd with boot.initrd.secrets:
boot.initrd.secrets = {
"/path/to/secret1" = "/etc/secrets/initrd/path/to/secret1";
"/path/to/secret2" = "/etc/secrets/initrd/path/to/secret2";
};
See the boot.initrd.secrets option documentation for more information.
'')
];
}

View file

@ -49,7 +49,6 @@ my $extraPrepareConfig = get("extraPrepareConfig");
my $extraPerEntryConfig = get("extraPerEntryConfig");
my $extraEntries = get("extraEntries");
my $extraEntriesBeforeNixOS = get("extraEntriesBeforeNixOS") eq "true";
my $extraInitrd = get("extraInitrd");
my $splashImage = get("splashImage");
my $splashMode = get("splashMode");
my $backgroundColor = get("backgroundColor");
@ -232,13 +231,6 @@ my $grubStore;
if ($copyKernels == 0) {
$grubStore = GrubFs($storePath);
}
my $extraInitrdPath;
if ($extraInitrd) {
if (! -f $extraInitrd) {
print STDERR "Warning: the specified extraInitrd " . $extraInitrd . " doesn't exist. Your system won't boot without it.\n";
}
$extraInitrdPath = GrubFs($extraInitrd);
}
# Generate the header.
my $conf .= "# Automatically generated. DO NOT EDIT THIS FILE!\n";
@ -363,9 +355,30 @@ sub addEntry {
my $kernel = copyToKernelsDir(Cwd::abs_path("$path/kernel"));
my $initrd = copyToKernelsDir(Cwd::abs_path("$path/initrd"));
if ($extraInitrd) {
$initrd .= " " .$extraInitrdPath->path;
# Include second initrd with secrets
if (-e -x "$path/append-initrd-secrets") {
my $initrdName = basename($initrd);
my $initrdSecretsPath = "$bootPath/kernels/$initrdName-secrets";
mkpath(dirname($initrdSecretsPath), 0, 0755);
my $oldUmask = umask;
# Make sure initrd is not world readable (won't work if /boot is FAT)
umask 0137;
my $initrdSecretsPathTemp = File::Temp::mktemp("$initrdSecretsPath.XXXXXXXX");
system("$path/append-initrd-secrets", $initrdSecretsPathTemp) == 0 or die "failed to create initrd secrets\n";
# Check whether any secrets were actually added
if (-e $initrdSecretsPathTemp && ! -z _) {
rename $initrdSecretsPathTemp, $initrdSecretsPath or die "failed to move initrd secrets into place\n";
$copied{$initrdSecretsPath} = 1;
$initrd .= " " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/kernels/$initrdName-secrets";
} else {
unlink $initrdSecretsPathTemp;
rmdir dirname($initrdSecretsPathTemp);
}
umask $oldUmask;
}
my $xen = -e "$path/xen.gz" ? copyToKernelsDir(Cwd::abs_path("$path/xen.gz")) : undef;
# FIXME: $confName
@ -388,9 +401,6 @@ sub addEntry {
if ($copyKernels == 0) {
$conf .= $grubStore->search . "\n";
}
if ($extraInitrd) {
$conf .= $extraInitrdPath->search . "\n";
}
$conf .= " $extraPerEntryConfig\n" if $extraPerEntryConfig;
$conf .= " multiboot $xen $xenParams\n" if $xen;
$conf .= " " . ($xen ? "module" : "linux") . " $kernel $kernelParams\n";