nix-community / disko

Declarative disk partitioning and formatting using nix [maintainer=@Lassulus]
MIT License
1.62k stars 177 forks source link

Q: Setup with encrypted nix-store+swap, unencrypted boot and impermenance? #490

Open Kreyren opened 8 months ago

Kreyren commented 8 months ago

I figured out this configuration, but i feel like i don't know what am I doing..

{ ... }:

# Nix-based Disk Management of SINNENFREUDE with disko and impermenance on tmpfs

###! * Should have 4096 sectors of unallocated space before the first partition
###! * The partition following should be an **UN**ENCRYPTED bootable /boot partition with FAT32 filesystem of size 512M
###! * The next partiion is expected to be the ENCRYPTED nix-store mounted on /nix with size of -100GB from the end of SSD
###! * Last partition should be an ENCRYPTED SWAP (filesystem not file) with size 100% of the remaining and set up as resume device from hibernation
###! * Impermenance requires to declare the following:
###! ```nix
###! fileSystems = {
###!    "/" = {
###!        device = "none";
###!        fsType = "tmpfs";
###!        options = [ "size=3G" "mode=755" ];
###!    };
###!    "/home/raptor" = {
###!        device = "none";
###!        fsType = "tmpfs";
###!        options = [ "size=4G" "mode=777" ];
###!    };
###! };

# FIXME(Krey): Should use a keyFile from a flash disk to decrypt

{
    # Taken from previous setup
    boot.initrd.luks.devices."luks-f5e6fd45-31bb-453a-9066-c8cc92b7eab0".device = "/dev/disk/by-uuid/f5e6fd45-31bb-453a-9066-c8cc92b7eab0"; # Rootfs
    boot.initrd.luks.devices."luks-452ab52a-080e-40c0-83ed-a7c9363a4ef7".device = "/dev/disk/by-uuid/452ab52a-080e-40c0-83ed-a7c9363a4ef7"; # SWAP

    disko.devices = {
        disk = {
            system = {
                # FIXME-SECURITY()
                device = "/dev/disk/by-id/ata-CT500MX500SSD1_21052CD42FFF"; # SSD
                type = "disk";
                content = {
                    type = "gpt";
                    partitions = {
                        # NOTE(Krey): Do NOT encrypt
                        ESP = {
                            type = "EF00"; # EFI System Partition
                            size = "512M"; # 1024M = 1G -> This is one half
                            content = {
                                type = "filesystem";
                                format = "vfat"; # FAT32
                                mountpoint = "/boot";
                            };
                        };
                        # FIXME(Krey): Encrypt this with known passphrase
                        nix-store = {
                            # type = "???"; # Set for purity?
                            size = "-100G";
                            content = {
                                type = "filesystem";
                                format = "btrfs";
                                mountpoint = "/nix";
                                #mountOptions = [ "subvol=@" ]; # Do we need this?
                            };
                        };
                        # FIXME(Krey): This swap has to be encrypted, randomEncryption doesn't work with hibernation as you won't be able to decrypt it during bootloader phase unless you can guess the random passphrase
                        # NOTE(Krey): The passphrase should be the same as the one for nix-store atm
                        swap = {
                            # type = "???"; # Set for purity?
                            size = "100%";
                            content = {
                                type = "swap";
                                resumeDevice = true; # resume from hiberation from this device
                            };
                        };
                        # Impermanance stuff
                        rootfs = {
                            fsType = "tmpfs";
                            mountOptions = [ "size=3G" "mode=755" ];
                        };
                        "/home/raptor" = {
                            fsType = "tmpfs";
                            mountOptions = [ "size=4G" "mode=777" ];
                        };
                    };
                };
            };
        };
    };

    # Impermanence
    environment.persistence."/nix/persist/system" = {
        hideMounts = true; # For added security and less clutter in the system
        directories = [
            "/var/log" # Logs
            "/var/lib/bluetooth" # Keep bluetooth configs
            "/var/lib/nixos" # Nix stuff? Dunno why
            "/var/lib/systemd/coredump" # Dunno
            "/etc/NetworkManager/system-connections" # WiFi configs
            { directory = "/var/lib/colord"; user = "colord"; group = "colord"; mode = "u=rwx,g=rx,o="; } # No idea
        ];
        files = [
            "/etc/machine-id" # To avoid confusing systemd
            { file = "/etc/nix/id_rsa"; parentDirectory = { mode = "u=rwx,g=,o="; }; } # No idea

            # To make SSH connections consistent without having to refresh known_hosts
            "/etc/ssh/ssh_host_ed25519_key"
            "/etc/ssh/ssh_host_ed25519_key.pub"
        ];
        # FIXME(Krey): Move this in user declaration?
        # FIXME-SECURITY(Krey): Username is confidential, using placeholder atm
        users.raptor = {
            directories = [
                # FIXME(Krey): This is projected to be deprecated as home-manager will be part of our nix-config
                ".config/home-manager"
            ];
            # files = [
            #   ".screenrc"
            # ];
        };
    };
}

See the ###! for intent, i am not sure how to declare the encryption as the projected usecase is to boot into a recovery that automatically applies the nixos configuration on the disk and reboots for like this "absolute" purity where the whole system gets wiped and OS re-installed.

Kreyren commented 8 months ago

and i guess using the table declaration (https://github.com/nix-community/disko/blob/master/example/legacy-table.nix) would be more manageable as it can declare exactly on which sector to have what compared to the current that sets size = "512M" ?

Lassulus commented 8 months ago

whats the error? the legacy table is deprecated and lacks a lot of features. gpt table can also set start and end instead of size, size is just an alias for end = "+${size}"

Kreyren commented 8 months ago

whats the error? the legacy table is deprecated and lacks a lot of features. gpt table can also set start and end instead of size, size is just an alias for end = "+${size}" -- @Lassulus (https://github.com/nix-community/disko/issues/490#issuecomment-1873938795)

I didn't try to run it yet, because i felt like i didn't know what i was doing and am unsure how to set it up so that it does encryption in a sane way with disko tbh

gpt table can also set start and end instead of size, size is just an alias for end = "+${size}"

Can that be declared in sectors? expected is sector size of 1 * 512 = 512 bytes

I feel like i get more control over the partitioning by using sectors, but unsure

Lassulus commented 8 months ago

yeah the start, stop and size parameters of gpt also support sectors. just specify them without a suffix. Weil if you want to specify the password interactively just don't specify a keyFile/passwordFIle and you should be asked interactively. Best way to figure out problems is to try it out