mirror of
https://github.com/NixOS/nixpkgs.git
synced 2024-12-28 00:24:18 +00:00
4f0dadbf38
After final improvements to the official formatter implementation, this commit now performs the first treewide reformat of Nix files using it. This is part of the implementation of RFC 166. Only "inactive" files are reformatted, meaning only files that aren't being touched by any PR with activity in the past 2 months. This is to avoid conflicts for PRs that might soon be merged. Later we can do a full treewide reformat to get the rest, which should not cause as many conflicts. A CI check has already been running for some time to ensure that new and already-formatted files are formatted, so the files being reformatted here should also stay formatted. This commit was automatically created and can be verified using nix-builda08b3a4d19
.tar.gz \ --argstr baseRevb32a094368
result/bin/apply-formatting $NIXPKGS_PATH
222 lines
7.3 KiB
Nix
222 lines
7.3 KiB
Nix
# opinionated module that can be used to build nixos images with
|
|
# a dm-verity protected nix store
|
|
{
|
|
config,
|
|
pkgs,
|
|
lib,
|
|
...
|
|
}:
|
|
let
|
|
cfg = config.image.repart.verityStore;
|
|
|
|
verityMatchKey = "store";
|
|
|
|
# TODO: make these and other arch mappings available from systemd-lib for example
|
|
partitionTypes = {
|
|
usr =
|
|
{
|
|
"x86_64" = "usr-x86-64";
|
|
"arm64" = "usr-arm64";
|
|
}
|
|
."${pkgs.stdenv.hostPlatform.linuxArch}";
|
|
|
|
usr-verity =
|
|
{
|
|
"x86_64" = "usr-x86-64-verity";
|
|
"arm64" = "usr-arm64-verity";
|
|
}
|
|
."${pkgs.stdenv.hostPlatform.linuxArch}";
|
|
};
|
|
|
|
verityHashCheck =
|
|
pkgs.buildPackages.writers.writePython3Bin "assert_uki_repart_match.py"
|
|
{
|
|
flakeIgnore = [ "E501" ]; # ignores PEP8's line length limit of 79 (black defaults to 88 characters)
|
|
}
|
|
(
|
|
builtins.replaceStrings
|
|
[ "@NIX_STORE_VERITY@" ]
|
|
[
|
|
partitionTypes.usr-verity
|
|
]
|
|
(builtins.readFile ./assert_uki_repart_match.py)
|
|
);
|
|
in
|
|
{
|
|
options.image.repart.verityStore = {
|
|
enable = lib.mkEnableOption "building images with a dm-verity protected nix store";
|
|
|
|
ukiPath = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "/EFI/Linux/${config.system.boot.loader.ukiFile}";
|
|
defaultText = "/EFI/Linux/\${config.system.boot.loader.ukiFile}";
|
|
description = ''
|
|
Specify the location on the ESP where the UKI is placed.
|
|
'';
|
|
};
|
|
|
|
partitionIds = {
|
|
esp = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "00-esp";
|
|
description = ''
|
|
Specify the attribute name of the ESP.
|
|
'';
|
|
};
|
|
store-verity = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "10-store-verity";
|
|
description = ''
|
|
Specify the attribute name of the store's dm-verity hash partition.
|
|
'';
|
|
};
|
|
store = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "20-store";
|
|
description = ''
|
|
Specify the attribute name of the store partition.
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
|
|
config = lib.mkIf cfg.enable {
|
|
boot.initrd.systemd.dmVerity.enable = true;
|
|
|
|
image.repart.partitions = {
|
|
# dm-verity hash partition
|
|
${cfg.partitionIds.store-verity}.repartConfig = {
|
|
Type = partitionTypes.usr-verity;
|
|
Verity = "hash";
|
|
VerityMatchKey = lib.mkDefault verityMatchKey;
|
|
Label = lib.mkDefault "store-verity";
|
|
};
|
|
# dm-verity data partition that contains the nix store
|
|
${cfg.partitionIds.store} = {
|
|
storePaths = [ config.system.build.toplevel ];
|
|
repartConfig = {
|
|
Type = partitionTypes.usr;
|
|
Verity = "data";
|
|
Format = lib.mkDefault "erofs";
|
|
VerityMatchKey = lib.mkDefault verityMatchKey;
|
|
Label = lib.mkDefault "store";
|
|
};
|
|
};
|
|
|
|
};
|
|
|
|
system.build = {
|
|
|
|
# intermediate system image without ESP
|
|
intermediateImage =
|
|
(config.system.build.image.override {
|
|
# always disable compression for the intermediate image
|
|
compression.enable = false;
|
|
}).overrideAttrs
|
|
(
|
|
_: previousAttrs: {
|
|
# make it easier to identify the intermediate image in build logs
|
|
pname = "${previousAttrs.pname}-intermediate";
|
|
|
|
# do not prepare the ESP, this is done in the final image
|
|
systemdRepartFlags = previousAttrs.systemdRepartFlags ++ [ "--defer-partitions=esp" ];
|
|
}
|
|
);
|
|
|
|
# UKI with embedded usrhash from intermediateImage
|
|
uki =
|
|
let
|
|
inherit (config.system.boot.loader) ukiFile;
|
|
cmdline = "init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}";
|
|
in
|
|
# override the default UKI
|
|
lib.mkOverride 99 (
|
|
pkgs.runCommand ukiFile
|
|
{
|
|
nativeBuildInputs = [
|
|
pkgs.jq
|
|
pkgs.systemdUkify
|
|
];
|
|
}
|
|
''
|
|
mkdir -p $out
|
|
|
|
# Extract the usrhash from the output of the systemd-repart invocation for the intermediate image.
|
|
usrhash=$(jq -r \
|
|
'.[] | select(.type=="${partitionTypes.usr-verity}") | .roothash' \
|
|
${config.system.build.intermediateImage}/repart-output.json
|
|
)
|
|
|
|
# Build UKI with the embedded usrhash.
|
|
ukify build \
|
|
--config=${config.boot.uki.configFile} \
|
|
--cmdline="${cmdline} usrhash=$usrhash" \
|
|
--output="$out/${ukiFile}"
|
|
''
|
|
);
|
|
|
|
# final system image that is created from the intermediate image by injecting the UKI from above
|
|
finalImage =
|
|
(config.system.build.image.override {
|
|
# continue building with existing intermediate image
|
|
createEmpty = false;
|
|
}).overrideAttrs
|
|
(
|
|
finalAttrs: previousAttrs: {
|
|
# add entry to inject UKI into ESP
|
|
finalPartitions = lib.recursiveUpdate previousAttrs.finalPartitions {
|
|
${cfg.partitionIds.esp}.contents = {
|
|
"${cfg.ukiPath}".source = "${config.system.build.uki}/${config.system.boot.loader.ukiFile}";
|
|
};
|
|
};
|
|
|
|
nativeBuildInputs = previousAttrs.nativeBuildInputs ++ [
|
|
pkgs.systemdUkify
|
|
verityHashCheck
|
|
pkgs.jq
|
|
];
|
|
|
|
preBuild = ''
|
|
# check that we build the final image with the same intermediate image for
|
|
# which the injected UKI was built by comparing the UKI cmdline with the repart output
|
|
# of the intermediate image
|
|
#
|
|
# This is necessary to notice incompatible substitutions of
|
|
# non-reproducible store paths, for example when working with distributed
|
|
# builds, or when offline-signing the UKI.
|
|
ukify --json=short inspect ${config.system.build.uki}/${config.system.boot.loader.ukiFile} \
|
|
| assert_uki_repart_match.py "${config.system.build.intermediateImage}/repart-output.json"
|
|
|
|
# copy the uncompressed intermediate image, so that systemd-repart picks it up
|
|
cp -v ${config.system.build.intermediateImage}/${config.image.repart.imageFileBasename}.raw .
|
|
chmod +w ${config.image.repart.imageFileBasename}.raw
|
|
'';
|
|
|
|
# replace "TBD" with the original roothash values
|
|
preInstall = ''
|
|
mv -v repart-output{.json,_orig.json}
|
|
|
|
jq --slurp --indent -1 \
|
|
'.[0] as $intermediate | .[1] as $final
|
|
| $intermediate | map(select(.roothash != null) | { "uuid":.uuid,"roothash":.roothash }) as $uuids
|
|
| $final + $uuids
|
|
| group_by(.uuid)
|
|
| map(add)
|
|
| sort_by(.offset)' \
|
|
${config.system.build.intermediateImage}/repart-output.json \
|
|
repart-output_orig.json \
|
|
> repart-output.json
|
|
|
|
rm -v repart-output_orig.json
|
|
'';
|
|
}
|
|
);
|
|
};
|
|
};
|
|
|
|
meta.maintainers = with lib.maintainers; [
|
|
nikstur
|
|
willibutz
|
|
];
|
|
}
|