Merge commit staging+systemd into closure-size

Many non-conflict problems weren't (fully) resolved in this commit yet.
This commit is contained in:
Vladimír Čunát
2015-10-03 13:33:37 +02:00
6304 changed files with 708451 additions and 130034 deletions
@@ -115,10 +115,6 @@ in
''
# Various log/runtime directories.
touch /run/utmp # must exist
chgrp ${toString config.ids.gids.utmp} /run/utmp
chmod 664 /run/utmp
mkdir -m 0755 -p /run/nix/current-load # for distributed builds
mkdir -m 0700 -p /run/nix/remote-stores
@@ -97,7 +97,7 @@ sub parseFstab {
sub parseUnit {
my ($filename) = @_;
my $info = {};
parseKeyValues($info, read_file($filename));
parseKeyValues($info, read_file($filename)) if -f $filename;
parseKeyValues($info, read_file("${filename}.d/overrides.conf")) if -f "${filename}.d/overrides.conf";
return $info;
}
@@ -157,7 +157,8 @@ while (my ($unit, $state) = each %{$activePrev}) {
if (-e $prevUnitFile && ($state->{state} eq "active" || $state->{state} eq "activating")) {
if (! -e $newUnitFile || abs_path($newUnitFile) eq "/dev/null") {
$unitsToStop{$unit} = 1;
my $unitInfo = parseUnit($prevUnitFile);
$unitsToStop{$unit} = 1 if boolIsTrue($unitInfo->{'X-StopOnRemoval'} // "yes");
}
elsif ($unit =~ /\.target$/) {
+17 -2
View File
@@ -50,7 +50,7 @@ let
ln -s ${config.system.build.initialRamdisk}/initrd $out/initrd
ln -s ${config.hardware.firmware} $out/firmware
ln -s ${config.hardware.firmware}/lib/firmware $out/firmware
''}
echo "$activationScript" > $out/activate
@@ -81,6 +81,8 @@ let
substituteAll ${./switch-to-configuration.pl} $out/bin/switch-to-configuration
chmod +x $out/bin/switch-to-configuration
echo -n "${toString config.system.extraDependencies}" > $out/extra-dependencies
${config.system.extraSystemBuilderCmds}
'';
@@ -97,8 +99,11 @@ let
# makes it bootable.
baseSystem = showWarnings (
if [] == failed then pkgs.stdenv.mkDerivation {
name = "nixos-${config.system.nixosVersion}";
name = let hn = config.networking.hostName;
nn = if (hn != "") then hn else "unnamed";
in "nixos-system-${nn}-${config.system.nixosVersion}";
preferLocalBuild = true;
allowSubstitutes = false;
buildCommand = systemBuilder;
inherit (pkgs) utillinux coreutils;
@@ -188,6 +193,16 @@ in
'';
};
system.extraDependencies = mkOption {
type = types.listOf types.package;
default = [];
description = ''
A list of packages that should be included in the system
closure but not otherwise made available to users. This is
primarily used by the installation tests.
'';
};
system.replaceRuntimeDependencies = mkOption {
default = [];
example = lib.literalExample "[ ({ original = pkgs.openssl; replacement = pkgs.callPackage /path/to/openssl { ... }; }) ]";
+51
View File
@@ -0,0 +1,51 @@
{ config, lib, pkgs, ... }:
with lib;
{
options = {
systemd.coredump = {
enable = mkOption {
default = false;
type = types.bool;
description = ''
Enables storing core dumps in systemd.
Note that this alone is not enough to enable core dumps. The maximum
file size for core dumps must be specified in limits.conf as well. See
<option>security.pam.loginLimits</option> as well as the limits.conf(5)
man page.
'';
};
extraConfig = mkOption {
default = "";
type = types.lines;
example = "Storage=journal";
description = ''
Extra config options for systemd-coredump. See coredump.conf(5) man page
for available options.
'';
};
};
};
config = mkIf config.systemd.coredump.enable {
environment.etc."systemd/coredump.conf".text =
''
[Coredump]
${config.systemd.coredump.extraConfig}
'';
# Have the kernel pass core dumps to systemd's coredump helper binary.
# From systemd's 50-coredump.conf file. See:
# <https://github.com/systemd/systemd/blob/v218/sysctl.d/50-coredump.conf.in>
boot.kernel.sysctl."kernel.core_pattern" = "|${pkgs.systemd}/lib/systemd/systemd-coredump %p %u %g %s %t %e";
};
}
+4 -5
View File
@@ -49,9 +49,8 @@ in
type = types.int;
default = 4;
description = ''
The kernel console log level. Only log messages with a
priority numerically less than this will appear on the
console.
The kernel console log level. Log messages with a priority
numerically less than this will not appear on the console.
'';
};
@@ -159,7 +158,7 @@ in
boot.kernel.sysctl."kernel.printk" = config.boot.consoleLogLevel;
boot.kernelModules = [ "loop" "configs" ];
boot.kernelModules = [ "loop" "configs" "atkbd" ];
boot.initrd.availableKernelModules =
[ # Note: most of these (especially the SATA/PATA modules)
@@ -217,7 +216,7 @@ in
];
# The Linux kernel >= 2.6.27 provides firmware.
hardware.firmware = [ "${kernel}/lib/firmware" ];
hardware.firmware = [ kernel ];
# Create /etc/modules-load.d/nixos.conf, which is read by
# systemd-modules-load.service to load required kernel modules.
+1 -1
View File
@@ -15,7 +15,7 @@ with lib;
efiSysMountPoint = mkOption {
default = "/boot";
type = types.string;
type = types.str;
description = "Where the EFI System Partition is mounted.";
};
@@ -0,0 +1,44 @@
{ config, lib, pkgs, ... }:
with lib;
let
blCfg = config.boot.loader;
cfg = blCfg.generic-extlinux-compatible;
timeoutStr = if blCfg.timeout == null then "-1" else toString blCfg.timeout;
builder = import ./extlinux-conf-builder.nix { inherit pkgs; };
in
{
options = {
boot.loader.generic-extlinux-compatible = {
enable = mkOption {
default = false;
type = types.bool;
description = ''
Whether to generate an extlinux-compatible configuration file
under <literal>/boot/extlinux.conf</literal>. For instance,
U-Boot's generic distro boot support uses this file format.
See <link xlink:href="http://git.denx.de/?p=u-boot.git;a=blob;f=doc/README.distro;hb=refs/heads/master">U-boot's documentation</link>
for more information.
'';
};
configurationLimit = mkOption {
default = 20;
example = 10;
type = types.int;
description = ''
Maximum number of configurations in the boot menu.
'';
};
};
};
config = mkIf cfg.enable {
system.build.installBootLoader = "${builder} -g ${toString cfg.configurationLimit} -t ${timeoutStr} -c";
system.boot.loader.id = "generic-extlinux-compatible";
};
}
@@ -0,0 +1,9 @@
{ pkgs }:
pkgs.substituteAll {
src = ./extlinux-conf-builder.sh;
isExecutable = true;
path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
inherit (pkgs) bash;
kernelDTB = pkgs.stdenv.platform.kernelDTB or false;
}
@@ -0,0 +1,140 @@
#! @bash@/bin/sh -e
shopt -s nullglob
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
exit 1
}
timeout= # Timeout in centiseconds
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
case "$opt" in
t) # U-Boot interprets '0' as infinite and negative as instant boot
if [ "$OPTARG" -lt 0 ]; then
timeout=0
elif [ "$OPTARG" = 0 ]; then
timeout=-10
else
timeout=$((OPTARG * 10))
fi
;;
c) default="$OPTARG" ;;
d) target="$OPTARG" ;;
g) numGenerations="$OPTARG" ;;
\?) usage ;;
esac
done
[ "$timeout" = "" -o "$default" = "" ] && usage
mkdir -p $target/nixos
mkdir -p $target/extlinux
# Convert a path to a file in the Nix store such as
# /nix/store/<hash>-<name>/file to <hash>-<name>-<file>.
cleanName() {
local path="$1"
echo "$path" | sed 's|^/nix/store/||' | sed 's|/|-|g'
}
# Copy a file from the Nix store to $target/nixos.
declare -A filesCopied
copyToKernelsDir() {
local src=$(readlink -f "$1")
local dst="$target/nixos/$(cleanName $src)"
# Don't copy the file if $dst already exists. This means that we
# have to create $dst atomically to prevent partially copied
# kernels or initrd if this script is ever interrupted.
if ! test -e $dst; then
local dstTmp=$dst.tmp.$$
cp -r $src $dstTmp
mv $dstTmp $dst
fi
filesCopied[$dst]=1
result=$dst
}
# Copy its kernel, initrd and dtbs to $target/nixos, and echo out an
# extlinux menu entry
addEntry() {
local path=$(readlink -f "$1")
local tag="$2" # Generation number or 'default'
if ! test -e $path/kernel -a -e $path/initrd; then
return
fi
copyToKernelsDir "$path/kernel"; kernel=$result
copyToKernelsDir "$path/initrd"; initrd=$result
if [ -n "@kernelDTB@" ]; then
# XXX UGLY: maybe the system config should have a top-level "dtbs" entry?
copyToKernelsDir $(readlink -m "$path/kernel/../dtbs"); dtbs=$result
fi
timestampEpoch=$(stat -L -c '%Z' $path)
timestamp=$(date "+%Y-%m-%d %H:%M" -d @$timestampEpoch)
nixosVersion="$(cat $path/nixos-version)"
extraParams="$(cat $path/kernel-params)"
echo
echo "LABEL nixos-$tag"
if [ "$tag" = "default" ]; then
echo " MENU LABEL NixOS - Default"
else
echo " MENU LABEL NixOS - Configuration $tag ($timestamp - $nixosVersion)"
fi
echo " LINUX ../nixos/$(basename $kernel)"
echo " INITRD ../nixos/$(basename $initrd)"
if [ -n "@kernelDTB@" ]; then
echo " FDTDIR ../nixos/$(basename $dtbs)"
fi
echo " APPEND systemConfig=$path init=$path/init $extraParams"
}
tmpFile="$target/extlinux/extlinux.conf.tmp.$$"
cat > $tmpFile <<EOF
# Generated file, all changes will be lost on nixos-rebuild!
# Change this to e.g. nixos-42 to temporarily boot to an older configuration.
DEFAULT nixos-default
MENU TITLE ------------------------------------------------------------
TIMEOUT $timeout
EOF
addEntry $default default >> $tmpFile
if [ "$numGenerations" -gt 0 ]; then
# Add up to $numGenerations generations of the system profile to the menu,
# in reverse (most recent to least recent) order.
for generation in $(
(cd /nix/var/nix/profiles && ls -d system-*-link) \
| sed 's/system-\([0-9]\+\)-link/\1/' \
| sort -n -r \
| head -n $numGenerations); do
link=/nix/var/nix/profiles/system-$generation-link
addEntry $link $generation
done >> $tmpFile
fi
mv -f $tmpFile $target/extlinux/extlinux.conf
# Remove obsolete files from $target/nixos.
for fn in $target/nixos/*; do
if ! test "${filesCopied[$fn]}" = 1; then
echo "Removing no longer needed boot file: $fn"
chmod +w -- "$fn"
rm -rf -- "$fn"
fi
done
+182 -28
View File
@@ -10,7 +10,8 @@ let
realGrub = if cfg.version == 1 then pkgs.grub
else if cfg.zfsSupport then pkgs.grub2.override { zfsSupport = true; }
else pkgs.grub2;
else if cfg.enableTrustedBoot then pkgs.trustedGrub
else pkgs.grub2;
grub =
# Don't include GRUB if we're only generating a GRUB menu (e.g.,
@@ -21,25 +22,36 @@ let
grubEfi =
# EFI version of Grub v2
if (cfg.devices != ["nodev"]) && cfg.efiSupport && (cfg.version == 2)
if cfg.efiSupport && (cfg.version == 2)
then realGrub.override { efiSupport = cfg.efiSupport; }
else null;
f = x: if x == null then "" else "" + x;
grubConfig = pkgs.writeText "grub-config.xml" (builtins.toXML
{ splashImage = f config.boot.loader.grub.splashImage;
grubConfig = args:
let
efiSysMountPoint = if args.efiSysMountPoint == null then args.path else args.efiSysMountPoint;
efiSysMountPoint' = replaceChars [ "/" ] [ "-" ] efiSysMountPoint;
in
pkgs.writeText "grub-config.xml" (builtins.toXML
{ splashImage = f cfg.splashImage;
grub = f grub;
grubTarget = f (grub.grubTarget or "");
shell = "${pkgs.stdenv.shell}";
fullName = (builtins.parseDrvName realGrub.name).name;
fullVersion = (builtins.parseDrvName realGrub.name).version;
grubEfi = f grubEfi;
grubTargetEfi = if cfg.efiSupport && (cfg.version == 2) then f (grubEfi.grubTarget or "") else "";
inherit (efi) efiSysMountPoint canTouchEfiVariables;
bootPath = args.path;
storePath = config.boot.loader.grub.storePath;
bootloaderId = if args.efiBootloaderId == null then "NixOS${efiSysMountPoint'}" else args.efiBootloaderId;
inherit efiSysMountPoint;
inherit (args) devices;
inherit (efi) canTouchEfiVariables;
inherit (cfg)
version extraConfig extraPerEntryConfig extraEntries
extraEntriesBeforeNixOS extraPrepareConfig configurationLimit copyKernels timeout
default devices fsIdentifier efiSupport;
default fsIdentifier efiSupport gfxmodeEfi gfxmodeBios;
path = (makeSearchPath "bin" ([
pkgs.coreutils pkgs.gnused pkgs.gnugrep pkgs.findutils pkgs.diffutils pkgs.btrfsProgs
pkgs.utillinux ] ++ (if cfg.efiSupport && (cfg.version == 2) then [pkgs.efibootmgr ] else [])
@@ -48,6 +60,9 @@ let
]);
});
bootDeviceCounters = fold (device: attr: attr // { "${device}" = (attr."${device}" or 0) + 1; }) {}
(concatMap (args: args.devices) cfg.mirroredBoots);
in
{
@@ -97,10 +112,68 @@ in
description = ''
The devices on which the boot loader, GRUB, will be
installed. Can be used instead of <literal>device</literal> to
install grub into multiple devices (e.g., if as softraid arrays holding /boot).
install GRUB onto multiple devices.
'';
};
mirroredBoots = mkOption {
default = [ ];
example = [
{ path = "/boot1"; devices = [ "/dev/sda" ]; }
{ path = "/boot2"; devices = [ "/dev/sdb" ]; }
];
description = ''
Mirror the boot configuration to multiple partitions and install grub
to the respective devices corresponding to those partitions.
'';
type = types.listOf types.optionSet;
options = {
path = mkOption {
example = "/boot1";
type = types.str;
description = ''
The path to the boot directory where GRUB will be written. Generally
this boot path should double as an EFI path.
'';
};
efiSysMountPoint = mkOption {
default = null;
example = "/boot1/efi";
type = types.nullOr types.str;
description = ''
The path to the efi system mount point. Usually this is the same
partition as the above path and can be left as null.
'';
};
efiBootloaderId = mkOption {
default = null;
example = "NixOS-fsid";
type = types.nullOr types.str;
description = ''
The id of the bootloader to store in efi nvram.
The default is to name it NixOS and append the path or efiSysMountPoint.
This is only used if <literal>boot.loader.efi.canTouchEfiVariables</literal> is true.
'';
};
devices = mkOption {
default = [ ];
example = [ "/dev/sda" "/dev/sdb" ];
type = types.listOf types.str;
description = ''
The path to the devices which will have the GRUB MBR written.
Note these are typically device paths and not paths to partitions.
'';
};
};
};
configurationName = mkOption {
default = "";
example = "Stable 2.6.21";
@@ -110,12 +183,21 @@ in
'';
};
storePath = mkOption {
default = "/nix/store";
type = types.str;
description = ''
Path to the Nix store when looking for kernels at boot.
Only makes sense when copyKernels is false.
'';
};
extraPrepareConfig = mkOption {
default = "";
type = types.lines;
description = ''
Additional bash commands to be run at the script that
prepares the grub menu entries.
prepares the GRUB menu entries.
'';
};
@@ -189,6 +271,24 @@ in
'';
};
gfxmodeEfi = mkOption {
default = "auto";
example = "1024x768";
type = types.str;
description = ''
The gfxmode to pass to GRUB when loading a graphical boot interface under EFI.
'';
};
gfxmodeBios = mkOption {
default = "1024x768";
example = "auto";
type = types.str;
description = ''
The gfxmode to pass to GRUB when loading a graphical boot interface under BIOS.
'';
};
configurationLimit = mkOption {
default = 100;
example = 120;
@@ -230,10 +330,10 @@ in
type = types.addCheck types.str
(type: type == "uuid" || type == "label" || type == "provided");
description = ''
Determines how grub will identify devices when generating the
Determines how GRUB will identify devices when generating the
configuration file. A value of uuid / label signifies that grub
will always resolve the uuid or label of the device before using
it in the configuration. A value of provided means that grub will
it in the configuration. A value of provided means that GRUB will
use the device name as show in <command>df</command> or
<command>mount</command>. Note, zfs zpools / datasets are ignored
and will always be mounted using their labels.
@@ -244,7 +344,7 @@ in
default = false;
type = types.bool;
description = ''
Whether grub should be build against libzfs.
Whether GRUB should be build against libzfs.
ZFS support is only available for GRUB v2.
This option is ignored for GRUB v1.
'';
@@ -254,7 +354,7 @@ in
default = false;
type = types.bool;
description = ''
Whether grub should be build with EFI support.
Whether GRUB should be build with EFI support.
EFI support is only available for GRUB v2.
This option is ignored for GRUB v1.
'';
@@ -264,11 +364,20 @@ in
default = false;
type = types.bool;
description = ''
Enable support for encrypted partitions. Grub should automatically
Enable support for encrypted partitions. GRUB should automatically
unlock the correct encrypted partition and look for filesystems.
'';
};
enableTrustedBoot = mkOption {
default = false;
type = types.bool;
description = ''
Enable trusted boot. GRUB will measure all critical components during
the boot process to offer TCG (TPM) support.
'';
};
};
};
@@ -284,20 +393,25 @@ in
sha256 = "14kqdx2lfqvh40h6fjjzqgff1mwk74dmbjvmqphi6azzra7z8d59";
}
# GRUB 1.97 doesn't support gzipped XPMs.
else ./winkler-gnu-blue-640x480.png);
else "${pkgs.nixos-artwork}/share/artwork/gnome/Gnome_Dark.png");
}
(mkIf cfg.enable {
boot.loader.grub.devices = optional (cfg.device != "") cfg.device;
system.build.installBootLoader =
if cfg.devices == [] then
throw "You must set the option boot.loader.grub.device to make the system bootable."
else
"PERL5LIB=${makePerlPath (with pkgs.perlPackages; [ FileSlurp XMLLibXML XMLSAX ListCompare ])} " +
(if cfg.enableCryptodisk then "GRUB_ENABLE_CRYPTODISK=y " else "") +
"${pkgs.perl}/bin/perl ${./install-grub.pl} ${grubConfig}";
boot.loader.grub.mirroredBoots = optionals (cfg.devices != [ ]) [
{ path = "/boot"; inherit (cfg) devices; inherit (efi) efiSysMountPoint; }
];
system.build.installBootLoader = pkgs.writeScript "install-grub.sh" (''
#!${pkgs.stdenv.shell}
set -e
export PERL5LIB=${makePerlPath (with pkgs.perlPackages; [ FileSlurp XMLLibXML XMLSAX ListCompare ])}
${optionalString cfg.enableCryptodisk "export GRUB_ENABLE_CRYPTODISK=y"}
'' + flip concatMapStrings cfg.mirroredBoots (args: ''
${pkgs.perl}/bin/perl ${./install-grub.pl} ${grubConfig args} $@
''));
system.build.grub = grub;
@@ -312,13 +426,53 @@ in
${pkgs.coreutils}/bin/cp -pf "${v}" "/boot/${n}"
'') config.boot.loader.grub.extraFiles);
assertions = [{ assertion = !cfg.zfsSupport || cfg.version == 2;
message = "Only grub version 2 provides zfs support";}]
++ flip map cfg.devices (dev: {
assertion = dev == "nodev" || hasPrefix "/" dev;
message = "Grub devices must be absolute paths, not ${dev}";
});
assertions = [
{
assertion = !cfg.zfsSupport || cfg.version == 2;
message = "Only GRUB version 2 provides ZFS support";
}
{
assertion = cfg.mirroredBoots != [ ];
message = "You must set the option boot.loader.grub.devices or "
+ "'boot.loader.grub.mirroredBoots' to make the system bootable.";
}
{
assertion = all (c: c < 2) (mapAttrsToList (_: c: c) bootDeviceCounters);
message = "You cannot have duplicated devices in mirroredBoots";
}
{
assertion = !cfg.enableTrustedBoot || cfg.version == 2;
message = "Trusted GRUB is only available for GRUB 2";
}
{
assertion = !cfg.efiSupport || !cfg.enableTrustedBoot;
message = "Trusted GRUB does not have EFI support";
}
{
assertion = !cfg.zfsSupport || !cfg.enableTrustedBoot;
message = "Trusted GRUB does not have ZFS support";
}
{
assertion = !cfg.enableTrustedBoot;
message = "Trusted GRUB can break your system. Remove assertion if you want to test trustedGRUB nevertheless.";
}
] ++ flip concatMap cfg.mirroredBoots (args: [
{
assertion = args.devices != [ ];
message = "A boot path cannot have an empty devices string in ${arg.path}";
}
{
assertion = hasPrefix "/" args.path;
message = "Boot paths must be absolute, not ${args.path}";
}
{
assertion = if args.efiSysMountPoint == null then true else hasPrefix "/" args.efiSysMountPoint;
message = "Efi paths must be absolute, not ${args.efiSysMountPoint}";
}
] ++ flip map args.devices (device: {
assertion = device == "nodev" || hasPrefix "/" device;
message = "GRUB devices must be absolute paths, not ${dev} in ${args.path}";
}));
})
];
@@ -7,6 +7,7 @@ use File::Path;
use File::stat;
use File::Copy;
use File::Slurp;
use File::Temp;
require List::Compare;
use POSIX;
use Cwd;
@@ -54,24 +55,29 @@ my $defaultEntry = int(get("default"));
my $fsIdentifier = get("fsIdentifier");
my $grubEfi = get("grubEfi");
my $grubTargetEfi = get("grubTargetEfi");
my $bootPath = get("bootPath");
my $storePath = get("storePath");
my $canTouchEfiVariables = get("canTouchEfiVariables");
my $efiSysMountPoint = get("efiSysMountPoint");
my $gfxmodeEfi = get("gfxmodeEfi");
my $gfxmodeBios = get("gfxmodeBios");
my $bootloaderId = get("bootloaderId");
$ENV{'PATH'} = get("path");
die "unsupported GRUB version\n" if $grubVersion != 1 && $grubVersion != 2;
print STDERR "updating GRUB $grubVersion menu...\n";
mkpath("/boot/grub", 0, 0700);
mkpath("$bootPath/grub", 0, 0700);
# Discover whether /boot is on the same filesystem as / and
# Discover whether the bootPath is on the same filesystem as / and
# /nix/store. If not, then all kernels and initrds must be copied to
# /boot.
if (stat("/boot")->dev != stat("/nix/store")->dev) {
# the bootPath.
if (stat($bootPath)->dev != stat("/nix/store")->dev) {
$copyKernels = 1;
}
# Discover information about the location of /boot
# Discover information about the location of the bootPath
struct(Fs => {
device => '$',
type => '$',
@@ -180,7 +186,7 @@ sub GrubFs {
if ($status != 0) {
die "Failed to retrieve subvolume info for @{[$fs->mount]}\n";
}
my @ids = join("", @id_info) =~ m/Object ID:[ \t\n]*([^ \t\n]*)/;
my @ids = join("", @id_info) =~ m/Subvolume ID:[ \t\n]*([^ \t\n]*)/;
if ($#ids > 0) {
die "Btrfs subvol name for @{[$fs->device]} listed multiple times in mount\n"
} elsif ($#ids == 0) {
@@ -206,10 +212,10 @@ sub GrubFs {
}
return Grub->new(path => $path, search => $search);
}
my $grubBoot = GrubFs("/boot");
my $grubBoot = GrubFs($bootPath);
my $grubStore;
if ($copyKernels == 0) {
$grubStore = GrubFs("/nix/store");
$grubStore = GrubFs($storePath);
}
# Generate the header.
@@ -221,7 +227,7 @@ if ($grubVersion == 1) {
timeout $timeout
";
if ($splashImage) {
copy $splashImage, "/boot/background.xpm.gz" or die "cannot copy $splashImage to /boot\n";
copy $splashImage, "$bootPath/background.xpm.gz" or die "cannot copy $splashImage to $bootPath\n";
$conf .= "splashimage " . $grubBoot->path . "/background.xpm.gz\n";
}
}
@@ -231,6 +237,7 @@ else {
$conf .= "
" . $grubStore->search;
}
# FIXME: should use grub-mkconfig.
$conf .= "
" . $grubBoot->search . "
if [ -s \$prefix/grubenv ]; then
@@ -239,24 +246,35 @@ else {
# grub-reboot sets a one-time saved entry, which we process here and
# then delete.
if [ \"\${saved_entry}\" ]; then
# The next line *has* to look exactly like this, otherwise KDM's
# reboot feature won't work properly with GRUB 2.
if [ \"\${next_entry}\" ]; then
# FIXME: KDM expects the next line to be present.
set default=\"\${saved_entry}\"
set saved_entry=
set prev_saved_entry=
save_env saved_entry
save_env prev_saved_entry
set default=\"\${next_entry}\"
set next_entry=
save_env next_entry
set timeout=1
else
set default=$defaultEntry
set timeout=$timeout
fi
if loadfont " . $grubBoot->path . "/grub/fonts/unicode.pf2; then
set gfxmode=640x480
insmod gfxterm
# Setup the graphics stack for bios and efi systems
if [ \"\${grub_platform}\" = \"efi\" ]; then
insmod efi_gop
insmod efi_uga
else
insmod vbe
fi
insmod font
if loadfont " . $grubBoot->path . "/grub/fonts/unicode.pf2; then
insmod gfxterm
if [ \"\${grub_platform}\" = \"efi\" ]; then
set gfxmode=$gfxmodeEfi
set gfxpayload=keep
else
set gfxmode=$gfxmodeBios
set gfxpayload=text
fi
terminal_output gfxterm
fi
";
@@ -264,7 +282,7 @@ else {
if ($splashImage) {
# FIXME: GRUB 1.97 doesn't resize the background image if it
# doesn't match the video resolution.
copy $splashImage, "/boot/background.png" or die "cannot copy $splashImage to /boot\n";
copy $splashImage, "$bootPath/background.png" or die "cannot copy $splashImage to $bootPath\n";
$conf .= "
insmod png
if background_image " . $grubBoot->path . "/background.png; then
@@ -285,14 +303,14 @@ $conf .= "$extraConfig\n";
$conf .= "\n";
my %copied;
mkpath("/boot/kernels", 0, 0755) if $copyKernels;
mkpath("$bootPath/kernels", 0, 0755) if $copyKernels;
sub copyToKernelsDir {
my ($path) = @_;
return $grubStore->path . substr($path, length("/nix/store")) unless $copyKernels;
$path =~ /\/nix\/store\/(.*)/ or die;
my $name = $1; $name =~ s/\//-/g;
my $dst = "/boot/kernels/$name";
my $dst = "$bootPath/kernels/$name";
# Don't copy the file if $dst already exists. This means that we
# have to create $dst atomically to prevent partially copied
# kernels or initrd if this script is ever interrupted.
@@ -396,14 +414,14 @@ if ($extraPrepareConfig ne "") {
}
# Atomically update the GRUB config.
my $confFile = $grubVersion == 1 ? "/boot/grub/menu.lst" : "/boot/grub/grub.cfg";
my $confFile = $grubVersion == 1 ? "$bootPath/grub/menu.lst" : "$bootPath/grub/grub.cfg";
my $tmpFile = $confFile . ".tmp";
writeFile($tmpFile, $conf);
rename $tmpFile, $confFile or die "cannot rename $tmpFile to $confFile\n";
# Remove obsolete files from /boot/kernels.
foreach my $fn (glob "/boot/kernels/*") {
# Remove obsolete files from $bootPath/kernels.
foreach my $fn (glob "$bootPath/kernels/*") {
next if defined $copied{$fn};
print STDERR "removing obsolete file $fn\n";
unlink $fn;
@@ -415,15 +433,18 @@ foreach my $fn (glob "/boot/kernels/*") {
#
struct(GrubState => {
name => '$',
version => '$',
efi => '$',
devices => '$',
efiMountPoint => '$',
});
sub readGrubState {
my $defaultGrubState = GrubState->new(version => "", efi => "", devices => "", efiMountPoint => "" );
open FILE, "</boot/grub/state" or return $defaultGrubState;
my $defaultGrubState = GrubState->new(name => "", version => "", efi => "", devices => "", efiMountPoint => "" );
open FILE, "<$bootPath/grub/state" or return $defaultGrubState;
local $/ = "\n";
my $name = <FILE>;
chomp($name);
my $version = <FILE>;
chomp($version);
my $efi = <FILE>;
@@ -433,7 +454,7 @@ sub readGrubState {
my $efiMountPoint = <FILE>;
chomp($efiMountPoint);
close FILE;
my $grubState = GrubState->new(version => $version, efi => $efi, devices => $devices, efiMountPoint => $efiMountPoint );
my $grubState = GrubState->new(name => $name, version => $version, efi => $efi, devices => $devices, efiMountPoint => $efiMountPoint );
return $grubState
}
@@ -478,12 +499,16 @@ my $efiTarget = getEfiTarget();
my $prevGrubState = readGrubState();
my @prevDeviceTargets = split/:/, $prevGrubState->devices;
my $devicesDiffer = scalar (List::Compare->new( '-u', '-a', \@deviceTargets, \@prevDeviceTargets)->get_symmetric_difference() );
my $versionDiffer = (get("fullVersion") eq \$prevGrubState->version);
my $efiDiffer = ($efiTarget eq \$prevGrubState->efi);
my $efiMountPointDiffer = ($efiSysMountPoint eq \$prevGrubState->efiMountPoint);
my $requireNewInstall = $devicesDiffer || $versionDiffer || $efiDiffer || $efiMountPointDiffer || (($ENV{'NIXOS_INSTALL_GRUB'} // "") eq "1");
my $devicesDiffer = scalar (List::Compare->new( '-u', '-a', \@deviceTargets, \@prevDeviceTargets)->get_symmetric_difference());
my $nameDiffer = get("fullName") ne $prevGrubState->name;
my $versionDiffer = get("fullVersion") ne $prevGrubState->version;
my $efiDiffer = $efiTarget ne $prevGrubState->efi;
my $efiMountPointDiffer = $efiSysMountPoint ne $prevGrubState->efiMountPoint;
my $requireNewInstall = $devicesDiffer || $nameDiffer || $versionDiffer || $efiDiffer || $efiMountPointDiffer || (($ENV{'NIXOS_INSTALL_GRUB'} // "") 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";
# install non-EFI GRUB
if (($requireNewInstall != 0) && ($efiTarget eq "no" || $efiTarget eq "both")) {
@@ -491,10 +516,10 @@ if (($requireNewInstall != 0) && ($efiTarget eq "no" || $efiTarget eq "both")) {
next if $dev eq "nodev";
print STDERR "installing the GRUB $grubVersion boot loader on $dev...\n";
if ($grubTarget eq "") {
system("$grub/sbin/grub-install", "--recheck", Cwd::abs_path($dev)) == 0
system("$grub/sbin/grub-install", "--recheck", "--root-directory=$tmpDir", Cwd::abs_path($dev)) == 0
or die "$0: installation of GRUB on $dev failed\n";
} else {
system("$grub/sbin/grub-install", "--recheck", "--target=$grubTarget", Cwd::abs_path($dev)) == 0
system("$grub/sbin/grub-install", "--recheck", "--root-directory=$tmpDir", "--target=$grubTarget", Cwd::abs_path($dev)) == 0
or die "$0: installation of GRUB on $dev failed\n";
}
}
@@ -505,10 +530,10 @@ if (($requireNewInstall != 0) && ($efiTarget eq "no" || $efiTarget eq "both")) {
if (($requireNewInstall != 0) && ($efiTarget eq "only" || $efiTarget eq "both")) {
print STDERR "installing the GRUB $grubVersion EFI boot loader into $efiSysMountPoint...\n";
if ($canTouchEfiVariables eq "true") {
system("$grubEfi/sbin/grub-install", "--recheck", "--target=$grubTargetEfi", "--efi-directory=$efiSysMountPoint") == 0
system("$grubEfi/sbin/grub-install", "--recheck", "--target=$grubTargetEfi", "--boot-directory=$bootPath", "--efi-directory=$efiSysMountPoint", "--bootloader-id=$bootloaderId") == 0
or die "$0: installation of GRUB EFI into $efiSysMountPoint failed\n";
} else {
system("$grubEfi/sbin/grub-install", "--recheck", "--target=$grubTargetEfi", "--efi-directory=$efiSysMountPoint", "--no-nvram") == 0
system("$grubEfi/sbin/grub-install", "--recheck", "--target=$grubTargetEfi", "--boot-directory=$bootPath", "--efi-directory=$efiSysMountPoint", "--no-nvram") == 0
or die "$0: installation of GRUB EFI into $efiSysMountPoint failed\n";
}
}
@@ -516,7 +541,8 @@ if (($requireNewInstall != 0) && ($efiTarget eq "only" || $efiTarget eq "both"))
# update GRUB state file
if ($requireNewInstall != 0) {
open FILE, ">/boot/grub/state" or die "cannot create /boot/grub/state: $!\n";
open FILE, ">$bootPath/grub/state" or die "cannot create $bootPath/grub/state: $!\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;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

@@ -1,6 +0,0 @@
This is a resized version of
http://www.gnu.org/graphics/winkler-gnu-blue.png
by Kyle Winkler and released under the Free Art License
(http://artlibre.org/licence.php/lalgb.html).
@@ -60,22 +60,26 @@ addEntry() {
fi
local kernel=$(readlink -f $path/kernel)
# local initrd=$(readlink -f $path/initrd)
local initrd=$(readlink -f $path/initrd)
if test -n "@copyKernels@"; then
copyToKernelsDir $kernel; kernel=$result
# copyToKernelsDir $initrd; initrd=$result
copyToKernelsDir $initrd; initrd=$result
fi
echo $(readlink -f $path) > $outdir/$generation-system
echo $(readlink -f $path/init) > $outdir/$generation-init
cp $path/kernel-params $outdir/$generation-cmdline.txt
# echo $initrd > $outdir/$generation-initrd
echo $initrd > $outdir/$generation-initrd
echo $kernel > $outdir/$generation-kernel
if test $(readlink -f "$path") = "$default"; then
copyForced $kernel /boot/kernel.img
# copyForced $initrd /boot/initrd
if [ @version@ -eq 1 ]; then
copyForced $kernel /boot/kernel.img
else
copyForced $kernel /boot/kernel7.img
fi
copyForced $initrd /boot/initrd
cp "$(readlink -f "$path/init")" /boot/nixos-init
echo "`cat $path/kernel-params` init=$path/init" >/boot/cmdline.txt
@@ -98,8 +102,11 @@ fwdir=@firmware@/share/raspberrypi/boot/
copyForced $fwdir/bootcode.bin /boot/bootcode.bin
copyForced $fwdir/fixup.dat /boot/fixup.dat
copyForced $fwdir/fixup_cd.dat /boot/fixup_cd.dat
copyForced $fwdir/fixup_db.dat /boot/fixup_db.dat
copyForced $fwdir/start.elf /boot/start.elf
copyForced $fwdir/start_cd.elf /boot/start_cd.elf
copyForced $fwdir/start_db.elf /boot/start_db.elf
copyForced $fwdir/start_x.elf /boot/start_x.elf
# Remove obsolete files from /boot/old.
for fn in /boot/old/*linux* /boot/old/*initrd*; do
@@ -3,6 +3,7 @@
with lib;
let
cfg = config.boot.loader.raspberryPi;
builder = pkgs.substituteAll {
src = ./builder.sh;
@@ -10,6 +11,7 @@ let
inherit (pkgs) bash;
path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
firmware = pkgs.raspberrypifw;
version = cfg.version;
};
platform = pkgs.stdenv.platform;
@@ -29,11 +31,23 @@ in
'';
};
boot.loader.raspberryPi.version = mkOption {
default = 2;
type = types.int;
description = ''
'';
};
};
config = mkIf config.boot.loader.raspberryPi.enable {
system.build.installBootLoader = builder;
system.boot.loader.id = "raspberrypi";
system.boot.loader.kernelFile = platform.kernelTarget;
assertions = [
{ assertion = (cfg.version == 1 || cfg.version == 2);
message = "loader.raspberryPi.version should be 1 or 2";
}
];
};
}
+39 -28
View File
@@ -5,7 +5,7 @@ with lib;
let
luks = config.boot.initrd.luks;
openCommand = { name, device, keyFile, keyFileSize, allowDiscards, yubikey, ... }: ''
openCommand = { name, device, header, keyFile, keyFileSize, allowDiscards, yubikey, ... }: ''
# Wait for luksRoot to appear, e.g. if on a usb drive.
# XXX: copied and adapted from stage-1-init.sh - should be
# available as a function.
@@ -33,6 +33,7 @@ let
open_normally() {
cryptsetup luksOpen ${device} ${name} ${optionalString allowDiscards "--allow-discards"} \
${optionalString (header != null) "--header=${header}"} \
${optionalString (keyFile != null) "--key-file=${keyFile} ${optionalString (keyFileSize != null) "--keyfile-size=${toString keyFileSize}"}"}
}
@@ -211,7 +212,7 @@ in
};
boot.initrd.luks.cryptoModules = mkOption {
type = types.listOf types.string;
type = types.listOf types.str;
default =
[ "aes" "aes_generic" "blowfish" "twofish"
"serpent" "cbc" "xts" "lrw" "sha1" "sha256" "sha512"
@@ -241,20 +242,30 @@ in
name = mkOption {
example = "luksroot";
type = types.string;
type = types.str;
description = "Named to be used for the generated device in /dev/mapper.";
};
device = mkOption {
example = "/dev/sda2";
type = types.string;
type = types.str;
description = "Path of the underlying block device.";
};
header = mkOption {
default = null;
example = "/root/header.img";
type = types.nullOr types.str;
description = ''
The name of the file or block device that
should be used as header for the encrypted device.
'';
};
keyFile = mkOption {
default = null;
example = "/dev/sdb1";
type = types.nullOr types.string;
type = types.nullOr types.str;
description = ''
The name of the file (can be a raw device or a partition) that
should be used as the decryption key for the encrypted device. If
@@ -286,8 +297,8 @@ in
type = types.bool;
description = ''
Whether to allow TRIM requests to the underlying device. This option
has security implications, please read the LUKS documentation before
activating in.
has security implications; please read the LUKS documentation before
activating it.
'';
};
@@ -303,43 +314,43 @@ in
twoFactor = mkOption {
default = true;
type = types.bool;
description = "Whether to use a passphrase and a Yubikey (true), or only a Yubikey (false)";
description = "Whether to use a passphrase and a Yubikey (true), or only a Yubikey (false).";
};
slot = mkOption {
default = 2;
type = types.int;
description = "Which slot on the Yubikey to challenge";
description = "Which slot on the Yubikey to challenge.";
};
saltLength = mkOption {
default = 16;
type = types.int;
description = "Length of the new salt in byte (64 is the effective maximum)";
description = "Length of the new salt in byte (64 is the effective maximum).";
};
keyLength = mkOption {
default = 64;
type = types.int;
description = "Length of the LUKS slot key derived with PBKDF2 in byte";
description = "Length of the LUKS slot key derived with PBKDF2 in byte.";
};
iterationStep = mkOption {
default = 0;
type = types.int;
description = "How much the iteration count for PBKDF2 is increased at each successful authentication";
description = "How much the iteration count for PBKDF2 is increased at each successful authentication.";
};
gracePeriod = mkOption {
default = 2;
type = types.int;
description = "Time in seconds to wait before attempting to find the Yubikey";
description = "Time in seconds to wait before attempting to find the Yubikey.";
};
ramfsMountPoint = mkOption {
default = "/crypt-ramfs";
type = types.string;
description = "Path where the ramfs used to update the LUKS key will be mounted in stage-1";
type = types.str;
description = "Path where the ramfs used to update the LUKS key will be mounted during early boot.";
};
/* TODO: Add to the documentation of the current module:
@@ -358,19 +369,19 @@ in
fsType = mkOption {
default = "vfat";
type = types.string;
description = "The filesystem of the unencrypted device";
type = types.str;
description = "The filesystem of the unencrypted device.";
};
mountPoint = mkOption {
default = "/crypt-storage";
type = types.string;
description = "Path where the unencrypted device will be mounted in stage-1";
type = types.str;
description = "Path where the unencrypted device will be mounted during early boot.";
};
path = mkOption {
default = "/crypt-storage/default";
type = types.string;
type = types.str;
description = ''
Absolute path of the salt on the unencrypted device with
that device's root directory as "/".
@@ -419,10 +430,10 @@ in
mkdir -p $out/etc/ssl
cp -pdv ${pkgs.openssl}/etc/ssl/openssl.cnf $out/etc/ssl
cat > $out/bin/openssl-wrap <<EOF
#!$out/bin/sh
EOF
chmod +x $out/bin/openssl-wrap
cat > $out/bin/openssl-wrap <<EOF
#!$out/bin/sh
EOF
chmod +x $out/bin/openssl-wrap
''}
'';
@@ -432,10 +443,10 @@ EOF
$out/bin/ykchalresp -V
$out/bin/ykinfo -V
cat > $out/bin/openssl-wrap <<EOF
#!$out/bin/sh
export OPENSSL_CONF=$out/etc/ssl/openssl.cnf
$out/bin/openssl "\$@"
EOF
#!$out/bin/sh
export OPENSSL_CONF=$out/etc/ssl/openssl.cnf
$out/bin/openssl "\$@"
EOF
$out/bin/openssl-wrap version
''}
'';
+3 -6
View File
@@ -35,6 +35,7 @@ with lib;
fi
'';
meta.priority = 4;
};
description = ''
Wrapper around modprobe that sets the path to the modules
@@ -84,11 +85,7 @@ with lib;
'')}
${config.boot.extraModprobeConfig}
'';
environment.etc."modprobe.d/usb-load-ehci-first.conf".text =
''
softdep uhci_hcd pre: ehci_hcd
softdep ohci_hcd pre: ehci_hcd
'';
environment.etc."modprobe.d/debian.conf".source = pkgs.kmod-debian-aliases;
environment.systemPackages = [ config.system.sbin.modprobe pkgs.kmod ];
@@ -101,7 +98,7 @@ with lib;
echo ${config.system.sbin.modprobe}/sbin/modprobe > /proc/sys/kernel/modprobe
'';
environment.variables.MODULE_DIR = "/run/current-system/kernel-modules/lib/modules";
environment.sessionVariables.MODULE_DIR = "/run/current-system/kernel-modules/lib/modules";
};
+6 -4
View File
@@ -132,7 +132,7 @@ let
commonNetworkOptions = {
enable = mkOption {
default = false;
default = true;
type = types.bool;
description = ''
Whether to manage network configuration using <command>systemd-network</command>.
@@ -482,6 +482,11 @@ let
};
};
commonMatchText = def: ''
[Match]
${attrsToSection def.matchConfig}
'';
linkToUnit = name: def:
{ inherit (def) enable;
text = commonMatchText def +
@@ -636,9 +641,6 @@ in
environment.etc."systemd/network".source =
generateUnits "network" cfg.units [] [];
users.extraUsers.systemd-network.uid = config.ids.uids.systemd-network;
users.extraGroups.systemd-network.gid = config.ids.gids.systemd-network;
systemd.services.systemd-networkd = {
wantedBy = [ "multi-user.target" ];
before = [ "network-interfaces.target" ];
-3
View File
@@ -30,9 +30,6 @@ with lib;
DNS=${concatStringsSep " " config.networking.nameservers}
'';
users.extraUsers.systemd-resolve.uid = config.ids.uids.systemd-resolve;
users.extraGroups.systemd-resolve.gid = config.ids.gids.systemd-resolve;
};
}
+25 -12
View File
@@ -135,7 +135,7 @@ ln -s @modulesClosure@/lib/modules /lib/modules
echo @extraUtils@/bin/modprobe > /proc/sys/kernel/modprobe
for i in @kernelModules@; do
echo "loading module $(basename $i)..."
modprobe $i || true
modprobe $i
done
@@ -146,7 +146,7 @@ ln -sfn @udevRules@ /etc/udev/rules.d
mkdir -p /dev/.mdadm
systemd-udevd --daemon
udevadm trigger --action=add
udevadm settle || true
udevadm settle
# Load boot-time keymap before any LVM/LUKS initialization
@@ -182,9 +182,9 @@ if test -e /sys/power/resume -a -e /sys/power/disk; then
for sd in @resumeDevices@; do
# Try to detect resume device. According to Ubuntu bug:
# https://bugs.launchpad.net/ubuntu/+source/pm-utils/+bug/923326/comments/1
# When there are multiple swap devices, we can't know where will hibernate
# image reside. We can check all of them for swsuspend blkid.
resumeInfo="$(udevadm info -q property "$sd" )"
# when there are multiple swap devices, we can't know where the hibernate
# image will reside. We can check all of them for swsuspend blkid.
resumeInfo="$(test -e "$sd" && udevadm info -q property "$sd")"
if [ "$(echo "$resumeInfo" | sed -n 's/^ID_FS_TYPE=//p')" = "swsuspend" ]; then
resumeDev="$sd"
break
@@ -290,10 +290,23 @@ mountFS() {
if [ -z "$fsType" ]; then fsType=auto; fi
fi
echo "$device /mnt-root$mountPoint $fsType $options" >> /etc/fstab
# Filter out x- options, which busybox doesn't do yet.
local optionsFiltered="$(IFS=,; for i in $options; do if [ "${i:0:2}" != "x-" ]; then echo -n $i,; fi; done)"
echo "$device /mnt-root$mountPoint $fsType $optionsFiltered" >> /etc/fstab
checkFS "$device" "$fsType"
# Optionally resize the filesystem.
case $options in
*x-nixos.autoresize*)
if [ "$fsType" = ext2 -o "$fsType" = ext3 -o "$fsType" = ext4 ]; then
echo "resizing $device..."
resize2fs "$device"
fi
;;
esac
# Create backing directories for unionfs-fuse.
if [ "$fsType" = unionfs-fuse ]; then
for i in $(IFS=:; echo ${options##*,dirs=}); do
@@ -303,7 +316,7 @@ mountFS() {
echo "mounting $device on $mountPoint..."
mkdir -p "/mnt-root$mountPoint" || true
mkdir -p "/mnt-root$mountPoint"
# For CIFS mounts, retry a few times before giving up.
local n=0
@@ -317,7 +330,7 @@ mountFS() {
# Try to find and mount the root device.
mkdir /mnt-root
mkdir -p $targetRoot
exec 3< @fsInfo@
@@ -375,7 +388,7 @@ while read -u 3 mountPoint; do
# Wait once more for the udev queue to empty, just in case it's
# doing something with $device right now.
udevadm settle || true
udevadm settle
mountFS "$device" "$mountPoint" "$options" "$fsType"
done
@@ -388,9 +401,9 @@ exec 3>&-
# Emit a udev rule for /dev/root to prevent systemd from complaining.
if [ -e /mnt-root/iso ]; then
eval $(udevadm info --export --export-prefix=ROOT_ --device-id-of-file=/mnt-root/iso || true)
eval $(udevadm info --export --export-prefix=ROOT_ --device-id-of-file=/mnt-root/iso)
else
eval $(udevadm info --export --export-prefix=ROOT_ --device-id-of-file=$targetRoot || true)
eval $(udevadm info --export --export-prefix=ROOT_ --device-id-of-file=$targetRoot)
fi
if [ "$ROOT_MAJOR" -a "$ROOT_MINOR" -a "$ROOT_MAJOR" != 0 ]; then
mkdir -p /run/udev/rules.d
@@ -399,7 +412,7 @@ fi
# Stop udevd.
udevadm control --exit || true
udevadm control --exit
# Kill any remaining processes, just to be sure we're not taking any
# with us into stage 2. But keep storage daemons like unionfs-fuse.
+10 -2
View File
@@ -70,6 +70,12 @@ let
copy_bin_and_libs ${pkgs.kmod}/bin/kmod
ln -sf kmod $out/bin/modprobe
# Copy resize2fs if needed.
${optionalString (any (fs: fs.autoResize) (attrValues config.fileSystems)) ''
# We need mke2fs in the initrd.
copy_bin_and_libs ${pkgs.e2fsprogs}/sbin/resize2fs
''}
${config.boot.initrd.extraUtilsCommands}
# Copy ld manually since it isn't detected correctly
@@ -241,6 +247,9 @@ let
};
symlink = "/etc/modprobe.d/ubuntu.conf";
}
{ object = pkgs.kmod-debian-aliases;
symlink = "/etc/modprobe.d/debian.conf";
}
];
};
@@ -358,7 +367,7 @@ in
boot.initrd.supportedFilesystems = mkOption {
default = [ ];
example = [ "btrfs" ];
type = types.listOf types.string;
type = types.listOf types.str;
description = "Names of supported filesystem types in the initial ramdisk.";
};
@@ -390,7 +399,6 @@ in
}
];
system.build.bootStage1 = bootStage1;
system.build.initialRamdisk = initialRamdisk;
system.build.extraUtils = extraUtils;
+7 -3
View File
@@ -85,8 +85,10 @@ done
# More special file systems, initialise required directories.
mkdir -m 0755 /dev/shm
mount -t tmpfs -o "rw,nosuid,nodev,size=@devShmSize@" tmpfs /dev/shm
if ! mountpoint -q /dev/shm; then
mkdir -m 0755 /dev/shm
mount -t tmpfs -o "rw,nosuid,nodev,size=@devShmSize@" tmpfs /dev/shm
fi
mkdir -m 0755 -p /dev/pts
[ -e /proc/bus/usb ] && mount -t usbfs usbfs /proc/bus/usb # UML doesn't have USB by default
mkdir -m 01777 -p /tmp
@@ -162,7 +164,9 @@ $systemConfig/activate
# Restore the system time from the hardware clock. We do this after
# running the activation script to be sure that /etc/localtime points
# at the current time zone.
hwclock --hctosys
if [ -e /dev/rtc ]; then
hwclock --hctosys
fi
# Record the boot configuration.
+76 -3
View File
@@ -13,20 +13,93 @@ rec {
pathSafeName = lib.replaceChars ["@" ":" "\\"] ["-" "-" "-"] name;
in
if unit.enable then
pkgs.runCommand "unit-${pathSafeName}" { preferLocalBuild = true; inherit (unit) text; }
pkgs.runCommand "unit-${pathSafeName}"
{ preferLocalBuild = true;
allowSubstitutes = false;
inherit (unit) text;
}
''
mkdir -p $out
echo -n "$text" > $out/${shellEscape name}
''
else
pkgs.runCommand "unit-${pathSafeName}-disabled" { preferLocalBuild = true; }
pkgs.runCommand "unit-${pathSafeName}-disabled"
{ preferLocalBuild = true;
allowSubstitutes = false;
}
''
mkdir -p $out
ln -s /dev/null $out/${shellEscape name}
'';
boolValues = [true false "yes" "no"];
digits = map toString (range 0 9);
isByteFormat = s:
let
l = reverseList (stringToCharacters s);
suffix = head l;
nums = tail l;
in elem suffix (["K" "M" "G" "T"] ++ digits)
&& all (num: elem num digits) nums;
assertByteFormat = name: group: attr:
optional (attr ? ${name} && ! isByteFormat attr.${name})
"Systemd ${group} field `${name}' must be in byte format [0-9]+[KMGT].";
hexChars = stringToCharacters "0123456789abcdefABCDEF";
isMacAddress = s: stringLength s == 17
&& flip all (splitString ":" s) (bytes:
all (byte: elem byte hexChars) (stringToCharacters bytes)
);
assertMacAddress = name: group: attr:
optional (attr ? ${name} && ! isMacAddress attr.${name})
"Systemd ${group} field `${name}' must be a valid mac address.";
assertValueOneOf = name: values: group: attr:
optional (attr ? ${name} && !elem attr.${name} values)
"Systemd ${group} field `${name}' cannot have value `${attr.${name}}'.";
assertHasField = name: group: attr:
optional (!(attr ? ${name}))
"Systemd ${group} field `${name}' must exist.";
assertRange = name: min: max: group: attr:
optional (attr ? ${name} && !(min <= attr.${name} && max >= attr.${name}))
"Systemd ${group} field `${name}' is outside the range [${toString min},${toString max}]";
assertOnlyFields = fields: group: attr:
let badFields = filter (name: ! elem name fields) (attrNames attr); in
optional (badFields != [ ])
"Systemd ${group} has extra fields [${concatStringsSep " " badFields}].";
checkUnitConfig = group: checks: v:
let errors = concatMap (c: c group v) checks; in
if errors == [] then true
else builtins.trace (concatStringsSep "\n" errors) false;
toOption = x:
if x == true then "true"
else if x == false then "false"
else toString x;
attrsToSection = as:
concatStrings (concatLists (mapAttrsToList (name: value:
map (x: ''
${name}=${toOption x}
'')
(if isList value then value else [value]))
as));
generateUnits = type: units: upstreamUnits: upstreamWants:
pkgs.runCommand "${type}-units" { preferLocalBuild = true; } ''
pkgs.runCommand "${type}-units"
{ preferLocalBuild = true;
allowSubstitutes = false;
} ''
mkdir -p $out
# Copy the upstream systemd units we're interested in.
@@ -1,58 +1,9 @@
{ config, lib }:
with lib;
with import ./systemd-lib.nix { inherit config lib pkgs; };
let
boolValues = [true false "yes" "no"];
assertValueOneOf = name: values: group: attr:
optional (attr ? ${name} && !elem attr.${name} values)
"Systemd ${group} field `${name}' cannot have value `${attr.${name}}'.";
assertHasField = name: group: attr:
optional (!(attr ? ${name}))
"Systemd ${group} field `${name}' must exist.";
assertOnlyFields = fields: group: attr:
let badFields = filter (name: ! elem name fields) (attrNames attr); in
optional (badFields != [ ])
"Systemd ${group} has extra fields [${concatStringsSep " " badFields}].";
assertRange = name: min: max: group: attr:
optional (attr ? ${name} && !(min <= attr.${name} && max >= attr.${name}))
"Systemd ${group} field `${name}' is outside the range [${toString min},${toString max}]";
digits = map toString (range 0 9);
isByteFormat = s:
let
l = reverseList (stringToCharacters s);
suffix = head l;
nums = tail l;
in elem suffix (["K" "M" "G" "T"] ++ digits)
&& all (num: elem num digits) nums;
assertByteFormat = name: group: attr:
optional (attr ? ${name} && ! isByteFormat attr.${name})
"Systemd ${group} field `${name}' must be in byte format [0-9]+[KMGT].";
hexChars = stringToCharacters "0123456789abcdefABCDEF";
isMacAddress = s: stringLength s == 17
&& flip all (splitString ":" s) (bytes:
all (byte: elem byte hexChars) (stringToCharacters bytes)
);
assertMacAddress = name: group: attr:
optional (attr ? ${name} && ! isMacAddress attr.${name})
"Systemd ${group} field `${name}' must be a valid mac address.";
checkUnitConfig = group: checks: v:
let errors = concatMap (c: c group v) checks; in
if errors == [] then true
else builtins.trace (concatStringsSep "\n" errors) false;
checkService = checkUnitConfig "Service" [
(assertValueOneOf "Type" [
"simple" "forking" "oneshot" "dbus" "notify" "idle"
@@ -91,13 +42,13 @@ in rec {
requiredBy = mkOption {
default = [];
type = types.listOf types.string;
type = types.listOf types.str;
description = "Units that require (i.e. depend on and need to go down with) this unit.";
};
wantedBy = mkOption {
default = [];
type = types.listOf types.string;
type = types.listOf types.str;
description = "Units that want (i.e. depend on) this unit.";
};
+64 -55
View File
@@ -69,6 +69,7 @@ let
"systemd-journal-flush.service"
"systemd-journal-gatewayd.socket"
"systemd-journal-gatewayd.service"
"systemd-journald-audit.socket"
"systemd-journald-dev-log.socket"
"syslog.socket"
@@ -109,8 +110,6 @@ let
"systemd-hibernate.service"
"systemd-suspend.service"
"systemd-hybrid-sleep.service"
"systemd-shutdownd.socket"
"systemd-shutdownd.service"
# Reboot stuff.
"reboot.target"
@@ -276,19 +275,6 @@ let
};
};
toOption = x:
if x == true then "true"
else if x == false then "false"
else toString x;
attrsToSection = as:
concatStrings (concatLists (mapAttrsToList (name: value:
map (x: ''
${name}=${toOption x}
'')
(if isList value then value else [value]))
as));
commonUnitText = def: ''
[Unit]
${attrsToSection def.unitConfig}
@@ -369,11 +355,6 @@ let
'';
};
commonMatchText = def: ''
[Match]
${attrsToSection def.matchConfig}
'';
in
{
@@ -463,6 +444,17 @@ in
'';
};
systemd.generators = mkOption {
type = types.attrsOf types.path;
default = {};
example = { "systemd-gpt-auto-generator" = "/dev/null"; };
description = ''
Definition of systemd generators.
For each <literal>NAME = VALUE</literal> pair of the attrSet, a link is generated from
<literal>/etc/systemd/system-generators/NAME</literal> to <literal>VALUE</literal>.
'';
};
systemd.defaultUnit = mkOption {
default = "multi-user.target";
type = types.str;
@@ -509,7 +501,7 @@ in
services.journald.rateLimitBurst = mkOption {
default = 100;
type = types.uniq types.int;
type = types.int;
description = ''
Configures the rate limiting burst limit (number of messages per
interval) that is applied to all messages generated on the system.
@@ -619,20 +611,17 @@ in
environment.systemPackages = [ systemd ];
environment.etc."systemd/system".source =
generateUnits "system" cfg.units upstreamSystemUnits upstreamSystemWants;
environment.etc = {
"systemd/system".source = generateUnits "system" cfg.units upstreamSystemUnits upstreamSystemWants;
environment.etc."systemd/user".source =
generateUnits "user" cfg.user.units upstreamUserUnits [];
"systemd/user".source = generateUnits "user" cfg.user.units upstreamUserUnits [];
environment.etc."systemd/system.conf".text =
''
"systemd/system.conf".text = ''
[Manager]
${config.systemd.extraConfig}
'';
environment.etc."systemd/journald.conf".text =
''
"systemd/journald.conf".text = ''
[Journal]
RateLimitInterval=${config.services.journald.rateLimitInterval}
RateLimitBurst=${toString config.services.journald.rateLimitBurst}
@@ -643,29 +632,44 @@ in
${config.services.journald.extraConfig}
'';
environment.etc."systemd/logind.conf".text =
''
"systemd/logind.conf".text = ''
[Login]
${config.services.logind.extraConfig}
'';
environment.etc."systemd/sleep.conf".text =
''
"systemd/sleep.conf".text = ''
[Sleep]
'';
"tmpfiles.d/systemd.conf".source = "${systemd}/example/tmpfiles.d/systemd.conf";
"tmpfiles.d/x11.conf".source = "${systemd}/example/tmpfiles.d/x11.conf";
"tmpfiles.d/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}
'';
} // mapAttrs' (n: v: nameValuePair "systemd/system-generators/${n}" {"source"=v;}) cfg.generators;
system.activationScripts.systemd = stringAfter [ "groups" ]
''
mkdir -m 0755 -p /var/lib/udev
mkdir -p /var/log/journal
chmod 0755 /var/log/journal
# Make all journals readable to users in the wheel and adm
# groups, in addition to those in the systemd-journal group.
# Users can always read their own journals.
${pkgs.acl.bin}/bin/setfacl -nm g:wheel:rx,d:g:wheel:rx,g:adm:rx,d:g:adm:rx /var/log/journal || true
if ! [ -e /etc/machine-id ]; then
${systemd}/bin/systemd-machine-id-setup
fi
# Keep a persistent journal. Note that systemd-tmpfiles will
# set proper ownership/permissions.
mkdir -m 0700 -p /var/log/journal
'';
users.extraUsers.systemd-network.uid = config.ids.uids.systemd-network;
users.extraGroups.systemd-network.gid = config.ids.gids.systemd-network;
users.extraUsers.systemd-resolve.uid = config.ids.uids.systemd-resolve;
users.extraGroups.systemd-resolve.gid = config.ids.gids.systemd-resolve;
# Target for charon send-keys to hook into.
users.extraGroups.keys.gid = config.ids.gids.keys;
@@ -729,6 +733,14 @@ in
})
(filterAttrs (name: service: service.startAt != "") cfg.services);
# Generate timer units for all services that have a startAt value.
systemd.user.timers =
mapAttrs (name: service:
{ wantedBy = [ "timers.target" ];
timerConfig.OnCalendar = service.startAt;
})
(filterAttrs (name: service: service.startAt != "") cfg.user.services);
systemd.sockets.systemd-journal-gatewayd.wantedBy =
optional config.services.journald.enableHttpGateway "sockets.target";
@@ -740,24 +752,21 @@ in
startSession = true;
};
environment.etc."tmpfiles.d/x11.conf".source = "${systemd}/example/tmpfiles.d/x11.conf";
environment.etc."tmpfiles.d/nixos.conf".text =
''
# This file is created automatically and should not be modified.
# Please change the option systemd.tmpfiles.rules instead.
z /var/log/journal 2755 root systemd-journal - -
z /var/log/journal/%m 2755 root systemd-journal - -
z /var/log/journal/%m/* 0640 root systemd-journal - -
${concatStringsSep "\n" cfg.tmpfiles.rules}
'';
# Some overrides to upstream units.
systemd.services."systemd-backlight@".restartIfChanged = false;
systemd.services."systemd-rfkill@".restartIfChanged = false;
systemd.services."user@".restartIfChanged = false;
systemd.services.systemd-remount-fs.restartIfChanged = false;
systemd.services.systemd-journal-flush.restartIfChanged = false;
systemd.services.systemd-random-seed.restartIfChanged = false;
systemd.services.systemd-remount-fs.restartIfChanged = false;
systemd.services.systemd-update-utmp.restartIfChanged = false;
systemd.services.systemd-user-sessions.restartIfChanged = false; # Restart kills all active sessions.
systemd.targets.local-fs.unitConfig.X-StopOnReconfiguration = true;
systemd.targets.remote-fs.unitConfig.X-StopOnReconfiguration = true;
# Don't bother with certain units in containers.
systemd.services.systemd-remount-fs.unitConfig.ConditionVirtualization = "!container";
systemd.services.systemd-random-seed.unitConfig.ConditionVirtualization = "!container";
};
+1
View File
@@ -14,6 +14,7 @@ let
builder = ./make-etc.sh;
preferLocalBuild = true;
allowSubstitutes = false;
/* !!! Use toXML. */
sources = map (x: x.source) etc';