Merge remote-tracking branch 'origin/staging' into systemd-219
Conflicts: pkgs/os-specific/linux/kernel/linux-3.4.nix pkgs/os-specific/linux/systemd/default.nix
This commit is contained in:
@@ -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}
|
||||
'';
|
||||
|
||||
@@ -99,6 +101,7 @@ let
|
||||
if [] == failed then pkgs.stdenv.mkDerivation {
|
||||
name = "nixos-${config.system.nixosVersion}";
|
||||
preferLocalBuild = true;
|
||||
allowSubstitutes = false;
|
||||
buildCommand = systemBuilder;
|
||||
|
||||
inherit (pkgs) utillinux coreutils;
|
||||
@@ -188,6 +191,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
nixos/modules/system/boot/coredump.nix
Normal file
51
nixos/modules/system/boot/coredump.nix
Normal 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";
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -159,7 +159,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)
|
||||
|
||||
@@ -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,8 @@
|
||||
{ pkgs }:
|
||||
|
||||
pkgs.substituteAll {
|
||||
src = ./extlinux-conf-builder.sh;
|
||||
isExecutable = true;
|
||||
inherit (pkgs) bash;
|
||||
path = [pkgs.coreutils pkgs.gnused pkgs.gnugrep];
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
#! @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
|
||||
# XXX UGLY: maybe the system config should have a top-level "dtbs" entry?
|
||||
copyToKernelsDir $(readlink -m "$path/kernel/../dtbs"); dtbs=$result
|
||||
|
||||
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)"
|
||||
echo " FDTDIR ../nixos/$(basename $dtbs)"
|
||||
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
|
||||
|
||||
TIMEOUT $timeout
|
||||
$(addEntry $default default)
|
||||
EOF
|
||||
|
||||
# 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
|
||||
|
||||
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
|
||||
@@ -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
|
||||
|
||||
{
|
||||
@@ -101,6 +116,64 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
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 parth 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,6 +183,15 @@ 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;
|
||||
@@ -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;
|
||||
@@ -269,6 +369,15 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
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";
|
||||
}
|
||||
}
|
||||
@@ -253,10 +259,23 @@ else {
|
||||
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 +283,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 +304,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 +415,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 +434,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 +455,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 +500,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 +517,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 +531,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 +542,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).
|
||||
@@ -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"
|
||||
@@ -251,6 +252,16 @@ in
|
||||
description = "Path of the underlying block device.";
|
||||
};
|
||||
|
||||
header = mkOption {
|
||||
default = null;
|
||||
example = "/root/header.img";
|
||||
type = types.nullOr types.string;
|
||||
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";
|
||||
|
||||
@@ -101,7 +101,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";
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -317,7 +317,7 @@ mountFS() {
|
||||
|
||||
|
||||
# Try to find and mount the root device.
|
||||
mkdir /mnt-root
|
||||
mkdir -p $targetRoot
|
||||
|
||||
exec 3< @fsInfo@
|
||||
|
||||
|
||||
@@ -358,7 +358,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.";
|
||||
};
|
||||
|
||||
|
||||
@@ -13,13 +13,20 @@ 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}
|
||||
@@ -89,7 +96,10 @@ rec {
|
||||
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.
|
||||
|
||||
@@ -42,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.";
|
||||
};
|
||||
|
||||
|
||||
@@ -490,7 +490,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.
|
||||
|
||||
@@ -14,6 +14,7 @@ let
|
||||
builder = ./make-etc.sh;
|
||||
|
||||
preferLocalBuild = true;
|
||||
allowSubstitutes = false;
|
||||
|
||||
/* !!! Use toXML. */
|
||||
sources = map (x: x.source) etc';
|
||||
|
||||
Reference in New Issue
Block a user