Techne: A practical knowledge base

Table of Contents generated with DocToc

Debian

Install Debian with LUKS2 Btrfs and GRUB via Debootstrap

Source: https://gist.github.com/meeas/b574e4bede396783b1898c90afa20a30

Pre-installation setup

Boot into the live ISO, open a terminal, and become root. Install needed packages.

sudo -i
apt update
apt install -y debootstrap cryptsetup arch-install-scripts

Create paritions.

cfdisk /dev/nvme0n1
mkfs.fat -F 32 -n EFI /dev/nvme0n1p1
cryptsetup -y -v --type luks2 luksFormat --label Debian /dev/nvme01np2
cryptsetup luksOpen /dev/nvne0n1p2 cryptroot
mkfs.btrfs /dev/mapper/cryptroot

Make Btrfs subvolumes.

mount /dev/mapper/cryptroot /mnt
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@swap
umount -lR /mnt

Re-mount subvolumes as partitions.

mount -t btrfs -o defaults,subvol=@,compress=zstd:1 /dev/mapper/cryptroot /mnt
mkdir -p /mnt/{boot,home}
mkdir /mnt/boot/efi
mount /dev/nvme0n1p1 /mnt/boot/efi
mount -t btrfs -o defaults,subvol=@home,compress=zstd:1 /dev/mapper/cryptroot /mnt/home

Setup swapfile.

mkdir -p /mnt/swap
mount -t btrfs -o subvol=@swap /dev/mapper/cryptroot /mnt/swap
touch /mnt/swap/swapfile
chmod 600 /mnt/swap/swapfile
chattr +C /mnt/swap/swapfile
btrfs property set ./swapfile compression none
dd if=/dev/zero of=/mnt/swap/swapfile bs=1M count=16384
mkswap /mnt/swap/swapfile
swapon /mnt/swap/swapfile

Base installation

Create a nested subvolume for /var/log under the @ subvolume. This will be automounted with @ so there is no need to add it to /etc/fstab. Nested subvolumes are not included in snapshots of the parent subvolume. Creating a nested subvolume for /var/log will ensure the log files remain untouched when we restore the rootfs from a snapshot.

mkdir -p /mnt/var
btrfs subvolume create /mnt/var/log
debootstrap --arch amd64 <suite> /mnt

Copy the mounted file systems table.

Bind the pseudo-filesystems for chroot.

mount --rbind /dev /mnt/dev
mount --rbind /sys /mnt/sys
mount -t proc proc /mnt/proc

Generate fstab.

genfstab -U /mnt >> /mnt/etc/fstab

Chroot into the new system.

cp -v /etc/resolv.conf /mnt/etc/
chroot /mnt

Configure the new installation

Set the timezone, locale, keyboard configuration, and console.

apt install -y locales
dpkg-reconfigure tzdata locales keyboard-configuration console-setup

Set the hostname.

echo 'hostname' > /etc/hostname
echo '127.0.1.1 hostname.localdomain hostname' >> /etc/hosts

Configure APT sources on /etc/apt/sources.list

deb https://deb.debian.org/debian <suite> main contrib non-free non-free-firmware
deb https://deb.debian.org/debian <suite>-updates main contrib non-free non-free-firmware
deb https://deb.debian.org/debian <suite>-backports main contrib non-free non-free-firmware
deb https://deb.debian.org/debian-security <suite>-security main contrib non-free non-free-firmware

Install essential packages.

apt update -t <suite>-backports
apt dist-upgrade -t <suite>-backports
apt install -y neovim linux-image-amd64 linux-headers-amd64 firmware-linux firmware-linux-nonfree sudo command-not-found systemd-timesyncd systemd-resolved cryptsetup cryptsetup-initramfs efibootmgr btrfs-progs grub-efi

Install desktop environment.

apt install task-gnome-desktop task-desktop task-ssh-server

If installing on a laptop:

sudo apt install -y task-laptop powertop

Create users and groups.

passwd root
adduser jas
echo "jas ALL=(ALL) NOPASSWD: ALL" | tee -a /etc/sudoers.d/jas
chmod 640 /etc/sudoers.d/jas
usermod -aG systemd-journal jas

Setting up the bootloader

Optional package for extra protection of suspended laptops.

apt install cryptsetup-suspend

Setup encryption parameters.

blkid -s UUID -o value /dev/nvme0n1p2

Edit /etc/crypttab.

cryptroot UUID=<uuid> none luks

Setup bootloader.

grub-install --target=x86_64-efi --efi-directory=/boot/efi --recheck --bootloader-id="Debian"

Edit /etc/default/grub.

GRUB_CMDLINE_LINUX_DEFAULT=""
GRUB_CMDLINE_LINUX=""
GRUB_ENABLE_CRYPTODISK=y
GRUB_TERMINAL=console

Update grub.

update-grub

Exit chroot and reboot.

exit
umount -lR /mnt
reboot

Emergency recovery from live ISO

sudo -i
cryptsetup luksOpen /dev/nvme0n1p2 cryptroot
mount -t btrfs -o defaults,subvol=@,compress=zstd:1 /dev/mapper/cryptroot /mnt
mount /dev/nvme0n1p1 /mnt/boot/efi
mount -t btrfs -o defaults,subvol=@home,compress=zstd:1 /dev/mapper/cryptroot /mnt/home
mount -t btrfs -o subvol=@swap /dev/mapper/cryptroot /mnt/swap
swapon /mnt/swap/swapfile
mount --rbind /dev /mnt/dev
mount --rbind /sys /mnt/sys
mount -t proc proc /mnt/proc
chroot /mnt

Debian Root on ZFS

Sources:

Configure live environment

Add contrib repo to /etc/apt/sources.list.

deb http://deb.debian.org/debian bookworm main contrib

Install required utilities.

apt update
apt install -y debootstrap gdisk dkms linux-headers-amd64
apt install -y zfsutils-linux

Generate /etc/hostid.

zgenhostid -f 0x00bab10c

Define disk variables

For single NVMe:

export BOOT_DISK="/dev/nvme0n1"
export BOOT_PART="1"
export BOOT_DEVICE="${BOOT_DISK}p${BOOT_PART}"
export POOL_DISK="/dev/nvme0n1"
export POOL_PART="2"
export POOL_DEVICE="${POOL_DISK}p${POOL_PART}"

Disk preparation

Wipe partitions.

zpool labelclear -f "$POOL_DISK"
wipefs -af "$POOL_DISK"
wipefs -af "$BOOT_DISK"
sgdisk --zap-all "$POOL_DISK"
sgdisk --zap-all "$BOOT_DISK"

Create EFI boot partition.

sgdisk -n "${BOOT_PART}:1m:+512m" -t "${BOOT_PART}:ef00" "$BOOT_DISK"

Create zpool partition.

sgdisk -n "${POOL_PART}:0:-10m" -t "${POOL_PART}:bf00" "$POOL_DISK"

ZFS pool creation

IMPORTANT Note the change in case for the -o autotrim= and -o compatibility= options.

Unencrypted:

zpool create -f -o ashift=12 \
    -O compression=lz4 \
    -O acltype=posixacl \
    -O xattr=sa \
    -O relatime=on \
    -o autotrim=on \
    -o compatibility=openzfs-2.1-linux \
    -m none zroot "$POOL_DEVICE"

Encrypted:

echo "passphrase" > /etc/zfs/zroot.key
chmod 000 /etc/zfs/zroot.key

zpool create -f -o ashift=12 \
    -O compression=lz4 \
    -O acltype=posixacl \
    -O xattr=sa \
    -O relatime=on \
    -O encryption=aes-256-gcm \
    -O keylocation=file:///etc/zfs/zroot.key \
    -O keyformat=passphrase \
    -o autotrim=on \
    -o compatibility=openzfs-2.1-linux \
    -m none zroot "$POOL_DEVICE"

Create initial file systems.

zfs create -o mountpoint=none zroot/ROOT
zfs create -o mountpoint=/ -o canmount=noauto zroot/ROOT/debian
zfs create -o mountpoint=/home zroot/home
zpool set bootfs=zroot/ROOT/debian zroot

Export then re-import with a temp mountpoint of /mnt.

zpool export zroot
zpool import -N -R /mnt zroot

# for encrypted
zfs load-key -L prompt zroot

zfs mount zroot/ROOT/debian
zfs mount zroot/home

Verify that everything mounted correctly.

mount | grep mnt
zroot/ROOT/debian on /mnt type zfs (rw,relatime,xattr,posixacl)
zroot/home on /mnt/home type zfs (rw,relatime,xattr,posixacl)

Update device symlinks.

udevadm trigger

Install Debian

debootstrap bookworm /mnt

Copy files to new install.

cp -v /etc/hostid /mnt/etc/hostid
cp -v /etc/resolv.conf /mnt/etc/

# for encrypted
mkdir /mnt/etc/zfs
cp -v /etc/zfs/zroot.key /mnt/etc/zfs

Chroot into the new OS.

mount -t proc proc /mnt/proc
mount -t sysfs sys /mnt/sys
mount -B /dev /mnt/dev
mount -t devpts pts /mnt/dev/pts
chroot /mnt /bin/bash

Basic Debian configuration

echo 'hostname' > /etc/hostname
passwd

Edit /etc/apt/sources.list.

deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware
deb http://deb.debian.org/debian bookworm-updates main contrib non-free non-free-firmware
deb http://deb.debian.org/debian bookworm-backports main contrib non-free non-free-firmware
deb http://deb.debian.org/debian-security bookworm-security main contrib non-free non-free-firmware

Disable APT downloading translations: /etc/apt/apt.conf.d/99translations.

Acquire::Languages "none";

Install additional base packages.

apt update
apt install locales keyboard-configuration console-setup

Configure locales, tzdata, keyboard-configuration, and console-setup.

dpkg-reconfigure locales tzdata keyboard-configuration console-setup

ZFS configuration

Install required packages.

apt install linux-headers-amd64 linux-image-amd64 zfs-initramfs dosfstools
echo "REMAKE_INITRD=yes" > /etc/dkms/zfs.conf

Enable ZFS systemd services.

systemctl enable zfs.target
systemctl enable zfs-import-cache
systemctl enable zfs-mount
systemctl enable zfs-import.target

Configure initramfs-tools.

echo "UMASK=0077" > /etc/initramfs-tools/conf.d/umask.conf

Rebuild the initramfs.

update-initramfs -c -k all

Install and configure ZFSBootMenu

Unencrypted:

zfs set org.zfsbootmenu:commandline="quiet" zroot/ROOT

Encrypted:

zfs set org.zfsbootmenu:commandline="quiet" zroot/ROOT
zfs set org.zfsbootmenu:keysource="zroot/ROOT/debian" zroot

Create a vfat filesystem.

mkfs.vfat -F32 "$BOOT_DEVICE"

Create an fstab entry and mount.

cat << EOF >> /etc/fstab
$(blkid | grep "$BOOT_DEVICE" | cut -d ' ' -f 2) /boot/efi vfat defaults 0 0
EOF

mkdir -p /boot/efi
mount /boot/efi

Install ZFSBootMenu.

apt install -y curl
mkdir -p /boot/efi/EFI/ZBM
curl -o /boot/efi/EFI/ZBM/VMLINUZ.EFI -L https://get.zfsbootmenu.org/efi
cp -v /boot/efi/EFI/ZBM/VMLINUZ.EFI /boot/efi/EFI/ZBM/VMLINUZ-BACKUP.EFI

Configure EFI boot entries.

mount -t efivarfs efivarfs /sys/firmware/efi/efivars
apt install -y efibootmgr

efibootmgr -c -d "$BOOT_DISK" -p "$BOOT_PART" \
    -L "ZFSBootMenu (Backup)" \
    -l '\EFI\ZBM\VMLINUZ-BACKUP.EFI'
    
efibootmgr -c -d "$BOOT_DISK" -p "$BOOT_PART" \
    -L "ZFSBootMenu" \
    -l '\EFI\ZBM\VMLINUZ.EFI'

Prepare for first boot

Add user.

adduser jas
apt install -y sudo
echo 'Defaults secure_path="/usr/bin:/usr/sbin:/bin:/sbin:/usr/local/bin:/home/linuxbrew/.linuxbrew/bin"' | tee -a /etc/sudoers.d/jas
echo 'jas ALL=(ALL) NOPASSWD: ALL' | tee -a /etc/sudoers.d/jas
chmod 640 /etc/sudoers.d/jas

Exit the chroot, unmount everything.

exit
umount -n -lR /mnt
zpool export zroot
systemctl reboot

Reply to this post by email ↪