chore(): New blog post on installing NixOS on ecrypted ZFS

This commit is contained in:
Elia el Lazkani 2021-10-17 13:52:21 +02:00
parent 1903876116
commit d3513686ee
2 changed files with 468 additions and 0 deletions

View file

@ -5903,6 +5903,232 @@ I made my modification to the =base.tmpl= and rendered the blog. It was that sim
**** Conclusion **** Conclusion
You can always clone the /theme repository/ and make your modifications to it. But maintenance becomes an issue. This seems to be a cleaner way for me to make modifications on the original /theme/ I'm using. This is how you can too. You can always clone the /theme repository/ and make your modifications to it. But maintenance becomes an issue. This seems to be a cleaner way for me to make modifications on the original /theme/ I'm using. This is how you can too.
** Nix :@nix:
*** DONE NixOS on encrypted ZFS :@nixos:zfs:encryption:
:PROPERTIES:
:EXPORT_HUGO_LASTMOD: 2021-10-17
:EXPORT_DATE: 2021-10-17
:EXPORT_FILE_NAME: nixos-on-encrypted-zfs
:CUSTOM_ID: nixos-on-encrypted-zfs
:END:
I wouldn't call myself a distro hopper. The decision of distribution is solely
based on requirements. I have requirements and I want the distribution to
fulfill them as much as possible. After 15 years, I know what I want and I go
and find it.
In this case, an unexpected project caught my eye. The idea is so radically
different that I wasn't actually searching for it this time. It is one of those
times where it found me first.
After looking into *Nix* and *NixOS*, I decided it is going to be my
distribution of choice on the desktop. I will use that as my test bed before
migrating all the serious work there. That's how I got my first taste of *NixOS*
outside of the deterministic virtualization layer and into the wild.
#+hugo: more
**** Requirements
Before installing any new system, I draftdown a list of requirements I would
need this system to run. These are things that are very hard to change on the
fly in the future without some serious work. Also, things that simply need to be
there in this day and age.
***** Filesystem
I'm a big fan of ~zfs~. I've been running it on Linux, since the ~openzfs~
project successfully ported it, with no issues. It's a solid choice for a
filesystem and I don't see a reason not to choose it.
Is it really a requirement ?
Well, yes. By now, ~openzfs~ should be accessible to all distributions but my
choice of distribution is not usually for the beginner user. I need to know
it's supported and documented. I can figure out the rest from there.
***** Encryption
This is the first requirement, I always want encryption. The reason why I put it
second in the list is that I needed to talk about ~zfs~ first.
The ~zfs~ filesystem offers encryption. Unfortunately, my research have shown
that ~zfs~ might not encrypt some metadata. This might not be a big deal but the
choice of using Luks is there as well.
With Luks, we can encrypt the whole drive. So let's do that; Luks with ~zfs~ on top.
**** NixOS
*NixOS* utilizes *Nix* to build you an OS from a configuration file. This
configuration file is written in the ~nix~ language. It is very analogous to
written an ~Ansible~ playbook but it builds an OS instead.
The idea sounded appealing to me. A good friend of mine, [[https://setkeh.com/][setkeh]], gave me a quick and
dirty overview, at first. That pushed me into doing more research of my own
where I found out that I can spawn off a ~nix-shell~ with whatever dependencies
I want without having them installed on my system. What a great concept for
development or even running applications you don't really want to run. ~Java~
stuff for example.
Anyway, for all of these different reasons I have chosen *NixOS* to be the OS of
choice to go on the desktop.
**** Installation
After testing [[https://nixos.org/][*NixOS*]] in a VM a few times, I got =setkeh= on a conference
session and we dug into this.
***** Filesystem partitioning
For the filesystem, we're going to create two partitions. We need one, ~vfat~,
for the boot and another, ~zfs~, for the rest of the filesystem.
#+BEGIN_EXPORT html
<div class="admonition note">
<p class="admonition-title"><b>Note</b></p>
#+END_EXPORT
The assumption is that we're installing *NixOS* on an ~EFI~ enabled system.
#+BEGIN_EXPORT html
</div>
#+END_EXPORT
We can start by creating the first partition of =1GB=.
#+begin_src shell
sgdisk -n3:1M:+1024M -t3:EF00 /dev/disk/by-id/VENDOR-ID
#+end_src
Followed by the rest of the filesystem.
#+begin_src shell
sgdisk -n1:0:0 -t1:BF01 /dev/disk/by-id/VENDOR-ID
#+end_src
#+BEGIN_EXPORT html
<div class="admonition note">
<p class="admonition-title"><b>Note</b></p>
#+END_EXPORT
It is usually easier to do the partitioning using =GParted=. Make sure that the
partitions are unformatted, if you do so.
#+BEGIN_EXPORT html
</div>
#+END_EXPORT
#+BEGIN_EXPORT html
<div class="admonition warning">
<p class="admonition-title"><b>Warning</b></p>
#+END_EXPORT
Do *NOT* forget to enable the boot flag on the first partition or your system
will not boot.
#+BEGIN_EXPORT html
</div>
#+END_EXPORT
***** Filesystem formatting
Now that we got our partitions creates, let's go ahead and format them properly.
Starting with the ~boot~ partition first.
#+begin_src shell
mkfs.vfat /dev/disk/by-id/VENDOR-ID-part1
#+end_src
#+BEGIN_EXPORT html
<div class="admonition warning">
<p class="admonition-title"><b>Warning</b></p>
#+END_EXPORT
At this sage, you're formatting a partition. Make sure you're pointing to the
partition and not your whole disk as in the previous section.
#+BEGIN_EXPORT html
</div>
#+END_EXPORT
Then our ~zfs~ partition, but we need to encrypt it first. So, we create the
Luks partition.
#+begin_src shell
cryptsetup luksFormat /dev/disk/by-id/VENDOR-ID-part2
#+end_src
At this stage, stage we are done with the filesystem formatting and we need to
create the ~zfs~ pool. To do so, we need to mount the encrypted ~root~
filesystem; Luks.
#+begin_src shell
cryptsetup open --type luks /dev/disk/by-id/VENDOR-ID-part2 crypt
#+end_src
This mounts the filesystem in =/dev/mapper/crypt=. We'll use that to create the pool.
#+begin_src shell
zpool create -O mountpoint=none rpool /dev/mapper/crypt
zfs create -o mountpoint=legacy rpool/root
zfs create -o mountpoint=legacy rpool/root/nixos
zfs create -o mountpoint=legacy rpool/home
#+end_src
***** Filesystem mounting
After creating the filesystem, let's mount everything.
#+begin_src shell
# Mounting filesystem
mount -t zfs rpool/root/nixos /mnt
mkdir /mnt/home
mkdir /mnt/boot
# Mounting home directory
mount -t zfs rpool/home /mnt/home
# Mounting boot partition
mount /dev/disk/by-id/VENDOR-ID-part1 /mnt/boot
#+end_src
***** Generating NixOS configuration
At this stage, we need a =nix= configuration to build our system from. I didn't
have any configuration to start from so I generated one.
#+begin_src shell
nixos-generate-config --root /mnt
#+end_src
***** NixOS configuration
Due to the weird configuration we've had, we need to make a few adjustements to
the suggested configuration layed out in the docs.
The required configuration bits to be added to
=/mnt/etc/nixos/configuration.nix= are:
#+begin_src nix
boot.supportedFilesystems = [ "zfs" ];
# Make sure you set the networking.hostId option, which ZFS requires:
networking.hostId = "<random 8-digit hex string>";
# See https://nixos.org/nixos/manual/options.html#opt-networking.hostId for more.
# Use the GRUB 2 boot loader.
boot.loader.grub = {
enable = true;
version =2;
device = "nodev";
efiSupport = true;
enableCryptodisk = true;
};
boot.initrd.luks.devices = {
root = {
device = "/dev/disk/by-uuid/VENDOR-UUID-part2"; ## Use blkid to find this UUID
# Required even if we're not using LVM
preLVM = true;
};
};
#+end_src
***** NixOS installation
If we're done with all of the configuration as described above, we should be
able to build a bootable system. Let's try that out by installing *NixOS*.
#+begin_src shell
nixos-install
#+end_src
**** Conclusion
It took a bit of trial and error, and a loooooooot of mounting over and over
again. At the end, though, it wasn't as bad as I thought it would be. I'm still
trying to get myself familiarised with *NixOS* and the new way of doing things.
All in all, I would recommend trying *NixOS*, or the very least *Nix*.
** Revision Control :@revision_control: ** Revision Control :@revision_control:
*** DONE Git! First Steps... :git: *** DONE Git! First Steps... :git:
:PROPERTIES: :PROPERTIES:

View file

@ -0,0 +1,242 @@
+++
title = "NixOS on encrypted ZFS"
author = ["Elia el Lazkani"]
date = 2021-10-17
lastmod = 2021-10-17
tags = ["zfs", "encryption"]
categories = ["nix", "nixos"]
draft = false
+++
I wouldn't call myself a distro hopper. The decision of distribution is solely
based on requirements. I have requirements and I want the distribution to
fulfill them as much as possible. After 15 years, I know what I want and I go
and find it.
In this case, an unexpected project caught my eye. The idea is so radically
different that I wasn't actually searching for it this time. It is one of those
times where it found me first.
After looking into **Nix** and **NixOS**, I decided it is going to be my
distribution of choice on the desktop. I will use that as my test bed before
migrating all the serious work there. That's how I got my first taste of **NixOS**
outside of the deterministic virtualization layer and into the wild.
<!--more-->
## Requirements {#requirements}
Before installing any new system, I draftdown a list of requirements I would
need this system to run. These are things that are very hard to change on the
fly in the future without some serious work. Also, things that simply need to be
there in this day and age.
### Filesystem {#filesystem}
I'm a big fan of `zfs`. I've been running it on Linux, since the `openzfs`
project successfully ported it, with no issues. It's a solid choice for a
filesystem and I don't see a reason not to choose it.
Is it really a requirement ?
Well, yes. By now, `openzfs` should be accessible to all distributions but my
choice of distribution is not usually for the beginner user. I need to know
it's supported and documented. I can figure out the rest from there.
### Encryption {#encryption}
This is the first requirement, I always want encryption. The reason why I put it
second in the list is that I needed to talk about `zfs` first.
The `zfs` filesystem offers encryption. Unfortunately, my research have shown
that `zfs` might not encrypt some metadata. This might not be a big deal but the
choice of using Luks is there as well.
With Luks, we can encrypt the whole drive. So let's do that; Luks with `zfs` on top.
## NixOS {#nixos}
**NixOS** utilizes **Nix** to build you an OS from a configuration file. This
configuration file is written in the `nix` language. It is very analogous to
written an `Ansible` playbook but it builds an OS instead.
The idea sounded appealing to me. A good friend of mine, [setkeh](https://setkeh.com/), gave me a quick and
dirty overview, at first. That pushed me into doing more research of my own
where I found out that I can spawn off a `nix-shell` with whatever dependencies
I want without having them installed on my system. What a great concept for
development or even running applications you don't really want to run. `Java`
stuff for example.
Anyway, for all of these different reasons I have chosen **NixOS** to be the OS of
choice to go on the desktop.
## Installation {#installation}
After testing [**NixOS**](https://nixos.org/) in a VM a few times, I got `setkeh` on a conference
session and we dug into this.
### Filesystem partitioning {#filesystem-partitioning}
For the filesystem, we're going to create two partitions. We need one, `vfat`,
for the boot and another, `zfs`, for the rest of the filesystem.
<div class="admonition note">
<p class="admonition-title"><b>Note</b></p>
The assumption is that we're installing **NixOS** on an `EFI` enabled system.
</div>
We can start by creating the first partition of `1GB`.
```shell
sgdisk -n3:1M:+1024M -t3:EF00 /dev/disk/by-id/VENDOR-ID
```
Followed by the rest of the filesystem.
```shell
sgdisk -n1:0:0 -t1:BF01 /dev/disk/by-id/VENDOR-ID
```
<div class="admonition note">
<p class="admonition-title"><b>Note</b></p>
It is usually easier to do the partitioning using `GParted`. Make sure that the
partitions are unformatted, if you do so.
</div>
<div class="admonition warning">
<p class="admonition-title"><b>Warning</b></p>
Do **NOT** forget to enable the boot flag on the first partition or your system
will not boot.
</div>
### Filesystem formatting {#filesystem-formatting}
Now that we got our partitions creates, let's go ahead and format them properly.
Starting with the `boot` partition first.
```shell
mkfs.vfat /dev/disk/by-id/VENDOR-ID-part1
```
<div class="admonition warning">
<p class="admonition-title"><b>Warning</b></p>
At this sage, you're formatting a partition. Make sure you're pointing to the
partition and not your whole disk as in the previous section.
</div>
Then our `zfs` partition, but we need to encrypt it first. So, we create the
Luks partition.
```shell
cryptsetup luksFormat /dev/disk/by-id/VENDOR-ID-part2
```
At this stage, stage we are done with the filesystem formatting and we need to
create the `zfs` pool. To do so, we need to mount the encrypted `root`
filesystem; Luks.
```shell
cryptsetup open --type luks /dev/disk/by-id/VENDOR-ID-part2 crypt
```
This mounts the filesystem in `/dev/mapper/crypt`. We'll use that to create the pool.
```shell
zpool create -O mountpoint=none rpool /dev/mapper/crypt
zfs create -o mountpoint=legacy rpool/root
zfs create -o mountpoint=legacy rpool/root/nixos
zfs create -o mountpoint=legacy rpool/home
```
### Filesystem mounting {#filesystem-mounting}
After creating the filesystem, let's mount everything.
```shell
# Mounting filesystem
mount -t zfs rpool/root/nixos /mnt
mkdir /mnt/home
mkdir /mnt/boot
# Mounting home directory
mount -t zfs rpool/home /mnt/home
# Mounting boot partition
mount /dev/disk/by-id/VENDOR-ID-part1 /mnt/boot
```
### Generating NixOS configuration {#generating-nixos-configuration}
At this stage, we need a `nix` configuration to build our system from. I didn't
have any configuration to start from so I generated one.
```shell
nixos-generate-config --root /mnt
```
### NixOS configuration {#nixos-configuration}
Due to the weird configuration we've had, we need to make a few adjustements to
the suggested configuration layed out in the docs.
The required configuration bits to be added to
`/mnt/etc/nixos/configuration.nix` are:
```nix
boot.supportedFilesystems = [ "zfs" ];
# Make sure you set the networking.hostId option, which ZFS requires:
networking.hostId = "<random 8-digit hex string>";
# See https://nixos.org/nixos/manual/options.html#opt-networking.hostId for more.
# Use the GRUB 2 boot loader.
boot.loader.grub = {
enable = true;
version =2;
device = "nodev";
efiSupport = true;
enableCryptodisk = true;
};
boot.initrd.luks.devices = {
root = {
device = "/dev/disk/by-uuid/VENDOR-UUID-part2"; ## Use blkid to find this UUID
# Required even if we're not using LVM
preLVM = true;
};
};
```
### NixOS installation {#nixos-installation}
If we're done with all of the configuration as described above, we should be
able to build a bootable system. Let's try that out by installing **NixOS**.
```shell
nixos-install
```
## Conclusion {#conclusion}
It took a bit of trial and error, and a loooooooot of mounting over and over
again. At the end, though, it wasn't as bad as I thought it would be. I'm still
trying to get myself familiarised with **NixOS** and the new way of doing things.
All in all, I would recommend trying **NixOS**, or the very least **Nix**.