about summary refs log tree commit diff
path: root/nixos/modules/system/boot
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/system/boot')
-rw-r--r--nixos/modules/system/boot/kernel_config.nix5
-rw-r--r--nixos/modules/system/boot/loader/grub/grub.nix37
-rw-r--r--nixos/modules/system/boot/loader/grub/install-grub.pl36
-rw-r--r--nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py20
-rw-r--r--nixos/modules/system/boot/networkd.nix10
-rw-r--r--nixos/modules/system/boot/resolved.nix1
-rw-r--r--nixos/modules/system/boot/stage-1.nix5
-rw-r--r--nixos/modules/system/boot/systemd.nix9
-rw-r--r--nixos/modules/system/boot/timesyncd.nix1
9 files changed, 86 insertions, 38 deletions
diff --git a/nixos/modules/system/boot/kernel_config.nix b/nixos/modules/system/boot/kernel_config.nix
index a316782dfc57..85bd420e3044 100644
--- a/nixos/modules/system/boot/kernel_config.nix
+++ b/nixos/modules/system/boot/kernel_config.nix
@@ -22,7 +22,7 @@ let
 
   mergeFalseByDefault = locs: defs:
     if defs == [] then abort "This case should never happen."
-    else if any (x: x == false) defs then false
+    else if any (x: x == false) (getValues defs) then false
     else true;
 
   kernelItem = types.submodule {
@@ -55,6 +55,7 @@ let
         default = false;
         description = ''
           Wether option should generate a failure when unused.
+          Upon merging values, mandatory wins over optional.
         '';
       };
     };
@@ -121,7 +122,7 @@ in
       type = types.attrsOf kernelItem;
       example = literalExample '' with lib.kernel; {
         "9P_NET" = yes;
-        USB = optional yes;
+        USB = option yes;
         MMC_BLOCK_MINORS = freeform "32";
       }'';
       description = ''
diff --git a/nixos/modules/system/boot/loader/grub/grub.nix b/nixos/modules/system/boot/loader/grub/grub.nix
index c775632a4aa0..3975372e15ec 100644
--- a/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixos/modules/system/boot/loader/grub/grub.nix
@@ -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 ]
@@ -83,7 +83,7 @@ let
              ] ++ (optional (cfg.fontSize!=null) "--size ${toString cfg.fontSize}")))
          );
 
-  defaultSplash = "${pkgs.nixos-artwork.wallpapers.simple-dark-gray-bootloader}/share/artwork/gnome/nix-wallpaper-simple-dark-gray_bootloader.png";
+  defaultSplash = pkgs.nixos-artwork.wallpapers.simple-dark-gray-bootloader.gnomeFilePath;
 in
 
 {
@@ -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.
+      '')
     ];
 
 }
diff --git a/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixos/modules/system/boot/loader/grub/install-grub.pl
index 8df18cbd9013..e469b18abd09 100644
--- a/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -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";
diff --git a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
index f48a085ce57a..d8baed65c6df 100644
--- a/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
+++ b/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
@@ -47,9 +47,9 @@ def write_loader_conf(profile, generation):
         if "@timeout@" != "":
             f.write("timeout @timeout@\n")
         if profile:
-            f.write("default nixos-%s-generation-%d\n" % (profile, generation))
+            f.write("default nixos-%s-generation-%d.conf\n".format(profile, generation))
         else:
-            f.write("default nixos-generation-%d\n" % (generation))
+            f.write("default nixos-generation-%d.conf\n".format(generation))
         if not @editor@:
             f.write("editor 0\n");
         f.write("console-mode @consoleMode@\n");
@@ -197,6 +197,22 @@ def main():
             subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "install"])
         else:
             subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "--no-variables", "install"])
+    else:
+        # Update bootloader to latest if needed
+        systemd_version = subprocess.check_output(["@systemd@/bin/bootctl", "--version"], universal_newlines=True).split()[1]
+        sdboot_status = subprocess.check_output(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "status"], universal_newlines=True)
+
+        # See status_binaries() in systemd bootctl.c for code which generates this
+        m = re.search("^\W+File:.*/EFI/(BOOT|systemd)/.*\.efi \(systemd-boot (\d+)\)$",
+                      sdboot_status, re.IGNORECASE | re.MULTILINE)
+        if m is None:
+            print("could not find any previously installed systemd-boot")
+        else:
+            sdboot_version = m.group(2)
+            if systemd_version > sdboot_version:
+                print("updating systemd-boot from %s to %s" % (sdboot_version, systemd_version))
+                subprocess.check_call(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "update"])
+
 
     mkdir_p("@efiSysMountPoint@/efi/nixos")
     mkdir_p("@efiSysMountPoint@/loader/entries")
diff --git a/nixos/modules/system/boot/networkd.nix b/nixos/modules/system/boot/networkd.nix
index 9b34b12e73a5..b0545363b330 100644
--- a/nixos/modules/system/boot/networkd.nix
+++ b/nixos/modules/system/boot/networkd.nix
@@ -1178,14 +1178,22 @@ in
       users.users.systemd-network.group = "systemd-network";
 
       systemd.additionalUpstreamSystemUnits = [
-        "systemd-networkd.service" "systemd-networkd-wait-online.service"
+        "systemd-networkd-wait-online.service"
+        "systemd-networkd.service"
+        "systemd-networkd.socket"
       ];
 
       systemd.network.units = mapAttrs' (n: v: nameValuePair "${n}.netdev" (netdevToUnit n v)) cfg.netdevs
         // mapAttrs' (n: v: nameValuePair "${n}.network" (networkToUnit n v)) cfg.networks;
 
+      # systemd-networkd is socket-activated by kernel netlink route change
+      # messages. It is important to have systemd buffer those on behalf of
+      # networkd.
+      systemd.sockets.systemd-networkd.wantedBy = [ "sockets.target" ];
+
       systemd.services.systemd-networkd = {
         wantedBy = [ "multi-user.target" ];
+        aliases = [ "dbus-org.freedesktop.network1.service" ];
         restartTriggers = map (x: x.source) (attrValues unitFiles);
         # prevent race condition with interface renaming (#39069)
         requires = [ "systemd-udev-settle.service" ];
diff --git a/nixos/modules/system/boot/resolved.nix b/nixos/modules/system/boot/resolved.nix
index b7aaef575ac1..b024f9cf5ee9 100644
--- a/nixos/modules/system/boot/resolved.nix
+++ b/nixos/modules/system/boot/resolved.nix
@@ -148,6 +148,7 @@ in
 
     systemd.services.systemd-resolved = {
       wantedBy = [ "multi-user.target" ];
+      aliases = [ "dbus-org.freedesktop.resolve1.service" ];
       restartTriggers = [ config.environment.etc."systemd/resolved.conf".source ];
     };
 
diff --git a/nixos/modules/system/boot/stage-1.nix b/nixos/modules/system/boot/stage-1.nix
index dfd158e2d75f..d551466f52eb 100644
--- a/nixos/modules/system/boot/stage-1.nix
+++ b/nixos/modules/system/boot/stage-1.nix
@@ -517,8 +517,7 @@ in
     };
 
     boot.initrd.secrets = mkOption
-      { internal = true;
-        default = {};
+      { default = {};
         type = types.attrsOf (types.nullOr types.path);
         description =
           ''
@@ -585,7 +584,7 @@ in
       { assertion = !config.boot.loader.supportsInitrdSecrets ->
           all (source:
             builtins.isPath source ||
-            (builtins.isString source && hasPrefix source builtins.storeDir))
+            (builtins.isString source && hasPrefix builtins.storeDir source))
           (attrValues config.boot.initrd.secrets);
         message = ''
           boot.loader.initrd.secrets values must be unquoted paths when
diff --git a/nixos/modules/system/boot/systemd.nix b/nixos/modules/system/boot/systemd.nix
index 99892a28115c..a8e51fc09014 100644
--- a/nixos/modules/system/boot/systemd.nix
+++ b/nixos/modules/system/boot/systemd.nix
@@ -826,8 +826,13 @@ in
   config = {
 
     warnings = concatLists (mapAttrsToList (name: service:
-      optional (service.serviceConfig.Type or "" == "oneshot" && service.serviceConfig.Restart or "no" != "no")
-        "Service ‘${name}.service’ with ‘Type=oneshot’ must have ‘Restart=no’") cfg.services);
+      let
+        type = service.serviceConfig.Type or "";
+        restart = service.serviceConfig.Restart or "no";
+      in optional
+      (type == "oneshot" && (restart == "always" || restart == "on-success"))
+      "Service '${name}.service' with 'Type=oneshot' cannot have 'Restart=always' or 'Restart=on-success'")
+      cfg.services);
 
     system.build.units = cfg.units;
 
diff --git a/nixos/modules/system/boot/timesyncd.nix b/nixos/modules/system/boot/timesyncd.nix
index 9e2f36ca01f8..35fb5578b070 100644
--- a/nixos/modules/system/boot/timesyncd.nix
+++ b/nixos/modules/system/boot/timesyncd.nix
@@ -41,6 +41,7 @@ with lib;
 
     systemd.services.systemd-timesyncd = {
       wantedBy = [ "sysinit.target" ];
+      aliases = [ "dbus-org.freedesktop.timesync1.service" ];
       restartTriggers = [ config.environment.etc."systemd/timesyncd.conf".source ];
     };