nixos/systemd-repart: enable creating root partition
This commit is contained in:
parent
a8eea70935
commit
ef80e11032
2 changed files with 117 additions and 33 deletions
|
@ -1,4 +1,4 @@
|
||||||
{ config, pkgs, lib, ... }:
|
{ config, pkgs, lib, utils, ... }:
|
||||||
|
|
||||||
let
|
let
|
||||||
cfg = config.systemd.repart;
|
cfg = config.systemd.repart;
|
||||||
|
@ -26,7 +26,8 @@ let
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
boot.initrd.systemd.repart.enable = lib.mkEnableOption (lib.mdDoc "systemd-repart") // {
|
boot.initrd.systemd.repart = {
|
||||||
|
enable = lib.mkEnableOption (lib.mdDoc "systemd-repart") // {
|
||||||
description = lib.mdDoc ''
|
description = lib.mdDoc ''
|
||||||
Grow and add partitions to a partition table at boot time in the initrd.
|
Grow and add partitions to a partition table at boot time in the initrd.
|
||||||
systemd-repart only works with GPT partition tables.
|
systemd-repart only works with GPT partition tables.
|
||||||
|
@ -36,6 +37,20 @@ in
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
device = lib.mkOption {
|
||||||
|
type = with lib.types; nullOr str;
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
The device to operate on.
|
||||||
|
|
||||||
|
If `device == null`, systemd-repart will operate on the device
|
||||||
|
backing the root partition. So in order to dynamically *create* the
|
||||||
|
root partition in the initrd you need to set a device.
|
||||||
|
'';
|
||||||
|
default = null;
|
||||||
|
example = "/dev/vda";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
systemd.repart = {
|
systemd.repart = {
|
||||||
enable = lib.mkEnableOption (lib.mdDoc "systemd-repart") // {
|
enable = lib.mkEnableOption (lib.mdDoc "systemd-repart") // {
|
||||||
description = lib.mdDoc ''
|
description = lib.mdDoc ''
|
||||||
|
@ -84,7 +99,11 @@ in
|
||||||
contents."/etc/repart.d".source = definitionsDirectory;
|
contents."/etc/repart.d".source = definitionsDirectory;
|
||||||
|
|
||||||
# Override defaults in upstream unit.
|
# Override defaults in upstream unit.
|
||||||
services.systemd-repart = {
|
services.systemd-repart =
|
||||||
|
let
|
||||||
|
deviceUnit = "${utils.escapeSystemdPath initrdCfg.device}.device";
|
||||||
|
in
|
||||||
|
{
|
||||||
# systemd-repart tries to create directories in /var/tmp by default to
|
# systemd-repart tries to create directories in /var/tmp by default to
|
||||||
# store large temporary files that benefit from persistence on disk. In
|
# store large temporary files that benefit from persistence on disk. In
|
||||||
# the initrd, however, /var/tmp does not provide more persistence than
|
# the initrd, however, /var/tmp does not provide more persistence than
|
||||||
|
@ -98,16 +117,23 @@ in
|
||||||
# in the initrd itself.
|
# in the initrd itself.
|
||||||
''${config.boot.initrd.systemd.package}/bin/systemd-repart \
|
''${config.boot.initrd.systemd.package}/bin/systemd-repart \
|
||||||
--definitions=/etc/repart.d \
|
--definitions=/etc/repart.d \
|
||||||
--dry-run=no
|
--dry-run=no ${lib.optionalString (initrdCfg.device != null) initrdCfg.device}
|
||||||
''
|
''
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
# systemd-repart needs to run after /sysroot (or /sysuser, but we don't
|
# systemd-repart needs to run after /sysroot (or /sysuser, but we
|
||||||
# have it) has been mounted because otherwise it cannot determine the
|
# don't have it) has been mounted because otherwise it cannot
|
||||||
# device (i.e disk) to operate on. If you want to run systemd-repart
|
# determine the device (i.e disk) to operate on. If you want to run
|
||||||
# without /sysroot, you have to explicitly tell it which device to
|
# systemd-repart without /sysroot (i.e. to create the root
|
||||||
# operate on.
|
# partition), you have to explicitly tell it which device to operate
|
||||||
after = [ "sysroot.mount" ];
|
# on. The service then needs to be ordered to run after this device
|
||||||
|
# is available.
|
||||||
|
requires = lib.mkIf (initrdCfg.device != null) [ deviceUnit ];
|
||||||
|
after =
|
||||||
|
if initrdCfg.device == null then
|
||||||
|
[ "sysroot.mount" ]
|
||||||
|
else
|
||||||
|
[ deviceUnit ];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,8 @@ let
|
||||||
# however, creates separate filesystem images without a partition table, so
|
# however, creates separate filesystem images without a partition table, so
|
||||||
# we have to create a disk image manually.
|
# we have to create a disk image manually.
|
||||||
#
|
#
|
||||||
# This creates two partitions, an ESP mounted on /dev/vda1 and the root
|
# This creates two partitions, an ESP available as /dev/vda1 and the root
|
||||||
# partition mounted on /dev/vda2
|
# partition available as /dev/vda2.
|
||||||
system.build.diskImage = import ../lib/make-disk-image.nix {
|
system.build.diskImage = import ../lib/make-disk-image.nix {
|
||||||
inherit config pkgs lib;
|
inherit config pkgs lib;
|
||||||
# Use a raw format disk so that it can be resized before starting the
|
# Use a raw format disk so that it can be resized before starting the
|
||||||
|
@ -131,4 +131,62 @@ in
|
||||||
assert "Growing existing partition 1." in systemd_repart_logs
|
assert "Growing existing partition 1." in systemd_repart_logs
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
create-root = makeTest {
|
||||||
|
name = "systemd-repart-create-root";
|
||||||
|
meta.maintainers = with maintainers; [ nikstur ];
|
||||||
|
|
||||||
|
nodes.machine = { config, lib, pkgs, ... }: {
|
||||||
|
virtualisation.useDefaultFilesystems = false;
|
||||||
|
virtualisation.fileSystems = {
|
||||||
|
"/" = {
|
||||||
|
device = "/dev/disk/by-partlabel/created-root";
|
||||||
|
fsType = "ext4";
|
||||||
|
};
|
||||||
|
"/nix/store" = {
|
||||||
|
device = "/dev/vda2";
|
||||||
|
fsType = "ext4";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Create an image containing only the Nix store. This enables creating
|
||||||
|
# the root partition with systemd-repart and then successfully booting
|
||||||
|
# into a working system.
|
||||||
|
#
|
||||||
|
# This creates two partitions, an ESP available as /dev/vda1 and the Nix
|
||||||
|
# store available as /dev/vda2.
|
||||||
|
system.build.diskImage = import ../lib/make-disk-image.nix {
|
||||||
|
inherit config pkgs lib;
|
||||||
|
onlyNixStore = true;
|
||||||
|
format = "raw";
|
||||||
|
bootSize = "32M";
|
||||||
|
additionalSpace = "0M";
|
||||||
|
partitionTableType = "efi";
|
||||||
|
installBootLoader = false;
|
||||||
|
copyChannel = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
boot.initrd.systemd.enable = true;
|
||||||
|
|
||||||
|
boot.initrd.systemd.repart.enable = true;
|
||||||
|
boot.initrd.systemd.repart.device = "/dev/vda";
|
||||||
|
systemd.repart.partitions = {
|
||||||
|
"10-root" = {
|
||||||
|
Type = "root";
|
||||||
|
Label = "created-root";
|
||||||
|
Format = "ext4";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
testScript = { nodes, ... }: ''
|
||||||
|
${useDiskImage nodes.machine}
|
||||||
|
|
||||||
|
machine.start()
|
||||||
|
machine.wait_for_unit("multi-user.target")
|
||||||
|
|
||||||
|
systemd_repart_logs = machine.succeed("journalctl --boot --unit systemd-repart.service")
|
||||||
|
assert "Adding new partition 2 to partition table." in systemd_repart_logs
|
||||||
|
'';
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue