From 0c07311b0d05ae36a7cbb9b4a22747aabda18056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Billet?= Date: Thu, 4 Dec 2025 10:46:18 +0100 Subject: [PATCH] TEST --- config-files/disks/boot-1.nix | 3 +- config-files/disks/boot-2.nix | 7 +-- configuration.nix | 85 +++++++++++++++++++++++++---------- deploy.sh | 73 +++++++++++++++++++----------- 4 files changed, 113 insertions(+), 55 deletions(-) diff --git a/config-files/disks/boot-1.nix b/config-files/disks/boot-1.nix index 07aeaf8..9d67ea3 100644 --- a/config-files/disks/boot-1.nix +++ b/config-files/disks/boot-1.nix @@ -41,8 +41,9 @@ size = "100%"; content = { type = "luks"; - name = "crypted"; + name = "crypted-boot-1"; settings = { + keyFile = "/run/secrets/disks/boot-disk-1"; allowDiscards = true; }; content = { diff --git a/config-files/disks/boot-2.nix b/config-files/disks/boot-2.nix index a50516b..c871fbf 100644 --- a/config-files/disks/boot-2.nix +++ b/config-files/disks/boot-2.nix @@ -22,8 +22,9 @@ size = "100%"; content = { type = "luks"; - name = "nixos-p1"; + name = "crypted-boot-1"; settings = { + keyFile = "/run/secrets/disks/boot-disk-2"; allowDiscards = true; }; }; @@ -41,7 +42,7 @@ size = "100%"; content = { type = "luks"; - name = "nixos-p2"; + name = "crypted-boot-2"; settings = { allowDiscards = true; }; @@ -49,7 +50,7 @@ type = "btrfs"; extraArgs = [ "-d raid1" - "/dev/mapper/nixos-p1" + "/dev/mapper/crypted-boot-1" ]; subvolumes = { "/root" = { diff --git a/configuration.nix b/configuration.nix index cb7d595..44a66f0 100644 --- a/configuration.nix +++ b/configuration.nix @@ -1,21 +1,28 @@ { modulesPath, config, lib, pkgs, inputs, ... }: let - # Find all mount points that start with "/mnt/data-" - dataDiskMounts = lib.attrsets.attrNames ( - lib.attrsets.filterAttrs (name: value: lib.strings.hasPrefix "/mnt/data-" name) config.fileSystems - ); +# # Find all mount points that start with "/mnt/data-" +# dataDiskMounts = lib.attrsets.attrNames ( +# lib.attrsets.filterAttrs (name: value: lib.strings.hasPrefix "/mnt/data-" name) config.fileSystems +# ); +# +# # Find all mount points that start with "/mnt/parity-" +# parityDiskMounts = lib.attrsets.attrNames ( +# lib.attrsets.filterAttrs (name: value: lib.strings.hasPrefix "/mnt/parity-" name) config.fileSystems +# ); +# +# # Create an attribute set for snapraid data disks, e.g. { d1 = "/mnt/data-1"; d2 = "/mnt/data-2"; } +# snapraidDataDisks = lib.lists.foldl' +# (acc: path: acc // { "d${toString (acc.i + 1)}" = path; i = acc.i + 1; }) +# { i = 0; } +# dataDiskMounts; +#in - # Find all mount points that start with "/mnt/parity-" - parityDiskMounts = lib.attrsets.attrNames ( - lib.attrsets.filterAttrs (name: value: lib.strings.hasPrefix "/mnt/parity-" name) config.fileSystems - ); - - # Create an attribute set for snapraid data disks, e.g. { d1 = "/mnt/data-1"; d2 = "/mnt/data-2"; } - snapraidDataDisks = lib.lists.foldl' - (acc: path: acc // { "d${toString (acc.i + 1)}" = path; i = acc.i + 1; }) - { i = 0; } - dataDiskMounts; + # Helper to get mount points for data and parity disks from disko config + getMounts = prefix: lib.attrsets.attrNames (lib.attrsets.filterAttrs (n: v: v.mountPoint != null && lib.strings.hasPrefix v.mountPoint prefix) config.disko.devices.fs); + dataDiskMounts = getMounts "/mnt/data-"; + parityDiskMounts = getMounts "/mnt/parity-"; + snapraidDataDisks = lib.listToAttrs (lib.imap0 (i: path: { name = "d${toString (i + 1)}"; value = path; }) dataDiskMounts); in { @@ -24,6 +31,7 @@ in (modulesPath + "/profiles/qemu-guest.nix") inputs.sops-nix.nixosModules.sops ./disk-config.nix + ./ensure-pcr.nix ]; # Hardware settings @@ -44,21 +52,19 @@ in sops.secrets."docker/hass" = { owner = "numbus-admin"; path = "/etc/docker-compose/hass/.env"; }; sops.secrets."docker/pihole" = { owner = "numbus-admin"; path = "/etc/docker-compose/pihole/.env"; }; sops.secrets."docker/immich" = { owner = "numbus-admin"; path = "/etc/docker-compose/immich/.env"; }; - sops.secrets."disks/data_disk_1" = { owner = "root"; }; - sops.secrets."disks/data_disk_2" = { owner = "root"; }; - sops.secrets."disks/data_disk_3" = { owner = "root"; }; - sops.secrets."disks/data_disk_4" = { owner = "root"; }; - sops.secrets."disks/data_disk_5" = { owner = "root"; }; - sops.secrets."disks/data_disk_6" = { owner = "root"; }; - sops.secrets."disks/parity_disk_1" = { owner = "root"; }; - sops.secrets."disks/parity_disk_2" = { owner = "root"; }; - sops.secrets."disks/parity_disk_3" = { owner = "root"; }; # Bootloader options boot.initrd.systemd.enable = true; + boot.initrd.systemd.tpm2.enable = true; boot.loader.systemd-boot.enable = true; boot.loader.efi.canTouchEfiVariables = true; + # TPM2 PCR check + systemIdentity.enable = true; + # On first boot, get the value with: systemd-analyze pcrs 15 --json=short | jq -r ".[0].sha256" + # and place it here. + systemIdentity.pcr15 = null; # "6214de8c3d861c4b451acc8c4e24294c95d55bcec516bbf15c077ca3bffb6547"; + # Timezone time.timeZone = "Europe/Paris"; @@ -198,12 +204,43 @@ in ]; }; +# # Hard drives decryption +# environment.etc."crypttab".text = '' +# crypted-data-1 /dev/disk/by-uuid/THE-UUID-OF-DATA-DISK-1 /run/secrets/disks/data-disk-1 +# crypted-data-2 /dev/disk/by-uuid/THE-UUID-OF-DATA-DISK-2 /run/secrets/disks/data-disk-2 +# crypted-data-3 /dev/disk/by-uuid/THE-UUID-OF-DATA-DISK-3 /run/secrets/disks/data-disk-3 +# crypted-data-4 /dev/disk/by-uuid/THE-UUID-OF-DATA-DISK-4 /run/secrets/disks/data-disk-4 +# crypted-data-5 /dev/disk/by-uuid/THE-UUID-OF-DATA-DISK-5 /run/secrets/disks/data-disk-5 +# crypted-data-6 /dev/disk/by-uuid/THE-UUID-OF-DATA-DISK-6 /run/secrets/disks/data-disk-6 +# crypted-parity-1 /dev/disk/by-uuid/THE-UUID-OF-PARITY-DISK-1 /run/secrets/disks/parity-disk-1 +# crypted-parity-2 /dev/disk/by-uuid/THE-UUID-OF-PARITY-DISK-2 /run/secrets/disks/parity-disk-2 +# crypted-parity-3 /dev/disk/by-uuid/THE-UUID-OF-PARITY-DISK-3 /run/secrets/disks/parity-disk-3 +# ''; + + # Declarative LUKS decryption for data and parity disks + boot.luks.devices = + let + # This function generates the attribute set for a LUKS device + mkLuksDevice = type: index: + lib.nameValuePair "crypted-${type}-${toString index}" { + device = "/dev/disk/by-partlabel/${type}-disk-${toString index}"; + keyFile = "/run/secrets/disks/${type}-disk-${toString index}"; + # This option tells systemd to measure the LUKS header into PCR 15 + }; + in + # Merge attributes for data and parity disks + lib.attrsets.listToAttrs ( + (lib.lists.imap1 (i: _: mkLuksDevice "data" i) dataDiskMounts) ++ + (lib.lists.imap1 (i: _: mkLuksDevice "parity" i) parityDiskMounts) + ); + # SnapRAID for data redundancy services.snapraid = { enable = true; contentFiles = map (disk: "${disk}/snapraid.content") dataDiskMounts; parityFiles = map (disk: "${disk}/snapraid.parity") parityDiskMounts; - dataDisks = builtins.removeAttrs snapraidDataDisks [ "i" ]; # This correctly creates the required attribute set. +# dataDisks = builtins.removeAttrs snapraidDataDisks [ "i" ]; # This correctly creates the required attribute set. + dataDisks = snapraidDataDisks; # Using default sync and scrub schedules: # Sync runs daily at 01:00. # Scrub runs weekly on Monday at 02:00. diff --git a/deploy.sh b/deploy.sh index 75e92f1..7e76079 100755 --- a/deploy.sh +++ b/deploy.sh @@ -174,38 +174,42 @@ files_generation() { export IMMICH_DB_DATABASE_NAME="$(openssl rand -hex 10)" export IMMICH_DB_USERNAME="$(openssl rand -hex 10)" export IMMICH_DB_PASSWORD="$(openssl rand -base64 32 | tr -d '\=+/')" - export DATA_DISK_1="$(openssl rand -base64 32 | tr -d '\=+/')" - export DATA_DISK_2="$(openssl rand -base64 32 | tr -d '\=+/')" - export DATA_DISK_3="$(openssl rand -base64 32 | tr -d '\=+/')" - export DATA_DISK_4="$(openssl rand -base64 32 | tr -d '\=+/')" - export DATA_DISK_5="$(openssl rand -base64 32 | tr -d '\=+/')" - export DATA_DISK_6="$(openssl rand -base64 32 | tr -d '\=+/')" - export PARITY_DISK_1="$(openssl rand -base64 32 | tr -d '\=+/ ')" - export PARITY_DISK_2="$(openssl rand -base64 32 | tr -d '\=+/ ')" - export PARITY_DISK_3="$(openssl rand -base64 32 | tr -d '\=+/ ')" + export DATA_DISK_1_KEY="$(openssl rand -base64 10 | tr -d '\=+/')" + export DATA_DISK_2_KEY="$(openssl rand -base64 10 | tr -d '\=+/')" + export DATA_DISK_3_KEY="$(openssl rand -base64 10 | tr -d '\=+/')" + export DATA_DISK_4_KEY="$(openssl rand -base64 10 | tr -d '\=+/')" + export DATA_DISK_5_KEY="$(openssl rand -base64 10 | tr -d '\=+/')" + export DATA_DISK_6_KEY="$(openssl rand -base64 10 | tr -d '\=+/')" + export PARITY_DISK_1_KEY="$(openssl rand -base64 10 | tr -d '\=+/ ')" + export PARITY_DISK_2_KEY="$(openssl rand -base64 10 | tr -d '\=+/ ')" + export PARITY_DISK_3_KEY="$(openssl rand -base64 10 | tr -d '\=+/ ')" + export BOOT_DISK_1_KEY="$(openssl rand -base64 10 | tr -d '\=+/ ')" + export BOOT_DISK_2_KEY="$(openssl rand -base64 10 | tr -d '\=+/ ')" echo "$REMOTE_PASS" | ssh_to_host """ sudo -S mkdir -p /run/secrets/disks/ - echo -n $DATA_DISK_1 | sudo -S tee /run/secrets/disks/data-disk-1 > /dev/null - echo -n $DATA_DISK_2 | sudo -S tee /run/secrets/disks/data-disk-2 > /dev/null - echo -n $DATA_DISK_3 | sudo -S tee /run/secrets/disks/data-disk-3 > /dev/null - echo -n $DATA_DISK_4 | sudo -S tee /run/secrets/disks/data-disk-4 > /dev/null - echo -n $DATA_DISK_5 | sudo -S tee /run/secrets/disks/data-disk-5 > /dev/null - echo -n $DATA_DISK_6 | sudo -S tee /run/secrets/disks/data-disk-6 > /dev/null - echo -n $PARITY_DISK_1 | sudo -S tee /run/secrets/disks/parity-disk-1 > /dev/null - echo -n $PARITY_DISK_2 | sudo -S tee /run/secrets/disks/parity-disk-2 > /dev/null - echo -n $PARITY_DISK_3 | sudo -S tee /run/secrets/disks/parity-disk-3 > /dev/null + echo -n $DATA_DISK_1_KEY | sudo -S tee /run/secrets/disks/data-disk-1 > /dev/null + echo -n $DATA_DISK_2_KEY | sudo -S tee /run/secrets/disks/data-disk-2 > /dev/null + echo -n $DATA_DISK_3_KEY | sudo -S tee /run/secrets/disks/data-disk-3 > /dev/null + echo -n $DATA_DISK_4_KEY | sudo -S tee /run/secrets/disks/data-disk-4 > /dev/null + echo -n $DATA_DISK_5_KEY | sudo -S tee /run/secrets/disks/data-disk-5 > /dev/null + echo -n $DATA_DISK_6_KEY | sudo -S tee /run/secrets/disks/data-disk-6 > /dev/null + echo -n $PARITY_DISK_1_KEY | sudo -S tee /run/secrets/disks/parity-disk-1 > /dev/null + echo -n $PARITY_DISK_2_KEY | sudo -S tee /run/secrets/disks/parity-disk-2 > /dev/null + echo -n $PARITY_DISK_3_KEY | sudo -S tee /run/secrets/disks/parity-disk-3 > /dev/null + echo -n $BOOT_DISK_1_KEY | sudo -S tee /run/secrets/disks/boot-disk-1 > /dev/null + echo -n $BOOT_DISK_2_KEY | sudo -S tee /run/secrets/disks/boot-disk-2 > /dev/null """ mkdir -p extra-files/run/secrets/disks/ - echo -n $DATA_DISK_1 > extra-files/run/secrets/disks/data-disk-1 - echo -n $DATA_DISK_2 > extra-files/run/secrets/disks/data-disk-2 - echo -n $DATA_DISK_3 > extra-files/run/secrets/disks/data-disk-3 - echo -n $DATA_DISK_4 > extra-files/run/secrets/disks/data-disk-4 - echo -n $DATA_DISK_5 > extra-files/run/secrets/disks/data-disk-5 - echo -n $DATA_DISK_6 > extra-files/run/secrets/disks/data-disk-6 - echo -n $PARITY_DISK_1 > extra-files/run/secrets/disks/parity-disk-1 - echo -n $PARITY_DISK_2 > extra-files/run/secrets/disks/parity-disk-2 - echo -n $PARITY_DISK_3 > extra-files/run/secrets/disks/parity-disk-3 + echo -n $DATA_DISK_1_KEY > extra-files/run/secrets/disks/data-disk-1 + echo -n $DATA_DISK_2_KEY > extra-files/run/secrets/disks/data-disk-2 + echo -n $DATA_DISK_3_KEY > extra-files/run/secrets/disks/data-disk-3 + echo -n $DATA_DISK_4_KEY > extra-files/run/secrets/disks/data-disk-4 + echo -n $DATA_DISK_5_KEY > extra-files/run/secrets/disks/data-disk-5 + echo -n $DATA_DISK_6_KEY > extra-files/run/secrets/disks/data-disk-6 + echo -n $PARITY_DISK_1_KEY > extra-files/run/secrets/disks/parity-disk-1 + echo -n $PARITY_DISK_2_KEY > extra-files/run/secrets/disks/parity-disk-2 + echo -n $PARITY_DISK_3_KEY > extra-files/run/secrets/disks/parity-disk-3 echo -e "\n ✅ Encrypting secrets in the correct file..." envsubst < "config-files/sops-nix/secrets.yaml" | sops encrypt --filename-override secrets.yaml \ @@ -486,6 +490,19 @@ deploy() { sleep 1 } +sum_up() { + echo $DATA_DISK_1_KEY + echo $DATA_DISK_2_KEY + echo $DATA_DISK_3_KEY + echo $DATA_DISK_4_KEY + echo $DATA_DISK_5_KEY + echo $DATA_DISK_6_KEY + echo $PARITY_DISK_1_KEY + echo $PARITY_DISK_2_KEY + echo $PARITY_DISK_3_KEY + +} + postrun_action() { echo "" } @@ -553,6 +570,8 @@ elif [[ "$ACTION_ANSWER" == "[2] 💽 Deploy NixOS on a remote machine with a fi files_generation disk_config_generation deploy + sum_up + postrun_action elif [[ "$ACTION_ANSWER" == "[3] 🛠️ Update a NixOS remote machine" ]]; then echo -e "\n ➡️ Proceeding with update…" gum style --border normal --margin "1" --padding "1 2" --border-foreground 212 "➡️ On the target host : make sure the NixOS installation you want