Install ArchLinux from within NixOS
Introduction#
I want to install Arch Linux but
- I don't want to boot into the Live installation media.
- I don't want the installer to screw up my bootloader, I want to be in control of that
- NixOS has pacman and other tools in the store, I don't really need to boot into an installer.
I will be following the official installation guide for getting Arch installed.
Getting the partitions up and running#
Create the ZFS volumes and mount them at /mnt/arch.
sudo zfs create -o mountpoint=none olympus/system/arch
sudo zfs create -o mountpoint=legacy olympus/system/arch/root
sudo zfs create -o mountpoint=legacy olympus/system/arch/var
sudo zfs create -o mountpoint=legacy olympus/system/arch/nix
sudo zfs create -o mountpoint=legacy olympus/user/yl/arch-homeAnd mount the volumes. I used NixOS to mount the volumes where they supposed to go at and within /mnt/arch.
Installing the base#
Open a shell with the required packages from nixpkgs
nix shell nixpkgs#pacman nixpkgs#arch-install-scriptsCreate /etc/pacman.conf, you can use their official Gitlab to download it. Modify the core and extra repository to disable signature requirements. I was not able to make signature work, too bad but should be fine for getting the base and the kernel installed.
You also need /etc/pacman.d/mirrorlist, and you can use this page to generate it.
Install the base operating system
sudo pacstrap -K /mnt/arch baseOnce installed, you can finally chroot into the new Arch installation
sudo arch-chroot /mnt/archConfigure locale, timezone, hostname and password#
Important This steps is needed to remove errors about missing locale.
Edit /mnt/arch/etc/locale.gen and uncomment en_US.UTF-8 UTF-8 then run the following command:
ln -sf /usr/share/zoneinfo/America/Los_Angeles /etc/localtime
locale-genSetup the hostname, example below is for my hercules
echo hercules-arch > /etc/hostnameAnd finally set a password for the root account by running
passwdInstalling the linux and linux-firmware packages#
The steps are a bit complicated because we need the kernel to live within the /boot/EFI/arch directory as opposed to assume /boot belongs to it:
- Install the packages with
pacman -Sy linux linux-firmware - Edit
/mnt/arch/etc/mkinitcpio.d/linux.presetand update the location of all files to be within/boot/EFI/arch - Remove the 3 files added to the root of
/boot:initramfs-linux-fallback.img,initramfs-linux.img, andvmlinuz-linux. - Re-install the linux package with
pacman -S linux
Encrypted root#
In order to boot from an encrypt partition, you need two things:
- You must add the
keyboardandencryptto the hooks of the mkinitcpio - You must configure the boot options to include the appropriate options.
Initramfs#
Make sure to add the keyboard and the encrypt hooks
HOOKS=(... udev ... keyboard encrypt block ...)and then re-generate the initcpio
mkinitcpio -PKernel options#
In order for the boot to decrypt the root partition, you need to add the following option to the kernel: cryptdevice=/dev/disk/by-uuid/...:cryptroot. Putting it together, we get this:
title Arch Linux
sort-key arch
version Main
linux /EFI/arch/vmlinuz-linux
initrd /EFI/arch/initramfs-linux.img
options spl.spl_hostid=0x4a92c82f cryptdevice=/dev/disk/by-uuid/5f4422ca-eb45-4532-931b-63225c2143d5:cryptroot zfs=olympus/system/arch/root rw
machine-id eb9cb30c8e1d473e91ef3c792d4af65cSwap#
The Swap partition is encrypted and Arch Linux pretty much sucks at unlocking encrypted partitions compared to NixOS, I can't have one partition when unlocked become the unlocking key for other partitions; For that reason, I had to create a file on the root partition that becomes a key to the swap partition. Here's everything I did to make this happen:
sudo dd if=/dev/random of=/mnt/arch/etc/cryptswap.key bs=1 count=14336
sudo chmod 400 /mnt/arch/etc/cryptswap.key
sudo cryptsetup luksAddKey --key-file=/dev/mapper/cryptkey /dev/disk/by-uuid/0249ea43-7216-4a9b-9c57-377f22c41bfc /mnt/arch/etc/cryptswap.keyAnd finally add this to /etc/crypttab
cryptswap UUID=0249ea43-7216-4a9b-9c57-377f22c41bfc /etc/cryptswap.keyZFS#
Install necessary packages#
Add the following to /etc/pacman.conf
[archzfs]
Server = [https://archzfs.com/$repo/$arch](https://archzfs.com/$repo/$arch)Get the GnuPG keys
pacman-key -r DDF7DB817396A49B2A2723F7403BD972F75D9D76
pacman-key --lsign-key DDF7DB817396A49B2A2723F7403BD972F75D9D76The package I'm interested in is archzfs-linux but the problem is that it's built for an outdated Linux version that is no longer delivered by the official core repository. So now we have to add this new repository that keeps a copy of old packages:
[zfs-linux]
Server = [http://kernels.archzfs.com/$repo/](http://kernels.archzfs.com/$repo/)Now I can install the package that will give me Linux and the zfs module
pacman -Sy archzfs-linuxConfigure hostId#
/etc/hostid is required for ZFS, and once it's been updated then you must also update the initramfs but that's OK since it'll be done in the next section. I'm not sure if it's mandatory that both Arch and NixOS shares the same hostId but let's assume that it is, plus it makes it easier to have a valid hostid.
sudo cp /etc/hostid /mnt/arch/etc/hostidUpdate initramfs#
Edit /etc/mkinitcpio.conf and add zfs to the HOOKS
HOOKS=(... keyboard sd-encrypt zfs ...)and re-generate the initramfs
mkinitcpio -PFixing pool already open by another host#
I fixed it by adding the following option to the kernel parameters: spl.spl_hostid=0x4a92c82f The 0x is added as a prefix to the same value set in NixOS!