forked from mirrors/nixpkgs
initrd: Optional systemd-based initrd
This commit is contained in:
parent
25113740a5
commit
2d4ebf1259
nixos
lib
modules
pkgs/os-specific/linux/systemd
|
@ -291,16 +291,10 @@ in rec {
|
|||
};
|
||||
};
|
||||
|
||||
serviceConfig = { name, config, ... }: {
|
||||
mkServiceConfig = path: { name, config, ... }: {
|
||||
config = mkMerge
|
||||
[ { # Default path for systemd services. Should be quite minimal.
|
||||
path = mkAfter
|
||||
[ pkgs.coreutils
|
||||
pkgs.findutils
|
||||
pkgs.gnugrep
|
||||
pkgs.gnused
|
||||
systemd
|
||||
];
|
||||
path = mkAfter path;
|
||||
environment.PATH = "${makeBinPath config.path}:${makeSearchPathOutput "bin" "sbin" config.path}";
|
||||
}
|
||||
(mkIf (config.preStart != "")
|
||||
|
@ -330,6 +324,16 @@ in rec {
|
|||
];
|
||||
};
|
||||
|
||||
serviceConfig = mkServiceConfig [
|
||||
pkgs.coreutils
|
||||
pkgs.findutils
|
||||
pkgs.gnugrep
|
||||
pkgs.gnused
|
||||
systemd
|
||||
];
|
||||
|
||||
initrdServiceConfig = mkServiceConfig [];
|
||||
|
||||
mountConfig = { config, ... }: {
|
||||
config = {
|
||||
mountConfig =
|
||||
|
@ -387,6 +391,15 @@ in rec {
|
|||
'';
|
||||
};
|
||||
|
||||
initrdServiceToUnit = name: def:
|
||||
{ inherit (def) aliases wantedBy requiredBy enable;
|
||||
text = commonUnitText def +
|
||||
''
|
||||
[Service]
|
||||
${attrsToSection def.serviceConfig}
|
||||
'';
|
||||
};
|
||||
|
||||
socketToUnit = name: def:
|
||||
{ inherit (def) aliases wantedBy requiredBy enable;
|
||||
text = commonUnitText def +
|
||||
|
|
|
@ -12,6 +12,7 @@ rec {
|
|||
}));
|
||||
|
||||
services = with types; attrsOf (submodule [ { options = serviceOptions; } unitConfig serviceConfig ]);
|
||||
initrdServices = with types; attrsOf (submodule [ { options = serviceOptions; } unitConfig initrdServiceConfig ]);
|
||||
|
||||
targets = with types; attrsOf (submodule [ { options = targetOptions; } unitConfig ]);
|
||||
|
||||
|
|
|
@ -1172,6 +1172,7 @@
|
|||
./system/boot/systemd/nspawn.nix
|
||||
./system/boot/systemd/tmpfiles.nix
|
||||
./system/boot/systemd/user.nix
|
||||
./system/boot/systemd/initrd.nix
|
||||
./system/boot/timesyncd.nix
|
||||
./system/boot/tmp.nix
|
||||
./system/etc/etc-activation.nix
|
||||
|
|
|
@ -706,8 +706,12 @@ in
|
|||
}
|
||||
];
|
||||
|
||||
system.build =
|
||||
{ inherit bootStage1 initialRamdisk initialRamdiskSecretAppender extraUtils; };
|
||||
system.build = mkMerge [
|
||||
{ inherit bootStage1 initialRamdiskSecretAppender extraUtils; }
|
||||
|
||||
# generated in nixos/modules/system/boot/systemd/initrd.nix
|
||||
(mkIf (!config.boot.initrd.systemd.enable) { inherit initialRamdisk; })
|
||||
];
|
||||
|
||||
system.requiredKernelConfig = with config.lib.kernelConfig; [
|
||||
(isYes "TMPFS")
|
||||
|
|
|
@ -11,10 +11,7 @@ let
|
|||
systemd = cfg.package;
|
||||
|
||||
inherit (systemdUtils.lib)
|
||||
makeUnit
|
||||
generateUnits
|
||||
makeJobScript
|
||||
commonUnitText
|
||||
targetToUnit
|
||||
serviceToUnit
|
||||
socketToUnit
|
||||
|
|
355
nixos/modules/system/boot/systemd/initrd.nix
Normal file
355
nixos/modules/system/boot/systemd/initrd.nix
Normal file
|
@ -0,0 +1,355 @@
|
|||
{ lib, config, utils, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
inherit (utils) systemdUtils escapeSystemdPath;
|
||||
inherit (systemdUtils.lib)
|
||||
generateUnits
|
||||
pathToUnit
|
||||
initrdServiceToUnit
|
||||
sliceToUnit
|
||||
socketToUnit
|
||||
targetToUnit
|
||||
timerToUnit
|
||||
mountToUnit
|
||||
automountToUnit;
|
||||
|
||||
|
||||
cfg = config.boot.initrd.systemd;
|
||||
|
||||
# Copied from fedora
|
||||
upstreamUnits = [
|
||||
"basic.target"
|
||||
"ctrl-alt-del.target"
|
||||
"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"
|
||||
"initrd-udevadm-cleanup-db.service"
|
||||
"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"
|
||||
"systemd-hibernate-resume@.service"
|
||||
"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-random-seed.service"
|
||||
"systemd-reboot.service"
|
||||
"systemd-sysctl.service"
|
||||
"systemd-tmpfiles-setup-dev.service"
|
||||
"systemd-tmpfiles-setup.service"
|
||||
"systemd-udevd-control.socket"
|
||||
"systemd-udevd-kernel.socket"
|
||||
"systemd-udevd.service"
|
||||
"systemd-udev-settle.service"
|
||||
"systemd-udev-trigger.service"
|
||||
"systemd-vconsole-setup.service"
|
||||
"timers.target"
|
||||
"umount.target"
|
||||
|
||||
# TODO: Networking
|
||||
# "network-online.target"
|
||||
# "network-pre.target"
|
||||
# "network.target"
|
||||
# "nss-lookup.target"
|
||||
# "nss-user-lookup.target"
|
||||
# "remote-fs-pre.target"
|
||||
# "remote-fs.target"
|
||||
] ++ cfg.additionalUpstreamUnits;
|
||||
|
||||
upstreamWants = [
|
||||
"sysinit.target.wants"
|
||||
];
|
||||
|
||||
enabledUpstreamUnits = filter (n: ! elem n cfg.suppressedUnits) upstreamUnits;
|
||||
enabledUnits = filterAttrs (n: v: ! elem n cfg.suppressedUnits) cfg.units;
|
||||
|
||||
stage1Units = generateUnits {
|
||||
type = "initrd";
|
||||
units = enabledUnits;
|
||||
upstreamUnits = enabledUpstreamUnits;
|
||||
inherit upstreamWants;
|
||||
inherit (cfg) packages package;
|
||||
};
|
||||
|
||||
fileSystems = filter utils.fsNeededForBoot config.system.build.fileSystems;
|
||||
|
||||
fstab = pkgs.writeText "fstab" (lib.concatMapStringsSep "\n"
|
||||
({ fsType, mountPoint, device, options, ... }:
|
||||
"${device} /sysroot${mountPoint} ${fsType} ${lib.concatStringsSep "," options}") fileSystems);
|
||||
|
||||
kernel-name = config.boot.kernelPackages.kernel.name or "kernel";
|
||||
modulesTree = config.system.modulesTree.override { name = kernel-name + "-modules"; };
|
||||
firmware = config.hardware.firmware;
|
||||
# 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;
|
||||
kernel = modulesTree;
|
||||
firmware = firmware;
|
||||
allowMissing = false;
|
||||
};
|
||||
|
||||
initrdBinEnv = pkgs.buildEnv {
|
||||
name = "initrd-emergency-env";
|
||||
paths = map getBin cfg.initrdBin;
|
||||
pathsToLink = ["/bin" "/sbin"];
|
||||
};
|
||||
|
||||
initialRamdisk = pkgs.makeInitrdNG {
|
||||
contents = cfg.objects;
|
||||
};
|
||||
|
||||
in {
|
||||
options.boot.initrd.systemd = {
|
||||
enable = mkEnableOption ''systemd in initrd.
|
||||
|
||||
Note: This is in very early development and is highly
|
||||
experimental. Most of the features NixOS supports in initrd are
|
||||
not yet supported by the intrd generated with this option.
|
||||
'';
|
||||
|
||||
package = (lib.mkPackageOption pkgs "systemd" {
|
||||
default = "systemdMinimal";
|
||||
}) // {
|
||||
visible = false;
|
||||
};
|
||||
|
||||
objects = mkOption {
|
||||
description = "List of objects to include in the initrd, and their symlinks";
|
||||
example = literalExpression ''
|
||||
[ { object = "''${systemd}/lib/systemd/systemd"; symlink = "/init"; } ]
|
||||
'';
|
||||
visible = false;
|
||||
type = types.listOf (types.submodule {
|
||||
options = {
|
||||
object = mkOption {
|
||||
type = types.path;
|
||||
description = "The object to include in initrd.";
|
||||
};
|
||||
symlink = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
description = "A symlink to create in initrd pointing to the object.";
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
emergencyHashedPassword = mkOption {
|
||||
type = types.str;
|
||||
visible = false;
|
||||
description = ''
|
||||
Hashed password for the super user account in stage 1 emergency mode
|
||||
|
||||
Blank for no password, ! for super user disabled.
|
||||
'';
|
||||
default = "!";
|
||||
};
|
||||
|
||||
initrdBin = mkOption {
|
||||
type = types.listOf types.package;
|
||||
default = [];
|
||||
visible = false;
|
||||
description = ''
|
||||
Packages to include in /bin for the stage 1 emergency shell.
|
||||
'';
|
||||
};
|
||||
|
||||
additionalUpstreamUnits = mkOption {
|
||||
default = [ ];
|
||||
type = types.listOf types.str;
|
||||
visible = false;
|
||||
example = [ "debug-shell.service" "systemd-quotacheck.service" ];
|
||||
description = ''
|
||||
Additional units shipped with systemd that shall be enabled.
|
||||
'';
|
||||
};
|
||||
|
||||
suppressedUnits = mkOption {
|
||||
default = [ ];
|
||||
type = types.listOf types.str;
|
||||
example = [ "systemd-backlight@.service" ];
|
||||
visible = false;
|
||||
description = ''
|
||||
A list of units to suppress when generating system systemd configuration directory. This has
|
||||
priority over upstream units, <option>systemd.units</option>, and
|
||||
<option>systemd.additionalUpstreamSystemUnits</option>. The main purpose of this is to
|
||||
suppress a upstream systemd unit with any modifications made to it by other NixOS modules.
|
||||
'';
|
||||
};
|
||||
|
||||
units = mkOption {
|
||||
description = "Definition of systemd units.";
|
||||
default = {};
|
||||
visible = false;
|
||||
type = systemdUtils.types.units;
|
||||
};
|
||||
|
||||
packages = mkOption {
|
||||
default = [];
|
||||
visible = false;
|
||||
type = types.listOf types.package;
|
||||
example = literalExpression "[ pkgs.systemd-cryptsetup-generator ]";
|
||||
description = "Packages providing systemd units and hooks.";
|
||||
};
|
||||
|
||||
targets = mkOption {
|
||||
default = {};
|
||||
visible = false;
|
||||
type = systemdUtils.types.targets;
|
||||
description = "Definition of systemd target units.";
|
||||
};
|
||||
|
||||
services = mkOption {
|
||||
default = {};
|
||||
type = systemdUtils.types.initrdServices;
|
||||
visible = false;
|
||||
description = "Definition of systemd service units.";
|
||||
};
|
||||
|
||||
sockets = mkOption {
|
||||
default = {};
|
||||
type = systemdUtils.types.sockets;
|
||||
visible = false;
|
||||
description = "Definition of systemd socket units.";
|
||||
};
|
||||
|
||||
timers = mkOption {
|
||||
default = {};
|
||||
type = systemdUtils.types.timers;
|
||||
visible = false;
|
||||
description = "Definition of systemd timer units.";
|
||||
};
|
||||
|
||||
paths = mkOption {
|
||||
default = {};
|
||||
type = systemdUtils.types.paths;
|
||||
visible = false;
|
||||
description = "Definition of systemd path units.";
|
||||
};
|
||||
|
||||
mounts = mkOption {
|
||||
default = [];
|
||||
type = systemdUtils.types.mounts;
|
||||
visible = false;
|
||||
description = ''
|
||||
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;
|
||||
visible = false;
|
||||
description = ''
|
||||
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;
|
||||
visible = false;
|
||||
description = "Definition of slice configurations.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf (config.boot.initrd.enable && cfg.enable) {
|
||||
system.build = { inherit initialRamdisk; };
|
||||
boot.initrd.systemd = {
|
||||
initrdBin = [pkgs.bash pkgs.coreutils pkgs.kmod cfg.package];
|
||||
|
||||
objects = [
|
||||
{ object = "${cfg.package}/lib/systemd/systemd"; symlink = "/init"; }
|
||||
{ object = stage1Units; symlink = "/etc/systemd/system"; }
|
||||
|
||||
# TODO: Limit this to the bare necessities
|
||||
{ object = "${cfg.package}/lib"; }
|
||||
|
||||
{ object = "${cfg.package.util-linux}/bin/mount"; }
|
||||
{ object = "${cfg.package.util-linux}/bin/umount"; }
|
||||
{ object = "${cfg.package.util-linux}/bin/sulogin"; }
|
||||
|
||||
# TODO: Not sure why this needs to be here for the recovery shell to work
|
||||
{ object = "${pkgs.glibc}/lib/libnss_files.so"; }
|
||||
|
||||
{ object = config.environment.etc.os-release.source; symlink = "/etc/initrd-release"; }
|
||||
{ object = config.environment.etc.os-release.source; symlink = "/etc/os-release"; }
|
||||
{ object = fstab; symlink = "/etc/fstab"; }
|
||||
{
|
||||
object = "${modulesClosure}/lib/modules";
|
||||
symlink = "/lib/modules";
|
||||
}
|
||||
{
|
||||
symlink = "/etc/modules-load.d/nixos.conf";
|
||||
object = pkgs.writeText "nixos.conf"
|
||||
(lib.concatStringsSep "\n" config.boot.initrd.kernelModules);
|
||||
}
|
||||
{
|
||||
object = builtins.toFile "passwd" "root:x:0:0:System Administrator:/root:/bin/bash";
|
||||
symlink = "/etc/passwd";
|
||||
}
|
||||
{
|
||||
object = builtins.toFile "shadow" "root:${config.boot.initrd.systemd.emergencyHashedPassword}:::::::";
|
||||
symlink = "/etc/shadow";
|
||||
}
|
||||
{ object = "${initrdBinEnv}/bin"; symlink = "/bin"; }
|
||||
{ object = "${initrdBinEnv}/sbin"; symlink = "/sbin"; }
|
||||
{ object = builtins.toFile "bashrc" "PATH=/bin:/sbin"; symlink = "/etc/bashrc"; }
|
||||
{ object = builtins.toFile "sysctl.conf" "kernel.modprobe = /sbin/modprobe"; symlink = "/etc/sysctl.d/nixos.conf"; }
|
||||
];
|
||||
|
||||
targets.initrd.aliases = ["default.target"];
|
||||
units =
|
||||
mapAttrs' (n: v: nameValuePair "${n}.path" (pathToUnit n v)) cfg.paths
|
||||
// mapAttrs' (n: v: nameValuePair "${n}.service" (initrdServiceToUnit n v)) cfg.services
|
||||
// mapAttrs' (n: v: nameValuePair "${n}.slice" (sliceToUnit n v)) cfg.slices
|
||||
// mapAttrs' (n: v: nameValuePair "${n}.socket" (socketToUnit n v)) cfg.sockets
|
||||
// mapAttrs' (n: v: nameValuePair "${n}.target" (targetToUnit n v)) cfg.targets
|
||||
// mapAttrs' (n: v: nameValuePair "${n}.timer" (timerToUnit n v)) cfg.timers
|
||||
// listToAttrs (map
|
||||
(v: let n = escapeSystemdPath v.where;
|
||||
in nameValuePair "${n}.mount" (mountToUnit n v)) cfg.mounts)
|
||||
// listToAttrs (map
|
||||
(v: let n = escapeSystemdPath v.where;
|
||||
in nameValuePair "${n}.automount" (automountToUnit n v)) cfg.automounts);
|
||||
};
|
||||
};
|
||||
}
|
|
@ -603,7 +603,7 @@ stdenv.mkDerivation {
|
|||
# runtime; otherwise we can't and we need to reboot.
|
||||
interfaceVersion = 2;
|
||||
|
||||
inherit withCryptsetup;
|
||||
inherit withCryptsetup util-linux;
|
||||
|
||||
tests = {
|
||||
inherit (nixosTests) switchTest;
|
||||
|
|
Loading…
Reference in a new issue