~yoctocell/yoctocell.xyz

daba9d8e6d4540f2bc290475e4d11f3798fd1871 — yoctocell 11 months ago 5110411
posts/nixos-on-btrfs: Init
1 files changed, 188 insertions(+), 0 deletions(-)

A posts/nixos-on-btrfs-with-encrypted-root.org
A posts/nixos-on-btrfs-with-encrypted-root.org => posts/nixos-on-btrfs-with-encrypted-root.org +188 -0
@@ 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