Just documenting my installation. There’s nothing really special, and the manual is fairly exhaustive, but maybe it can help out someone who never did any (semi-)manual OS installation. It is actually based of: https://wiki.archlinux.org/index.php/Dm-crypt/Encrypting_an_entire_system#LUKS_on_LVM .
To be honest, if there’s something you don’t understand you really should try to look at the --help
and/or the manpages: things start to slowly make sense when you stare at them long enough and these are valuable sources of information. Also don’t hesitate to try out things yourself, the worst that can happen is restarting the entire installation. (I’m saying this because I remember my first time installing arch, I had this fear that if I entered some incorrect command everything would explode…) Just don’t forget to backup your personal data, or even better, don’t keep it near the installation.
Boot from installation media
liveusb
Making the installation media comes down to:
$ dd if=nix.iso of=/dev/usb bs=1M status=progress
use lsblk
or df
to identify devices.
post-boot
Check for internet connection (see here, here, or even here and well try to look for examples on google I guess). Personnally I’m wired and it worked out of the box.
Decide on a partition scheme, for me it will be this:
NAME SIZE TYPE MOUNTPOINT
sda 232.9G disk
├─sda1 512M part /boot
└─sda2 232.4G part
├─vg0-swap 8G lvm [SWAP]
├─vg0-nixos 50G lvm
│ └─nixos 50G crypt /
└─vg0-home 174.4G lvm
└─home 174.4G crypt /home
I’m using Luks-on-LVM. If you’re reading this it’s probably the same for you. But if that’s not the case, the reason for this choice is so I can encrypt my root and home parition separately. That way I can boot from my other OS and mount the /home
alone (without the root partition) and if I ever want to install another distro but keep my /home
I can also do that very easily.
prepare Disks
paritionning
I’ll use gdisk here.
$ gdisk /dev/sda
-- create new partition table
o > y
-- efi boot partition
n > default(ENTER) > 512M > ef00 > p
-- lvm parition (everything else)
n > default(ENTER) > default > 8300 > p
-- write changes
w > y
We only need 2 partitions, the rest will be done with LVM.
prepare LVMs
$ pvcreate /dev/sda2
$ vgcreate vg0 /dev/sda2
$ lvcreate -L 8G vg0 -n swap
$ lvcreate -L 50G vg0 -n nixos
$ lvcreate -l +100%FREE vg0 -n home
Nothing special here, we just init /dev/sda2
, make a volume group called vg0
on it and add:
- a 8G volume named
swap
- a 50G volume named
nixos
- a volume named
home
with the remaining space
crypt, format & mount the root-parition
Here we encrypt the root partition (vg0-nixos
) with a passphrase, and open (decrypt) it, we name the decrypted volume nixos
. Since it’s still a blank volume, we need to format it with our filesystem of choice. Personnally I decided to try out xfs. The default on linux tends to be ext4
though, if that’s what you’d prefer use mkfs.ext4
.
$ cryptsetup luksFromat -c aes-xts-plain64 -y -s 512 /dev/mapper/vg0-nixos
$ cryptsetup open /dev/mapper/vg0-nixos nixos
$ mkfs.xfs -L NIXROOT /dev/mapper/nixos # or mkfs.ext4
$ mount /dev/mapper/nixos /mnt
btw if your install failed and you need to reboot from a liveusb, instead of redoing the entire installation process you can just mount the disks again by doing :
$ cryptsetup open /dev/mapper/vg0-nixos nixos
$ mount /dev/mapper/nixos /mnt
that way you don’t have to repartition and reformat everything, you can directly mount/open the volumes. Depending on your problem, it also saves you from reinstalling everything (because repartition/formatting wipe all your data, you would have to do that step everytime you had a problem too).
boot-parition
We start by erasing everything on the boot partition. Just in case.
$ dd if=/dev/zero of=/dev/sda1 bs=1M status=progress
Since we’re on UEFI, we need to format the parition with fat32. We then mount it on /mnt/boot
.
$ mkfs.fat -F 32 -n boot /dev/sda1
$ mkdir /mnt/boot
$ mount /dev/sda1 /mnt/boot
swap
Nothing magic here, just use the normal commands for making swap.
$ mkswap -L swap /dev/mapper/vg0-swap
$ swapon /dev/mapper/vg0-swap
Voilà, disks are ready. We’ll do /home
later.
Install NixOS
Now we’ll let nix do some work for us:
$ nixos-generate-config --root /mnt
$ vim /mnt/etc/nixos/configuration.nix
This is a very minimal configuration, we just want to install nixos, reboot and see if everything’s okay so far (easier to troubleshoot one thing at a time). We’ll have to re-edit the file for our /home
, and to customize our install later anyway.
{ config, pkgs, ... }:
{
imports = [ ./hardware-confguration.nix ];
networking.hostName = "foo";
# these might be defaults
boot.loader.grub.enable = true;
boot.loader.grub.version = 2;
boot.loader.grub.efiSupport = true;
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
# might use a decent editor for our next edit
environment.systemPackages = with pkgs; [
vim
];
}
Now’s the time to configure your internet connection, and make some offerings to the Lord. If this hasn’t been done already!
$ nixos-install
$ reboot
Configure
Now the reason we delayed the creation of the /home
is so we could troubleshoot it on its own if we messed up. But the whole NixOs generations makes it a breeze though… The plan is to encrypt /home
but without actually having to give a passphrase for it. We decrypt our /home
with a keyfile instead, stored in the root partition. Remember we need a passphrase to decrypt the root parition. So once we decrypted root, the system can use the keyfile to decrypt our home. Luks devices can have multiple keys, so if you share the home partition with multiple distros, each one of them can have a separate keyfile, so you don’t necessarily have to copy your keyfile around. And you can add a normal passphrase, just in case you lose the keyfile. That way we only have one passphrase to enter on boot, but we can’t decrypt /home
without giving a passphrase.
First, make the key:
$ mkdir -m 700 /luks-keys
$ dd if=/dev/urandom of=/luks-keys/home bs=1 count=256 status=progress
then we create, format and mount the volume:
$ cryptsetup luksFormat -v /dev/mapper/vg0-home /luks-keys/home
$ cryptsetup -d /luks-keys/home -y /dev/mapper/vg0-home # also make a passphrase
$ cryptsetup -d /luks-keys/home open /dev/mapper/vh0-home home
$ mkfs.xfs -L HOME /dev/mapper/home
$ mount /dev/mapper/home home
The second command is optional, I made a passphrase just in case I decide to install a new system but forget to backup the keyfile, or make a new one. So I can always access my /home
without the root-partitions and the keyfile on them. Or in case my root gets nuked and I still want to save the home, idk pick your disaster I guess.
Another run of:
$ nixos-generate-config
Now we need to comment out the following line in the /etc/nixos/hardware-configuration.nix
# boot.initrd.luks.devices."home".device = "/dev/disk/by-uuid/<UUID>"
and instead decrypt the disk via crypttab
, in the /etc/nixos/configuration.nix
:
systemd.generator-packages = [ pkgs.systemd-cryptsetup-generator ];
environment.etc = {
"crypttab" = {
enable = true;
text = ''
home UUID=<UUID> /luks-keys/home luks
'';
};
}
From what I understand all the boot.initrd.luks.devices
are decrypted before the root’s mounted. Which is not what we want, our keyfile is on the root. That’s why we use crypttab
instead. If you know of another solution, please tell me, I’d be happy to hear it.
tip: If you want to reencrypt your swap at each reboot, you can also do that here:
swap /dev/mapper/vg0-swap /dev/urandom swap,cipher=aes-xts-plain64,size=256
Again:
$ nixos-rebuild switch
$ reboot
pray and check if your /home
is correctly mounted with lsblk
after reboot. Check the uuids and make sure you only gave your passphrase for the root partition.
Post-install
Voilà that’s the basic Luks-on-LVM UEFi installation. From here on it’s just modifying the configuration.nix
to your needs. Plenty of stuff covers that already. Some places you can start: