summaryrefslogtreecommitdiff
path: root/sys/boot
diff options
context:
space:
mode:
authorAlejandro Soto <alejandro@34project.org>2024-07-14 17:53:13 -0600
committerAlejandro Soto <alejandro@34project.org>2024-07-15 09:34:00 -0600
commit02abf4ed0131237c25e0a10db50fa4c41a902a50 (patch)
tree20904894fc0952806e341cdaff5941e81b3ce51c /sys/boot
parent08e746700341dda3e3bdf704332fc3c07053d3e7 (diff)
sys: final merge of dmz, hv into sys
Diffstat (limited to '')
-rw-r--r--sys/boot.nix116
-rw-r--r--sys/boot/chain.nix37
-rw-r--r--sys/boot/default.nix13
-rw-r--r--sys/boot/detached-luks.nix73
-rw-r--r--sys/boot/efi.nix35
-rw-r--r--sys/boot/firmware.nix29
-rw-r--r--sys/boot/fscrypt.nix23
-rw-r--r--sys/boot/impermanence.nix53
-rw-r--r--sys/boot/namespaced.nix27
-rw-r--r--sys/boot/sb.nix37
-rw-r--r--sys/boot/stack/btrfs-toplevel-multidrive.nix94
-rw-r--r--sys/boot/stack/default.nix6
-rw-r--r--sys/boot/stack/luks-ext4-fscrypt-impermanence.nix96
13 files changed, 523 insertions, 116 deletions
diff --git a/sys/boot.nix b/sys/boot.nix
deleted file mode 100644
index 1e8685a..0000000
--- a/sys/boot.nix
+++ /dev/null
@@ -1,116 +0,0 @@
-{ lib, config, pkgs, ... }:
-with lib; let
- cfg = config.local;
-in
-{
- options.local = with lib.types; {
- loader = mkOption {
- type = enum [ "grub" "systemd-boot" ];
- };
-
- cpuVendor = mkOption {
- type = enum [ "amd" "intel" ];
- };
-
- canTouchEfiVariables = mkOption {
- type = bool;
- };
-
- videoDrivers = mkOption {
- type = listOf str;
- };
-
- initrdModules = mkOption {
- type = listOf str;
- };
- };
-
- config = {
- boot = {
- kernelPackages = pkgs.linuxPackages_latest;
-
- loader = (if cfg.loader == "grub" then {
- grub = {
- enable = true;
- device = "nodev";
- efiSupport = true;
- };
- } else {
- systemd-boot.enable = true;
- }) // {
- efi = {
- inherit (cfg) canTouchEfiVariables;
- };
- };
-
- initrd =
- let
- crypt = cfg.crypt.toplevel;
- headerPathEscaped = escapeShellArg "/initrd-boot/${crypt.headerFromBoot}";
- in
- {
- availableKernelModules = cfg.initrdModules;
- supportedFilesystems = [ "vfat" ];
-
- preDeviceCommands = optionalString (crypt != null) ''
- mkdir -p `dirname ${headerPathEscaped}`
- touch ${headerPathEscaped}
- '';
-
- preLVMCommands = optionalString cfg.portable ''
- sleep 2 #TODO
- '';
-
- postMountCommands =
- let
- fromRoot = path: escapeShellArg "/mnt-root/${path}";
- auxOpen = aux: ''
- cryptsetup -v open \
- --header ${fromRoot aux.header} \
- --key-file ${fromRoot aux.keyfile} \
- ${aux.device} ${aux.target}
- '';
- in
- concatStringsSep "\n" (map auxOpen cfg.crypt.aux);
-
- luks.devices = mkIf (crypt != null) {
- "${crypt.target}" = {
- inherit (crypt) device;
- header = "/initrd-boot/${crypt.headerFromBoot}";
- preLVM = false;
-
- preOpenCommands = ''
- mount -o ro -t vfat ${escapeShellArg cfg.fs.boot.device} /initrd-boot
- '';
-
- postOpenCommands = ''
- umount /initrd-boot
- '';
- };
- };
-
- #network = {
- # enable = true;
-
- # ssh = {
- # enable = true;
- # port = 2234;
- # };
- #};
- };
- };
-
- hardware = {
- cpu =
- let
- ucode.updateMicrocode = true;
- in
- {
- amd = mkIf (cfg.cpuVendor == "amd") ucode;
- intel = mkIf (cfg.cpuVendor == "intel") ucode;
- };
-
- enableRedistributableFirmware = true;
- };
- };
-}
diff --git a/sys/boot/chain.nix b/sys/boot/chain.nix
new file mode 100644
index 0000000..c726cf8
--- /dev/null
+++ b/sys/boot/chain.nix
@@ -0,0 +1,37 @@
+{ config, lib, pkgs, ... }:
+with lib; let
+ cfg = config.local.boot;
+in
+{
+ options.local.boot = {
+ enable = mkEnableOption "system boot";
+
+ loader = mkOption {
+ type = types.enum [ "grub" "systemd-boot" ];
+ };
+
+ kernel = mkOption {
+ type = types.raw;
+ };
+ };
+
+ config = mkIf cfg.enable {
+ boot = {
+ kernelPackages = cfg.kernel;
+
+ loader =
+ if cfg.loader == "grub" then {
+ grub = {
+ enable = true;
+ device = "nodev";
+ efiSupport = true;
+ };
+ } else {
+ systemd-boot = {
+ enable = true;
+ editor = true;
+ };
+ };
+ };
+ };
+}
diff --git a/sys/boot/default.nix b/sys/boot/default.nix
new file mode 100644
index 0000000..157ba0e
--- /dev/null
+++ b/sys/boot/default.nix
@@ -0,0 +1,13 @@
+{
+ imports = [
+ ./chain.nix
+ ./detached-luks.nix
+ ./efi.nix
+ ./firmware.nix
+ ./fscrypt.nix
+ ./impermanence.nix
+ ./namespaced.nix
+ ./sb.nix
+ ./stack
+ ];
+}
diff --git a/sys/boot/detached-luks.nix b/sys/boot/detached-luks.nix
new file mode 100644
index 0000000..a7b1bc9
--- /dev/null
+++ b/sys/boot/detached-luks.nix
@@ -0,0 +1,73 @@
+{ config, lib, pkgs, ... }:
+with lib; let
+ cfg = config.local.boot.detachedLuks;
+in
+{
+ options.local.boot.detachedLuks = {
+ enable = mkEnableOption "detached LUKS header in initrd";
+
+ headerFromBoot = mkOption {
+ type = types.str;
+ };
+
+ crypt = mkOption {
+ type = types.str;
+ };
+
+ target = mkOption {
+ type = types.str;
+ };
+ };
+
+ config = mkIf cfg.enable {
+ boot.initrd =
+ let
+ headerPath = "/initrd-boot/${cfg.headerFromBoot}";
+ in
+ {
+ preDeviceCommands =
+ let
+ headerPathEscaped = escapeShellArg headerPath;
+ in
+ ''
+ mkdir -p `dirname ${headerPathEscaped}`
+ touch ${headerPathEscaped}
+ '';
+
+ postDeviceCommands = mkIf (!config.boot.initrd.systemd.enable) ''
+ # Set the system time from the hardware clock to work around a
+ # bug in qemu-kvm > 1.5.2 (where the VM clock is initialised
+ # to the *boot time* of the host).
+ hwclock -s
+ '';
+
+ #FIXME: Demasiado vulgar
+ preLVMCommands = optionalString (config.local.boot.efi.enable && config.local.boot.efi.removable) ''
+ sleep 2
+ '';
+
+ luks.devices.${cfg.target} = {
+ device = cfg.crypt;
+ header = headerPath;
+ preLVM = false;
+
+ preOpenCommands =
+ let
+ boot = config.fileSystems."/boot";
+ in
+ ''
+ mount -o ro -t ${boot.fsType} ${boot.device} /initrd-boot
+ '';
+
+ postOpenCommands = mkBefore ''
+ umount /initrd-boot
+ '';
+ };
+ };
+
+ local.boot.stack = {
+ btrfsToplevelMultidrive.toplevel.device = "/dev/mapper/${cfg.target}";
+ luksExt4FscryptImpermanence = { inherit (cfg) target; };
+ };
+ };
+}
diff --git a/sys/boot/efi.nix b/sys/boot/efi.nix
new file mode 100644
index 0000000..35cf687
--- /dev/null
+++ b/sys/boot/efi.nix
@@ -0,0 +1,35 @@
+{ config, lib, ... }:
+with lib; let
+ cfg = config.local.boot.efi;
+in
+{
+ options.local.boot.efi = {
+ enable = mkEnableOption "EFI with FAT32 system partition";
+
+ esp.uuid = mkOption {
+ type = types.strMatching "[0-9A-F]{4}-[0-9A-F]{4}";
+ };
+
+ removable = mkOption {
+ type = types.bool;
+ };
+ };
+
+ config = mkIf cfg.enable {
+ boot = {
+ initrd.supportedFilesystems = [ "vfat" ];
+
+ loader = {
+ efi.canTouchEfiVariables = !cfg.removable;
+ grub.efiInstallAsRemovable = cfg.removable;
+ };
+ };
+
+ fileSystems."/boot" = {
+ device = "/dev/disk/by-uuid/${cfg.esp.uuid}";
+ fsType = "vfat";
+ options = [ "noatime" "umask=027" "sync" ];
+ neededForBoot = true;
+ };
+ };
+}
diff --git a/sys/boot/firmware.nix b/sys/boot/firmware.nix
new file mode 100644
index 0000000..70a3c4b
--- /dev/null
+++ b/sys/boot/firmware.nix
@@ -0,0 +1,29 @@
+{ config, lib, pkgs, ... }:
+with lib; let
+ cfg = config.local.boot.firmware;
+in
+{
+ options.local.boot.firmware = {
+ mode = mkOption {
+ type = types.enum [ "none" "redistributable" "all" ];
+ };
+
+ cpuVendor = mkOption {
+ type = types.enum [ "amd" "intel" ];
+ };
+ };
+
+ config = mkIf (cfg.mode != "none") {
+ hardware = {
+ cpu = {
+ amd.updateMicrocode = cfg.cpuVendor == "amd";
+ intel.updateMicrocode = cfg.cpuVendor == "intel";
+ };
+
+ enableAllFirmware = cfg.mode == "all";
+ enableRedistributableFirmware = true;
+ };
+
+ services.fwupd.enable = true;
+ };
+}
diff --git a/sys/boot/fscrypt.nix b/sys/boot/fscrypt.nix
new file mode 100644
index 0000000..e6a745c
--- /dev/null
+++ b/sys/boot/fscrypt.nix
@@ -0,0 +1,23 @@
+{ config, lib, pkgs, ... }:
+with lib; let
+ cfg = config.local.boot.fscrypt;
+in
+{
+ options.local.boot.fscrypt = {
+ enable = mkEnableOption "fscrypt support";
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = [ pkgs.fscrypt-experimental ];
+
+ local.boot.impermanence = {
+ directories = [
+ { directory = "/.fscrypt"; mode = "u=rwx,g=rx,o=rx"; }
+ ];
+
+ files = [
+ "/etc/fscrypt.conf"
+ ];
+ };
+ };
+}
diff --git a/sys/boot/impermanence.nix b/sys/boot/impermanence.nix
new file mode 100644
index 0000000..4902239
--- /dev/null
+++ b/sys/boot/impermanence.nix
@@ -0,0 +1,53 @@
+{ config, lib, ... }:
+with lib; let
+ cfg = config.local.boot.impermanence;
+in
+{
+ options.local.boot.impermanence = {
+ enable = mkEnableOption "root fs impermanence";
+
+ #TODO: type correcto de files, directories?
+
+ directories = mkOption {
+ type = with lib.types; listOf (either str attrs);
+ default = [ ];
+ };
+
+ files = mkOption {
+ type = with lib.types; listOf (either str attrs);
+ default = [ ];
+ };
+ };
+
+ config = mkMerge [
+ {
+ local.boot.impermanence = {
+ directories = [
+ "/etc/lvm"
+ "/var/lib/nixos"
+ "/var/log"
+ ];
+
+ files = [
+ "/etc/machine-id"
+ "/var/lib/logrotate.status"
+ ];
+ };
+ }
+ (mkIf cfg.enable {
+ assertions = [
+ {
+ assertion = (config.fileSystems ? "/persist") && config.fileSystems."/persist".neededForBoot;
+ message = "Impermanence requires /persist to be a neededForBoot mountpoint";
+ }
+ ];
+
+ environment.persistence."/persist" = {
+ hideMounts = true;
+
+ files = cfg.files;
+ directories = cfg.directories;
+ };
+ })
+ ];
+}
diff --git a/sys/boot/namespaced.nix b/sys/boot/namespaced.nix
new file mode 100644
index 0000000..9927ae2
--- /dev/null
+++ b/sys/boot/namespaced.nix
@@ -0,0 +1,27 @@
+{ config, lib, options, ... }:
+with lib; let
+ cfg = config.local.boot.namespaced;
+in
+{
+ options.local.boot.namespaced = {
+ enable = mkEnableOption "system containerization";
+ };
+
+ config = mkIf cfg.enable {
+ boot.isContainer = true;
+
+ local.boot = mkMerge ([
+ {
+ enable = mkForce false;
+
+ efi.enable = mkForce false;
+ secureBoot.enable = mkForce false;
+ impermanence.enable = mkForce false;
+ }
+ ] ++ map
+ (name: {
+ stack.${name}.enable = mkForce false;
+ })
+ (attrNames options.local.boot.stack));
+ };
+}
diff --git a/sys/boot/sb.nix b/sys/boot/sb.nix
new file mode 100644
index 0000000..bdf7f0f
--- /dev/null
+++ b/sys/boot/sb.nix
@@ -0,0 +1,37 @@
+{ config, lib, pkgs, ... }:
+with lib; let
+ cfg = config.local.boot.secureBoot;
+in
+{
+ options.local.boot.secureBoot = {
+ enable = mkEnableOption "secure boot";
+ };
+
+ config = mkIf cfg.enable {
+ assertions = [
+ {
+ assertion = config.local.boot.efi.enable;
+ message = "secure boot requires EFI";
+ }
+ {
+ assertion = config.local.boot.loader == "systemd-boot";
+ message = "lanzaboote requires systemd-boot";
+ }
+ ];
+
+ boot = {
+ loader.systemd-boot.enable = mkForce false;
+
+ lanzaboote = {
+ enable = true;
+ pkiBundle = "/etc/secureboot";
+ };
+ };
+
+ environment.systemPackages = [
+ pkgs.sbctl
+ ];
+
+ local.boot.impermanence.directories = [ "/etc/secureboot" ];
+ };
+}
diff --git a/sys/boot/stack/btrfs-toplevel-multidrive.nix b/sys/boot/stack/btrfs-toplevel-multidrive.nix
new file mode 100644
index 0000000..1dbfa14
--- /dev/null
+++ b/sys/boot/stack/btrfs-toplevel-multidrive.nix
@@ -0,0 +1,94 @@
+{ config, lib, ... }:
+with lib; let
+ cfg = config.local.boot.stack.btrfsToplevelMultidrive;
+in
+{
+ options.local.boot.stack.btrfsToplevelMultidrive = {
+ enable = mkEnableOption "filesystem stack: persistent btrfs toplevel with optional hdd drive";
+
+ toplevel = {
+ device = mkOption {
+ type = types.str;
+ };
+
+ ssd = mkOption {
+ type = types.bool;
+ };
+
+ snapshot = mkOption {
+ type = types.bool;
+ default = false;
+ };
+
+ root = mkOption {
+ type = types.str;
+ };
+
+ pivot = mkOption {
+ type = types.str;
+ default = "/";
+ };
+ };
+
+ secondary = {
+ device = mkOption {
+ type = types.str;
+ };
+
+ ssd = mkOption {
+ type = types.bool;
+ };
+
+ snapshot = mkOption {
+ type = types.bool;
+ default = false;
+ };
+
+ home = mkOption {
+ type = types.str;
+ };
+
+ pivot = mkOption {
+ type = types.str;
+ default = "/";
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ local.btrfs = {
+ mounts = {
+ "/" = {
+ inherit (cfg.toplevel) device ssd;
+ subvol = cfg.toplevel.root;
+ };
+
+ "/toplevel" = {
+ inherit (cfg.toplevel) device ssd;
+ subvol = cfg.toplevel.pivot;
+ };
+
+ #FIXME: Este nombre es legacy
+ "/hdd" = {
+ inherit (cfg.secondary) device ssd;
+ subvol = cfg.secondary.pivot;
+ };
+
+ "/home" = {
+ inherit (cfg.secondary) device ssd;
+ subvol = cfg.secondary.home;
+ };
+ };
+
+ snapper = optionalAttrs cfg.toplevel.snapshot
+ {
+ root = "/";
+ } // optionalAttrs cfg.secondary.snapshot {
+ home = "/home";
+ };
+ };
+
+ # Asegura que /hdd sea descifrado antes de intentar montar /home
+ fileSystems."/home".depends = [ "/hdd" ];
+ };
+}
diff --git a/sys/boot/stack/default.nix b/sys/boot/stack/default.nix
new file mode 100644
index 0000000..ff211e6
--- /dev/null
+++ b/sys/boot/stack/default.nix
@@ -0,0 +1,6 @@
+{
+ imports = [
+ ./btrfs-toplevel-multidrive.nix
+ ./luks-ext4-fscrypt-impermanence.nix
+ ];
+}
diff --git a/sys/boot/stack/luks-ext4-fscrypt-impermanence.nix b/sys/boot/stack/luks-ext4-fscrypt-impermanence.nix
new file mode 100644
index 0000000..72336d6
--- /dev/null
+++ b/sys/boot/stack/luks-ext4-fscrypt-impermanence.nix
@@ -0,0 +1,96 @@
+{ config, lib, pkgs, ... }:
+with lib; let
+ cfg = config.local.boot.stack.luksExt4FscryptImpermanence;
+in
+{
+ options.local.boot.stack.luksExt4FscryptImpermanence = {
+ enable = mkEnableOption "filesystem stack: whatever LUKS approach+ext4+impermanence with per-boot keys";
+
+ target = mkOption {
+ type = types.str;
+ };
+ };
+
+ # - boot device
+ # - some unknown fs, probably vfat
+ # - detached luks header file
+ #
+ # - toplevel device
+ # - headerless luks
+ # - /toplevel (ext4)
+ # - /toplevel/nix
+ # - /toplevel/persist
+ # - /toplevel/boot-archive.pub
+ # - /toplevel/boot-keys
+ # - /toplevel/boot-keys/2000-01-01T00:00:00-06:00.key.crypt (encrypted for /toplevel/boot-archive.pub)
+ # - /toplevel/boot-keys/...
+ # - /toplevel/boot-keys/last.key.crypt -> 2000-01-01T00:00:00-06:00.key.crypt
+ # - /toplevel/boots
+ # - /toplevel/boots/2000-01-01T00:00:00-06:00 (raw protector in last.key.crypt)
+ # - /toplevel/boots/...
+ # - /toplevel/boots/last -> 2000-01-01T00:00:00-06:00 (mounted as /)
+ config = mkIf cfg.enable {
+ boot.initrd.luks.devices.${cfg.target}.postOpenCommands =
+ let
+ fscryptctl = "${pkgs.fscryptctl}/bin/fscryptctl";
+ in
+ ''
+ # FIXME: posiblemente algunos --make-* son innecesarios a partir de aquĆ­
+ mkdir -p /mnt-root /mnt-toplevel
+ mount -o noatime /dev/mapper/${cfg.target} /mnt-toplevel
+ mount --make-private /mnt-toplevel
+
+ boot_stamp="$(date -Is)"
+ root_from_toplevel="/mnt-toplevel/boots/$boot_stamp"
+
+ mkdir -p "$root_from_toplevel" /mnt-toplevel/boot-keys
+ chmod 700 /mnt-toplevel/boot-keys
+
+ head -c64 /dev/urandom >/boot-key
+ key_id=$(${fscryptctl} add_key /mnt-toplevel </boot-key)
+ ${fscryptctl} set_policy "$key_id" "$root_from_toplevel"
+ (umask 077; test -f /mnt-toplevel/boot-archive.pub && \
+ ${pkgs.openssl}/bin/openssl pkeyutl -encrypt \
+ -in /boot-key -pubin -inkey /mnt-toplevel/boot-archive.pub \
+ -out "/mnt-toplevel/boot-keys/$boot_stamp.key.crypt")
+ rm -f /boot-key
+
+ ln -Tsf "$boot_stamp" /mnt-toplevel/boots/last
+ ln -Tsf "$boot_stamp.key.crypt" /mnt-toplevel/boot-keys/last.key.crypt
+
+ mount --bind "$root_from_toplevel" /mnt-root
+ mount --make-shared /mnt-root
+
+ # mount --move es mala idea, ya que "moving a mount residing under a
+ # shared mount is unsupported"
+ mkdir -p /mnt-root/toplevel
+ mount --bind /mnt-toplevel /mnt-root/toplevel
+ mount --make-private /mnt-root/toplevel
+ umount /mnt-toplevel
+ '';
+
+ fileSystems = {
+ "/" = {
+ device = "none";
+ fsType = "ext4";
+ options = [ "remount" ];
+ };
+
+ "/nix" = {
+ device = "/persist/nix";
+ options = [ "bind" ];
+ };
+
+ "/persist" = {
+ device = "/toplevel/persist";
+ options = [ "bind" ];
+ neededForBoot = true;
+ };
+ };
+
+ local.boot = {
+ fscrypt.enable = true;
+ impermanence.enable = true;
+ };
+ };
+}