2023-04-29 16:46:19 +00:00
|
|
|
|
{ lib, options, config, utils, pkgs, ... }:
|
2022-04-03 18:54:34 +00:00
|
|
|
|
|
|
|
|
|
with lib;
|
|
|
|
|
|
|
|
|
|
let
|
|
|
|
|
inherit (utils) systemdUtils escapeSystemdPath;
|
|
|
|
|
inherit (systemdUtils.lib)
|
|
|
|
|
generateUnits
|
|
|
|
|
pathToUnit
|
|
|
|
|
serviceToUnit
|
|
|
|
|
sliceToUnit
|
|
|
|
|
socketToUnit
|
|
|
|
|
targetToUnit
|
|
|
|
|
timerToUnit
|
|
|
|
|
mountToUnit
|
|
|
|
|
automountToUnit;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cfg = config.boot.initrd.systemd;
|
|
|
|
|
|
|
|
|
|
upstreamUnits = [
|
|
|
|
|
"basic.target"
|
|
|
|
|
"ctrl-alt-del.target"
|
2024-04-21 15:54:59 +00:00
|
|
|
|
"debug-shell.service"
|
2022-04-03 18:54:34 +00:00
|
|
|
|
"emergency.service"
|
|
|
|
|
"emergency.target"
|
|
|
|
|
"final.target"
|
|
|
|
|
"halt.target"
|
|
|
|
|
"initrd-cleanup.service"
|
|
|
|
|
"initrd-fs.target"
|
|
|
|
|
"initrd-parse-etc.service"
|
|
|
|
|
"initrd-root-device.target"
|
|
|
|
|
"initrd-root-fs.target"
|
|
|
|
|
"initrd-switch-root.service"
|
|
|
|
|
"initrd-switch-root.target"
|
|
|
|
|
"initrd.target"
|
|
|
|
|
"kexec.target"
|
|
|
|
|
"kmod-static-nodes.service"
|
|
|
|
|
"local-fs-pre.target"
|
|
|
|
|
"local-fs.target"
|
|
|
|
|
"multi-user.target"
|
|
|
|
|
"paths.target"
|
|
|
|
|
"poweroff.target"
|
|
|
|
|
"reboot.target"
|
|
|
|
|
"rescue.service"
|
|
|
|
|
"rescue.target"
|
|
|
|
|
"rpcbind.target"
|
|
|
|
|
"shutdown.target"
|
|
|
|
|
"sigpwr.target"
|
|
|
|
|
"slices.target"
|
|
|
|
|
"sockets.target"
|
|
|
|
|
"swap.target"
|
|
|
|
|
"sysinit.target"
|
|
|
|
|
"sys-kernel-config.mount"
|
|
|
|
|
"syslog.socket"
|
|
|
|
|
"systemd-ask-password-console.path"
|
|
|
|
|
"systemd-ask-password-console.service"
|
|
|
|
|
"systemd-fsck@.service"
|
|
|
|
|
"systemd-halt.service"
|
2024-02-07 01:22:34 +00:00
|
|
|
|
"systemd-hibernate-resume.service"
|
2022-04-03 18:54:34 +00:00
|
|
|
|
"systemd-journald-audit.socket"
|
|
|
|
|
"systemd-journald-dev-log.socket"
|
|
|
|
|
"systemd-journald.service"
|
|
|
|
|
"systemd-journald.socket"
|
|
|
|
|
"systemd-kexec.service"
|
|
|
|
|
"systemd-modules-load.service"
|
|
|
|
|
"systemd-poweroff.service"
|
|
|
|
|
"systemd-reboot.service"
|
|
|
|
|
"systemd-sysctl.service"
|
|
|
|
|
"systemd-tmpfiles-setup-dev.service"
|
|
|
|
|
"systemd-tmpfiles-setup.service"
|
|
|
|
|
"timers.target"
|
|
|
|
|
"umount.target"
|
2024-01-25 14:12:00 +00:00
|
|
|
|
"systemd-bsod.service"
|
2022-04-03 18:54:34 +00:00
|
|
|
|
] ++ cfg.additionalUpstreamUnits;
|
|
|
|
|
|
|
|
|
|
upstreamWants = [
|
|
|
|
|
"sysinit.target.wants"
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
enabledUpstreamUnits = filter (n: ! elem n cfg.suppressedUnits) upstreamUnits;
|
|
|
|
|
enabledUnits = filterAttrs (n: v: ! elem n cfg.suppressedUnits) cfg.units;
|
2022-04-15 01:41:22 +00:00
|
|
|
|
jobScripts = concatLists (mapAttrsToList (_: unit: unit.jobScripts or []) (filterAttrs (_: v: v.enable) cfg.services));
|
2022-04-03 18:54:34 +00:00
|
|
|
|
|
|
|
|
|
stage1Units = generateUnits {
|
|
|
|
|
type = "initrd";
|
|
|
|
|
units = enabledUnits;
|
|
|
|
|
upstreamUnits = enabledUpstreamUnits;
|
|
|
|
|
inherit upstreamWants;
|
|
|
|
|
inherit (cfg) packages package;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
kernel-name = config.boot.kernelPackages.kernel.name or "kernel";
|
|
|
|
|
# Determine the set of modules that we need to mount the root FS.
|
|
|
|
|
modulesClosure = pkgs.makeModulesClosure {
|
|
|
|
|
rootModules = config.boot.initrd.availableKernelModules ++ config.boot.initrd.kernelModules;
|
2024-04-21 15:54:59 +00:00
|
|
|
|
kernel = config.system.modulesTree;
|
|
|
|
|
firmware = config.hardware.firmware;
|
2022-04-03 18:54:34 +00:00
|
|
|
|
allowMissing = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
initrdBinEnv = pkgs.buildEnv {
|
2022-04-15 01:41:22 +00:00
|
|
|
|
name = "initrd-bin-env";
|
2022-04-03 18:54:34 +00:00
|
|
|
|
paths = map getBin cfg.initrdBin;
|
|
|
|
|
pathsToLink = ["/bin" "/sbin"];
|
2023-03-04 12:14:45 +00:00
|
|
|
|
postBuild = concatStringsSep "\n" (mapAttrsToList (n: v: "ln -sf '${v}' $out/bin/'${n}'") cfg.extraBin);
|
2022-04-03 18:54:34 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
initialRamdisk = pkgs.makeInitrdNG {
|
2022-04-27 09:35:20 +00:00
|
|
|
|
name = "initrd-${kernel-name}";
|
|
|
|
|
inherit (config.boot.initrd) compressor compressorArgs prepend;
|
2022-08-12 12:06:08 +00:00
|
|
|
|
inherit (cfg) strip;
|
2022-04-27 09:35:20 +00:00
|
|
|
|
|
2022-04-03 18:54:34 +00:00
|
|
|
|
contents = map (path: { object = path; symlink = ""; }) (subtractLists cfg.suppressedStorePaths cfg.storePaths)
|
|
|
|
|
++ mapAttrsToList (_: v: { object = v.source; symlink = v.target; }) (filterAttrs (_: v: v.enable) cfg.contents);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
in {
|
|
|
|
|
options.boot.initrd.systemd = {
|
2024-04-21 15:54:59 +00:00
|
|
|
|
enable = mkEnableOption "systemd in initrd" // {
|
|
|
|
|
description = ''
|
2023-04-29 16:46:19 +00:00
|
|
|
|
Whether to enable systemd in initrd. The unit options such as
|
|
|
|
|
{option}`boot.initrd.systemd.services` are the same as their
|
|
|
|
|
stage 2 counterparts such as {option}`systemd.services`,
|
|
|
|
|
except that `restartTriggers` and `reloadTriggers` are not
|
|
|
|
|
supported.
|
2022-09-09 14:08:57 +00:00
|
|
|
|
'';
|
|
|
|
|
};
|
2022-04-03 18:54:34 +00:00
|
|
|
|
|
2023-10-09 19:29:22 +00:00
|
|
|
|
package = lib.mkOption {
|
|
|
|
|
type = lib.types.package;
|
|
|
|
|
default = config.systemd.package;
|
|
|
|
|
defaultText = lib.literalExpression "config.systemd.package";
|
|
|
|
|
description = ''
|
|
|
|
|
The systemd package to use.
|
|
|
|
|
'';
|
2022-04-03 18:54:34 +00:00
|
|
|
|
};
|
|
|
|
|
|
2022-12-28 21:21:41 +00:00
|
|
|
|
extraConfig = mkOption {
|
|
|
|
|
default = "";
|
|
|
|
|
type = types.lines;
|
|
|
|
|
example = "DefaultLimitCORE=infinity";
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = ''
|
2022-12-28 21:21:41 +00:00
|
|
|
|
Extra config options for systemd. See systemd-system.conf(5) man page
|
|
|
|
|
for available options.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
2023-03-15 16:39:30 +00:00
|
|
|
|
managerEnvironment = mkOption {
|
|
|
|
|
type = with types; attrsOf (nullOr (oneOf [ str path package ]));
|
|
|
|
|
default = {};
|
|
|
|
|
example = { SYSTEMD_LOG_LEVEL = "debug"; };
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = ''
|
2023-03-15 16:39:30 +00:00
|
|
|
|
Environment variables of PID 1. These variables are
|
|
|
|
|
*not* passed to started units.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
2022-04-03 18:54:34 +00:00
|
|
|
|
contents = mkOption {
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = "Set of files that have to be linked into the initrd";
|
2022-04-03 18:54:34 +00:00
|
|
|
|
example = literalExpression ''
|
|
|
|
|
{
|
|
|
|
|
"/etc/hostname".text = "mymachine";
|
|
|
|
|
}
|
|
|
|
|
'';
|
|
|
|
|
default = {};
|
2022-04-27 09:35:20 +00:00
|
|
|
|
type = utils.systemdUtils.types.initrdContents;
|
2022-04-03 18:54:34 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
storePaths = mkOption {
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = ''
|
2022-04-03 18:54:34 +00:00
|
|
|
|
Store paths to copy into the initrd as well.
|
|
|
|
|
'';
|
2022-04-27 09:35:20 +00:00
|
|
|
|
type = with types; listOf (oneOf [ singleLineStr package ]);
|
2022-04-03 18:54:34 +00:00
|
|
|
|
default = [];
|
|
|
|
|
};
|
|
|
|
|
|
2022-08-12 12:06:08 +00:00
|
|
|
|
strip = mkOption {
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = ''
|
2022-08-12 12:06:08 +00:00
|
|
|
|
Whether to completely strip executables and libraries copied to the initramfs.
|
|
|
|
|
|
|
|
|
|
Setting this to false may save on the order of 30MiB on the
|
|
|
|
|
machine building the system (by avoiding a binutils
|
|
|
|
|
reference), at the cost of ~1MiB of initramfs size. This puts
|
|
|
|
|
this option firmly in the territory of micro-optimisation.
|
|
|
|
|
'';
|
|
|
|
|
type = types.bool;
|
|
|
|
|
default = true;
|
|
|
|
|
};
|
|
|
|
|
|
2022-04-15 01:41:22 +00:00
|
|
|
|
extraBin = mkOption {
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = ''
|
2022-04-15 01:41:22 +00:00
|
|
|
|
Tools to add to /bin
|
|
|
|
|
'';
|
|
|
|
|
example = literalExpression ''
|
|
|
|
|
{
|
|
|
|
|
umount = ''${pkgs.util-linux}/bin/umount;
|
|
|
|
|
}
|
|
|
|
|
'';
|
|
|
|
|
type = types.attrsOf types.path;
|
|
|
|
|
default = {};
|
|
|
|
|
};
|
|
|
|
|
|
2022-04-03 18:54:34 +00:00
|
|
|
|
suppressedStorePaths = mkOption {
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = ''
|
2022-04-03 18:54:34 +00:00
|
|
|
|
Store paths specified in the storePaths option that
|
|
|
|
|
should not be copied.
|
|
|
|
|
'';
|
|
|
|
|
type = types.listOf types.singleLineStr;
|
|
|
|
|
default = [];
|
|
|
|
|
};
|
|
|
|
|
|
2024-04-21 15:54:59 +00:00
|
|
|
|
root = lib.mkOption {
|
|
|
|
|
type = lib.types.enum [ "fstab" "gpt-auto" ];
|
|
|
|
|
default = "fstab";
|
|
|
|
|
example = "gpt-auto";
|
|
|
|
|
description = ''
|
|
|
|
|
Controls how systemd will interpret the root FS in initrd. See
|
|
|
|
|
{manpage}`kernel-command-line(7)`. NixOS currently does not
|
|
|
|
|
allow specifying the root file system itself this
|
|
|
|
|
way. Instead, the `fstab` value is used in order to interpret
|
|
|
|
|
the root file system specified with the `fileSystems` option.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
2022-04-03 18:54:34 +00:00
|
|
|
|
emergencyAccess = mkOption {
|
2022-08-12 12:06:08 +00:00
|
|
|
|
type = with types; oneOf [ bool (nullOr (passwdEntry str)) ];
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = ''
|
2022-04-03 18:54:34 +00:00
|
|
|
|
Set to true for unauthenticated emergency access, and false for
|
|
|
|
|
no emergency access.
|
|
|
|
|
|
|
|
|
|
Can also be set to a hashed super user password to allow
|
|
|
|
|
authenticated access to the emergency mode.
|
|
|
|
|
'';
|
|
|
|
|
default = false;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
initrdBin = mkOption {
|
|
|
|
|
type = types.listOf types.package;
|
|
|
|
|
default = [];
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = ''
|
2022-04-03 18:54:34 +00:00
|
|
|
|
Packages to include in /bin for the stage 1 emergency shell.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
additionalUpstreamUnits = mkOption {
|
|
|
|
|
default = [ ];
|
|
|
|
|
type = types.listOf types.str;
|
|
|
|
|
example = [ "debug-shell.service" "systemd-quotacheck.service" ];
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = ''
|
2022-04-03 18:54:34 +00:00
|
|
|
|
Additional units shipped with systemd that shall be enabled.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
suppressedUnits = mkOption {
|
|
|
|
|
default = [ ];
|
|
|
|
|
type = types.listOf types.str;
|
|
|
|
|
example = [ "systemd-backlight@.service" ];
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = ''
|
2022-04-03 18:54:34 +00:00
|
|
|
|
A list of units to skip when generating system systemd configuration directory. This has
|
2022-08-12 12:06:08 +00:00
|
|
|
|
priority over upstream units, {option}`boot.initrd.systemd.units`, and
|
|
|
|
|
{option}`boot.initrd.systemd.additionalUpstreamUnits`. The main purpose of this is to
|
2022-04-03 18:54:34 +00:00
|
|
|
|
prevent a upstream systemd unit from being added to the initrd with any modifications made to it
|
|
|
|
|
by other NixOS modules.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
units = mkOption {
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = "Definition of systemd units.";
|
2022-04-03 18:54:34 +00:00
|
|
|
|
default = {};
|
2023-04-29 16:46:19 +00:00
|
|
|
|
visible = "shallow";
|
2022-04-03 18:54:34 +00:00
|
|
|
|
type = systemdUtils.types.units;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
packages = mkOption {
|
|
|
|
|
default = [];
|
|
|
|
|
type = types.listOf types.package;
|
|
|
|
|
example = literalExpression "[ pkgs.systemd-cryptsetup-generator ]";
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = "Packages providing systemd units and hooks.";
|
2022-04-03 18:54:34 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
targets = mkOption {
|
|
|
|
|
default = {};
|
2023-04-29 16:46:19 +00:00
|
|
|
|
visible = "shallow";
|
2022-04-03 18:54:34 +00:00
|
|
|
|
type = systemdUtils.types.initrdTargets;
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = "Definition of systemd target units.";
|
2022-04-03 18:54:34 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
services = mkOption {
|
|
|
|
|
default = {};
|
|
|
|
|
type = systemdUtils.types.initrdServices;
|
2023-04-29 16:46:19 +00:00
|
|
|
|
visible = "shallow";
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = "Definition of systemd service units.";
|
2022-04-03 18:54:34 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
sockets = mkOption {
|
|
|
|
|
default = {};
|
|
|
|
|
type = systemdUtils.types.initrdSockets;
|
2023-04-29 16:46:19 +00:00
|
|
|
|
visible = "shallow";
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = "Definition of systemd socket units.";
|
2022-04-03 18:54:34 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
timers = mkOption {
|
|
|
|
|
default = {};
|
|
|
|
|
type = systemdUtils.types.initrdTimers;
|
2023-04-29 16:46:19 +00:00
|
|
|
|
visible = "shallow";
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = "Definition of systemd timer units.";
|
2022-04-03 18:54:34 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
paths = mkOption {
|
|
|
|
|
default = {};
|
|
|
|
|
type = systemdUtils.types.initrdPaths;
|
2023-04-29 16:46:19 +00:00
|
|
|
|
visible = "shallow";
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = "Definition of systemd path units.";
|
2022-04-03 18:54:34 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
mounts = mkOption {
|
|
|
|
|
default = [];
|
|
|
|
|
type = systemdUtils.types.initrdMounts;
|
2023-04-29 16:46:19 +00:00
|
|
|
|
visible = "shallow";
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = ''
|
2022-04-03 18:54:34 +00:00
|
|
|
|
Definition of systemd mount units.
|
|
|
|
|
This is a list instead of an attrSet, because systemd mandates the names to be derived from
|
|
|
|
|
the 'where' attribute.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
automounts = mkOption {
|
|
|
|
|
default = [];
|
|
|
|
|
type = systemdUtils.types.automounts;
|
2023-04-29 16:46:19 +00:00
|
|
|
|
visible = "shallow";
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = ''
|
2022-04-03 18:54:34 +00:00
|
|
|
|
Definition of systemd automount units.
|
|
|
|
|
This is a list instead of an attrSet, because systemd mandates the names to be derived from
|
|
|
|
|
the 'where' attribute.
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
slices = mkOption {
|
|
|
|
|
default = {};
|
|
|
|
|
type = systemdUtils.types.slices;
|
2023-04-29 16:46:19 +00:00
|
|
|
|
visible = "shallow";
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = "Definition of slice configurations.";
|
2022-04-03 18:54:34 +00:00
|
|
|
|
};
|
2023-10-09 19:29:22 +00:00
|
|
|
|
|
|
|
|
|
enableTpm2 = mkOption {
|
|
|
|
|
default = true;
|
|
|
|
|
type = types.bool;
|
2024-04-21 15:54:59 +00:00
|
|
|
|
description = ''
|
2023-10-09 19:29:22 +00:00
|
|
|
|
Whether to enable TPM2 support in the initrd.
|
|
|
|
|
'';
|
|
|
|
|
};
|
2022-04-03 18:54:34 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
config = mkIf (config.boot.initrd.enable && cfg.enable) {
|
2024-04-21 15:54:59 +00:00
|
|
|
|
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: {
|
2023-11-16 04:20:00 +00:00
|
|
|
|
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" ]
|
|
|
|
|
[ "network" "postCommands" ]
|
|
|
|
|
];
|
|
|
|
|
|
2022-04-03 18:54:34 +00:00
|
|
|
|
system.build = { inherit initialRamdisk; };
|
2022-04-15 01:41:22 +00:00
|
|
|
|
|
2022-10-30 15:09:59 +00:00
|
|
|
|
boot.initrd.availableKernelModules = [
|
2023-02-02 18:25:31 +00:00
|
|
|
|
# systemd needs this for some features
|
2023-11-16 04:20:00 +00:00
|
|
|
|
"autofs"
|
2023-02-02 18:25:31 +00:00
|
|
|
|
# systemd-cryptenroll
|
2023-10-09 19:29:22 +00:00
|
|
|
|
] ++ lib.optional cfg.enableTpm2 "tpm-tis"
|
2024-04-21 15:54:59 +00:00
|
|
|
|
++ lib.optional (cfg.enableTpm2 && !(pkgs.stdenv.hostPlatform.isRiscV64 || pkgs.stdenv.hostPlatform.isArmv7)) "tpm-crb"
|
|
|
|
|
++ lib.optional cfg.package.withEfi "efivarfs";
|
|
|
|
|
|
|
|
|
|
boot.kernelParams = [
|
|
|
|
|
"root=${config.boot.initrd.systemd.root}"
|
|
|
|
|
] ++ lib.optional (config.boot.resumeDevice != "") "resume=${config.boot.resumeDevice}"
|
|
|
|
|
# `systemd` mounts root in initrd as read-only unless "rw" is on the kernel command line.
|
|
|
|
|
# For NixOS activation to succeed, we need to have root writable in initrd.
|
|
|
|
|
++ lib.optional (config.boot.initrd.systemd.root == "gpt-auto") "rw";
|
2022-04-15 01:41:22 +00:00
|
|
|
|
|
2022-04-03 18:54:34 +00:00
|
|
|
|
boot.initrd.systemd = {
|
2024-04-21 15:54:59 +00:00
|
|
|
|
# bashInteractive is easier to use and also required by debug-shell.service
|
|
|
|
|
initrdBin = [pkgs.bashInteractive pkgs.coreutils cfg.package.kmod cfg.package];
|
2022-04-15 01:41:22 +00:00
|
|
|
|
extraBin = {
|
|
|
|
|
less = "${pkgs.less}/bin/less";
|
|
|
|
|
mount = "${cfg.package.util-linux}/bin/mount";
|
|
|
|
|
umount = "${cfg.package.util-linux}/bin/umount";
|
2023-03-15 16:39:30 +00:00
|
|
|
|
fsck = "${cfg.package.util-linux}/bin/fsck";
|
2022-04-15 01:41:22 +00:00
|
|
|
|
};
|
2022-04-03 18:54:34 +00:00
|
|
|
|
|
2023-03-15 16:39:30 +00:00
|
|
|
|
managerEnvironment.PATH = "/bin:/sbin";
|
|
|
|
|
|
2022-04-03 18:54:34 +00:00
|
|
|
|
contents = {
|
2023-03-27 19:17:25 +00:00
|
|
|
|
"/tmp/.keep".text = "systemd requires the /tmp mount point in the initrd cpio archive";
|
2022-04-03 18:54:34 +00:00
|
|
|
|
"/init".source = "${cfg.package}/lib/systemd/systemd";
|
|
|
|
|
"/etc/systemd/system".source = stage1Units;
|
|
|
|
|
|
|
|
|
|
"/etc/systemd/system.conf".text = ''
|
|
|
|
|
[Manager]
|
2023-04-29 16:46:19 +00:00
|
|
|
|
DefaultEnvironment=PATH=/bin:/sbin
|
2022-12-28 21:21:41 +00:00
|
|
|
|
${cfg.extraConfig}
|
2023-03-15 16:39:30 +00:00
|
|
|
|
ManagerEnvironment=${lib.concatStringsSep " " (lib.mapAttrsToList (n: v: "${n}=${lib.escapeShellArg v}") cfg.managerEnvironment)}
|
2022-04-03 18:54:34 +00:00
|
|
|
|
'';
|
|
|
|
|
|
2024-01-13 08:15:51 +00:00
|
|
|
|
"/lib".source = "${modulesClosure}/lib";
|
2022-04-03 18:54:34 +00:00
|
|
|
|
|
|
|
|
|
"/etc/modules-load.d/nixos.conf".text = concatStringsSep "\n" config.boot.initrd.kernelModules;
|
|
|
|
|
|
2023-04-29 16:46:19 +00:00
|
|
|
|
# We can use either ! or * to lock the root account in the
|
|
|
|
|
# console, but some software like OpenSSH won't even allow you
|
|
|
|
|
# to log in with an SSH key if you use ! so we use * instead
|
|
|
|
|
"/etc/shadow".text = "root:${if isBool cfg.emergencyAccess then optionalString (!cfg.emergencyAccess) "*" else cfg.emergencyAccess}:::::::";
|
2022-04-03 18:54:34 +00:00
|
|
|
|
|
|
|
|
|
"/bin".source = "${initrdBinEnv}/bin";
|
|
|
|
|
"/sbin".source = "${initrdBinEnv}/sbin";
|
|
|
|
|
|
|
|
|
|
"/etc/sysctl.d/nixos.conf".text = "kernel.modprobe = /sbin/modprobe";
|
2022-04-15 01:41:22 +00:00
|
|
|
|
"/etc/modprobe.d/systemd.conf".source = "${cfg.package}/lib/modprobe.d/systemd.conf";
|
|
|
|
|
"/etc/modprobe.d/ubuntu.conf".source = pkgs.runCommand "initrd-kmod-blacklist-ubuntu" { } ''
|
|
|
|
|
${pkgs.buildPackages.perl}/bin/perl -0pe 's/## file: iwlwifi.conf(.+?)##/##/s;' $src > $out
|
|
|
|
|
'';
|
|
|
|
|
"/etc/modprobe.d/debian.conf".source = pkgs.kmod-debian-aliases;
|
|
|
|
|
|
2022-08-12 12:06:08 +00:00
|
|
|
|
"/etc/os-release".source = config.boot.initrd.osRelease;
|
|
|
|
|
"/etc/initrd-release".source = config.boot.initrd.osRelease;
|
|
|
|
|
|
2022-10-06 18:32:54 +00:00
|
|
|
|
} // optionalAttrs (config.environment.etc ? "modprobe.d/nixos.conf") {
|
|
|
|
|
"/etc/modprobe.d/nixos.conf".source = config.environment.etc."modprobe.d/nixos.conf".source;
|
2022-04-03 18:54:34 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
storePaths = [
|
2022-04-15 01:41:22 +00:00
|
|
|
|
# systemd tooling
|
2024-01-25 14:12:00 +00:00
|
|
|
|
"${cfg.package}/lib/systemd/systemd-executor"
|
2022-04-15 01:41:22 +00:00
|
|
|
|
"${cfg.package}/lib/systemd/systemd-fsck"
|
|
|
|
|
"${cfg.package}/lib/systemd/systemd-hibernate-resume"
|
|
|
|
|
"${cfg.package}/lib/systemd/systemd-journald"
|
2024-01-02 11:29:13 +00:00
|
|
|
|
"${cfg.package}/lib/systemd/systemd-makefs"
|
2022-04-15 01:41:22 +00:00
|
|
|
|
"${cfg.package}/lib/systemd/systemd-modules-load"
|
|
|
|
|
"${cfg.package}/lib/systemd/systemd-remount-fs"
|
|
|
|
|
"${cfg.package}/lib/systemd/systemd-shutdown"
|
|
|
|
|
"${cfg.package}/lib/systemd/systemd-sulogin-shell"
|
|
|
|
|
"${cfg.package}/lib/systemd/systemd-sysctl"
|
2024-01-25 14:12:00 +00:00
|
|
|
|
"${cfg.package}/lib/systemd/systemd-bsod"
|
2022-04-15 01:41:22 +00:00
|
|
|
|
|
2022-04-27 09:35:20 +00:00
|
|
|
|
# generators
|
|
|
|
|
"${cfg.package}/lib/systemd/system-generators/systemd-debug-generator"
|
|
|
|
|
"${cfg.package}/lib/systemd/system-generators/systemd-fstab-generator"
|
|
|
|
|
"${cfg.package}/lib/systemd/system-generators/systemd-gpt-auto-generator"
|
|
|
|
|
"${cfg.package}/lib/systemd/system-generators/systemd-hibernate-resume-generator"
|
|
|
|
|
"${cfg.package}/lib/systemd/system-generators/systemd-run-generator"
|
2022-04-15 01:41:22 +00:00
|
|
|
|
|
|
|
|
|
# utilities needed by systemd
|
2022-04-03 18:54:34 +00:00
|
|
|
|
"${cfg.package.util-linux}/bin/mount"
|
|
|
|
|
"${cfg.package.util-linux}/bin/umount"
|
|
|
|
|
"${cfg.package.util-linux}/bin/sulogin"
|
|
|
|
|
|
2024-06-05 15:53:02 +00:00
|
|
|
|
# required for script services, and some tools like xfs still want the sh symlink
|
|
|
|
|
"${pkgs.bash}/bin"
|
2024-04-21 15:54:59 +00:00
|
|
|
|
|
2022-04-03 18:54:34 +00:00
|
|
|
|
# so NSS can look up usernames
|
2022-04-15 01:41:22 +00:00
|
|
|
|
"${pkgs.glibc}/lib/libnss_files.so.2"
|
2023-10-09 19:29:22 +00:00
|
|
|
|
] ++ optionals (cfg.package.withCryptsetup && cfg.enableTpm2) [
|
2022-10-30 15:09:59 +00:00
|
|
|
|
# tpm2 support
|
|
|
|
|
"${cfg.package}/lib/cryptsetup/libcryptsetup-token-systemd-tpm2.so"
|
|
|
|
|
pkgs.tpm2-tss
|
2023-10-09 19:29:22 +00:00
|
|
|
|
] ++ optionals cfg.package.withCryptsetup [
|
2022-10-30 15:09:59 +00:00
|
|
|
|
# fido2 support
|
|
|
|
|
"${cfg.package}/lib/cryptsetup/libcryptsetup-token-systemd-fido2.so"
|
|
|
|
|
"${pkgs.libfido2}/lib/libfido2.so.1"
|
2022-04-15 01:41:22 +00:00
|
|
|
|
] ++ jobScripts;
|
2022-04-03 18:54:34 +00:00
|
|
|
|
|
|
|
|
|
targets.initrd.aliases = ["default.target"];
|
|
|
|
|
units =
|
2024-05-15 15:35:15 +00:00
|
|
|
|
mapAttrs' (n: v: nameValuePair "${n}.path" (pathToUnit v)) cfg.paths
|
|
|
|
|
// mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit v)) cfg.services
|
|
|
|
|
// mapAttrs' (n: v: nameValuePair "${n}.slice" (sliceToUnit v)) cfg.slices
|
|
|
|
|
// mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit v)) cfg.sockets
|
|
|
|
|
// mapAttrs' (n: v: nameValuePair "${n}.target" (targetToUnit v)) cfg.targets
|
|
|
|
|
// mapAttrs' (n: v: nameValuePair "${n}.timer" (timerToUnit v)) cfg.timers
|
2022-04-03 18:54:34 +00:00
|
|
|
|
// listToAttrs (map
|
|
|
|
|
(v: let n = escapeSystemdPath v.where;
|
2024-05-15 15:35:15 +00:00
|
|
|
|
in nameValuePair "${n}.mount" (mountToUnit v)) cfg.mounts)
|
2022-04-03 18:54:34 +00:00
|
|
|
|
// listToAttrs (map
|
|
|
|
|
(v: let n = escapeSystemdPath v.where;
|
2024-05-15 15:35:15 +00:00
|
|
|
|
in nameValuePair "${n}.automount" (automountToUnit v)) cfg.automounts);
|
2022-04-03 18:54:34 +00:00
|
|
|
|
|
2022-08-12 12:06:08 +00:00
|
|
|
|
# make sure all the /dev nodes are set up
|
|
|
|
|
services.systemd-tmpfiles-setup-dev.wantedBy = ["sysinit.target"];
|
|
|
|
|
|
2022-04-15 01:41:22 +00:00
|
|
|
|
services.initrd-nixos-activation = {
|
|
|
|
|
after = [ "initrd-fs.target" ];
|
|
|
|
|
requiredBy = [ "initrd.target" ];
|
|
|
|
|
unitConfig.AssertPathExists = "/etc/initrd-release";
|
|
|
|
|
serviceConfig.Type = "oneshot";
|
|
|
|
|
description = "NixOS Activation";
|
|
|
|
|
|
|
|
|
|
script = /* bash */ ''
|
|
|
|
|
set -uo pipefail
|
|
|
|
|
export PATH="/bin:${cfg.package.util-linux}/bin"
|
|
|
|
|
|
|
|
|
|
# Figure out what closure to boot
|
|
|
|
|
closure=
|
|
|
|
|
for o in $(< /proc/cmdline); do
|
|
|
|
|
case $o in
|
|
|
|
|
init=*)
|
|
|
|
|
IFS== read -r -a initParam <<< "$o"
|
2024-04-21 15:54:59 +00:00
|
|
|
|
closure="''${initParam[1]}"
|
2022-04-15 01:41:22 +00:00
|
|
|
|
;;
|
|
|
|
|
esac
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
# Sanity check
|
|
|
|
|
if [ -z "''${closure:-}" ]; then
|
|
|
|
|
echo 'No init= parameter on the kernel command line' >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2024-04-21 15:54:59 +00:00
|
|
|
|
# Resolve symlinks in the init parameter. We need this for some boot loaders
|
|
|
|
|
# (e.g. boot.loader.generationsDir).
|
|
|
|
|
closure="$(chroot /sysroot ${pkgs.coreutils}/bin/realpath "$closure")"
|
|
|
|
|
|
|
|
|
|
# Assume the directory containing the init script is the closure.
|
|
|
|
|
closure="$(dirname "$closure")"
|
|
|
|
|
|
2022-04-15 01:41:22 +00:00
|
|
|
|
# If we are not booting a NixOS closure (e.g. init=/bin/sh),
|
|
|
|
|
# we don't know what root to prepare so we don't do anything
|
2023-02-16 17:41:37 +00:00
|
|
|
|
if ! [ -x "/sysroot$(readlink "/sysroot$closure/prepare-root" || echo "$closure/prepare-root")" ]; then
|
2022-04-15 01:41:22 +00:00
|
|
|
|
echo "NEW_INIT=''${initParam[1]}" > /etc/switch-root.conf
|
|
|
|
|
echo "$closure does not look like a NixOS installation - not activating"
|
|
|
|
|
exit 0
|
|
|
|
|
fi
|
|
|
|
|
echo 'NEW_INIT=' > /etc/switch-root.conf
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# We need to propagate /run for things like /run/booted-system
|
|
|
|
|
# and /run/current-system.
|
|
|
|
|
mkdir -p /sysroot/run
|
|
|
|
|
mount --bind /run /sysroot/run
|
|
|
|
|
|
|
|
|
|
# Initialize the system
|
|
|
|
|
export IN_NIXOS_SYSTEMD_STAGE1=true
|
|
|
|
|
exec chroot /sysroot $closure/prepare-root
|
|
|
|
|
'';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
# This will either call systemctl with the new init as the last parameter (which
|
|
|
|
|
# is the case when not booting a NixOS system) or with an empty string, causing
|
|
|
|
|
# systemd to bypass its verification code that checks whether the next file is a systemd
|
|
|
|
|
# and using its compiled-in value
|
|
|
|
|
services.initrd-switch-root.serviceConfig = {
|
|
|
|
|
EnvironmentFile = "-/etc/switch-root.conf";
|
|
|
|
|
ExecStart = [
|
|
|
|
|
""
|
|
|
|
|
''systemctl --no-block switch-root /sysroot "''${NEW_INIT}"''
|
|
|
|
|
];
|
|
|
|
|
};
|
2022-04-27 09:35:20 +00:00
|
|
|
|
|
|
|
|
|
services.panic-on-fail = {
|
|
|
|
|
wantedBy = ["emergency.target"];
|
|
|
|
|
unitConfig = {
|
|
|
|
|
DefaultDependencies = false;
|
|
|
|
|
ConditionKernelCommandLine = [
|
|
|
|
|
"|boot.panic_on_fail"
|
|
|
|
|
"|stage1panic"
|
|
|
|
|
];
|
|
|
|
|
};
|
|
|
|
|
script = ''
|
|
|
|
|
echo c > /proc/sysrq-trigger
|
|
|
|
|
'';
|
|
|
|
|
serviceConfig.Type = "oneshot";
|
|
|
|
|
};
|
2022-04-03 18:54:34 +00:00
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
}
|