Table of Contents generated with DocToc
- Debian
Debian
Install Debian with LUKS2 Btrfs and systemd-boot via Debootstrap
Source: https://gist.github.com/meeas/b574e4bede396783b1898c90afa20a30
- Use a Debian Live ISO
- Single LUKS2 encrypted partition
- Single Btrfs filesystem with @, @home, @swap, and other subvolumes
- Encrypted swapfile in Btrfs subvolume
- systemd-boot bootloader
- Optional removal of crypto keys from RAM during laptop suspend
- Optional configurations for laptops
- Proper user groups for common security tools (sudo-less Wireshark, etc)
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
- GPT partition table
- 512M
/dev/nvme0n1p1
EFI System partition (EF00) - 100%+
/dev/nvme0n1p2
Linux filesystem
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
debootstrap --arch amd64 <suite> /mnt
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.
Copy the mounted file systems table.
cp -v /etc/mtab /mnt/etc/mtab
Bind the pseudo-filesystems for chroot.
mount -o bind /dev /mnt/dev
mount -o bind /dev/pts /mnt/dev/pts
mount -o bind /proc /mnt/proc
mount -o bind /sys /mnt/sys
Generate fstab.
genfstab -U /mnt >> /mnt/etc/fstab
Chroot into the new system.
chroot /mnt
Configure the new installation
Set the timezone.
dpkg-reconfigure tzdata
Set the locale.
apt install -y locales
dpkg-reconfigure locales
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 systemd-boot
Install desktop environment.
apt install task-xfce-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,wireshark 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 systemd-boot.
bootctl install
mkdir -p /boot/efi/`cat /etc/machine-id`
kernel-install add `uname -r` /boot/vmlinuz-`uname -r`
Setup autoupdating of systemd-boot.
touch /etc/kernel/postinst.d/zz-update-systemd-boot
chmod +x /etc/kernel/postinst.d/zz-update-systemd-boot
Edit /etc/kernel/postinst.d/zz-update-systemd-boot
.
#!/bin/sh
set -e
/usr/bin/kernel-install add "$1" "$2"
exit 0
Create and set permissions on the auto-remove script.
touch /etc/kernel/postrm.d/zz-update-systemd-boot
chmod +x /etc/kernel/postrm.d/zz-update-systemd-boot
Edit /etc/kernel/postrm.d/zz-update-systemd-boot
.
#!/bin/sh
set -e
/usr/bin/kernel-install remove "$1"
exit 0
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
cp -v /etc/mtab /mnt/etc/mtab
mount -o bind /dev /mnt/dev
mount -o bind /dev/pts /mnt/dev/pts
mount -o bind /proc /mnt/proc
mount -o bind /sys /mnt/sys
chroot /mnt
Setup unattended-upgrades
Edit /etc/apt/apt.conf.d/50unattended-upgrades
. Comment out the following lines.
Unattended-Upgrade::Origins-Pattern {
// Codename based matching:
// This will follow the migration of a release through different
// archives (e.g. from testing to stable and later oldstable).
// Software will be the latest available for the named release,
// but the Debian release itself will not be automatically upgraded.
"origin=Debian,codename=${distro_codename}-updates";
"origin=Debian,codename=${distro_codename}-proposed-updates";
"origin=Debian,codename=${distro_codename},label=Debian";
"origin=Debian,codename=${distro_codename},label=Debian-Security";
"origin=Debian,codename=${distro_codename}-security,label=Debian-Security";
// Archive or Suite based matching:
// Note that this will silently match a different release after
// migration to the specified archive (e.g. testing becomes the
// new stable).
// "o=Debian,a=stable";
// "o=Debian,a=stable-updates";
// "o=Debian,a=proposed-updates";
"o=Debian Backports,a=${distro_codename}-backports,l=Debian Backports";
};
Unattended-Upgrade::Remove-Unused-Dependencies "true";
Issue the command below to enable automatic updates:
sudo dpkg-reconfigure --priority=low unattended-upgrades
/etc/apt/apt.conf.d/20auto-upgrades
should contain the following:
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
Enable the systemd service:
sudo systemctl enable --now unattended-upgrades.service
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