aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/nixos/modules/system/boot
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/modules/system/boot')
-rw-r--r--nixpkgs/nixos/modules/system/boot/emergency-mode.nix2
-rw-r--r--nixpkgs/nixos/modules/system/boot/initrd-network.nix2
-rw-r--r--nixpkgs/nixos/modules/system/boot/initrd-openvpn.nix81
-rw-r--r--nixpkgs/nixos/modules/system/boot/kernel_config.nix7
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/generations-dir/generations-dir-builder.sh2
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix29
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh17
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix143
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl195
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/init-script/init-script-builder.sh2
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.nix4
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.sh5
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py22
-rw-r--r--nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix4
-rw-r--r--nixpkgs/nixos/modules/system/boot/luksroot.nix38
-rw-r--r--nixpkgs/nixos/modules/system/boot/modprobe.nix2
-rw-r--r--nixpkgs/nixos/modules/system/boot/networkd.nix1502
-rw-r--r--nixpkgs/nixos/modules/system/boot/plymouth.nix3
-rw-r--r--nixpkgs/nixos/modules/system/boot/resolved.nix1
-rw-r--r--nixpkgs/nixos/modules/system/boot/stage-1-init.sh22
-rw-r--r--nixpkgs/nixos/modules/system/boot/stage-1.nix35
-rw-r--r--nixpkgs/nixos/modules/system/boot/stage-2-init.sh2
-rw-r--r--nixpkgs/nixos/modules/system/boot/stage-2.nix10
-rw-r--r--nixpkgs/nixos/modules/system/boot/systemd-nspawn.nix6
-rw-r--r--nixpkgs/nixos/modules/system/boot/systemd-unit-options.nix12
-rw-r--r--nixpkgs/nixos/modules/system/boot/systemd.nix161
-rw-r--r--nixpkgs/nixos/modules/system/boot/timesyncd.nix1
-rw-r--r--nixpkgs/nixos/modules/system/boot/tmp.nix2
28 files changed, 1605 insertions, 707 deletions
diff --git a/nixpkgs/nixos/modules/system/boot/emergency-mode.nix b/nixpkgs/nixos/modules/system/boot/emergency-mode.nix
index 9cdab841619..ec697bcee26 100644
--- a/nixpkgs/nixos/modules/system/boot/emergency-mode.nix
+++ b/nixpkgs/nixos/modules/system/boot/emergency-mode.nix
@@ -34,4 +34,4 @@ with lib;
};
-} \ No newline at end of file
+}
diff --git a/nixpkgs/nixos/modules/system/boot/initrd-network.nix b/nixpkgs/nixos/modules/system/boot/initrd-network.nix
index 0ab6e626b34..ec794d6eb01 100644
--- a/nixpkgs/nixos/modules/system/boot/initrd-network.nix
+++ b/nixpkgs/nixos/modules/system/boot/initrd-network.nix
@@ -139,7 +139,7 @@ in
boot.initrd.postMountCommands = mkIf cfg.flushBeforeStage2 ''
for iface in $ifaces; do
ip address flush "$iface"
- ip link down "$iface"
+ ip link set "$iface" down
done
'';
diff --git a/nixpkgs/nixos/modules/system/boot/initrd-openvpn.nix b/nixpkgs/nixos/modules/system/boot/initrd-openvpn.nix
new file mode 100644
index 00000000000..e59bc7b6678
--- /dev/null
+++ b/nixpkgs/nixos/modules/system/boot/initrd-openvpn.nix
@@ -0,0 +1,81 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.boot.initrd.network.openvpn;
+
+in
+
+{
+
+ options = {
+
+ boot.initrd.network.openvpn.enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Starts an OpenVPN client during initrd boot. It can be used to e.g.
+ remotely accessing the SSH service controlled by
+ <option>boot.initrd.network.ssh</option> or other network services
+ included. Service is killed when stage-1 boot is finished.
+ '';
+ };
+
+ boot.initrd.network.openvpn.configuration = mkOption {
+ type = types.path; # Same type as boot.initrd.secrets
+ description = ''
+ The configuration file for OpenVPN.
+
+ <warning>
+ <para>
+ Unless your bootloader supports initrd secrets, this configuration
+ is stored insecurely in the global Nix store.
+ </para>
+ </warning>
+ '';
+ example = "./configuration.ovpn";
+ };
+
+ };
+
+ config = mkIf (config.boot.initrd.network.enable && cfg.enable) {
+ assertions = [
+ {
+ assertion = cfg.configuration != null;
+ message = "You should specify a configuration for initrd OpenVPN";
+ }
+ ];
+
+ # Add kernel modules needed for OpenVPN
+ boot.initrd.kernelModules = [ "tun" "tap" ];
+
+ # Add openvpn and ip binaries to the initrd
+ # The shared libraries are required for DNS resolution
+ boot.initrd.extraUtilsCommands = ''
+ copy_bin_and_libs ${pkgs.openvpn}/bin/openvpn
+ copy_bin_and_libs ${pkgs.iproute}/bin/ip
+
+ cp -pv ${pkgs.glibc}/lib/libresolv.so.2 $out/lib
+ cp -pv ${pkgs.glibc}/lib/libnss_dns.so.2 $out/lib
+ '';
+
+ boot.initrd.secrets = {
+ "/etc/initrd.ovpn" = cfg.configuration;
+ };
+
+ # openvpn --version would exit with 1 instead of 0
+ boot.initrd.extraUtilsCommandsTest = ''
+ $out/bin/openvpn --show-gateway
+ '';
+
+ # Add `iproute /bin/ip` to the config, to ensure that openvpn
+ # is able to set the routes
+ boot.initrd.network.postCommands = ''
+ (cat /etc/initrd.ovpn; echo -e '\niproute /bin/ip') | \
+ openvpn /dev/stdin &
+ '';
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/system/boot/kernel_config.nix b/nixpkgs/nixos/modules/system/boot/kernel_config.nix
index a316782dfc5..783685c9dfe 100644
--- a/nixpkgs/nixos/modules/system/boot/kernel_config.nix
+++ b/nixpkgs/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 {
@@ -54,7 +54,8 @@ let
type = types.bool // { merge = mergeFalseByDefault; };
default = false;
description = ''
- Wether option should generate a failure when unused.
+ Whether 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/nixpkgs/nixos/modules/system/boot/loader/generations-dir/generations-dir-builder.sh b/nixpkgs/nixos/modules/system/boot/loader/generations-dir/generations-dir-builder.sh
index e723b9eb7cb..8ae23dc988c 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/generations-dir/generations-dir-builder.sh
+++ b/nixpkgs/nixos/modules/system/boot/loader/generations-dir/generations-dir-builder.sh
@@ -63,7 +63,7 @@ addEntry() {
copyToKernelsDir $kernel; kernel=$result
copyToKernelsDir $initrd; initrd=$result
fi
-
+
mkdir -p $outdir
ln -sf $(readlink -f $path) $outdir/system
ln -sf $(readlink -f $path/init) $outdir/init
diff --git a/nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix b/nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix
index af39c7bb684..bd508bbe8ea 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix
+++ b/nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/default.nix
@@ -4,11 +4,15 @@ with lib;
let
blCfg = config.boot.loader;
+ dtCfg = config.hardware.deviceTree;
cfg = blCfg.generic-extlinux-compatible;
timeoutStr = if blCfg.timeout == null then "-1" else toString blCfg.timeout;
+ # The builder used to write during system activation
builder = import ./extlinux-conf-builder.nix { inherit pkgs; };
+ # The builder exposed in populateCmd, which runs on the build architecture
+ populateBuilder = import ./extlinux-conf-builder.nix { pkgs = pkgs.buildPackages; };
in
{
options = {
@@ -34,11 +38,28 @@ in
Maximum number of configurations in the boot menu.
'';
};
+
+ populateCmd = mkOption {
+ type = types.str;
+ readOnly = true;
+ description = ''
+ Contains the builder command used to populate an image,
+ honoring all options except the <literal>-c &lt;path-to-default-configuration&gt;</literal>
+ argument.
+ Useful to have for sdImage.populateRootCommands
+ '';
+ };
+
};
};
- config = mkIf cfg.enable {
- system.build.installBootLoader = "${builder} -g ${toString cfg.configurationLimit} -t ${timeoutStr} -c";
- system.boot.loader.id = "generic-extlinux-compatible";
- };
+ config = let
+ builderArgs = "-g ${toString cfg.configurationLimit} -t ${timeoutStr}" + lib.optionalString (dtCfg.name != null) " -n ${dtCfg.name}";
+ in
+ mkIf cfg.enable {
+ system.build.installBootLoader = "${builder} ${builderArgs} -c";
+ system.boot.loader.id = "generic-extlinux-compatible";
+
+ boot.loader.generic-extlinux-compatible.populateCmd = "${populateBuilder} ${builderArgs}";
+ };
}
diff --git a/nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh b/nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh
index 0092ee92b62..854684b87fa 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh
+++ b/nixpkgs/nixos/modules/system/boot/loader/generic-extlinux-compatible/extlinux-conf-builder.sh
@@ -6,7 +6,7 @@ export PATH=/empty
for i in @path@; do PATH=$PATH:$i/bin; done
usage() {
- echo "usage: $0 -t <timeout> -c <path-to-default-configuration> [-d <boot-dir>] [-g <num-generations>]" >&2
+ echo "usage: $0 -t <timeout> -c <path-to-default-configuration> [-d <boot-dir>] [-g <num-generations>] [-n <dtbName>]" >&2
exit 1
}
@@ -15,7 +15,7 @@ default= # Default configuration
target=/boot # Target directory
numGenerations=0 # Number of other generations to include in the menu
-while getopts "t:c:d:g:" opt; do
+while getopts "t:c:d:g:n:" opt; do
case "$opt" in
t) # U-Boot interprets '0' as infinite and negative as instant boot
if [ "$OPTARG" -lt 0 ]; then
@@ -29,6 +29,7 @@ while getopts "t:c:d:g:" opt; do
c) default="$OPTARG" ;;
d) target="$OPTARG" ;;
g) numGenerations="$OPTARG" ;;
+ n) dtbName="$OPTARG" ;;
\?) usage ;;
esac
done
@@ -96,7 +97,17 @@ addEntry() {
echo " LINUX ../nixos/$(basename $kernel)"
echo " INITRD ../nixos/$(basename $initrd)"
if [ -d "$dtbDir" ]; then
- echo " FDTDIR ../nixos/$(basename $dtbs)"
+ # if a dtbName was specified explicitly, use that, else use FDTDIR
+ if [ -n "$dtbName" ]; then
+ echo " FDT ../nixos/$(basename $dtbs)/${dtbName}"
+ else
+ echo " FDTDIR ../nixos/$(basename $dtbs)"
+ fi
+ else
+ if [ -n "$dtbName" ]; then
+ echo "Explicitly requested dtbName $dtbName, but there's no FDTDIR - bailing out." >&2
+ exit 1
+ fi
fi
echo " APPEND systemConfig=$path init=$path/init $extraParams"
}
diff --git a/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix b/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
index c775632a4aa..20e39628eab 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
+++ b/nixpkgs/nixos/modules/system/boot/loader/grub/grub.nix
@@ -55,12 +55,15 @@ let
storePath = config.boot.loader.grub.storePath;
bootloaderId = if args.efiBootloaderId == null then "NixOS${efiSysMountPoint'}" else args.efiBootloaderId;
timeout = if config.boot.loader.timeout == null then -1 else config.boot.loader.timeout;
+ users = if cfg.users == {} || cfg.version != 1 then cfg.users else throw "GRUB version 1 does not support user accounts.";
+ theme = f cfg.theme;
inherit efiSysMountPoint;
inherit (args) devices;
inherit (efi) canTouchEfiVariables;
inherit (cfg)
version extraConfig extraPerEntryConfig extraEntries forceInstall useOSProber
- extraEntriesBeforeNixOS extraPrepareConfig extraInitrd configurationLimit copyKernels
+ extraGrubInstallArgs
+ 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 +86,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
{
@@ -137,6 +140,67 @@ in
'';
};
+ users = mkOption {
+ default = {};
+ example = {
+ root = { hashedPasswordFile = "/path/to/file"; };
+ };
+ description = ''
+ User accounts for GRUB. When specified, the GRUB command line and
+ all boot options except the default are password-protected.
+ All passwords and hashes provided will be stored in /boot/grub/grub.cfg,
+ and will be visible to any local user who can read this file. Additionally,
+ any passwords and hashes provided directly in a Nix configuration
+ (as opposed to external files) will be copied into the Nix store, and
+ will be visible to all local users.
+ '';
+ type = with types; attrsOf (submodule {
+ options = {
+ hashedPasswordFile = mkOption {
+ example = "/path/to/file";
+ default = null;
+ type = with types; uniq (nullOr str);
+ description = ''
+ Specifies the path to a file containing the password hash
+ for the account, generated with grub-mkpasswd-pbkdf2.
+ This hash will be stored in /boot/grub/grub.cfg, and will
+ be visible to any local user who can read this file.
+ '';
+ };
+ hashedPassword = mkOption {
+ example = "grub.pbkdf2.sha512.10000.674DFFDEF76E13EA...2CC972B102CF4355";
+ default = null;
+ type = with types; uniq (nullOr str);
+ description = ''
+ Specifies the password hash for the account,
+ generated with grub-mkpasswd-pbkdf2.
+ This hash will be copied to the Nix store, and will be visible to all local users.
+ '';
+ };
+ passwordFile = mkOption {
+ example = "/path/to/file";
+ default = null;
+ type = with types; uniq (nullOr str);
+ description = ''
+ Specifies the path to a file containing the
+ clear text password for the account.
+ This password will be stored in /boot/grub/grub.cfg, and will
+ be visible to any local user who can read this file.
+ '';
+ };
+ password = mkOption {
+ example = "Pa$$w0rd!";
+ default = null;
+ type = with types; uniq (nullOr str);
+ description = ''
+ Specifies the clear text password for the account.
+ This password will be copied to the Nix store, and will be visible to all local users.
+ '';
+ };
+ };
+ });
+ };
+
mirroredBoots = mkOption {
default = [ ];
example = [
@@ -236,6 +300,33 @@ in
'';
};
+ extraGrubInstallArgs = mkOption {
+ default = [ ];
+ example = [ "--modules=nativedisk ahci pata part_gpt part_msdos diskfilter mdraid1x lvm ext2" ];
+ type = types.listOf types.str;
+ description = ''
+ Additional arguments passed to <literal>grub-install</literal>.
+
+ A use case for this is to build specific GRUB2 modules
+ directly into the GRUB2 kernel image, so that they are available
+ and activated even in the <literal>grub rescue</literal> shell.
+
+ They are also necessary when the BIOS/UEFI is bugged and cannot
+ correctly read large disks (e.g. above 2 TB), so GRUB2's own
+ <literal>nativedisk</literal> and related modules can be used
+ to use its own disk drivers. The example shows one such case.
+ This is also useful for booting from USB.
+ See the
+ <link xlink:href="http://git.savannah.gnu.org/cgit/grub.git/tree/grub-core/commands/nativedisk.c?h=grub-2.04#n326">
+ GRUB source code
+ </link>
+ for which disk modules are available.
+
+ The list elements are passed directly as <literal>argv</literal>
+ arguments to the <literal>grub-install</literal> program, in order.
+ '';
+ };
+
extraPerEntryConfig = mkOption {
default = "";
example = "root (hd0)";
@@ -292,19 +383,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;
@@ -349,6 +427,19 @@ in
'';
};
+ theme = mkOption {
+ type = types.nullOr types.path;
+ example = literalExample "pkgs.nixos-grub2-theme";
+ default = null;
+ description = ''
+ Grub theme to be used.
+
+ <note><para>
+ This options has no effect for GRUB 1.
+ </para></note>
+ '';
+ };
+
splashMode = mkOption {
type = types.enum [ "normal" "stretch" ];
default = "stretch";
@@ -608,6 +699,8 @@ in
{ path = "/boot"; inherit (cfg) devices; inherit (efi) efiSysMountPoint; }
];
+ boot.loader.supportsInitrdSecrets = true;
+
system.build.installBootLoader =
let
install-grub-pl = pkgs.substituteAll {
@@ -618,7 +711,7 @@ in
in pkgs.writeScript "install-grub.sh" (''
#!${pkgs.runtimeShell}
set -e
- export PERL5LIB=${with pkgs.perlPackages; makePerlPath [ FileSlurp XMLLibXML XMLSAX XMLSAXBase ListCompare ]}
+ export PERL5LIB=${with pkgs.perlPackages; makePerlPath [ FileSlurp FileCopyRecursive XMLLibXML XMLSAX XMLSAXBase ListCompare JSON ]}
${optionalString cfg.enableCryptodisk "export GRUB_ENABLE_CRYPTODISK=y"}
'' + flip concatMapStrings cfg.mirroredBoots (args: ''
${pkgs.perl}/bin/perl ${install-grub-pl} ${grubConfig args} $@
@@ -705,6 +798,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/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl b/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl
index 8df18cbd901..59f5638044f 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl
+++ b/nixpkgs/nixos/modules/system/boot/loader/grub/install-grub.pl
@@ -6,8 +6,11 @@ use File::Basename;
use File::Path;
use File::stat;
use File::Copy;
+use File::Copy::Recursive qw(rcopy pathrm);
use File::Slurp;
use File::Temp;
+use JSON;
+use File::Find;
require List::Compare;
use POSIX;
use Cwd;
@@ -20,6 +23,16 @@ my $dom = XML::LibXML->load_xml(location => $ARGV[0]);
sub get { my ($name) = @_; return $dom->findvalue("/expr/attrs/attr[\@name = '$name']/*/\@value"); }
+sub getList {
+ my ($name) = @_;
+ my @list = ();
+ foreach my $entry ($dom->findnodes("/expr/attrs/attr[\@name = '$name']/list/string/\@value")) {
+ $entry = $entry->findvalue(".") or die;
+ push(@list, $entry);
+ }
+ return @list;
+}
+
sub readFile {
my ($fn) = @_; local $/ = undef;
open FILE, "<$fn" or return undef; my $s = <FILE>; close FILE;
@@ -49,7 +62,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");
@@ -72,6 +84,7 @@ my $gfxpayloadBios = get("gfxpayloadBios");
my $bootloaderId = get("bootloaderId");
my $forceInstall = get("forceInstall");
my $font = get("font");
+my $theme = get("theme");
$ENV{'PATH'} = get("path");
die "unsupported GRUB version\n" if $grubVersion != 1 && $grubVersion != 2;
@@ -232,13 +245,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";
@@ -249,12 +255,51 @@ if ($grubVersion == 1) {
timeout $timeout
";
if ($splashImage) {
- copy $splashImage, "$bootPath/background.xpm.gz" or die "cannot copy $splashImage to $bootPath\n";
+ copy $splashImage, "$bootPath/background.xpm.gz" or die "cannot copy $splashImage to $bootPath: $!\n";
$conf .= "splashimage " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/background.xpm.gz\n";
}
}
else {
+ my @users = ();
+ foreach my $user ($dom->findnodes('/expr/attrs/attr[@name = "users"]/attrs/attr')) {
+ my $name = $user->findvalue('@name') or die;
+ my $hashedPassword = $user->findvalue('./attrs/attr[@name = "hashedPassword"]/string/@value');
+ my $hashedPasswordFile = $user->findvalue('./attrs/attr[@name = "hashedPasswordFile"]/string/@value');
+ my $password = $user->findvalue('./attrs/attr[@name = "password"]/string/@value');
+ my $passwordFile = $user->findvalue('./attrs/attr[@name = "passwordFile"]/string/@value');
+
+ if ($hashedPasswordFile) {
+ open(my $f, '<', $hashedPasswordFile) or die "Can't read file '$hashedPasswordFile'!";
+ $hashedPassword = <$f>;
+ chomp $hashedPassword;
+ }
+ if ($passwordFile) {
+ open(my $f, '<', $passwordFile) or die "Can't read file '$passwordFile'!";
+ $password = <$f>;
+ chomp $password;
+ }
+
+ if ($hashedPassword) {
+ if (index($hashedPassword, "grub.pbkdf2.") == 0) {
+ $conf .= "\npassword_pbkdf2 $name $hashedPassword";
+ }
+ else {
+ die "Password hash for GRUB user '$name' is not valid!";
+ }
+ }
+ elsif ($password) {
+ $conf .= "\npassword $name $password";
+ }
+ else {
+ die "GRUB user '$name' has no password!";
+ }
+ push(@users, $name);
+ }
+ if (@users) {
+ $conf .= "\nset superusers=\"" . join(' ',@users) . "\"\n";
+ }
+
if ($copyKernels == 0) {
$conf .= "
" . $grubStore->search;
@@ -288,7 +333,7 @@ else {
";
if ($font) {
- copy $font, "$bootPath/converted-font.pf2" or die "cannot copy $font to $bootPath\n";
+ copy $font, "$bootPath/converted-font.pf2" or die "cannot copy $font to $bootPath: $!\n";
$conf .= "
insmod font
if loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/converted-font.pf2; then
@@ -316,7 +361,7 @@ else {
background_color '$backgroundColor'
";
}
- copy $splashImage, "$bootPath/background$suffix" or die "cannot copy $splashImage to $bootPath\n";
+ copy $splashImage, "$bootPath/background$suffix" or die "cannot copy $splashImage to $bootPath: $!\n";
$conf .= "
insmod " . substr($suffix, 1) . "
if background_image --mode '$splashMode' " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/background$suffix; then
@@ -328,6 +373,28 @@ else {
fi
";
}
+
+ rmtree("$bootPath/theme") or die "cannot clean up theme folder in $bootPath\n" if -e "$bootPath/theme";
+
+ if ($theme) {
+ # Copy theme
+ rcopy($theme, "$bootPath/theme") or die "cannot copy $theme to $bootPath\n";
+ $conf .= "
+ # Sets theme.
+ set theme=" . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/theme.txt
+ export theme
+ # Load theme fonts, if any
+ ";
+
+ find( { wanted => sub {
+ if ($_ =~ /\.pf2$/i) {
+ $font = File::Spec->abs2rel($File::Find::name, $theme);
+ $conf .= "
+ loadfont " . ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/theme/$font
+ ";
+ }
+ }, no_chdir => 1 }, $theme );
+ }
}
$conf .= "$extraConfig\n";
@@ -350,22 +417,43 @@ sub copyToKernelsDir {
# kernels or initrd if this script is ever interrupted.
if (! -e $dst) {
my $tmp = "$dst.tmp";
- copy $path, $tmp or die "cannot copy $path to $tmp\n";
- rename $tmp, $dst or die "cannot rename $tmp to $dst\n";
+ copy $path, $tmp or die "cannot copy $path to $tmp: $!\n";
+ rename $tmp, $dst or die "cannot rename $tmp to $dst: $!\n";
}
$copied{$dst} = 1;
return ($grubBoot->path eq "/" ? "" : $grubBoot->path) . "/kernels/$name";
}
sub addEntry {
- my ($name, $path) = @_;
+ my ($name, $path, $options) = @_;
return unless -e "$path/kernel" && -e "$path/initrd";
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
@@ -383,14 +471,11 @@ sub addEntry {
$conf .= " " . ($xen ? "module" : "kernel") . " $kernel $kernelParams\n";
$conf .= " " . ($xen ? "module" : "initrd") . " $initrd\n\n";
} else {
- $conf .= "menuentry \"$name\" {\n";
+ $conf .= "menuentry \"$name\" " . ($options||"") . " {\n";
$conf .= $grubBoot->search . "\n";
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";
@@ -403,7 +488,7 @@ sub addEntry {
# Add default entries.
$conf .= "$extraEntries\n" if $extraEntriesBeforeNixOS;
-addEntry("NixOS - Default", $defaultConfig);
+addEntry("NixOS - Default", $defaultConfig, "--unrestricted");
$conf .= "$extraEntries\n" unless $extraEntriesBeforeNixOS;
@@ -526,7 +611,7 @@ if (get("useOSProber") eq "true") {
}
# Atomically switch to the new config
-rename $tmpFile, $confFile or die "cannot rename $tmpFile to $confFile\n";
+rename $tmpFile, $confFile or die "cannot rename $tmpFile to $confFile: $!\n";
# Remove obsolete files from $bootPath/kernels.
@@ -547,9 +632,12 @@ struct(GrubState => {
efi => '$',
devices => '$',
efiMountPoint => '$',
+ extraGrubInstallArgs => '@',
});
+# If you add something to the state file, only add it to the end
+# because it is read line-by-line.
sub readGrubState {
- my $defaultGrubState = GrubState->new(name => "", version => "", efi => "", devices => "", efiMountPoint => "" );
+ my $defaultGrubState = GrubState->new(name => "", version => "", efi => "", devices => "", efiMountPoint => "", extraGrubInstallArgs => () );
open FILE, "<$bootPath/grub/state" or return $defaultGrubState;
local $/ = "\n";
my $name = <FILE>;
@@ -562,24 +650,37 @@ sub readGrubState {
chomp($devices);
my $efiMountPoint = <FILE>;
chomp($efiMountPoint);
+ # Historically, arguments in the state file were one per each line, but that
+ # gets really messy when newlines are involved, structured arguments
+ # like lists are needed (they have to have a separator encoding), or even worse,
+ # when we need to remove a setting in the future. Thus, the 6th line is a JSON
+ # object that can store structured data, with named keys, and all new state
+ # should go in there.
+ my $jsonStateLine = <FILE>;
+ # For historical reasons we do not check the values above for un-definedness
+ # (that is, when the state file has too few lines and EOF is reached),
+ # because the above come from the first version of this logic and are thus
+ # guaranteed to be present.
+ $jsonStateLine = defined $jsonStateLine ? $jsonStateLine : '{}'; # empty JSON object
+ chomp($jsonStateLine);
+ if ($jsonStateLine eq "") {
+ $jsonStateLine = '{}'; # empty JSON object
+ }
+ my %jsonState = %{decode_json($jsonStateLine)};
+ my @extraGrubInstallArgs = exists($jsonState{'extraGrubInstallArgs'}) ? @{$jsonState{'extraGrubInstallArgs'}} : ();
close FILE;
- my $grubState = GrubState->new(name => $name, version => $version, efi => $efi, devices => $devices, efiMountPoint => $efiMountPoint );
+ my $grubState = GrubState->new(name => $name, version => $version, efi => $efi, devices => $devices, efiMountPoint => $efiMountPoint, extraGrubInstallArgs => \@extraGrubInstallArgs );
return $grubState
}
-sub getDeviceTargets {
- my @devices = ();
- foreach my $dev ($dom->findnodes('/expr/attrs/attr[@name = "devices"]/list/string/@value')) {
- $dev = $dev->findvalue(".") or die;
- push(@devices, $dev);
- }
- return @devices;
-}
-my @deviceTargets = getDeviceTargets();
+my @deviceTargets = getList('devices');
my $prevGrubState = readGrubState();
my @prevDeviceTargets = split/,/, $prevGrubState->devices;
+my @extraGrubInstallArgs = getList('extraGrubInstallArgs');
+my @prevExtraGrubInstallArgs = @{$prevGrubState->extraGrubInstallArgs};
my $devicesDiffer = scalar (List::Compare->new( '-u', '-a', \@deviceTargets, \@prevDeviceTargets)->get_symmetric_difference());
+my $extraGrubInstallArgsDiffer = scalar (List::Compare->new( '-u', '-a', \@extraGrubInstallArgs, \@prevExtraGrubInstallArgs)->get_symmetric_difference());
my $nameDiffer = get("fullName") ne $prevGrubState->name;
my $versionDiffer = get("fullVersion") ne $prevGrubState->version;
my $efiDiffer = $efiTarget ne $prevGrubState->efi;
@@ -588,25 +689,25 @@ if (($ENV{'NIXOS_INSTALL_GRUB'} // "") eq "1") {
warn "NIXOS_INSTALL_GRUB env var deprecated, use NIXOS_INSTALL_BOOTLOADER";
$ENV{'NIXOS_INSTALL_BOOTLOADER'} = "1";
}
-my $requireNewInstall = $devicesDiffer || $nameDiffer || $versionDiffer || $efiDiffer || $efiMountPointDiffer || (($ENV{'NIXOS_INSTALL_BOOTLOADER'} // "") eq "1");
+my $requireNewInstall = $devicesDiffer || $extraGrubInstallArgsDiffer || $nameDiffer || $versionDiffer || $efiDiffer || $efiMountPointDiffer || (($ENV{'NIXOS_INSTALL_BOOTLOADER'} // "") eq "1");
# install a symlink so that grub can detect the boot drive
-my $tmpDir = File::Temp::tempdir(CLEANUP => 1) or die "Failed to create temporary space";
-symlink "$bootPath", "$tmpDir/boot" or die "Failed to symlink $tmpDir/boot";
+my $tmpDir = File::Temp::tempdir(CLEANUP => 1) or die "Failed to create temporary space: $!";
+symlink "$bootPath", "$tmpDir/boot" or die "Failed to symlink $tmpDir/boot: $!";
# install non-EFI GRUB
if (($requireNewInstall != 0) && ($efiTarget eq "no" || $efiTarget eq "both")) {
foreach my $dev (@deviceTargets) {
next if $dev eq "nodev";
print STDERR "installing the GRUB $grubVersion boot loader on $dev...\n";
- my @command = ("$grub/sbin/grub-install", "--recheck", "--root-directory=$tmpDir", Cwd::abs_path($dev));
+ my @command = ("$grub/sbin/grub-install", "--recheck", "--root-directory=$tmpDir", Cwd::abs_path($dev), @extraGrubInstallArgs);
if ($forceInstall eq "true") {
push @command, "--force";
}
if ($grubTarget ne "") {
push @command, "--target=$grubTarget";
}
- (system @command) == 0 or die "$0: installation of GRUB on $dev failed\n";
+ (system @command) == 0 or die "$0: installation of GRUB on $dev failed: $!\n";
}
}
@@ -614,7 +715,7 @@ if (($requireNewInstall != 0) && ($efiTarget eq "no" || $efiTarget eq "both")) {
# install EFI GRUB
if (($requireNewInstall != 0) && ($efiTarget eq "only" || $efiTarget eq "both")) {
print STDERR "installing the GRUB $grubVersion EFI boot loader into $efiSysMountPoint...\n";
- my @command = ("$grubEfi/sbin/grub-install", "--recheck", "--target=$grubTargetEfi", "--boot-directory=$bootPath", "--efi-directory=$efiSysMountPoint");
+ my @command = ("$grubEfi/sbin/grub-install", "--recheck", "--target=$grubTargetEfi", "--boot-directory=$bootPath", "--efi-directory=$efiSysMountPoint", @extraGrubInstallArgs);
if ($forceInstall eq "true") {
push @command, "--force";
}
@@ -625,17 +726,29 @@ if (($requireNewInstall != 0) && ($efiTarget eq "only" || $efiTarget eq "both"))
push @command, "--removable" if $efiInstallAsRemovable eq "true";
}
- (system @command) == 0 or die "$0: installation of GRUB EFI into $efiSysMountPoint failed\n";
+ (system @command) == 0 or die "$0: installation of GRUB EFI into $efiSysMountPoint failed: $!\n";
}
# update GRUB state file
if ($requireNewInstall != 0) {
- open FILE, ">$bootPath/grub/state" or die "cannot create $bootPath/grub/state: $!\n";
+ # Temp file for atomic rename.
+ my $stateFile = "$bootPath/grub/state";
+ my $stateFileTmp = $stateFile . ".tmp";
+
+ open FILE, ">$stateFileTmp" or die "cannot create $stateFileTmp: $!\n";
print FILE get("fullName"), "\n" or die;
print FILE get("fullVersion"), "\n" or die;
print FILE $efiTarget, "\n" or die;
print FILE join( ",", @deviceTargets ), "\n" or die;
print FILE $efiSysMountPoint, "\n" or die;
+ my %jsonState = (
+ extraGrubInstallArgs => \@extraGrubInstallArgs
+ );
+ my $jsonStateLine = encode_json(\%jsonState);
+ print FILE $jsonStateLine, "\n" or die;
close FILE or die;
+
+ # Atomically switch to the new state file
+ rename $stateFileTmp, $stateFile or die "cannot rename $stateFileTmp to $stateFile: $!\n";
}
diff --git a/nixpkgs/nixos/modules/system/boot/loader/init-script/init-script-builder.sh b/nixpkgs/nixos/modules/system/boot/loader/init-script/init-script-builder.sh
index 6f48d2539ac..2a1ec479fea 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/init-script/init-script-builder.sh
+++ b/nixpkgs/nixos/modules/system/boot/loader/init-script/init-script-builder.sh
@@ -53,7 +53,7 @@ addEntry() {
echo "exec $stage2"
)"
- [ "$path" != "$defaultConfig" ] || {
+ [ "$path" != "$defaultConfig" ] || {
echo "$content" > $tmp
echo "# older configurations: $targetOther" >> $tmp
chmod +x $tmp
diff --git a/nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.nix b/nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.nix
index e75aa9d1387..7eb52e3d021 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.nix
+++ b/nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.nix
@@ -3,8 +3,8 @@
pkgs.substituteAll {
src = ./raspberrypi-builder.sh;
isExecutable = true;
- inherit (pkgs.buildPackages) bash;
- path = with pkgs.buildPackages; [coreutils gnused gnugrep];
+ inherit (pkgs) bash;
+ path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
firmware = pkgs.raspberrypifw;
inherit configTxt;
}
diff --git a/nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.sh b/nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.sh
index c8b5bf2e61a..0541ca1ba62 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.sh
+++ b/nixpkgs/nixos/modules/system/boot/loader/raspberrypi/raspberrypi-builder.sh
@@ -1,4 +1,7 @@
-#! @bash@/bin/sh -e
+#! @bash@/bin/sh
+
+# This can end up being called disregarding the shebang.
+set -e
shopt -s nullglob
diff --git a/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py b/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
index f48a085ce57..65c7b825f85 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py
+++ b/nixpkgs/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" % (profile, generation))
else:
- f.write("default nixos-generation-%d\n" % (generation))
+ f.write("default nixos-generation-%d.conf\n" % (generation))
if not @editor@:
f.write("editor 0\n");
f.write("console-mode @consoleMode@\n");
@@ -197,6 +197,24 @@ 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]
+ # Ideally this should use check_output as well, but as a temporary
+ # work-around for #97433 we ignore any errors.
+ sdboot_status = subprocess.run(["@systemd@/bin/bootctl", "--path=@efiSysMountPoint@", "status"], universal_newlines=True, stdout=subprocess.PIPE).stdout
+
+ # 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/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix b/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
index 22d459ceb04..f0bd76a3c1d 100644
--- a/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
+++ b/nixpkgs/nixos/modules/system/boot/loader/systemd-boot/systemd-boot.nix
@@ -64,10 +64,10 @@ in {
example = 120;
type = types.nullOr types.int;
description = ''
- Maximum number of latest generations in the boot menu.
+ Maximum number of latest generations in the boot menu.
Useful to prevent boot partition running out of disk space.
- <literal>null</literal> means no limit i.e. all generations
+ <literal>null</literal> means no limit i.e. all generations
that were not garbage collected yet.
'';
};
diff --git a/nixpkgs/nixos/modules/system/boot/luksroot.nix b/nixpkgs/nixos/modules/system/boot/luksroot.nix
index 31f1e22cda3..88190e8200b 100644
--- a/nixpkgs/nixos/modules/system/boot/luksroot.nix
+++ b/nixpkgs/nixos/modules/system/boot/luksroot.nix
@@ -140,7 +140,7 @@ let
umount /crypt-ramfs 2>/dev/null
'';
- openCommand = name': { name, device, header, keyFile, keyFileSize, keyFileOffset, allowDiscards, yubikey, gpgCard, fido2, fallbackToPassword, ... }: assert name' == name;
+ openCommand = name': { name, device, header, keyFile, keyFileSize, keyFileOffset, allowDiscards, yubikey, gpgCard, fido2, fallbackToPassword, preOpenCommands, postOpenCommands,... }: assert name' == name;
let
csopen = "cryptsetup luksOpen ${device} ${name} ${optionalString allowDiscards "--allow-discards"} ${optionalString (header != null) "--header=${header}"}";
cschange = "cryptsetup luksChangeKey ${device} ${optionalString (header != null) "--header=${header}"}";
@@ -412,11 +412,17 @@ let
}
''}
+ # commands to run right before we mount our device
+ ${preOpenCommands}
+
${if (luks.yubikeySupport && (yubikey != null)) || (luks.gpgSupport && (gpgCard != null)) || (luks.fido2Support && (fido2.credential != null)) then ''
open_with_hardware
'' else ''
open_normally
''}
+
+ # commands to run right after we mounted our device
+ ${postOpenCommands}
'';
askPass = pkgs.writeScriptBin "cryptsetup-askpass" ''
@@ -467,8 +473,6 @@ in
[ "aes" "aes_generic" "blowfish" "twofish"
"serpent" "cbc" "xts" "lrw" "sha1" "sha256" "sha512"
"af_alg" "algif_skcipher"
-
- (if pkgs.stdenv.hostPlatform.system == "x86_64-linux" then "aes_x86_64" else "aes_i586")
];
description = ''
A list of cryptographic kernel modules needed to decrypt the root device(s).
@@ -512,7 +516,7 @@ in
<filename>/dev/mapper/<replaceable>name</replaceable></filename>.
'';
- type = with types; loaOf (submodule (
+ type = with types; attrsOf (submodule (
{ name, ... }: { options = {
name = mkOption {
@@ -637,7 +641,7 @@ in
credential = mkOption {
default = null;
example = "f1d00200d8dc783f7fb1e10ace8da27f8312d72692abfca2f7e4960a73f48e82e1f7571f6ebfcee9fb434f9886ccc8fcc52a6614d8d2";
- type = types.str;
+ type = types.nullOr types.str;
description = "The FIDO2 credential ID.";
};
@@ -735,6 +739,30 @@ in
};
});
};
+
+ preOpenCommands = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ mkdir -p /tmp/persistent
+ mount -t zfs rpool/safe/persistent /tmp/persistent
+ '';
+ description = ''
+ Commands that should be run right before we try to mount our LUKS device.
+ This can be useful, if the keys needed to open the drive is on another partion.
+ '';
+ };
+
+ postOpenCommands = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ umount /tmp/persistent
+ '';
+ description = ''
+ Commands that should be run right after we have mounted our LUKS device.
+ '';
+ };
};
}));
};
diff --git a/nixpkgs/nixos/modules/system/boot/modprobe.nix b/nixpkgs/nixos/modules/system/boot/modprobe.nix
index dee0ab470c9..c75f32c4d99 100644
--- a/nixpkgs/nixos/modules/system/boot/modprobe.nix
+++ b/nixpkgs/nixos/modules/system/boot/modprobe.nix
@@ -28,7 +28,7 @@ with lib;
Any additional configuration to be appended to the generated
<filename>modprobe.conf</filename>. This is typically used to
specify module options. See
- <citerefentry><refentrytitle>modprobe.conf</refentrytitle>
+ <citerefentry><refentrytitle>modprobe.d</refentrytitle>
<manvolnum>5</manvolnum></citerefentry> for details.
'';
type = types.lines;
diff --git a/nixpkgs/nixos/modules/system/boot/networkd.nix b/nixpkgs/nixos/modules/system/boot/networkd.nix
index 9b34b12e73a..47689b2a470 100644
--- a/nixpkgs/nixos/modules/system/boot/networkd.nix
+++ b/nixpkgs/nixos/modules/system/boot/networkd.nix
@@ -8,359 +8,714 @@ let
cfg = config.systemd.network;
- checkLink = checkUnitConfig "Link" [
- (assertOnlyFields [
- "Description" "Alias" "MACAddressPolicy" "MACAddress" "NamePolicy" "Name" "OriginalName"
- "MTUBytes" "BitsPerSecond" "Duplex" "AutoNegotiation" "WakeOnLan" "Port" "Advertise"
- "TCPSegmentationOffload" "TCP6SegmentationOffload" "GenericSegmentationOffload"
- "GenericReceiveOffload" "LargeReceiveOffload" "RxChannels" "TxChannels"
- "OtherChannels" "CombinedChannels"
- ])
- (assertValueOneOf "MACAddressPolicy" ["persistent" "random" "none"])
- (assertMacAddress "MACAddress")
- (assertByteFormat "MTUBytes")
- (assertByteFormat "BitsPerSecond")
- (assertValueOneOf "Duplex" ["half" "full"])
- (assertValueOneOf "AutoNegotiation" boolValues)
- (assertValueOneOf "WakeOnLan" ["phy" "unicast" "multicast" "broadcast" "arp" "magic" "secureon" "off"])
- (assertValueOneOf "Port" ["tp" "aui" "bnc" "mii" "fibre"])
- (assertValueOneOf "TCPSegmentationOffload" boolValues)
- (assertValueOneOf "TCP6SegmentationOffload" boolValues)
- (assertValueOneOf "GenericSegmentationOffload" boolValues)
- (assertValueOneOf "UDPSegmentationOffload" boolValues)
- (assertValueOneOf "GenericReceiveOffload" boolValues)
- (assertValueOneOf "LargeReceiveOffload" boolValues)
- (assertInt "RxChannels")
- (assertMinimum "RxChannels" 1)
- (assertInt "TxChannels")
- (assertMinimum "TxChannels" 1)
- (assertInt "OtherChannels")
- (assertMinimum "OtherChannels" 1)
- (assertInt "CombinedChannels")
- (assertMinimum "CombinedChannels" 1)
- ];
-
- checkNetdev = checkUnitConfig "Netdev" [
- (assertOnlyFields [
- "Description" "Name" "Kind" "MTUBytes" "MACAddress"
- ])
- (assertHasField "Name")
- (assertHasField "Kind")
- (assertValueOneOf "Kind" [
- "bond" "bridge" "dummy" "gre" "gretap" "ip6gre" "ip6tnl" "ip6gretap" "ipip"
- "ipvlan" "macvlan" "macvtap" "sit" "tap" "tun" "veth" "vlan" "vti" "vti6"
- "vxlan" "geneve" "vrf" "vcan" "vxcan" "wireguard" "netdevsim" "xfrm"
- ])
- (assertByteFormat "MTUBytes")
- (assertMacAddress "MACAddress")
- ];
-
- checkVRF = checkUnitConfig "VRF" [
- (assertOnlyFields [ "Table" ])
- (assertMinimum "Table" 0)
- ];
+ check = {
+
+ link = {
+
+ sectionLink = checkUnitConfig "Link" [
+ (assertOnlyFields [
+ "Description"
+ "Alias"
+ "MACAddressPolicy"
+ "MACAddress"
+ "NamePolicy"
+ "Name"
+ "AlternativeNamesPolicy"
+ "AlternativeName"
+ "MTUBytes"
+ "BitsPerSecond"
+ "Duplex"
+ "AutoNegotiation"
+ "WakeOnLan"
+ "Port"
+ "Advertise"
+ "ReceiveChecksumOffload"
+ "TransmitChecksumOffload"
+ "TCPSegmentationOffload"
+ "TCP6SegmentationOffload"
+ "GenericSegmentationOffload"
+ "GenericReceiveOffload"
+ "LargeReceiveOffload"
+ "RxChannels"
+ "TxChannels"
+ "OtherChannels"
+ "CombinedChannels"
+ "RxBufferSize"
+ "TxBufferSize"
+ ])
+ (assertValueOneOf "MACAddressPolicy" ["persistent" "random" "none"])
+ (assertMacAddress "MACAddress")
+ (assertByteFormat "MTUBytes")
+ (assertByteFormat "BitsPerSecond")
+ (assertValueOneOf "Duplex" ["half" "full"])
+ (assertValueOneOf "AutoNegotiation" boolValues)
+ (assertValueOneOf "WakeOnLan" ["phy" "unicast" "multicast" "broadcast" "arp" "magic" "secureon" "off"])
+ (assertValueOneOf "Port" ["tp" "aui" "bnc" "mii" "fibre"])
+ (assertValueOneOf "ReceiveChecksumOffload" boolValues)
+ (assertValueOneOf "TransmitChecksumOffload" boolValues)
+ (assertValueOneOf "TCPSegmentationOffload" boolValues)
+ (assertValueOneOf "TCP6SegmentationOffload" boolValues)
+ (assertValueOneOf "GenericSegmentationOffload" boolValues)
+ (assertValueOneOf "GenericReceiveOffload" boolValues)
+ (assertValueOneOf "LargeReceiveOffload" boolValues)
+ (assertInt "RxChannels")
+ (assertRange "RxChannels" 1 4294967295)
+ (assertInt "TxChannels")
+ (assertRange "TxChannels" 1 4294967295)
+ (assertInt "OtherChannels")
+ (assertRange "OtherChannels" 1 4294967295)
+ (assertInt "CombinedChannels")
+ (assertRange "CombinedChannels" 1 4294967295)
+ (assertInt "RxBufferSize")
+ (assertInt "TxBufferSize")
+ ];
+ };
- # NOTE The PrivateKey directive is missing on purpose here, please
- # do not add it to this list. The nix store is world-readable let's
- # refrain ourselves from providing a footgun.
- checkWireGuard = checkUnitConfig "WireGuard" [
- (assertOnlyFields [
- "PrivateKeyFile" "ListenPort" "FwMark"
- ])
- # The following check won't work on nix <= 2.2
- # see https://github.com/NixOS/nix/pull/2378
- #
- # Add this again when we'll have drop the
- # nix < 2.2 support.
- # (assertRange "FwMark" 1 4294967295)
- ];
+ netdev = let
+
+ tunChecks = [
+ (assertOnlyFields [
+ "MultiQueue"
+ "PacketInfo"
+ "VNetHeader"
+ "User"
+ "Group"
+ ])
+ (assertValueOneOf "MultiQueue" boolValues)
+ (assertValueOneOf "PacketInfo" boolValues)
+ (assertValueOneOf "VNetHeader" boolValues)
+ ];
+ in {
+
+ sectionNetdev = checkUnitConfig "Netdev" [
+ (assertOnlyFields [
+ "Description"
+ "Name"
+ "Kind"
+ "MTUBytes"
+ "MACAddress"
+ ])
+ (assertHasField "Name")
+ (assertHasField "Kind")
+ (assertValueOneOf "Kind" [
+ "bond"
+ "bridge"
+ "dummy"
+ "gre"
+ "gretap"
+ "erspan"
+ "ip6gre"
+ "ip6tnl"
+ "ip6gretap"
+ "ipip"
+ "ipvlan"
+ "macvlan"
+ "macvtap"
+ "sit"
+ "tap"
+ "tun"
+ "veth"
+ "vlan"
+ "vti"
+ "vti6"
+ "vxlan"
+ "geneve"
+ "l2tp"
+ "macsec"
+ "vrf"
+ "vcan"
+ "vxcan"
+ "wireguard"
+ "netdevsim"
+ "nlmon"
+ "fou"
+ "xfrm"
+ "ifb"
+ ])
+ (assertByteFormat "MTUBytes")
+ (assertMacAddress "MACAddress")
+ ];
- # NOTE The PresharedKey directive is missing on purpose here, please
- # do not add it to this list. The nix store is world-readable,let's
- # refrain ourselves from providing a footgun.
- checkWireGuardPeer = checkUnitConfig "WireGuardPeer" [
- (assertOnlyFields [
- "PublicKey" "PresharedKeyFile" "AllowedIPs"
- "Endpoint" "PersistentKeepalive"
- ])
- (assertRange "PersistentKeepalive" 1 65535)
- ];
+ sectionVLAN = checkUnitConfig "VLAN" [
+ (assertOnlyFields [
+ "Id"
+ "GVRP"
+ "MVRP"
+ "LooseBinding"
+ "ReorderHeader"
+ ])
+ (assertInt "Id")
+ (assertRange "Id" 0 4094)
+ (assertValueOneOf "GVRP" boolValues)
+ (assertValueOneOf "MVRP" boolValues)
+ (assertValueOneOf "LooseBinding" boolValues)
+ (assertValueOneOf "ReorderHeader" boolValues)
+ ];
- checkVlan = checkUnitConfig "VLAN" [
- (assertOnlyFields ["Id" "GVRP" "MVRP" "LooseBinding" "ReorderHeader"])
- (assertRange "Id" 0 4094)
- (assertValueOneOf "GVRP" boolValues)
- (assertValueOneOf "MVRP" boolValues)
- (assertValueOneOf "LooseBinding" boolValues)
- (assertValueOneOf "ReorderHeader" boolValues)
- ];
+ sectionMACVLAN = checkUnitConfig "MACVLAN" [
+ (assertOnlyFields [
+ "Mode"
+ ])
+ (assertValueOneOf "Mode" ["private" "vepa" "bridge" "passthru"])
+ ];
- checkMacvlan = checkUnitConfig "MACVLAN" [
- (assertOnlyFields ["Mode"])
- (assertValueOneOf "Mode" ["private" "vepa" "bridge" "passthru"])
- ];
+ sectionVXLAN = checkUnitConfig "VXLAN" [
+ (assertOnlyFields [
+ "VNI"
+ "Remote"
+ "Local"
+ "Group"
+ "TOS"
+ "TTL"
+ "MacLearning"
+ "FDBAgeingSec"
+ "MaximumFDBEntries"
+ "ReduceARPProxy"
+ "L2MissNotification"
+ "L3MissNotification"
+ "RouteShortCircuit"
+ "UDPChecksum"
+ "UDP6ZeroChecksumTx"
+ "UDP6ZeroChecksumRx"
+ "RemoteChecksumTx"
+ "RemoteChecksumRx"
+ "GroupPolicyExtension"
+ "GenericProtocolExtension"
+ "DestinationPort"
+ "PortRange"
+ "FlowLabel"
+ "IPDoNotFragment"
+ ])
+ (assertInt "VNI")
+ (assertRange "VNI" 1 16777215)
+ (assertValueOneOf "MacLearning" boolValues)
+ (assertInt "MaximumFDBEntries")
+ (assertValueOneOf "ReduceARPProxy" boolValues)
+ (assertValueOneOf "L2MissNotification" boolValues)
+ (assertValueOneOf "L3MissNotification" boolValues)
+ (assertValueOneOf "RouteShortCircuit" boolValues)
+ (assertValueOneOf "UDPChecksum" boolValues)
+ (assertValueOneOf "UDP6ZeroChecksumTx" boolValues)
+ (assertValueOneOf "UDP6ZeroChecksumRx" boolValues)
+ (assertValueOneOf "RemoteChecksumTx" boolValues)
+ (assertValueOneOf "RemoteChecksumRx" boolValues)
+ (assertValueOneOf "GroupPolicyExtension" boolValues)
+ (assertValueOneOf "GenericProtocolExtension" boolValues)
+ (assertInt "FlowLabel")
+ (assertRange "FlowLabel" 0 1048575)
+ (assertValueOneOf "IPDoNotFragment" (boolValues + ["inherit"]))
+ ];
- checkVxlan = checkUnitConfig "VXLAN" [
- (assertOnlyFields [
- "Id" "Remote" "Local" "TOS" "TTL" "MacLearning" "FDBAgeingSec"
- "MaximumFDBEntries" "ReduceARPProxy" "L2MissNotification"
- "L3MissNotification" "RouteShortCircuit" "UDPChecksum"
- "UDP6ZeroChecksumTx" "UDP6ZeroChecksumRx" "RemoteChecksumTx"
- "RemoteChecksumRx" "GroupPolicyExtension" "DestinationPort" "PortRange"
- "FlowLabel"
- ])
- (assertRange "TTL" 0 255)
- (assertValueOneOf "MacLearning" boolValues)
- (assertValueOneOf "ReduceARPProxy" boolValues)
- (assertValueOneOf "L2MissNotification" boolValues)
- (assertValueOneOf "L3MissNotification" boolValues)
- (assertValueOneOf "RouteShortCircuit" boolValues)
- (assertValueOneOf "UDPChecksum" boolValues)
- (assertValueOneOf "UDP6ZeroChecksumTx" boolValues)
- (assertValueOneOf "UDP6ZeroChecksumRx" boolValues)
- (assertValueOneOf "RemoteChecksumTx" boolValues)
- (assertValueOneOf "RemoteChecksumRx" boolValues)
- (assertValueOneOf "GroupPolicyExtension" boolValues)
- (assertRange "FlowLabel" 0 1048575)
- ];
+ sectionTunnel = checkUnitConfig "Tunnel" [
+ (assertOnlyFields [
+ "Local"
+ "Remote"
+ "TOS"
+ "TTL"
+ "DiscoverPathMTU"
+ "IPv6FlowLabel"
+ "CopyDSCP"
+ "EncapsulationLimit"
+ "Key"
+ "InputKey"
+ "OutputKey"
+ "Mode"
+ "Independent"
+ "AssignToLoopback"
+ "AllowLocalRemote"
+ "FooOverUDP"
+ "FOUDestinationPort"
+ "FOUSourcePort"
+ "Encapsulation"
+ "IPv6RapidDeploymentPrefix"
+ "ISATAP"
+ "SerializeTunneledPackets"
+ "ERSPANIndex"
+ ])
+ (assertInt "TTL")
+ (assertRange "TTL" 0 255)
+ (assertValueOneOf "DiscoverPathMTU" boolValues)
+ (assertValueOneOf "CopyDSCP" boolValues)
+ (assertValueOneOf "Mode" ["ip6ip6" "ipip6" "any"])
+ (assertValueOneOf "Independent" boolValues)
+ (assertValueOneOf "AssignToLoopback" boolValues)
+ (assertValueOneOf "AllowLocalRemote" boolValues)
+ (assertValueOneOf "FooOverUDP" boolValues)
+ (assertPort "FOUDestinationPort")
+ (assertPort "FOUSourcePort")
+ (assertValueOneOf "Encapsulation" ["FooOverUDP" "GenericUDPEncapsulation"])
+ (assertValueOneOf "ISATAP" boolValues)
+ (assertValueOneOf "SerializeTunneledPackets" boolValues)
+ (assertInt "ERSPANIndex")
+ (assertRange "ERSPANIndex" 1 1048575)
+ ];
- checkTunnel = checkUnitConfig "Tunnel" [
- (assertOnlyFields [
- "Local" "Remote" "TOS" "TTL" "DiscoverPathMTU" "IPv6FlowLabel" "CopyDSCP"
- "EncapsulationLimit" "Key" "InputKey" "OutputKey" "Mode" "Independent"
- "AllowLocalRemote"
- ])
- (assertRange "TTL" 0 255)
- (assertValueOneOf "DiscoverPathMTU" boolValues)
- (assertValueOneOf "CopyDSCP" boolValues)
- (assertValueOneOf "Mode" ["ip6ip6" "ipip6" "any"])
- (assertValueOneOf "Independent" boolValues)
- (assertValueOneOf "AllowLocalRemote" boolValues)
- ];
+ sectionPeer = checkUnitConfig "Peer" [
+ (assertOnlyFields [
+ "Name"
+ "MACAddress"
+ ])
+ (assertMacAddress "MACAddress")
+ ];
- checkPeer = checkUnitConfig "Peer" [
- (assertOnlyFields ["Name" "MACAddress"])
- (assertMacAddress "MACAddress")
- ];
+ sectionTun = checkUnitConfig "Tun" tunChecks;
+
+ sectionTap = checkUnitConfig "Tap" tunChecks;
+
+ # NOTE The PrivateKey directive is missing on purpose here, please
+ # do not add it to this list. The nix store is world-readable let's
+ # refrain ourselves from providing a footgun.
+ sectionWireGuard = checkUnitConfig "WireGuard" [
+ (assertOnlyFields [
+ "PrivateKeyFile"
+ "ListenPort"
+ "FirewallMark"
+ ])
+ (assertInt "FirewallMark")
+ (assertRange "FirewallMark" 1 4294967295)
+ ];
- tunTapChecks = [
- (assertOnlyFields ["OneQueue" "MultiQueue" "PacketInfo" "VNetHeader" "User" "Group"])
- (assertValueOneOf "OneQueue" boolValues)
- (assertValueOneOf "MultiQueue" boolValues)
- (assertValueOneOf "PacketInfo" boolValues)
- (assertValueOneOf "VNetHeader" boolValues)
- ];
+ # NOTE The PresharedKey directive is missing on purpose here, please
+ # do not add it to this list. The nix store is world-readable,let's
+ # refrain ourselves from providing a footgun.
+ sectionWireGuardPeer = checkUnitConfig "WireGuardPeer" [
+ (assertOnlyFields [
+ "PublicKey"
+ "PresharedKeyFile"
+ "AllowedIPs"
+ "Endpoint"
+ "PersistentKeepalive"
+ ])
+ (assertInt "PersistentKeepalive")
+ (assertRange "PersistentKeepalive" 0 65535)
+ ];
- checkTun = checkUnitConfig "Tun" tunTapChecks;
-
- checkTap = checkUnitConfig "Tap" tunTapChecks;
-
- checkBond = checkUnitConfig "Bond" [
- (assertOnlyFields [
- "Mode" "TransmitHashPolicy" "LACPTransmitRate" "MIIMonitorSec"
- "UpDelaySec" "DownDelaySec" "LearnPacketIntervalSec" "AdSelect"
- "FailOverMACPolicy" "ARPValidate" "ARPIntervalSec" "ARPIPTargets"
- "ARPAllTargets" "PrimaryReselectPolicy" "ResendIGMP" "PacketsPerSlave"
- "GratuitousARP" "AllSlavesActive" "MinLinks"
- ])
- (assertValueOneOf "Mode" [
- "balance-rr" "active-backup" "balance-xor"
- "broadcast" "802.3ad" "balance-tlb" "balance-alb"
- ])
- (assertValueOneOf "TransmitHashPolicy" [
- "layer2" "layer3+4" "layer2+3" "encap2+3" "encap3+4"
- ])
- (assertValueOneOf "LACPTransmitRate" ["slow" "fast"])
- (assertValueOneOf "AdSelect" ["stable" "bandwidth" "count"])
- (assertValueOneOf "FailOverMACPolicy" ["none" "active" "follow"])
- (assertValueOneOf "ARPValidate" ["none" "active" "backup" "all"])
- (assertValueOneOf "ARPAllTargets" ["any" "all"])
- (assertValueOneOf "PrimaryReselectPolicy" ["always" "better" "failure"])
- (assertRange "ResendIGMP" 0 255)
- (assertRange "PacketsPerSlave" 0 65535)
- (assertRange "GratuitousARP" 0 255)
- (assertValueOneOf "AllSlavesActive" boolValues)
- ];
+ sectionBond = checkUnitConfig "Bond" [
+ (assertOnlyFields [
+ "Mode"
+ "TransmitHashPolicy"
+ "LACPTransmitRate"
+ "MIIMonitorSec"
+ "UpDelaySec"
+ "DownDelaySec"
+ "LearnPacketIntervalSec"
+ "AdSelect"
+ "AdActorSystemPriority"
+ "AdUserPortKey"
+ "AdActorSystem"
+ "FailOverMACPolicy"
+ "ARPValidate"
+ "ARPIntervalSec"
+ "ARPIPTargets"
+ "ARPAllTargets"
+ "PrimaryReselectPolicy"
+ "ResendIGMP"
+ "PacketsPerSlave"
+ "GratuitousARP"
+ "AllSlavesActive"
+ "DynamicTransmitLoadBalancing"
+ "MinLinks"
+ ])
+ (assertValueOneOf "Mode" [
+ "balance-rr"
+ "active-backup"
+ "balance-xor"
+ "broadcast"
+ "802.3ad"
+ "balance-tlb"
+ "balance-alb"
+ ])
+ (assertValueOneOf "TransmitHashPolicy" [
+ "layer2"
+ "layer3+4"
+ "layer2+3"
+ "encap2+3"
+ "encap3+4"
+ ])
+ (assertValueOneOf "LACPTransmitRate" ["slow" "fast"])
+ (assertValueOneOf "AdSelect" ["stable" "bandwidth" "count"])
+ (assertInt "AdActorSystemPriority")
+ (assertRange "AdActorSystemPriority" 1 65535)
+ (assertInt "AdUserPortKey")
+ (assertRange "AdUserPortKey" 0 1023)
+ (assertValueOneOf "FailOverMACPolicy" ["none" "active" "follow"])
+ (assertValueOneOf "ARPValidate" ["none" "active" "backup" "all"])
+ (assertValueOneOf "ARPAllTargets" ["any" "all"])
+ (assertValueOneOf "PrimaryReselectPolicy" ["always" "better" "failure"])
+ (assertInt "ResendIGMP")
+ (assertRange "ResendIGMP" 0 255)
+ (assertInt "PacketsPerSlave")
+ (assertRange "PacketsPerSlave" 0 65535)
+ (assertInt "GratuitousARP")
+ (assertRange "GratuitousARP" 0 255)
+ (assertValueOneOf "AllSlavesActive" boolValues)
+ (assertValueOneOf "DynamicTransmitLoadBalancing" boolValues)
+ (assertInt "MinLinks")
+ (assertMinimum "MinLinks" 0)
+ ];
- checkXfrm = checkUnitConfig "Xfrm" [
- (assertOnlyFields [
- "InterfaceId" "Independent"
- ])
- # The following check won't work on nix <= 2.2
- # see https://github.com/NixOS/nix/pull/2378
- #
- # Add this again when we'll have drop the
- # nix < 2.2 support.
- # (assertRange "InterfaceId" 1 4294967295)
- (assertValueOneOf "Independent" boolValues)
- ];
+ sectionXfrm = checkUnitConfig "Xfrm" [
+ (assertOnlyFields [
+ "InterfaceId"
+ "Independent"
+ ])
+ (assertInt "InterfaceId")
+ (assertRange "InterfaceId" 1 4294967295)
+ (assertValueOneOf "Independent" boolValues)
+ ];
- checkNetwork = checkUnitConfig "Network" [
- (assertOnlyFields [
- "Description" "DHCP" "DHCPServer" "LinkLocalAddressing" "IPv4LLRoute"
- "IPv6Token" "LLMNR" "MulticastDNS" "DNSOverTLS" "DNSSEC"
- "DNSSECNegativeTrustAnchors" "LLDP" "EmitLLDP" "BindCarrier" "Address"
- "Gateway" "DNS" "Domains" "NTP" "IPForward" "IPMasquerade"
- "IPv6PrivacyExtensions" "IPv6AcceptRA" "IPv6DuplicateAddressDetection"
- "IPv6HopLimit" "IPv4ProxyARP" "IPv6ProxyNDP" "IPv6ProxyNDPAddress"
- "IPv6PrefixDelegation" "IPv6MTUBytes" "Bridge" "Bond" "VRF" "VLAN"
- "IPVLAN" "MACVLAN" "VXLAN" "Tunnel" "ActiveSlave" "PrimarySlave"
- "ConfigureWithoutCarrier" "Xfrm" "KeepConfiguration"
- ])
- # Note: For DHCP the values both, none, v4, v6 are deprecated
- (assertValueOneOf "DHCP" ["yes" "no" "ipv4" "ipv6" "both" "none" "v4" "v6"])
- (assertValueOneOf "DHCPServer" boolValues)
- (assertValueOneOf "LinkLocalAddressing" ["yes" "no" "ipv4" "ipv6" "ipv4-fallback" "fallback"])
- (assertValueOneOf "IPv4LLRoute" boolValues)
- (assertValueOneOf "LLMNR" ["yes" "resolve" "no"])
- (assertValueOneOf "MulticastDNS" ["yes" "resolve" "no"])
- (assertValueOneOf "DNSOverTLS" ["opportunistic" "no"])
- (assertValueOneOf "DNSSEC" ["yes" "allow-downgrade" "no"])
- (assertValueOneOf "LLDP" ["yes" "routers-only" "no"])
- (assertValueOneOf "EmitLLDP" ["yes" "no" "nearest-bridge" "non-tpmr-bridge" "customer-bridge"])
- (assertValueOneOf "IPForward" ["yes" "no" "ipv4" "ipv6"])
- (assertValueOneOf "IPMasquerade" boolValues)
- (assertValueOneOf "IPv6PrivacyExtensions" ["yes" "no" "prefer-public" "kernel"])
- (assertValueOneOf "IPv6AcceptRA" boolValues)
- (assertValueOneOf "IPv4ProxyARP" boolValues)
- (assertValueOneOf "IPv6ProxyNDP" boolValues)
- (assertValueOneOf "IPv6PrefixDelegation" (boolValues ++ [ "dhcpv6" "static" ]))
- (assertValueOneOf "ActiveSlave" boolValues)
- (assertValueOneOf "PrimarySlave" boolValues)
- (assertValueOneOf "ConfigureWithoutCarrier" boolValues)
- (assertValueOneOf "KeepConfiguration" (boolValues ++ ["static" "dhcp-on-stop" "dhcp"]))
- ];
+ sectionVRF = checkUnitConfig "VRF" [
+ (assertOnlyFields [
+ "Table"
+ ])
+ (assertInt "Table")
+ (assertMinimum "Table" 0)
+ ];
+ };
- checkAddress = checkUnitConfig "Address" [
- (assertOnlyFields [
- "Address" "Peer" "Broadcast" "Label" "PreferredLifetime" "Scope"
- "HomeAddress" "DuplicateAddressDetection" "ManageTemporaryAddress"
- "PrefixRoute" "AutoJoin"
- ])
- (assertHasField "Address")
- (assertValueOneOf "PreferredLifetime" ["forever" "infinity" "0" 0])
- (assertValueOneOf "HomeAddress" boolValues)
- (assertValueOneOf "DuplicateAddressDetection" boolValues)
- (assertValueOneOf "ManageTemporaryAddress" boolValues)
- (assertValueOneOf "PrefixRoute" boolValues)
- (assertValueOneOf "AutoJoin" boolValues)
- ];
+ network = {
+
+ sectionLink = checkUnitConfig "Link" [
+ (assertOnlyFields [
+ "MACAddress"
+ "MTUBytes"
+ "ARP"
+ "Multicast"
+ "AllMulticast"
+ "Unmanaged"
+ "RequiredForOnline"
+ ])
+ (assertMacAddress "MACAddress")
+ (assertByteFormat "MTUBytes")
+ (assertValueOneOf "ARP" boolValues)
+ (assertValueOneOf "Multicast" boolValues)
+ (assertValueOneOf "AllMulticast" boolValues)
+ (assertValueOneOf "Unmanaged" boolValues)
+ (assertValueOneOf "RequiredForOnline" (boolValues ++ [
+ "missing"
+ "off"
+ "no-carrier"
+ "dormant"
+ "degraded-carrier"
+ "carrier"
+ "degraded"
+ "enslaved"
+ "routable"
+ ]))
+ ];
- checkRoutingPolicyRule = checkUnitConfig "RoutingPolicyRule" [
- (assertOnlyFields [
- "TypeOfService" "From" "To" "FirewallMark" "Table" "Priority"
- "IncomingInterface" "OutgoingInterface" "SourcePort" "DestinationPort"
- "IPProtocol" "InvertRule" "Family"
- ])
- (assertRange "TypeOfService" 0 255)
- # The following check won't work on nix <= 2.2
- # see https://github.com/NixOS/nix/pull/2378
- #
- # Add this again when we'll have drop the
- # nix < 2.2 support.
- # (assertRange "FirewallMark" 1 4294967295)
- (assertInt "Priority")
- (assertPort "SourcePort")
- (assertPort "DestinationPort")
- (assertValueOneOf "InvertRule" boolValues)
- (assertValueOneOf "Family" ["ipv4" "ipv6" "both"])
- ];
+ sectionNetwork = checkUnitConfig "Network" [
+ (assertOnlyFields [
+ "Description"
+ "DHCP"
+ "DHCPServer"
+ "LinkLocalAddressing"
+ "IPv4LLRoute"
+ "DefaultRouteOnDevice"
+ "IPv6Token"
+ "LLMNR"
+ "MulticastDNS"
+ "DNSOverTLS"
+ "DNSSEC"
+ "DNSSECNegativeTrustAnchors"
+ "LLDP"
+ "EmitLLDP"
+ "BindCarrier"
+ "Address"
+ "Gateway"
+ "DNS"
+ "Domains"
+ "DNSDefaultRoute"
+ "NTP"
+ "IPForward"
+ "IPMasquerade"
+ "IPv6PrivacyExtensions"
+ "IPv6AcceptRA"
+ "IPv6DuplicateAddressDetection"
+ "IPv6HopLimit"
+ "IPv4ProxyARP"
+ "IPv6ProxyNDP"
+ "IPv6ProxyNDPAddress"
+ "IPv6PrefixDelegation"
+ "IPv6MTUBytes"
+ "Bridge"
+ "Bond"
+ "VRF"
+ "VLAN"
+ "IPVLAN"
+ "MACVLAN"
+ "VXLAN"
+ "Tunnel"
+ "MACsec"
+ "ActiveSlave"
+ "PrimarySlave"
+ "ConfigureWithoutCarrier"
+ "IgnoreCarrierLoss"
+ "Xfrm"
+ "KeepConfiguration"
+ ])
+ # Note: For DHCP the values both, none, v4, v6 are deprecated
+ (assertValueOneOf "DHCP" ["yes" "no" "ipv4" "ipv6"])
+ (assertValueOneOf "DHCPServer" boolValues)
+ (assertValueOneOf "LinkLocalAddressing" ["yes" "no" "ipv4" "ipv6" "fallback" "ipv4-fallback"])
+ (assertValueOneOf "IPv4LLRoute" boolValues)
+ (assertValueOneOf "DefaultRouteOnDevice" boolValues)
+ (assertValueOneOf "LLMNR" (boolValues ++ ["resolve"]))
+ (assertValueOneOf "MulticastDNS" (boolValues ++ ["resolve"]))
+ (assertValueOneOf "DNSOverTLS" (boolValues ++ ["opportunistic"]))
+ (assertValueOneOf "DNSSEC" (boolValues ++ ["allow-downgrade"]))
+ (assertValueOneOf "LLDP" (boolValues ++ ["routers-only"]))
+ (assertValueOneOf "EmitLLDP" (boolValues ++ ["nearest-bridge" "non-tpmr-bridge" "customer-bridge"]))
+ (assertValueOneOf "DNSDefaultRoute" boolValues)
+ (assertValueOneOf "IPForward" (boolValues ++ ["ipv4" "ipv6"]))
+ (assertValueOneOf "IPMasquerade" boolValues)
+ (assertValueOneOf "IPv6PrivacyExtensions" (boolValues ++ ["prefer-public" "kernel"]))
+ (assertValueOneOf "IPv6AcceptRA" boolValues)
+ (assertInt "IPv6DuplicateAddressDetection")
+ (assertMinimum "IPv6DuplicateAddressDetection" 0)
+ (assertInt "IPv6HopLimit")
+ (assertMinimum "IPv6HopLimit" 0)
+ (assertValueOneOf "IPv4ProxyARP" boolValues)
+ (assertValueOneOf "IPv6ProxyNDP" boolValues)
+ (assertValueOneOf "IPv6PrefixDelegation" ["static" "dhcpv6" "yes" "false"])
+ (assertByteFormat "IPv6MTUBytes")
+ (assertValueOneOf "ActiveSlave" boolValues)
+ (assertValueOneOf "PrimarySlave" boolValues)
+ (assertValueOneOf "ConfigureWithoutCarrier" boolValues)
+ (assertValueOneOf "IgnoreCarrierLoss" boolValues)
+ (assertValueOneOf "KeepConfiguration" (boolValues ++ ["static" "dhcp-on-stop" "dhcp"]))
+ ];
- checkRoute = checkUnitConfig "Route" [
- (assertOnlyFields [
- "Gateway" "GatewayOnLink" "Destination" "Source" "Metric"
- "IPv6Preference" "Scope" "PreferredSource" "Table" "Protocol" "Type"
- "InitialCongestionWindow" "InitialAdvertisedReceiveWindow" "QuickAck"
- "MTUBytes"
- ])
- ];
+ sectionAddress = checkUnitConfig "Address" [
+ (assertOnlyFields [
+ "Address"
+ "Peer"
+ "Broadcast"
+ "Label"
+ "PreferredLifetime"
+ "Scope"
+ "HomeAddress"
+ "DuplicateAddressDetection"
+ "ManageTemporaryAddress"
+ "AddPrefixRoute"
+ "AutoJoin"
+ ])
+ (assertHasField "Address")
+ (assertValueOneOf "PreferredLifetime" ["forever" "infinity" "0" 0])
+ (assertValueOneOf "HomeAddress" boolValues)
+ (assertValueOneOf "DuplicateAddressDetection" ["ipv4" "ipv6" "both" "none"])
+ (assertValueOneOf "ManageTemporaryAddress" boolValues)
+ (assertValueOneOf "AddPrefixRoute" boolValues)
+ (assertValueOneOf "AutoJoin" boolValues)
+ ];
- checkDhcpV4 = checkUnitConfig "DHCPv4" [
- (assertOnlyFields [
- "UseDNS" "RoutesToDNS" "UseNTP" "UseMTU" "Anonymize" "SendHostname" "UseHostname"
- "Hostname" "UseDomains" "UseRoutes" "UseTimezone"
- "ClientIdentifier" "VendorClassIdentifier" "UserClass" "MaxAttempts"
- "DUIDType" "DUIDRawData" "IAID" "RequestBroadcast" "RouteMetric" "RouteTable"
- "ListenPort" "SendRelease"
- ])
- (assertValueOneOf "UseDNS" boolValues)
- (assertValueOneOf "RoutesToDNS" boolValues)
- (assertValueOneOf "UseNTP" boolValues)
- (assertValueOneOf "UseMTU" boolValues)
- (assertValueOneOf "Anonymize" boolValues)
- (assertValueOneOf "SendHostname" boolValues)
- (assertValueOneOf "UseHostname" boolValues)
- (assertValueOneOf "UseDomains" ["yes" "no" "route"])
- (assertValueOneOf "UseRoutes" boolValues)
- (assertValueOneOf "UseTimezone" boolValues)
- (assertMinimum "MaxAttempts" 0)
- (assertValueOneOf "RequestBroadcast" boolValues)
- (assertInt "RouteTable")
- (assertMinimum "RouteTable" 0)
- (assertValueOneOf "SendRelease" boolValues)
- ];
+ sectionRoutingPolicyRule = checkUnitConfig "RoutingPolicyRule" [
+ (assertOnlyFields [
+ "TypeOfService"
+ "From"
+ "To"
+ "FirewallMark"
+ "Table"
+ "Priority"
+ "IncomingInterface"
+ "OutgoingInterface"
+ "SourcePort"
+ "DestinationPort"
+ "IPProtocol"
+ "InvertRule"
+ "Family"
+ "User"
+ "SuppressPrefixLength"
+ ])
+ (assertInt "TypeOfService")
+ (assertRange "TypeOfService" 0 255)
+ (assertInt "FirewallMark")
+ (assertRange "FirewallMark" 1 4294967295)
+ (assertInt "Priority")
+ (assertPort "SourcePort")
+ (assertPort "DestinationPort")
+ (assertValueOneOf "InvertRule" boolValues)
+ (assertValueOneOf "Family" ["ipv4" "ipv6" "both"])
+ (assertInt "SuppressPrefixLength")
+ (assertRange "SuppressPrefixLength" 0 128)
+ ];
- checkDhcpV6 = checkUnitConfig "DHCPv6" [
- (assertOnlyFields [
- "UseDns" "UseNTP" "RapidCommit" "ForceDHCPv6PDOtherInformation"
- "PrefixDelegationHint"
- ])
- (assertValueOneOf "UseDNS" boolValues)
- (assertValueOneOf "UseNTP" boolValues)
- (assertValueOneOf "RapidCommit" boolValues)
- (assertValueOneOf "ForceDHCPv6PDOtherInformation" boolValues)
- ];
+ sectionRoute = checkUnitConfig "Route" [
+ (assertOnlyFields [
+ "Gateway"
+ "GatewayOnLink"
+ "Destination"
+ "Source"
+ "Metric"
+ "IPv6Preference"
+ "Scope"
+ "PreferredSource"
+ "Table"
+ "Protocol"
+ "Type"
+ "InitialCongestionWindow"
+ "InitialAdvertisedReceiveWindow"
+ "QuickAck"
+ "FastOpenNoCookie"
+ "TTLPropagate"
+ "MTUBytes"
+ "IPServiceType"
+ "MultiPathRoute"
+ ])
+ (assertValueOneOf "GatewayOnLink" boolValues)
+ (assertInt "Metric")
+ (assertValueOneOf "IPv6Preference" ["low" "medium" "high"])
+ (assertValueOneOf "Scope" ["global" "site" "link" "host" "nowhere"])
+ (assertValueOneOf "Type" [
+ "unicast"
+ "local"
+ "broadcast"
+ "anycast"
+ "multicast"
+ "blackhole"
+ "unreachable"
+ "prohibit"
+ "throw"
+ "nat"
+ "xresolve"
+ ])
+ (assertValueOneOf "QuickAck" boolValues)
+ (assertValueOneOf "FastOpenNoCookie" boolValues)
+ (assertValueOneOf "TTLPropagate" boolValues)
+ (assertByteFormat "MTUBytes")
+ (assertValueOneOf "IPServiceType" ["CS6" "CS4"])
+ ];
- checkIpv6PrefixDelegation = checkUnitConfig "IPv6PrefixDelegation" [
- (assertOnlyFields [
- "Managed" "OtherInformation" "RouterLifetimeSec"
- "RouterPreference" "EmitDNS" "DNS" "EmitDomains" "Domains"
- "DNSLifetimeSec"
- ])
- (assertValueOneOf "Managed" boolValues)
- (assertValueOneOf "OtherInformation" boolValues)
- (assertValueOneOf "RouterPreference" ["high" "medium" "low" "normal" "default"])
- (assertValueOneOf "EmitDNS" boolValues)
- (assertValueOneOf "EmitDomains" boolValues)
- (assertMinimum "DNSLifetimeSec" 0)
- ];
+ sectionDHCPv4 = checkUnitConfig "DHCPv4" [
+ (assertOnlyFields [
+ "UseDNS"
+ "RoutesToDNS"
+ "UseNTP"
+ "UseSIP"
+ "UseMTU"
+ "Anonymize"
+ "SendHostname"
+ "UseHostname"
+ "Hostname"
+ "UseDomains"
+ "UseRoutes"
+ "UseTimezone"
+ "ClientIdentifier"
+ "VendorClassIdentifier"
+ "UserClass"
+ "MaxAttempts"
+ "DUIDType"
+ "DUIDRawData"
+ "IAID"
+ "RequestBroadcast"
+ "RouteMetric"
+ "RouteTable"
+ "RouteMTUBytes"
+ "ListenPort"
+ "SendRelease"
+ "SendDecline"
+ "BlackList"
+ "RequestOptions"
+ "SendOption"
+ ])
+ (assertValueOneOf "UseDNS" boolValues)
+ (assertValueOneOf "RoutesToDNS" boolValues)
+ (assertValueOneOf "UseNTP" boolValues)
+ (assertValueOneOf "UseSIP" boolValues)
+ (assertValueOneOf "UseMTU" boolValues)
+ (assertValueOneOf "Anonymize" boolValues)
+ (assertValueOneOf "SendHostname" boolValues)
+ (assertValueOneOf "UseHostname" boolValues)
+ (assertValueOneOf "UseDomains" (boolValues ++ ["route"]))
+ (assertValueOneOf "UseRoutes" boolValues)
+ (assertValueOneOf "UseTimezone" boolValues)
+ (assertValueOneOf "ClientIdentifier" ["mac" "duid" "duid-only"])
+ (assertInt "IAID")
+ (assertValueOneOf "RequestBroadcast" boolValues)
+ (assertInt "RouteMetric")
+ (assertInt "RouteTable")
+ (assertRange "RouteTable" 0 4294967295)
+ (assertByteFormat "RouteMTUBytes")
+ (assertPort "ListenPort")
+ (assertValueOneOf "SendRelease" boolValues)
+ (assertValueOneOf "SendDecline" boolValues)
+ ];
- checkIpv6Prefix = checkUnitConfig "IPv6Prefix" [
- (assertOnlyFields [
- "AddressAutoconfiguration" "OnLink" "Prefix"
- "PreferredLifetimeSec" "ValidLifetimeSec"
- ])
- (assertValueOneOf "AddressAutoconfiguration" boolValues)
- (assertValueOneOf "OnLink" boolValues)
- (assertMinimum "PreferredLifetimeSec" 0)
- (assertMinimum "ValidLifetimeSec" 0)
- ];
+ sectionDHCPv6 = checkUnitConfig "DHCPv6" [
+ (assertOnlyFields [
+ "UseDNS"
+ "UseNTP"
+ "RapidCommit"
+ "ForceDHCPv6PDOtherInformation"
+ "PrefixDelegationHint"
+ ])
+ (assertValueOneOf "UseDNS" boolValues)
+ (assertValueOneOf "UseNTP" boolValues)
+ (assertValueOneOf "RapidCommit" boolValues)
+ (assertValueOneOf "ForceDHCPv6PDOtherInformation" boolValues)
+ ];
+ sectionDHCPServer = checkUnitConfig "DHCPServer" [
+ (assertOnlyFields [
+ "PoolOffset"
+ "PoolSize"
+ "DefaultLeaseTimeSec"
+ "MaxLeaseTimeSec"
+ "EmitDNS"
+ "DNS"
+ "EmitNTP"
+ "NTP"
+ "EmitSIP"
+ "SIP"
+ "EmitRouter"
+ "EmitTimezone"
+ "Timezone"
+ "SendOption"
+ ])
+ (assertInt "PoolOffset")
+ (assertMinimum "PoolOffset" 0)
+ (assertInt "PoolSize")
+ (assertMinimum "PoolSize" 0)
+ (assertValueOneOf "EmitDNS" boolValues)
+ (assertValueOneOf "EmitNTP" boolValues)
+ (assertValueOneOf "EmitSIP" boolValues)
+ (assertValueOneOf "EmitRouter" boolValues)
+ (assertValueOneOf "EmitTimezone" boolValues)
+ ];
- checkDhcpServer = checkUnitConfig "DHCPServer" [
- (assertOnlyFields [
- "PoolOffset" "PoolSize" "DefaultLeaseTimeSec" "MaxLeaseTimeSec"
- "EmitDNS" "DNS" "EmitNTP" "NTP" "EmitRouter" "EmitTimezone" "Timezone"
- ])
- (assertValueOneOf "EmitDNS" boolValues)
- (assertValueOneOf "EmitNTP" boolValues)
- (assertValueOneOf "EmitRouter" boolValues)
- (assertValueOneOf "EmitTimezone" boolValues)
- ];
+ sectionIPv6PrefixDelegation = checkUnitConfig "IPv6PrefixDelegation" [
+ (assertOnlyFields [
+ "Managed"
+ "OtherInformation"
+ "RouterLifetimeSec"
+ "RouterPreference"
+ "EmitDNS"
+ "DNS"
+ "EmitDomains"
+ "Domains"
+ "DNSLifetimeSec"
+ ])
+ (assertValueOneOf "Managed" boolValues)
+ (assertValueOneOf "OtherInformation" boolValues)
+ (assertValueOneOf "RouterPreference" ["high" "medium" "low" "normal" "default"])
+ (assertValueOneOf "EmitDNS" boolValues)
+ (assertValueOneOf "EmitDomains" boolValues)
+ ];
- # .network files have a [Link] section with different options than in .netlink files
- checkNetworkLink = checkUnitConfig "Link" [
- (assertOnlyFields [
- "MACAddress" "MTUBytes" "ARP" "Multicast" "Unmanaged" "RequiredForOnline"
- ])
- (assertMacAddress "MACAddress")
- (assertByteFormat "MTUBytes")
- (assertValueOneOf "ARP" boolValues)
- (assertValueOneOf "Multicast" boolValues)
- (assertValueOneOf "Unmanaged" boolValues)
- (assertValueOneOf "RequiredForOnline" (boolValues ++ ["off" "no-carrier" "dormant" "degraded-carrier" "carrier" "degraded" "enslaved" "routable"]))
- ];
+ sectionIPv6Prefix = checkUnitConfig "IPv6Prefix" [
+ (assertOnlyFields [
+ "AddressAutoconfiguration"
+ "OnLink"
+ "Prefix"
+ "PreferredLifetimeSec"
+ "ValidLifetimeSec"
+ ])
+ (assertValueOneOf "AddressAutoconfiguration" boolValues)
+ (assertValueOneOf "OnLink" boolValues)
+ ];
+ };
+ };
commonNetworkOptions = {
@@ -406,7 +761,7 @@ let
linkConfig = mkOption {
default = {};
example = { MACAddress = "00:ff:ee:aa:cc:dd"; };
- type = types.addCheck (types.attrsOf unitOption) checkLink;
+ type = types.addCheck (types.attrsOf unitOption) check.link.sectionLink;
description = ''
Each attribute in this set specifies an option in the
<literal>[Link]</literal> section of the unit. See
@@ -417,12 +772,28 @@ let
};
+ wireguardPeerOptions = {
+ options = {
+ wireguardPeerConfig = mkOption {
+ default = {};
+ example = { };
+ type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionWireGuardPeer;
+ description = ''
+ Each attribute in this set specifies an option in the
+ <literal>[WireGuardPeer]</literal> section of the unit. See
+ <citerefentry><refentrytitle>systemd.network</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry> for details.
+ '';
+ };
+ };
+ };
+
netdevOptions = commonNetworkOptions // {
netdevConfig = mkOption {
default = {};
example = { Name = "mybridge"; Kind = "bridge"; };
- type = types.addCheck (types.attrsOf unitOption) checkNetdev;
+ type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionNetdev;
description = ''
Each attribute in this set specifies an option in the
<literal>[Netdev]</literal> section of the unit. See
@@ -431,65 +802,10 @@ let
'';
};
- vrfConfig = mkOption {
- default = {};
- example = { Table = 2342; };
- type = types.addCheck (types.attrsOf unitOption) checkVRF;
- description = ''
- Each attribute in this set specifies an option in the
- <literal>[VRF]</literal> section of the unit. See
- <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
- <manvolnum>5</manvolnum></citerefentry> for details.
- A detailed explanation about how VRFs work can be found in the
- <link xlink:href="https://www.kernel.org/doc/Documentation/networking/vrf.txt">kernel
- docs</link>.
- '';
- };
-
- wireguardConfig = mkOption {
- default = {};
- example = {
- PrivateKeyFile = "/etc/wireguard/secret.key";
- ListenPort = 51820;
- FwMark = 42;
- };
- type = types.addCheck (types.attrsOf unitOption) checkWireGuard;
- description = ''
- Each attribute in this set specifies an option in the
- <literal>[WireGuard]</literal> section of the unit. See
- <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
- <manvolnum>5</manvolnum></citerefentry> for details.
- Use <literal>PrivateKeyFile</literal> instead of
- <literal>PrivateKey</literal>: the nix store is
- world-readable.
- '';
- };
-
- wireguardPeers = mkOption {
- default = [];
- example = [ { wireguardPeerConfig={
- Endpoint = "192.168.1.1:51820";
- PublicKey = "27s0OvaBBdHoJYkH9osZpjpgSOVNw+RaKfboT/Sfq0g=";
- PresharedKeyFile = "/etc/wireguard/psk.key";
- AllowedIPs = [ "10.0.0.1/32" ];
- PersistentKeepalive = 15;
- };}];
- type = with types; listOf (submodule wireguardPeerOptions);
- description = ''
- Each item in this array specifies an option in the
- <literal>[WireGuardPeer]</literal> section of the unit. See
- <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
- <manvolnum>5</manvolnum></citerefentry> for details.
- Use <literal>PresharedKeyFile</literal> instead of
- <literal>PresharedKey</literal>: the nix store is
- world-readable.
- '';
- };
-
vlanConfig = mkOption {
default = {};
- example = { Id = "4"; };
- type = types.addCheck (types.attrsOf unitOption) checkVlan;
+ example = { Id = 4; };
+ type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionVLAN;
description = ''
Each attribute in this set specifies an option in the
<literal>[VLAN]</literal> section of the unit. See
@@ -501,7 +817,7 @@ let
macvlanConfig = mkOption {
default = {};
example = { Mode = "private"; };
- type = types.addCheck (types.attrsOf unitOption) checkMacvlan;
+ type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionMACVLAN;
description = ''
Each attribute in this set specifies an option in the
<literal>[MACVLAN]</literal> section of the unit. See
@@ -513,7 +829,7 @@ let
vxlanConfig = mkOption {
default = {};
example = { Id = "4"; };
- type = types.addCheck (types.attrsOf unitOption) checkVxlan;
+ type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionVXLAN;
description = ''
Each attribute in this set specifies an option in the
<literal>[VXLAN]</literal> section of the unit. See
@@ -525,7 +841,7 @@ let
tunnelConfig = mkOption {
default = {};
example = { Remote = "192.168.1.1"; };
- type = types.addCheck (types.attrsOf unitOption) checkTunnel;
+ type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionTunnel;
description = ''
Each attribute in this set specifies an option in the
<literal>[Tunnel]</literal> section of the unit. See
@@ -537,7 +853,7 @@ let
peerConfig = mkOption {
default = {};
example = { Name = "veth2"; };
- type = types.addCheck (types.attrsOf unitOption) checkPeer;
+ type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionPeer;
description = ''
Each attribute in this set specifies an option in the
<literal>[Peer]</literal> section of the unit. See
@@ -549,7 +865,7 @@ let
tunConfig = mkOption {
default = {};
example = { User = "openvpn"; };
- type = types.addCheck (types.attrsOf unitOption) checkTun;
+ type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionTun;
description = ''
Each attribute in this set specifies an option in the
<literal>[Tun]</literal> section of the unit. See
@@ -561,7 +877,7 @@ let
tapConfig = mkOption {
default = {};
example = { User = "openvpn"; };
- type = types.addCheck (types.attrsOf unitOption) checkTap;
+ type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionTap;
description = ''
Each attribute in this set specifies an option in the
<literal>[Tap]</literal> section of the unit. See
@@ -570,10 +886,50 @@ let
'';
};
+ wireguardConfig = mkOption {
+ default = {};
+ example = {
+ PrivateKeyFile = "/etc/wireguard/secret.key";
+ ListenPort = 51820;
+ FwMark = 42;
+ };
+ type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionWireGuard;
+ description = ''
+ Each attribute in this set specifies an option in the
+ <literal>[WireGuard]</literal> section of the unit. See
+ <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry> for details.
+ Use <literal>PrivateKeyFile</literal> instead of
+ <literal>PrivateKey</literal>: the nix store is
+ world-readable.
+ '';
+ };
+
+ wireguardPeers = mkOption {
+ default = [];
+ example = [ { wireguardPeerConfig={
+ Endpoint = "192.168.1.1:51820";
+ PublicKey = "27s0OvaBBdHoJYkH9osZpjpgSOVNw+RaKfboT/Sfq0g=";
+ PresharedKeyFile = "/etc/wireguard/psk.key";
+ AllowedIPs = [ "10.0.0.1/32" ];
+ PersistentKeepalive = 15;
+ };}];
+ type = with types; listOf (submodule wireguardPeerOptions);
+ description = ''
+ Each item in this array specifies an option in the
+ <literal>[WireGuardPeer]</literal> section of the unit. See
+ <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry> for details.
+ Use <literal>PresharedKeyFile</literal> instead of
+ <literal>PresharedKey</literal>: the nix store is
+ world-readable.
+ '';
+ };
+
bondConfig = mkOption {
default = {};
example = { Mode = "802.3ad"; };
- type = types.addCheck (types.attrsOf unitOption) checkBond;
+ type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionBond;
description = ''
Each attribute in this set specifies an option in the
<literal>[Bond]</literal> section of the unit. See
@@ -585,7 +941,7 @@ let
xfrmConfig = mkOption {
default = {};
example = { InterfaceId = 1; };
- type = types.addCheck (types.attrsOf unitOption) checkXfrm;
+ type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionXfrm;
description = ''
Each attribute in this set specifies an option in the
<literal>[Xfrm]</literal> section of the unit. See
@@ -594,6 +950,21 @@ let
'';
};
+ vrfConfig = mkOption {
+ default = {};
+ example = { Table = 2342; };
+ type = types.addCheck (types.attrsOf unitOption) check.netdev.sectionVRF;
+ description = ''
+ Each attribute in this set specifies an option in the
+ <literal>[VRF]</literal> section of the unit. See
+ <citerefentry><refentrytitle>systemd.netdev</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry> for details.
+ A detailed explanation about how VRFs work can be found in the
+ <link xlink:href="https://www.kernel.org/doc/Documentation/networking/vrf.txt">kernel
+ docs</link>.
+ '';
+ };
+
};
addressOptions = {
@@ -601,7 +972,7 @@ let
addressConfig = mkOption {
default = {};
example = { Address = "192.168.0.100/24"; };
- type = types.addCheck (types.attrsOf unitOption) checkAddress;
+ type = types.addCheck (types.attrsOf unitOption) check.network.sectionAddress;
description = ''
Each attribute in this set specifies an option in the
<literal>[Address]</literal> section of the unit. See
@@ -617,7 +988,7 @@ let
routingPolicyRuleConfig = mkOption {
default = { };
example = { routingPolicyRuleConfig = { Table = 10; IncomingInterface = "eth1"; Family = "both"; } ;};
- type = types.addCheck (types.attrsOf unitOption) checkRoutingPolicyRule;
+ type = types.addCheck (types.attrsOf unitOption) check.network.sectionRoutingPolicyRule;
description = ''
Each attribute in this set specifies an option in the
<literal>[RoutingPolicyRule]</literal> section of the unit. See
@@ -633,7 +1004,7 @@ let
routeConfig = mkOption {
default = {};
example = { Gateway = "192.168.0.1"; };
- type = types.addCheck (types.attrsOf unitOption) checkRoute;
+ type = types.addCheck (types.attrsOf unitOption) check.network.sectionRoute;
description = ''
Each attribute in this set specifies an option in the
<literal>[Route]</literal> section of the unit. See
@@ -644,28 +1015,12 @@ let
};
};
- wireguardPeerOptions = {
- options = {
- wireguardPeerConfig = mkOption {
- default = {};
- example = { };
- type = types.addCheck (types.attrsOf unitOption) checkWireGuardPeer;
- description = ''
- Each attribute in this set specifies an option in the
- <literal>[WireGuardPeer]</literal> section of the unit. See
- <citerefentry><refentrytitle>systemd.network</refentrytitle>
- <manvolnum>5</manvolnum></citerefentry> for details.
- '';
- };
- };
- };
-
ipv6PrefixOptions = {
options = {
ipv6PrefixConfig = mkOption {
default = {};
example = { Prefix = "fd00::/64"; };
- type = types.addCheck (types.attrsOf unitOption) checkIpv6Prefix;
+ type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6Prefix;
description = ''
Each attribute in this set specifies an option in the
<literal>[IPv6Prefix]</literal> section of the unit. See
@@ -676,13 +1031,24 @@ let
};
};
-
networkOptions = commonNetworkOptions // {
+ linkConfig = mkOption {
+ default = {};
+ example = { Unmanaged = true; };
+ type = types.addCheck (types.attrsOf unitOption) check.network.sectionLink;
+ description = ''
+ Each attribute in this set specifies an option in the
+ <literal>[Link]</literal> section of the unit. See
+ <citerefentry><refentrytitle>systemd.network</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry> for details.
+ '';
+ };
+
networkConfig = mkOption {
default = {};
example = { Description = "My Network"; };
- type = types.addCheck (types.attrsOf unitOption) checkNetwork;
+ type = types.addCheck (types.attrsOf unitOption) check.network.sectionNetwork;
description = ''
Each attribute in this set specifies an option in the
<literal>[Network]</literal> section of the unit. See
@@ -701,7 +1067,7 @@ let
dhcpV4Config = mkOption {
default = {};
example = { UseDNS = true; UseRoutes = true; };
- type = types.addCheck (types.attrsOf unitOption) checkDhcpV4;
+ type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPv4;
description = ''
Each attribute in this set specifies an option in the
<literal>[DHCPv4]</literal> section of the unit. See
@@ -713,7 +1079,7 @@ let
dhcpV6Config = mkOption {
default = {};
example = { UseDNS = true; UseRoutes = true; };
- type = types.addCheck (types.attrsOf unitOption) checkDhcpV6;
+ type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPv6;
description = ''
Each attribute in this set specifies an option in the
<literal>[DHCPv6]</literal> section of the unit. See
@@ -722,48 +1088,36 @@ let
'';
};
- ipv6PrefixDelegationConfig = mkOption {
+ dhcpServerConfig = mkOption {
default = {};
- example = { EmitDNS = true; Managed = true; OtherInformation = true; };
- type = types.addCheck (types.attrsOf unitOption) checkIpv6PrefixDelegation;
+ example = { PoolOffset = 50; EmitDNS = false; };
+ type = types.addCheck (types.attrsOf unitOption) check.network.sectionDHCPServer;
description = ''
Each attribute in this set specifies an option in the
- <literal>[IPv6PrefixDelegation]</literal> section of the unit. See
- <citerefentry><refentrytitle>systemd.network</refentrytitle>
- <manvolnum>5</manvolnum></citerefentry> for details.
- '';
- };
-
- ipv6Prefixes = mkOption {
- default = [];
- example = { AddressAutoconfiguration = true; OnLink = true; };
- type = with types; listOf (submodule ipv6PrefixOptions);
- description = ''
- A list of ipv6Prefix sections to be added to the unit. See
+ <literal>[DHCPServer]</literal> section of the unit. See
<citerefentry><refentrytitle>systemd.network</refentrytitle>
<manvolnum>5</manvolnum></citerefentry> for details.
'';
};
- dhcpServerConfig = mkOption {
+ ipv6PrefixDelegationConfig = mkOption {
default = {};
- example = { PoolOffset = 50; EmitDNS = false; };
- type = types.addCheck (types.attrsOf unitOption) checkDhcpServer;
+ example = { EmitDNS = true; Managed = true; OtherInformation = true; };
+ type = types.addCheck (types.attrsOf unitOption) check.network.sectionIPv6PrefixDelegation;
description = ''
Each attribute in this set specifies an option in the
- <literal>[DHCPServer]</literal> section of the unit. See
+ <literal>[IPv6PrefixDelegation]</literal> section of the unit. See
<citerefentry><refentrytitle>systemd.network</refentrytitle>
<manvolnum>5</manvolnum></citerefentry> for details.
'';
};
- linkConfig = mkOption {
- default = {};
- example = { Unmanaged = true; };
- type = types.addCheck (types.attrsOf unitOption) checkNetworkLink;
+ ipv6Prefixes = mkOption {
+ default = [];
+ example = { AddressAutoconfiguration = true; OnLink = true; };
+ type = with types; listOf (submodule ipv6PrefixOptions);
description = ''
- Each attribute in this set specifies an option in the
- <literal>[Link]</literal> section of the unit. See
+ A list of ipv6Prefix sections to be added to the unit. See
<citerefentry><refentrytitle>systemd.network</refentrytitle>
<manvolnum>5</manvolnum></citerefentry> for details.
'';
@@ -958,160 +1312,162 @@ let
};
};
- commonMatchText = def: optionalString (def.matchConfig != {}) ''
+ commonMatchText = def: optionalString (def.matchConfig != { }) ''
[Match]
${attrsToSection def.matchConfig}
'';
linkToUnit = name: def:
{ inherit (def) enable;
- text = commonMatchText def +
- ''
+ text = commonMatchText def
+ + ''
[Link]
${attrsToSection def.linkConfig}
-
- ${def.extraConfig}
- '';
+ ''
+ + def.extraConfig;
};
netdevToUnit = name: def:
{ inherit (def) enable;
- text = commonMatchText def +
- ''
+ text = commonMatchText def
+ + ''
[NetDev]
${attrsToSection def.netdevConfig}
-
- ${optionalString (def.vlanConfig != { }) ''
- [VLAN]
- ${attrsToSection def.vlanConfig}
-
- ''}
- ${optionalString (def.macvlanConfig != { }) ''
- [MACVLAN]
- ${attrsToSection def.macvlanConfig}
-
- ''}
- ${optionalString (def.vxlanConfig != { }) ''
- [VXLAN]
- ${attrsToSection def.vxlanConfig}
-
- ''}
- ${optionalString (def.tunnelConfig != { }) ''
- [Tunnel]
- ${attrsToSection def.tunnelConfig}
-
- ''}
- ${optionalString (def.peerConfig != { }) ''
- [Peer]
- ${attrsToSection def.peerConfig}
-
- ''}
- ${optionalString (def.tunConfig != { }) ''
- [Tun]
- ${attrsToSection def.tunConfig}
-
- ''}
- ${optionalString (def.tapConfig != { }) ''
- [Tap]
- ${attrsToSection def.tapConfig}
-
- ''}
- ${optionalString (def.bondConfig != { }) ''
- [Bond]
- ${attrsToSection def.bondConfig}
-
- ''}
- ${optionalString (def.xfrmConfig != { }) ''
- [Xfrm]
- ${attrsToSection def.xfrmConfig}
-
- ''}
- ${optionalString (def.vrfConfig != { }) ''
- [VRF]
- ${attrsToSection def.vrfConfig}
-
- ''}
- ${optionalString (def.wireguardConfig != { }) ''
- [WireGuard]
- ${attrsToSection def.wireguardConfig}
-
- ''}
- ${flip concatMapStrings def.wireguardPeers (x: ''
- [WireGuardPeer]
- ${attrsToSection x.wireguardPeerConfig}
-
- '')}
- ${def.extraConfig}
- '';
+ ''
+ + optionalString (def.vlanConfig != { }) ''
+ [VLAN]
+ ${attrsToSection def.vlanConfig}
+ ''
+ + optionalString (def.macvlanConfig != { }) ''
+ [MACVLAN]
+ ${attrsToSection def.macvlanConfig}
+ ''
+ + optionalString (def.vxlanConfig != { }) ''
+ [VXLAN]
+ ${attrsToSection def.vxlanConfig}
+ ''
+ + optionalString (def.tunnelConfig != { }) ''
+ [Tunnel]
+ ${attrsToSection def.tunnelConfig}
+ ''
+ + optionalString (def.peerConfig != { }) ''
+ [Peer]
+ ${attrsToSection def.peerConfig}
+ ''
+ + optionalString (def.tunConfig != { }) ''
+ [Tun]
+ ${attrsToSection def.tunConfig}
+ ''
+ + optionalString (def.tapConfig != { }) ''
+ [Tap]
+ ${attrsToSection def.tapConfig}
+ ''
+ + optionalString (def.wireguardConfig != { }) ''
+ [WireGuard]
+ ${attrsToSection def.wireguardConfig}
+ ''
+ + flip concatMapStrings def.wireguardPeers (x: ''
+ [WireGuardPeer]
+ ${attrsToSection x.wireguardPeerConfig}
+ '')
+ + optionalString (def.bondConfig != { }) ''
+ [Bond]
+ ${attrsToSection def.bondConfig}
+ ''
+ + optionalString (def.xfrmConfig != { }) ''
+ [Xfrm]
+ ${attrsToSection def.xfrmConfig}
+ ''
+ + optionalString (def.vrfConfig != { }) ''
+ [VRF]
+ ${attrsToSection def.vrfConfig}
+ ''
+ + def.extraConfig;
};
networkToUnit = name: def:
{ inherit (def) enable;
- text = commonMatchText def +
+ text = commonMatchText def
+ + optionalString (def.linkConfig != { }) ''
+ [Link]
+ ${attrsToSection def.linkConfig}
''
- ${optionalString (def.linkConfig != { }) ''
- [Link]
- ${attrsToSection def.linkConfig}
-
- ''}
-
+ + ''
[Network]
- ${attrsToSection def.networkConfig}
+ ''
+ + attrsToSection def.networkConfig
+ + optionalString (def.address != [ ]) ''
${concatStringsSep "\n" (map (s: "Address=${s}") def.address)}
+ ''
+ + optionalString (def.gateway != [ ]) ''
${concatStringsSep "\n" (map (s: "Gateway=${s}") def.gateway)}
+ ''
+ + optionalString (def.dns != [ ]) ''
${concatStringsSep "\n" (map (s: "DNS=${s}") def.dns)}
+ ''
+ + optionalString (def.ntp != [ ]) ''
${concatStringsSep "\n" (map (s: "NTP=${s}") def.ntp)}
+ ''
+ + optionalString (def.bridge != [ ]) ''
${concatStringsSep "\n" (map (s: "Bridge=${s}") def.bridge)}
+ ''
+ + optionalString (def.bond != [ ]) ''
${concatStringsSep "\n" (map (s: "Bond=${s}") def.bond)}
+ ''
+ + optionalString (def.vrf != [ ]) ''
${concatStringsSep "\n" (map (s: "VRF=${s}") def.vrf)}
+ ''
+ + optionalString (def.vlan != [ ]) ''
${concatStringsSep "\n" (map (s: "VLAN=${s}") def.vlan)}
+ ''
+ + optionalString (def.macvlan != [ ]) ''
${concatStringsSep "\n" (map (s: "MACVLAN=${s}") def.macvlan)}
+ ''
+ + optionalString (def.vxlan != [ ]) ''
${concatStringsSep "\n" (map (s: "VXLAN=${s}") def.vxlan)}
+ ''
+ + optionalString (def.tunnel != [ ]) ''
${concatStringsSep "\n" (map (s: "Tunnel=${s}") def.tunnel)}
+ ''
+ + optionalString (def.xfrm != [ ]) ''
${concatStringsSep "\n" (map (s: "Xfrm=${s}") def.xfrm)}
+ ''
+ + ''
- ${optionalString (def.dhcpV4Config != { }) ''
- [DHCPv4]
- ${attrsToSection def.dhcpV4Config}
-
- ''}
- ${optionalString (def.dhcpV6Config != {}) ''
- [DHCPv6]
- ${attrsToSection def.dhcpV6Config}
-
- ''}
- ${optionalString (def.ipv6PrefixDelegationConfig != {}) ''
- [IPv6PrefixDelegation]
- ${attrsToSection def.ipv6PrefixDelegationConfig}
-
- ''}
- ${flip concatMapStrings def.ipv6Prefixes (x: ''
- [IPv6Prefix]
- ${attrsToSection x.ipv6PrefixConfig}
-
- '')}
- ${optionalString (def.dhcpServerConfig != { }) ''
- [DHCPServer]
- ${attrsToSection def.dhcpServerConfig}
-
- ''}
- ${flip concatMapStrings def.addresses (x: ''
- [Address]
- ${attrsToSection x.addressConfig}
-
- '')}
- ${flip concatMapStrings def.routes (x: ''
- [Route]
- ${attrsToSection x.routeConfig}
-
- '')}
- ${flip concatMapStrings def.routingPolicyRules (x: ''
- [RoutingPolicyRule]
- ${attrsToSection x.routingPolicyRuleConfig}
-
- '')}
- ${def.extraConfig}
- '';
+ ''
+ + flip concatMapStrings def.addresses (x: ''
+ [Address]
+ ${attrsToSection x.addressConfig}
+ '')
+ + flip concatMapStrings def.routingPolicyRules (x: ''
+ [RoutingPolicyRule]
+ ${attrsToSection x.routingPolicyRuleConfig}
+ '')
+ + flip concatMapStrings def.routes (x: ''
+ [Route]
+ ${attrsToSection x.routeConfig}
+ '')
+ + optionalString (def.dhcpV4Config != { }) ''
+ [DHCPv4]
+ ${attrsToSection def.dhcpV4Config}
+ ''
+ + optionalString (def.dhcpV6Config != { }) ''
+ [DHCPv6]
+ ${attrsToSection def.dhcpV6Config}
+ ''
+ + optionalString (def.dhcpServerConfig != { }) ''
+ [DHCPServer]
+ ${attrsToSection def.dhcpServerConfig}
+ ''
+ + optionalString (def.ipv6PrefixDelegationConfig != { }) ''
+ [IPv6PrefixDelegation]
+ ${attrsToSection def.ipv6PrefixDelegationConfig}
+ ''
+ + flip concatMapStrings def.ipv6Prefixes (x: ''
+ [IPv6Prefix]
+ ${attrsToSection x.ipv6PrefixConfig}
+ '')
+ + def.extraConfig;
};
unitFiles = listToAttrs (map (name: {
@@ -1178,14 +1534,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/nixpkgs/nixos/modules/system/boot/plymouth.nix b/nixpkgs/nixos/modules/system/boot/plymouth.nix
index 23fce22366d..55e5b07ed61 100644
--- a/nixpkgs/nixos/modules/system/boot/plymouth.nix
+++ b/nixpkgs/nixos/modules/system/boot/plymouth.nix
@@ -102,6 +102,8 @@ in
systemd.services.plymouth-poweroff.wantedBy = [ "poweroff.target" ];
systemd.services.plymouth-reboot.wantedBy = [ "reboot.target" ];
systemd.services.plymouth-read-write.wantedBy = [ "sysinit.target" ];
+ systemd.services.systemd-ask-password-plymouth.wantedBy = ["multi-user.target"];
+ systemd.paths.systemd-ask-password-plymouth.wantedBy = ["multi-user.target"];
boot.initrd.extraUtilsCommands = ''
copy_bin_and_libs ${pkgs.plymouth}/bin/plymouthd
@@ -146,6 +148,7 @@ in
# 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
+ mkdir -p /run/plymouth
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
diff --git a/nixpkgs/nixos/modules/system/boot/resolved.nix b/nixpkgs/nixos/modules/system/boot/resolved.nix
index b7aaef575ac..b024f9cf5ee 100644
--- a/nixpkgs/nixos/modules/system/boot/resolved.nix
+++ b/nixpkgs/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/nixpkgs/nixos/modules/system/boot/stage-1-init.sh b/nixpkgs/nixos/modules/system/boot/stage-1-init.sh
index 607aec87f01..0c1be71cf53 100644
--- a/nixpkgs/nixos/modules/system/boot/stage-1-init.sh
+++ b/nixpkgs/nixos/modules/system/boot/stage-1-init.sh
@@ -144,6 +144,14 @@ for o in $(cat /proc/cmdline); do
set -- $(IFS==; echo $o)
stage2Init=$2
;;
+ boot.persistence=*)
+ set -- $(IFS==; echo $o)
+ persistence=$2
+ ;;
+ boot.persistence.opt=*)
+ set -- $(IFS==; echo $o)
+ persistence_opt=$2
+ ;;
boot.trace|debugtrace)
# Show each command.
set -x
@@ -370,12 +378,14 @@ mountFS() {
mkdir -p "/mnt-root$mountPoint"
- # For CIFS mounts, retry a few times before giving up.
+ # For ZFS and CIFS mounts, retry a few times before giving up.
+ # We do this for ZFS as a workaround for issue NixOS/nixpkgs#25383.
local n=0
while true; do
mount "/mnt-root$mountPoint" && break
- if [ "$fsType" != cifs -o "$n" -ge 10 ]; then fail; break; fi
+ if [ \( "$fsType" != cifs -a "$fsType" != zfs \) -o "$n" -ge 10 ]; then fail; break; fi
echo "retrying..."
+ sleep 1
n=$((n + 1))
done
@@ -534,6 +544,14 @@ while read -u 3 mountPoint; do
continue
fi
+ if [ "$mountPoint" = / ] && [ "$device" = tmpfs ] && [ ! -z "$persistence" ]; then
+ echo persistence...
+ waitDevice "$persistence"
+ echo enabling persistence...
+ mountFS "$persistence" "$mountPoint" "$persistence_opt" "auto"
+ continue
+ fi
+
mountFS "$device" "$mountPoint" "$options" "$fsType"
done
diff --git a/nixpkgs/nixos/modules/system/boot/stage-1.nix b/nixpkgs/nixos/modules/system/boot/stage-1.nix
index dfd158e2d75..6823e12847c 100644
--- a/nixpkgs/nixos/modules/system/boot/stage-1.nix
+++ b/nixpkgs/nixos/modules/system/boot/stage-1.nix
@@ -36,7 +36,7 @@ let
set -euo pipefail
declare -A seen
- declare -a left
+ left=()
patchelf="${pkgs.buildPackages.patchelf}/bin/patchelf"
@@ -48,7 +48,7 @@ let
done
}
- add_needed $1
+ add_needed "$1"
while [ ''${#left[@]} -ne 0 ]; do
next=''${left[0]}
@@ -111,20 +111,21 @@ let
copy_bin_and_libs ${pkgs.utillinux}/sbin/blkid
# Copy dmsetup and lvm.
- copy_bin_and_libs ${pkgs.lvm2}/sbin/dmsetup
- copy_bin_and_libs ${pkgs.lvm2}/sbin/lvm
+ copy_bin_and_libs ${getBin pkgs.lvm2}/bin/dmsetup
+ copy_bin_and_libs ${getBin pkgs.lvm2}/bin/lvm
# Add RAID mdadm tool.
copy_bin_and_libs ${pkgs.mdadm}/sbin/mdadm
copy_bin_and_libs ${pkgs.mdadm}/sbin/mdmon
# Copy udev.
- copy_bin_and_libs ${udev}/lib/systemd/systemd-udevd
- copy_bin_and_libs ${udev}/lib/systemd/systemd-sysctl
copy_bin_and_libs ${udev}/bin/udevadm
+ copy_bin_and_libs ${udev}/lib/systemd/systemd-sysctl
for BIN in ${udev}/lib/udev/*_id; do
copy_bin_and_libs $BIN
done
+ # systemd-udevd is only a symlink to udevadm these days
+ ln -sf udevadm $out/bin/systemd-udevd
# Copy modprobe.
copy_bin_and_libs ${pkgs.kmod}/bin/kmod
@@ -235,7 +236,7 @@ let
--replace cdrom_id ${extraUtils}/bin/cdrom_id \
--replace ${pkgs.coreutils}/bin/basename ${extraUtils}/bin/basename \
--replace ${pkgs.utillinux}/bin/blkid ${extraUtils}/bin/blkid \
- --replace ${pkgs.lvm2}/sbin ${extraUtils}/bin \
+ --replace ${getBin pkgs.lvm2}/bin ${extraUtils}/bin \
--replace ${pkgs.mdadm}/sbin ${extraUtils}/sbin \
--replace ${pkgs.bash}/bin/sh ${extraUtils}/bin/sh \
--replace ${udev} ${extraUtils}
@@ -374,7 +375,8 @@ let
) config.boot.initrd.secrets)
}
- (cd "$tmp" && find . | cpio -H newc -o) | gzip >>"$1"
+ (cd "$tmp" && find . -print0 | sort -z | cpio -o -H newc -R +0:+0 --reproducible --null) | \
+ ${config.boot.initrd.compressor} >> "$1"
'';
in
@@ -517,8 +519,7 @@ in
};
boot.initrd.secrets = mkOption
- { internal = true;
- default = {};
+ { default = {};
type = types.attrsOf (types.nullOr types.path);
description =
''
@@ -555,15 +556,17 @@ in
};
fileSystems = mkOption {
- type = with lib.types; loaOf (submodule {
+ type = with lib.types; attrsOf (submodule {
options.neededForBoot = mkOption {
default = false;
type = types.bool;
description = ''
- If set, this file system will be mounted in the initial
- ramdisk. By default, this applies to the root file system
- and to the file system containing
- <filename>/nix/store</filename>.
+ If set, this file system will be mounted in the initial ramdisk.
+ Note that the file system will always be mounted in the initial
+ ramdisk if its mount point is one of the following:
+ ${concatStringsSep ", " (
+ forEach utils.pathsNeededForBoot (i: "<filename>${i}</filename>")
+ )}.
'';
};
});
@@ -585,7 +588,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/nixpkgs/nixos/modules/system/boot/stage-2-init.sh b/nixpkgs/nixos/modules/system/boot/stage-2-init.sh
index d1de7920df9..936077b9df1 100644
--- a/nixpkgs/nixos/modules/system/boot/stage-2-init.sh
+++ b/nixpkgs/nixos/modules/system/boot/stage-2-init.sh
@@ -169,4 +169,4 @@ exec {logOutFd}>&- {logErrFd}>&-
echo "starting systemd..."
PATH=/run/current-system/systemd/lib/systemd:@fsPackagesPath@ \
LOCALE_ARCHIVE=/run/current-system/sw/lib/locale/locale-archive \
- exec systemd
+ exec @systemdExecutable@
diff --git a/nixpkgs/nixos/modules/system/boot/stage-2.nix b/nixpkgs/nixos/modules/system/boot/stage-2.nix
index 6b0b4722730..dd6d83ee009 100644
--- a/nixpkgs/nixos/modules/system/boot/stage-2.nix
+++ b/nixpkgs/nixos/modules/system/boot/stage-2.nix
@@ -10,6 +10,7 @@ let
src = ./stage-2-init.sh;
shellDebug = "${pkgs.bashInteractive}/bin/bash";
shell = "${pkgs.bash}/bin/bash";
+ inherit (config.boot) systemdExecutable;
isExecutable = true;
inherit (config.nix) readOnlyStore;
inherit useHostResolvConf;
@@ -72,6 +73,15 @@ in
'';
};
+ systemdExecutable = mkOption {
+ default = "systemd";
+ type = types.str;
+ description = ''
+ The program to execute to start systemd. Typically
+ <literal>systemd</literal>, which will find systemd in the
+ PATH.
+ '';
+ };
};
};
diff --git a/nixpkgs/nixos/modules/system/boot/systemd-nspawn.nix b/nixpkgs/nixos/modules/system/boot/systemd-nspawn.nix
index 06ea5ee49f7..b450d77429b 100644
--- a/nixpkgs/nixos/modules/system/boot/systemd-nspawn.nix
+++ b/nixpkgs/nixos/modules/system/boot/systemd-nspawn.nix
@@ -113,9 +113,9 @@ in {
config =
let
units = mapAttrs' (n: v: let nspawnFile = "${n}.nspawn"; in nameValuePair nspawnFile (instanceToUnit nspawnFile v)) cfg;
- in
+ in
mkMerge [
- (mkIf (cfg != {}) {
+ (mkIf (cfg != {}) {
environment.etc."systemd/nspawn".source = mkIf (cfg != {}) (generateUnits' false "nspawn" units [] []);
})
{
@@ -123,7 +123,7 @@ in {
# Workaround for https://github.com/NixOS/nixpkgs/pull/67232#issuecomment-531315437 and https://github.com/systemd/systemd/issues/13622
# Once systemd fixes this upstream, we can re-enable -U
- systemd.services."systemd-nspawn@".serviceConfig.ExecStart = [
+ systemd.services."systemd-nspawn@".serviceConfig.ExecStart = [
"" # deliberately empty. signals systemd to override the ExecStart
# Only difference between upstream is that we do not pass the -U flag
"${config.systemd.package}/bin/systemd-nspawn --quiet --keep-unit --boot --link-journal=try-guest --network-veth --settings=override --machine=%i"
diff --git a/nixpkgs/nixos/modules/system/boot/systemd-unit-options.nix b/nixpkgs/nixos/modules/system/boot/systemd-unit-options.nix
index bee21f1a8f3..5addc6f9ca4 100644
--- a/nixpkgs/nixos/modules/system/boot/systemd-unit-options.nix
+++ b/nixpkgs/nixos/modules/system/boot/systemd-unit-options.nix
@@ -233,7 +233,7 @@ in rec {
path = mkOption {
default = [];
- apply = ps: "${makeBinPath ps}:${makeSearchPathOutput "bin" "sbin" ps}";
+ type = with types; listOf (oneOf [ package str ]);
description = ''
Packages added to the service's <envar>PATH</envar>
environment variable. Both the <filename>bin</filename>
@@ -378,6 +378,16 @@ in rec {
'';
};
+ listenDatagrams = mkOption {
+ default = [];
+ type = types.listOf types.str;
+ example = [ "0.0.0.0:993" "/run/my-socket" ];
+ description = ''
+ For each item in this list, a <literal>ListenDatagram</literal>
+ option in the <literal>[Socket]</literal> section will be created.
+ '';
+ };
+
socketConfig = mkOption {
default = {};
example = { ListenStream = "/run/my-socket"; };
diff --git a/nixpkgs/nixos/modules/system/boot/systemd.nix b/nixpkgs/nixos/modules/system/boot/systemd.nix
index 99892a28115..74d6957678f 100644
--- a/nixpkgs/nixos/modules/system/boot/systemd.nix
+++ b/nixpkgs/nixos/modules/system/boot/systemd.nix
@@ -25,7 +25,7 @@ let
"nss-lookup.target"
"nss-user-lookup.target"
"time-sync.target"
- #"cryptsetup.target"
+ "cryptsetup.target"
"sigpwr.target"
"timers.target"
"paths.target"
@@ -73,7 +73,7 @@ let
"systemd-journald.service"
"systemd-journal-flush.service"
"systemd-journal-catalog-update.service"
- "systemd-journald-audit.socket"
+ ] ++ (optional (!config.boot.isContainer) "systemd-journald-audit.socket") ++ [
"systemd-journald-dev-log.socket"
"syslog.socket"
@@ -81,10 +81,6 @@ let
"systemd-coredump.socket"
"systemd-coredump@.service"
- # SysV init compatibility.
- "systemd-initctl.socket"
- "systemd-initctl.service"
-
# Kernel module loading.
"systemd-modules-load.service"
"kmod-static-nodes.service"
@@ -101,7 +97,7 @@ let
"dev-hugepages.mount"
"dev-mqueue.mount"
"sys-fs-fuse-connections.mount"
- "sys-kernel-config.mount"
+ ] ++ (optional (!config.boot.isContainer) "sys-kernel-config.mount") ++ [
"sys-kernel-debug.mount"
# Maintaining state across reboots.
@@ -261,7 +257,7 @@ let
pkgs.gnused
systemd
];
- environment.PATH = config.path;
+ environment.PATH = "${makeBinPath config.path}:${makeSearchPathOutput "bin" "sbin" config.path}";
}
(mkIf (config.preStart != "")
{ serviceConfig.ExecStartPre =
@@ -354,6 +350,7 @@ let
[Socket]
${attrsToSection def.socketConfig}
${concatStringsSep "\n" (map (s: "ListenStream=${s}") def.listenStreams)}
+ ${concatStringsSep "\n" (map (s: "ListenDatagram=${s}") def.listenDatagrams)}
'';
};
@@ -749,6 +746,25 @@ in
'';
};
+ systemd.tmpfiles.packages = mkOption {
+ type = types.listOf types.package;
+ default = [];
+ example = literalExample "[ pkgs.lvm2 ]";
+ apply = map getLib;
+ description = ''
+ List of packages containing <command>systemd-tmpfiles</command> rules.
+
+ All files ending in .conf found in
+ <filename><replaceable>pkg</replaceable>/lib/tmpfiles.d</filename>
+ will be included.
+ If this folder does not exist or does not contain any files an error will be returned instead.
+
+ If a <filename>lib</filename> output is available, rules are searched there and only there.
+ If there is no <filename>lib</filename> output it will fall back to <filename>out</filename>
+ and if that does not exist either, the default output will be used.
+ '';
+ };
+
systemd.user.units = mkOption {
description = "Definition of systemd per-user units.";
default = {};
@@ -818,6 +834,49 @@ in
'';
};
+ systemd.watchdog.device = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ example = "/dev/watchdog";
+ description = ''
+ The path to a hardware watchdog device which will be managed by systemd.
+ If not specified, systemd will default to /dev/watchdog.
+ '';
+ };
+
+ systemd.watchdog.runtimeTime = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "30s";
+ description = ''
+ The amount of time which can elapse before a watchdog hardware device
+ will automatically reboot the system. Valid time units include "ms",
+ "s", "min", "h", "d", and "w".
+ '';
+ };
+
+ systemd.watchdog.rebootTime = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "10m";
+ description = ''
+ The amount of time which can elapse after a reboot has been triggered
+ before a watchdog hardware device will automatically reboot the system.
+ Valid time units include "ms", "s", "min", "h", "d", and "w".
+ '';
+ };
+
+ systemd.watchdog.kexecTime = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "10m";
+ description = ''
+ The amount of time which can elapse when kexec is being executed before
+ a watchdog hardware device will automatically reboot the system. This
+ option should only be enabled if reloadTime is also enabled. Valid
+ time units include "ms", "s", "min", "h", "d", and "w".
+ '';
+ };
};
@@ -826,8 +885,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;
@@ -839,11 +903,9 @@ in
)
]);
passwd = (mkMerge [
- [ "mymachines" ]
(mkAfter [ "systemd" ])
]);
group = (mkMerge [
- [ "mymachines" ]
(mkAfter [ "systemd" ])
]);
};
@@ -884,6 +946,19 @@ in
DefaultIPAccounting=yes
''}
DefaultLimitCORE=infinity
+ ${optionalString (config.systemd.watchdog.device != null) ''
+ WatchdogDevice=${config.systemd.watchdog.device}
+ ''}
+ ${optionalString (config.systemd.watchdog.runtimeTime != null) ''
+ RuntimeWatchdogSec=${config.systemd.watchdog.runtimeTime}
+ ''}
+ ${optionalString (config.systemd.watchdog.rebootTime != null) ''
+ RebootWatchdogSec=${config.systemd.watchdog.rebootTime}
+ ''}
+ ${optionalString (config.systemd.watchdog.kexecTime != null) ''
+ KExecWatchdogSec=${config.systemd.watchdog.kexecTime}
+ ''}
+
${config.systemd.extraConfig}
'';
@@ -931,24 +1006,20 @@ in
"sysctl.d/50-coredump.conf".source = "${systemd}/example/sysctl.d/50-coredump.conf";
"sysctl.d/50-default.conf".source = "${systemd}/example/sysctl.d/50-default.conf";
- "tmpfiles.d/00-nixos.conf".text = ''
- # This file is created automatically and should not be modified.
- # Please change the option ‘systemd.tmpfiles.rules’ instead.
-
- ${concatStringsSep "\n" cfg.tmpfiles.rules}
- '';
-
- "tmpfiles.d/home.conf".source = "${systemd}/example/tmpfiles.d/home.conf";
- "tmpfiles.d/journal-nocow.conf".source = "${systemd}/example/tmpfiles.d/journal-nocow.conf";
- "tmpfiles.d/portables.conf".source = "${systemd}/example/tmpfiles.d/portables.conf";
- "tmpfiles.d/static-nodes-permissions.conf".source = "${systemd}/example/tmpfiles.d/static-nodes-permissions.conf";
- "tmpfiles.d/systemd.conf".source = "${systemd}/example/tmpfiles.d/systemd.conf";
- "tmpfiles.d/systemd-nologin.conf".source = "${systemd}/example/tmpfiles.d/systemd-nologin.conf";
- "tmpfiles.d/systemd-nspawn.conf".source = "${systemd}/example/tmpfiles.d/systemd-nspawn.conf";
- "tmpfiles.d/systemd-tmp.conf".source = "${systemd}/example/tmpfiles.d/systemd-tmp.conf";
- "tmpfiles.d/tmp.conf".source = "${systemd}/example/tmpfiles.d/tmp.conf";
- "tmpfiles.d/var.conf".source = "${systemd}/example/tmpfiles.d/var.conf";
- "tmpfiles.d/x11.conf".source = "${systemd}/example/tmpfiles.d/x11.conf";
+ "tmpfiles.d".source = (pkgs.symlinkJoin {
+ name = "tmpfiles.d";
+ paths = map (p: p + "/lib/tmpfiles.d") cfg.tmpfiles.packages;
+ postBuild = ''
+ for i in $(cat $pathsPath); do
+ (test -d "$i" && test $(ls "$i"/*.conf | wc -l) -ge 1) || (
+ echo "ERROR: The path '$i' from systemd.tmpfiles.packages contains no *.conf files."
+ exit 1
+ )
+ done
+ '' + concatMapStrings (name: optionalString (hasPrefix "tmpfiles.d/" name) ''
+ rm -f $out/${removePrefix "tmpfiles.d/" name}
+ '') config.system.build.etc.targets;
+ }) + "/*";
"systemd/system-generators" = { source = hooks "generators" cfg.generators; };
"systemd/system-shutdown" = { source = hooks "shutdown" cfg.shutdown; };
@@ -969,6 +1040,36 @@ in
unitConfig.X-StopOnReconfiguration = true;
};
+ systemd.tmpfiles.packages = [
+ # Default tmpfiles rules provided by systemd
+ (pkgs.runCommand "systemd-default-tmpfiles" {} ''
+ mkdir -p $out/lib/tmpfiles.d
+ cd $out/lib/tmpfiles.d
+
+ ln -s "${systemd}/example/tmpfiles.d/home.conf"
+ ln -s "${systemd}/example/tmpfiles.d/journal-nocow.conf"
+ ln -s "${systemd}/example/tmpfiles.d/static-nodes-permissions.conf"
+ ln -s "${systemd}/example/tmpfiles.d/systemd.conf"
+ ln -s "${systemd}/example/tmpfiles.d/systemd-nologin.conf"
+ ln -s "${systemd}/example/tmpfiles.d/systemd-nspawn.conf"
+ ln -s "${systemd}/example/tmpfiles.d/systemd-tmp.conf"
+ ln -s "${systemd}/example/tmpfiles.d/tmp.conf"
+ ln -s "${systemd}/example/tmpfiles.d/var.conf"
+ ln -s "${systemd}/example/tmpfiles.d/x11.conf"
+ '')
+ # User-specified tmpfiles rules
+ (pkgs.writeTextFile {
+ name = "nixos-tmpfiles.d";
+ destination = "/lib/tmpfiles.d/00-nixos.conf";
+ text = ''
+ # This file is created automatically and should not be modified.
+ # Please change the option ‘systemd.tmpfiles.rules’ instead.
+
+ ${concatStringsSep "\n" cfg.tmpfiles.rules}
+ '';
+ })
+ ];
+
systemd.units =
mapAttrs' (n: v: nameValuePair "${n}.path" (pathToUnit n v)) cfg.paths
// mapAttrs' (n: v: nameValuePair "${n}.service" (serviceToUnit n v)) cfg.services
diff --git a/nixpkgs/nixos/modules/system/boot/timesyncd.nix b/nixpkgs/nixos/modules/system/boot/timesyncd.nix
index 9e2f36ca01f..35fb5578b07 100644
--- a/nixpkgs/nixos/modules/system/boot/timesyncd.nix
+++ b/nixpkgs/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 ];
};
diff --git a/nixpkgs/nixos/modules/system/boot/tmp.nix b/nixpkgs/nixos/modules/system/boot/tmp.nix
index 5bf5e2eb2ec..26eb172210e 100644
--- a/nixpkgs/nixos/modules/system/boot/tmp.nix
+++ b/nixpkgs/nixos/modules/system/boot/tmp.nix
@@ -36,4 +36,4 @@ with lib;
};
-} \ No newline at end of file
+}