@@ 0,0 1,188 @@
+#+TITLE: NixOS on Btrfs with encrypted root
+#+DATE: 2020-12-01
+#+AUTHOR: yoctocell
+
+In this guide I will install NixOS on btrfs with an encrypted root partition.
+
+*Note*: This guide is mostly just some notes for myself, proceed at your own risk!
+
+** Prerequisites
+You are expected to have a basic knowledge of both [[https://nixos.org][NixOS]] and the [[https://btrfs.wiki.kernel.org/index.php/Main_Page][btrfs]] filesystem, and you will need an installation media if you are doing this on bare metal.
+
+First, download the NixOS iso and flash it to your usb, where =sdX= is the name of the usb drive.
+
+#+begin_src sh
+sudo dd if=/path/to/iso of=/dev/sdX bs=4M status=progress
+#+end_src
+
+** Get started
+Boot from the usb and setup your wifi connection
+
+#+begin_src sh
+wpa_supplicant -B -i interface -c <(wpa_passphrase '<SSID>' '<password>')
+#+end_src
+
+** Partitioning
+The next step is to partition your drives, I will create three partitions.
+
+| Name | Type | Size |
+|-----------+---------------------------+--------|
+| =/dev/sdX1= | EFI boot partition | 512 MB |
+| =/dev/sdX2= | Swap partition | 8 GB |
+| =/dev/sdX3= | Root partition with btrfs | <rest> |
+
+Use your favourite partition program, I will use =cfdisk=. Run =lsblk= to make sure everything you didn't mess things up.
+
+** Encryption
+We will encrypt the root partition (=/dev/sdX3=) using [[https://gitlab.com/cryptsetup/cryptsetup/-/wikis/DMCrypt][dm-crypt]]. First, format the partition and enter a passphrase which will be used for decrypting the partition.
+
+#+begin_src sh
+cryptsetup luksFormat /dev/sdX3
+#+end_src
+
+Decrypt the partition and give it a name, I will call it =crypted-nixos=.
+
+#+begin_src sh
+cryptsetup open /dev/sdX3 crypted-nixos
+#+end_src
+
+** Formatting
+Format the partition and label them.
+
+#+begin_src sh
+mkfs.vfat -F32 -n boot /dev/sdX1 # Boot
+mkswap -L swap /dev/sdX2 # Swap
+swapon /dev/sdX2 # Activate swap
+mkfs.btrfs -L nixos /dev/mapper/crypted-nixos # Root
+#+end_src
+
+** Mounting & Subvolumes
+We now have one btrfs volume and we will have to create some subvolumes.
+
+| Name | Mount point | Purpose |
+|-------+-------------+-----------------------------------|
+| @ | =/= | Root filesystem |
+| @home | =/home= | Home directory, will be backed up |
+
+The home directory will backed up, everything else is either managed by nix or just temporary files. We will first mount our encrypted root partition and then create the subvolumes.
+
+#+begin_src sh
+mount -t btfs /dev/mapper/crypted-nixos /mnt # Remember the device name?
+
+btrfs subvolume create /mnt/@
+btrfs subvolume create /mnt/@home
+
+umount /mnt
+#+end_src
+
+Once the subvolumes have been created, we will mount them with our desired options.
+
+#+begin_src sh
+mount -o subvol=@,compress=lzo,noatime /dev/mapper/crypted-nixos /mnt
+
+mkdir /mnt/home
+mount -o subvol=@home,compress=lzo,noatime /dev/mapper/crypted-nixos /mnt/home
+#+end_src
+
+And don't forget to mount the boot partition!
+
+#+begin_src sh
+mkdir /mnt/boot
+mount /dev/sdX1 /mnt/boot
+#+end_src
+
+We can run =btrfs subvol list /mnt/= to list our subvolumes and make sure everything is correct.
+
+** Configuration
+Now we can install NixOS on the filesystem. First, generate a base config.
+
+#+begin_src sh
+nixos-generate-config --root /mnt
+#+end_src
+
+Since we have encryption, we need to make sure that we have the following in our =hardware-configuration.nix= or =configuration.nix=.
+
+#+begin_src nix
+{ config, lib, pkgs, ... }:
+
+{
+ boot.supportedFilesystems = [ "btrfs" ];
+
+ boot.initrd.luks.devices = {
+ "crypted-nixos" = {
+ device = "/dev/disk/by-uuid/<uuid>";
+ };
+ };
+}
+#+end_src
+
+Replace =crypted-nixos= with the name of your device, and replace =<uuid>= with the uuid of =/dev/sdX3=. The rest of the config is left for you to configure yourself.
+
+Go back to the shell and install the system.
+
+#+begin_src sh
+nixos-install
+poweroff
+#+end_src
+
+If it all goes well, we should be able enter our dm-crypt passphrase and login as a user.
+
+** Post-installation
+When your system works you probably want to make snapshots on a regular basis in case something goes wrong. I like to take snapshots every time my system starts up and shuts down, so that's what we will configure in this guide.
+
+We first want to create a script which will take snapshot for us. The following script is based on a script from the [[https://wiki.gentoo.org/wiki/Btrfs#Snapshots][Gentoo wiki]].
+
+#+begin_src nix
+{ config, lib, pkgs, ... }:
+let
+ btrfsSnapshot = pkgs.writers.writeBashBin "btrfs-snapshot"
+ ''
+ NOW=$(date +"%Y-%m-%d_%H:%M:%S")
+
+ if [ ! -e /mnt/backup/home ]; then
+ mkdir -p /mnt/backup/home
+ fi
+
+ cd /
+ ${pkgs.btrfs-progs}/bin/btrfs subvolume snapshot /home "/mnt/backup/home/home_''${NOW}"
+ '';
+in
+{
+ environment.systemPackages = [
+ btrfsSnapshot
+ ];
+}
+#+end_src
+
+Now we want to create a systemd service that runs this script on startup and shutdown.
+
+#+begin_src nix
+{ config, lib, pkgs, ... }:
+
+{
+ systemd.services."btrfs-snapshot" = {
+ description = "Create btrfs snapshot on startup and shutdown.";
+ serviceConfig = rec {
+ ExecStart = "${btrfsSnapshot}/bin/btrfs-snapshot";
+ ExecStop = ExecStart;
+ Type = "oneshot";
+ RemainAfterExit = true;
+ };
+ requiredBy = [ "multi-user.target" ];
+ };
+}
+#+end_src
+
+We can also scrub our file system once every month.
+
+#+begin_src nix
+{ config, lib, pkgs, ... }:
+
+{
+ services.btrfs.autoScrub = {
+ enable = true;
+ fileSystems = [ "/" ];
+ interval = "monthly";
+ };
+}
+#+end_src