Minimal Debian Notes
- Foreword
- Prerequisites
- Disk Partitioning
- Encrypting Root
- Applying Filesystems and Mounting
Debootstrap
- The Chroot Environment
Foreword⌗
- Bare Minimal Install
- Only packages required for function as well as a text editor will be installed.
- LUKS Full Disk Encryption
- we will be utilizing
cryptsetup
to set up strong full disk encryption.
- we will be utilizing
- **efibootmgr **
- We will get debian to play nicely with efibootmgr, no GRUB needed!
- dracut
- We will configure debian to utilize
dracut
viceinitramfs-tools
, as it is easier to configure and automate.
- We will configure debian to utilize
Prerequisites⌗
This guide will assume you have the following:
- An internet connection
- A GNU/Linux system
- The following packages (can be found on nearly all distros)
cryptsetup
,dd
,debootstrap
,arch-chroot
ORchroot
partition scheme⌗
we will be creating 3 total partitions
- a /boot partition
- a /root partition (to be encrypted)
- a /home partition (to be encrypted)
in my system, the target device will be /dev/sdc
wiping the target device⌗
lsblk -f /dev/sdc
sdc
├─sdc1
├─sdc2
└─sdc3
currently, there are multiple partitions present. ensure there is no important data on it, and issue the following command to wipe it (including the partition table)
sudo shred -fuvzn 1 /dev/sdc
there is no need to wait for it to cycle through completely unless you are excessively paranoid.
now, verify that it’s been wiped.
lsblk -f /dev/sdc
sdc
assigning partitions⌗
now, let’s apply partitions to the drive.
sudo cfdisk /dev/sdc
/dev/sdc1 2048 526335 524288 256m efi system
/dev/sdc2 526336 419956735 419430400 200g linux filesystem
/dev/sdc3 419956736 976773119 556816384 265.5g linux filesystem
- first partition, between 256m and 1g “efi system” type partition
- second partition for root, can generally be quite a bit smaller than home. i went with 200g. default “linux filesystem” works here.
- third partition for home, use the remaining space. default “linux filesystem” works here.
encrypting the partitions⌗
now, we will encrypt our two partitions and unlock them
$ cryptsetup --label crypthome -c aes-xts-plain64 -y -s 512 luksformat /dev/sdc2
$ cryptsetup luksopen /dev/sdc2 cryptroot
$ cryptsetup --label crypthome -c aes-xts-plain64 -y -s 512 luksformat /dev/sdc3
$ cryptsetup luksopen /dev/sdc3 crypthome
applying filesystems and mounting⌗
$ mkfs.fat -f 32 /dev/sdc1
$ mkfs.ext4 /dev/mapper/cryptroot
$ mkfs.ext4 /dev/mapper/crypthome
$ mount /dev/mapper/cryptroot /mnt
$ mkdir /mnt/home
$ mount /dev/mapper/crypthome /mnt/home
$ mkdir /mnt/boot
$ mount /dev/sdc1 /mnt/boot
now, we must mount directories such as /proc and /sys as slaves. this will allow the chroot environment to access more aspects of the host system, such as efivars and networking (which becomes important later)
- note, arch-chroot does this for you. skip the mounting block below if you wish to utilize said command.
$ mount --types proc /proc /mnt/proc
$ mount --rbind /sys /mnt/sys
$ mount --make-rslave /mnt/sys
$ mount --rbind /dev /mnt/dev
$ mount --make-rslave /mnt/dev
$ mount --bind /run /mnt/run
$ mount --make-slave /mnt/run
debootstrapping⌗
now, before we can chroot in, we must deploy a base install of debian stable.
sudo debootstrap --arch amd64 stable /mnt https://deb.debian.org/debian
- this is super barebones, it does not come with a kernel, a bootloader, sudo/doas, wifi or any firmware. more on that later.
the chroot environment⌗
now that there is a bare system, let’s begin configuring it.
first, copy your resolvconf
sudo cp /etc/resolvconf.conf /mnt/etc/
execute the chroot
sudo arch-chroot /mnt
fstab, crypttab and /home⌗
before we proceed, let’s make it so our encrypted home is automatically unlocked and mounted when we unlock our root drive. to read more about this process, see my other page here
we will be working all with uuid’s below.
to orient ourselves, we need to run an lsblk -f
first.
name mountpoints fsuse% label fstype uuid
sdc
├─sdc1 /mnt/boot 19% vfat 47e8-f103
├─sdc2 cryptroot crypto_luks 0c401b77-7b4c-4a9f-95fd-502568c64c73
│ └─cryptroot /mnt 1% ext4 5c9e4f0a-92f2-4b50-a993-9c3bd81f060e
└─sdc3 crypthome crypto_luks 3db4034a-ac9d-433f-a50c-e2e7c4ecf503
└─crypthome /mnt/home 12% ext4 9fc3f7b3-ded3-40e8-94d8-78abacc5fdbc
the keyfile⌗
let’s first generate a keyfile for /dev/sdc3 so we can automate the unlocking.
mkdir /etc/keys
cd /etc/keys
dd if=/dev/random of=home.key bs=4096 count=1
cryptsetup luksaddkey /dev/sdc3 home.key
crypttab⌗
now, let’s tell crypttab to utilize the key on startup
edit your /etc/crypttab file to include the below information. remember, the uuid is the uuid of the crypto_luks partition containing the /home, not the unencrypted ext4 partition inside of it
crypthome uuid=3db4034a-ac9d-433f-a50c-e2e7c4ecf503 /etc/keys/home.key
fstab⌗
now, for the fstab, we will be working with uuids as well. this isn’t explicitly necessary, but on a device with many sata/nvme devices, it’s a very good habit to build.
# this is the uuid of the ext4 partition inside of /dev/sdc2
uuid=5c9e4f0a-92f2-4b50-a993-9c3bd81f060e / ext4 defaults,rw,noatime,nodiratime 0 1
# this is the uuid of the ext4 partition inside of /dev/sdc3, the one we made a keyfile for
uuid=9fc3f7b3-ded3-40e8-94d8-78abacc5fdbc /home ext4 defaults,rw,noatime,nodiratime 0 2
# this is the uuid of the vfat partition inside of /dev/sdc1
uuid=47e8-f103 /boot vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 2
configuring apt
⌗
to enable non-free, add the following to /etc/apt/sources.list
deb https://deb.debian.org/debian stable main non-free contrib non-free-firmware
optionally, to disable the auto installation of recommended/suggested software, add the following lines to /etc/apt/apt.conf
apt::install-recommends "false";
apt::install-suggests "false";
configuring dracut⌗
first, ensure dracut is installed
sudo apt install dracut
this will remove debian’s initramfs-tools, which is the goal here. do so.
in /etc/dracut.conf.d/, we will make a file ending in .conf
add the following lines to it. “amdgpu” isn’t needed unless you want the driver to load early.
# /etc/dracut.conf.d/10.conf
hostonly="yes"
add_drivers+=" amdgpu vfat "
add_dracutmodules+=" crypt "
installing efibootmgr
with kernel/
hooks⌗
first, install efibootmgr
sudo apt install efibootmgr
efibootmgr config file⌗
now, we must configure efibootmgr
to work functionally. we must create 3 files. this was taken and adapted from void linux’ implimentation of efibootmgr
, which will update your boot entry based on the correct kernel version.
first, the config file
cat /mnt/etc/default/efibootmgr-kernel-hook
# options for the kernel hook script installed by the efibootmgr package.
# to allow efibootmgr to modify boot entries, set
modify_efi_entries=1
# kernel command-line options. example:
options="quiet loglevel=3 fbcon=font:ter16x32 fbcon=nodefer rd.luks.name=0c401b77-7b4c-4a9f-95fd-502568c64c73=cryptroot root=/dev/mapper/cryptroot"
# disk where efi partition is. default is /dev/sda
disk="/dev/disk/by-id/ata-samsung_ssd_860_evo_500gb_s3z1ny0m626144t"
# partition number of efi partition. default is 1
part=1
as a note, my “disk=” points to the device by id, you could give an argument such as “/dev/nvme0n1” or “/dev/sda” depending on your actual target device.
additionally, ensure your “rd.luks.name” points to the crypto_luks uuid of your root partition.
postinst.d/ hook⌗
This hook will be ran when debian installs a new kernel. This will take the kernel installed to /boot with the correct version number and architechture, then generate and apply a new efibootmgr
entry to reflect the newly created initrd and vmlinuz files.
Place this script in /etc/kernel/postinst.d, I named mine zz-crypt. Ensure you make it executable!
#!/usr/bin/sh
#
# kernel hook for efibootmgr.
#
# arguments passed to this script: $1 pkgname, $2 version.
#
# use pkgname
pkgname="$1"
# not version
version="$2"
. "${rootdir}/etc/default/efibootmgr-kernel-hook"
if [ "x${modify_efi_entries}" != x1 ]; then
exit 0
fi
options="${options} initrd=/initrd.img-${pkgname}"
args=""
if [ "x${disk}" != x ]; then
args="-d $disk"
fi
if [ "x${part}" != x ]; then
args="$args -p $part"
fi
# get major version, e.g. "4.8" for "linux4.8"
major_version=$(echo $pkgname | cut -c 6-)
# look for previous entry for this major kernel version
existing_entry=$(efibootmgr | grep "debian-${pkgname}")
# get the boot order
# this is required because when in the next step the existing entry is removed,
# it is also removed from the order so it needs to be restored later
bootorder=$(efibootmgr |grep "bootorder: " |cut -c 12-)
# if existing, remove it
if [ "$existing_entry" != "" ]; then
/etc/kernel.d/postrm.d/zz-efibootmgr $pkgname
fi
# create the new entry
efibootmgr -qc $args -l "debian-${pkgname}" -l /vmlinuz-${pkgname} -u "${options}"
echo "efibootmgr -qc $args -l "debian-${pkgname}" -l /vmlinuz-${pkgname} -u "${options}""
# restore the boot order
efibootmgr -qo $bootorder
postrm.d/ hook⌗
This hook, much like the prior one, will detect your old entry and remove it. This will only trigger when an old kernel is removed.
#!/bin/sh
#
# Kernel hook for efibootmgr.
#
# Arguments passed to this script: $1 pkgname, $2 version.
#
PKGNAME="$1"
. "${ROOTDIR}/etc/default/efibootmgr-kernel-hook"
if [ "x${MODIFY_EFI_ENTRIES}" != x1 ]; then
exit 0
fi
# get major version, e.g. "4.8" for "linux4.8"
major_version=$(echo $PKGNAME | cut -c 6-)
# get hex number of the matching entry
hexnum=$(efibootmgr | grep "Debian-${PKGNAME}" | cut -c "5-8")
# delete it
echo "[ "$hexnum" ] && efibootmgr -Bq -b $hexnum"
[ "$hexnum" ] && efibootmgr -Bq -b $hexnum
Place this script in /etc/kernel/postrm.d, I named mine zz-crypt. Ensure you make it executable!
Users, groups and locales⌗
On a minimal install of debian, there is no implimentation of priv esc tools such as sudo
. We can use doas
in it’s stead. Additionally, we must create the proper groups and set up the locale.
Adding a User⌗
Let’s add a basic user which we’ll add to the wheel group later
useradd -m eternal
doas
installation⌗
sudo apt install doas
doas
, by default, installs no new groups, or default permissions. let’s configure that
doas
configuration⌗
Here’s an example of my /etc/doas.conf file. In my experience, for some tools when invoked inside of certain shells, it will only accept the absolute path of the binary; hence the seemingly duplicated lines.
This will allow the user “eternal” to run certain commands as root without a password, such as brightnessctl
and wg-quick
. The first line instructs it to permit all members of the wheel group root upon entry of a password, and to persist for some time.
permit keepenv persist :wheel
permit keepenv nopass eternal cmd /bin/lsblk
permit keepenv nopass eternal cmd /usr/bin/lsblk
permit keepenv nopass eternal as root cmd lsblk
permit keepenv nopass eternal as root cmd wg
permit keepenv nopass eternal as root cmd wg-quick
permit keepenv nopass eternal cmd /bin/brightnessctl
permit keepenv nopass eternal cmd /usr/bin/brightnessctl
permit keepenv nopass eternal as root cmd brightnessctl
Adding Wheel⌗
Now that we’ve told doas
to allow the :wheel group, we must add our user to the wheel group.
usermod -a -G wheel eternal
Changing root / user passwords⌗
It’s generally a good idea to have a root password as a fallback
passwd root
passwd eternal
Setting locale⌗
We’ll set the timezone like we’d normally do,
ln -sf /usr/share/zoneinfo/America/Chicago /etc/localtime
Now, for the locale, we must install locales
apt install locales
dpkg-reconfigure locales