docs: Add zfs disk encryption getting started guide with remote unlocking.

This commit is contained in:
Qubasa
2024-08-10 12:24:36 +02:00
parent 62c09f5dae
commit 6cf6cfa8a8
3 changed files with 303 additions and 0 deletions

View File

@@ -45,6 +45,7 @@ nav:
- Configure: getting-started/configure.md - Configure: getting-started/configure.md
- Secrets & Facts: getting-started/secrets.md - Secrets & Facts: getting-started/secrets.md
- Deploy Machine: getting-started/deploy.md - Deploy Machine: getting-started/deploy.md
- Disk Encryption: getting-started/disk-encryption.md
- Mesh VPN: getting-started/mesh-vpn.md - Mesh VPN: getting-started/mesh-vpn.md
- Backup & Restore: getting-started/backups.md - Backup & Restore: getting-started/backups.md
- Flake-parts: getting-started/flake-parts.md - Flake-parts: getting-started/flake-parts.md

View File

@@ -225,6 +225,7 @@ This is useful for machines that are not always online or are not part of the re
## What's next ? ## What's next ?
- [**Disk Encryption**](./disk-encryption.md): Configure disk encryption with remote decryption
- [**Mesh VPN**](./mesh-vpn.md): Configuring a secure mesh network. - [**Mesh VPN**](./mesh-vpn.md): Configuring a secure mesh network.
--- ---

View File

@@ -0,0 +1,301 @@
## Setting up Encryption with Remote Decryption in NixOS
This guide provides an example setup for a single-disk ZFS system with native encryption, accessible for decryption remotely. This configuration only applies to `systemd-boot` enabled systems and requires UEFI booting.
For a mirrored disk setup, add `mode = "mirror";` to `zroot`. Under the `disk` option, provide the additional disk identifier, e.g., `y = mirrorBoot /dev/disk/by-id/<second_disk_id>`.
Replace the disk `nvme-eui.002538b931b59865` with your own.
Below is the configuration for `disko.nix`
```nix
{ lib, ... }:
let
mirrorBoot = idx: {
type = "disk";
device = "/dev/disk/by-id/${idx}";
content = {
type = "gpt";
partitions = {
boot = {
size = "1M";
type = "EF02"; # for grub MBR
priority = 1;
};
ESP = lib.mkIf (idx == "nvme-eui.002538b931b59865") {
size = "1G";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "nofail" ];
};
};
zfs = {
size = "100%";
content = {
type = "zfs";
pool = "zroot";
};
};
};
};
};
in
{
boot.loader.systemd-boot.enable = true;
disko.devices = {
disk = {
x = mirrorBoot "nvme-eui.002538b931b59865";
};
zpool = {
zroot = {
type = "zpool";
rootFsOptions = {
compression = "lz4";
acltype = "posixacl";
xattr = "sa";
"com.sun:auto-snapshot" = "true";
mountpoint = "none";
};
datasets = {
"root" = {
type = "zfs_fs";
options = {
mountpoint = "none";
encryption = "aes-256-gcm";
keyformat = "passphrase";
keylocation = "file:///tmp/secret.key";
};
};
"root/nixos" = {
type = "zfs_fs";
options.mountpoint = "/";
mountpoint = "/";
};
"root/home" = {
type = "zfs_fs";
options.mountpoint = "/home";
mountpoint = "/home";
};
"root/tmp" = {
type = "zfs_fs";
mountpoint = "/tmp";
options = {
mountpoint = "/tmp";
sync = "disabled";
};
};
};
};
};
};
}
```
Add this to networking.nix and **replace** the `default` values as well as the name `gchq-local` and `networking.hostId` with your own.
```nix
{ config, lib, ... }:
{
options = {
networking.gchq-local.ipv4.address = lib.mkOption {
type = lib.types.str;
default = "192.168.178.177";
};
networking.gchq-local.ipv4.cidr = lib.mkOption {
type = lib.types.str;
default = "24";
};
networking.gchq-local.ipv4.gateway = lib.mkOption {
type = lib.types.str;
default = "192.168.178.1";
};
networking.gchq-local.ipv6.address = lib.mkOption {
type = lib.types.str;
default = "2003:100:6701:d500:fbbc:40fb:cff3:3b87";
};
networking.gchq-local.ipv6.cidr = lib.mkOption {
type = lib.types.str;
default = "64";
};
networking.gchq-local.ipv6.gateway = lib.mkOption {
type = lib.types.str;
default = "fe80::3ea6:2fff:feef:3435";
};
};
config = {
networking.dhcpcd.enable = false;
networking.nameservers = [ "127.0.0.1" ];
networking.hostId = "a76ebcca"; # Needs to be unique for each host
# The '10' in the network name is the priority, so this will be the first network to be configured
systemd.network.networks."10-eth" = {
matchConfig.Type = "ether";
addresses = [
{
Address=config.networking.gchq-local.ipv4.address + "/" + config.networking.gchq-local.ipv4.cidr;
}
{
Address=config.networking.gchq-local.ipv6.address + "/" + config.networking.gchq-local.ipv6.cidr;
}
];
DHCP = "yes";
};
};
}
```
Put this into initrd.nix and add your pubkey to `authorizedKeys`.
Replace `kernelModules` with the ethernet module loaded one on your system.
```nix
{config, pkgs, ...}:
{
boot.initrd.systemd = {
enable = true;
network.networks."10-eth" = config.systemd.network.networks."10-eth";
};
boot.initrd.network = {
enable = true;
ssh = {
enable = true;
port = 7172;
authorizedKeys = [ "<yourkey>" ];
hostKeys = [
"/var/lib/initrd-ssh-key"
];
};
};
boot.initrd.availableKernelModules = [
"xhci_pci"
];
# Check the network card by running `lspci -k` on the target machine
boot.initrd.kernelModules = [ "r8169" ];
}
```
### Step 1: Copying SSH Public Key
Before starting the installation process, ensure that the SSH public key is copied to the NixOS installer.
1. Copy your public SSH key to the installer, if it has not been copied already:
```bash
ssh-copy-id -o PreferredAuthentications=password -o PubkeyAuthentication=no root@nixos-installer.local
```
### Step 1.5: Prepare Secret Key and Clear Disk Data
1. Access the installer using SSH:
```bash
ssh root@nixos-installer.local
```
2. Create a `secret.key` file in `/tmp` using `nano` or another text editor:
```bash
nano /tmp/secret.key
```
3. Discard the old disk partition data:
```bash
blkdiscard /dev/disk/by-id/nvme-eui.002538b931b59865
```
4. Run the `clan` machine installation with the following command:
```bash
clan machines install gchq-local root@nixos-installer --yes --no-reboot
```
### Step 2: ZFS Pool Import and System Installation
1. SSH into the installer once again:
```bash
ssh root@nixos-installer.local
```
2. Perform the following commands on the remote installation environment:
```bash
zpool import zroot
zfs set keystate=prompt zroot/root
zfs load-key zroot/root
zfs set mountpoint=/mnt zroot/root/nixos
mount /dev/nvme0n1p2 /mnt/boot
```
3. Disconnect from the SSH session:
```bash
CTRL+D
```
4. Securely copy your local `initrd_rsa_key` to the installer's `/mnt` directory:
```bash
scp ~/.ssh/initrd_rsa_key root@nixos-installer.local:/mnt/var/lib/initrd-ssh-key
```
5. SSH back into the installer:
```bash
ssh root@nixos-installer.local
```
6. Navigate to the `/mnt` directory, enter the `nixos-enter` environment, and then exit:
```bash
cd /mnt
nixos-enter
realpath /run/current-system
exit
```
7. Run the `nixos-install` command with the appropriate system path `<SYS_PATH>`:
```bash
nixos-install --no-root-passwd --no-channel-copy --root /mnt --system <SYS_PATH>
```
8. After the installation process, unmount `/mnt/boot`, change the ZFS mountpoint, and reboot the system:
```bash
umount /mnt/boot
cd /
zfs set mountpoint=/ zroot/root/nixos
reboot
```
9. Perform a hard reboot of the machine and remove the USB stick.
### Step 3: Accessing the Initial Ramdisk (initrd) Environment
1. SSH into the initrd environment using the `initrd_rsa_key` and provided port:
```bash
ssh -p 7172 root@192.168.178.141
```
2. Run the `systemd-tty-ask-password-agent` utility to query a password:
```bash
systemd-tty-ask-password-agent --query
```
After completing these steps, your NixOS should be successfully installed and ready for use.
**Note:** Replace `root@nixos-installer.local` and `192.168.178.141` with the appropriate user and IP addresses for your setup. Also, adjust `<SYS_PATH>` to reflect the correct system path for your environment.