# Dotfiles ## NixOS Install instructions for NixOS. First open a shell with vim and git: ```bash nix-shell -p git vim ``` ### EXT4 ```bash parted /dev/nvme0n1 -- mklabel gpt parted /dev/nvme0n1 -- mkpart ESP fat32 1MB 512MB parted /dev/nvme0n1 -- mkpart root ext4 512MB 100% parted /dev/nvme0n1 -- set 1 esp on mkfs.fat -F 32 -n BOOT /dev/nvme0n1p1 mkfs.ext4 -L NixOS /dev/nvme0n1p2 mount /dev/disk/by-label/NixOS /mnt mkdir -p /mnt/boot mount -o umask=077 /dev/disk/by-label/BOOT /mnt/boot nixos-generate-config --root /mnt ``` ### ZFS First stop the zfs-zed service, and unload the ZFS kernel modules: ```bash systemctl stop zfs-zed lsmod | grep zfs | cut -d' ' -f1 | xargs rmmod -f ``` Then add the following to `/etc/nixos/configuration.nix`: ```bash boot.supportedFilesystems = [ "zfs" ]; ``` And rebuild the system: ```bash nixos-rebuild switch --upgrade ``` Partition the disk: ```bash parted --script /dev/nvme0n1 -- mklabel gpt mkpart esp fat32 1MiB 512MiB mkpart primary 512MiB 100% set 1 boot on ``` Create an encrypted pool. The `-O` flags set filesystem properties that every dataset inherits, so they only need to be given once here: ```bash zpool create -f \ -o ashift=12 \ -o autotrim=on \ -O encryption=on -O keyformat=passphrase \ -O compression=zstd \ -O dnodesize=auto \ -O xattr=sa \ -O acltype=posixacl \ -O relatime=on \ -O redundant_metadata=most \ -O mountpoint=none \ rpool /dev/nvme0n1p2 ``` Create the datasets. Keeping `/nix` separate from `/` means the store can be excluded from snapshot and rollback policy, which is what makes an erase-your-darlings setup possible later: ```bash zfs create -o mountpoint=legacy rpool/root zfs create -o mountpoint=legacy rpool/nix zfs create -o mountpoint=legacy rpool/home zfs create -o mountpoint=legacy -o recordsize=1M rpool/Storage zfs create -o mountpoint=none -o refreservation=2G rpool/reserved ``` Mount them: ```bash mkdir -p /mnt mount -t zfs rpool/root /mnt mkdir -p /mnt/nix /mnt/home /mnt/Storage mount -t zfs rpool/nix /mnt/nix mount -t zfs rpool/home /mnt/home mount -t zfs rpool/Storage /mnt/Storage ``` #### Why these properties Some of these can only be chosen when the pool or dataset is created, so they are worth getting right the first time. Creation-only, no way to change later without recreating the dataset: - `encryption` and `keyformat` enable native ZFS encryption. This cannot be turned on afterwards. - `dnodesize=auto` allows dnodes larger than 512 bytes. Combined with `xattr=sa` this keeps extended attributes inline instead of spilling into separate blocks, which matters for a Nix store holding a hundred thousand small files. Existing files keep whatever size they were written with. - `ashift=12` matches the 4K physical sector size of modern NVMe drives. Changeable later, but only applied to newly written blocks: - `compression=zstd` gives a better ratio than the `lz4` that plain `compression=on` selects. The Nix store compresses particularly well. - `acltype=posixacl` is needed for systemd-journald to grant journal access through ACLs. With the default of `off` that mechanism silently does nothing. - `redundant_metadata=most` reduces the number of duplicate metadata writes. - `recordsize=1M` suits bulk file storage. Leave it at the 128K default for general purpose datasets, and drop it to 16K for databases or VM images. - `autotrim=on` issues TRIM continuously. The `zpool-trim.timer` unit that NixOS enables covers this periodically instead, so either approach works. The `rpool/reserved` dataset never gets mounted. Its `refreservation` holds space back so that the pool can be brought below its full mark by destroying that one dataset. ZFS performance degrades noticeably above roughly 80% capacity. On a single disk pool there is no redundancy, so ZFS can detect corruption but never repair it. Setting `copies=2` on the datasets that hold irreplaceable data stores a second copy of each block at the cost of double the space: ```bash zfs set copies=2 rpool/home ``` Snapshots are configured through `services.sanoid` in `hosts/Common/zfs.nix`. ZFS dataset names are case sensitive, so an entry there has to match the dataset exactly. A name that does not resolve leaves that dataset with no snapshots at all while the service still reports success. Format the boot partition: ```bash mkfs.fat -F 32 -n BOOT /dev/nvme0n1p1 mkdir -p /mnt/boot mount -t vfat /dev/nvme0n1p1 /mnt/boot ``` Generate the configuration: ```bash nixos-generate-config --root /mnt ``` Add the following to /mnt/etc/nixos/configuration.nix: ```bash boot.initrd.supportedFilesystems = [ "zfs" ]; boot.supportedFilesystems = [ "zfs" ]; services.zfs.autoScrub.enable = true; networking.hostName = "Aloria"; networking.hostId = "abcdef01"; ``` ### Install Then either clone the repository: ``` git clone https://git.thomasave.be/thomasave/Dotfiles sudo nixos-install --impure --flake ./Dotfiles#Aloria mv ./Dotfiles /mnt/home/user/.dotfiles sudo ln -s /home/user/.dotfiles /mnt/etc/nixos ``` Or install it directly: ``` sudo nixos-install --impure --flake git+https://git.thomasave.be/thomasave/Dotfiles#Aloria ``` ### Post-install Clean-up: ```bash umount /mnt/{home,nix,Storage,boot} umount /mnt ``` If using ZFS: ```bash zpool export -a ```