Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save L0j1k/c8354c58904f8edc3cdb7223be6beaa4 to your computer and use it in GitHub Desktop.
Save L0j1k/c8354c58904f8edc3cdb7223be6beaa4 to your computer and use it in GitHub Desktop.
(Headless-optional) UEFI-bootable LUKS-encrypted Debian
### NOTE: if performing these steps from e.g. USB, you will
###       need to boot from an EFI-enabled live image and
###       then load the efivarfs kernel module in order to 
###       make changes to EFI variables with efibootmgr

# root shell
sudo -s

# load EFI kernel module
modprobe efivarfs

# stop active raid
mdadm --stop /dev/md[01]

# destroy partition table on hdds
dd if=/dev/zero of=/dev/sda bs=1M count=512
dd if=/dev/zero of=/dev/sdb bs=1M count=512
dd if=/dev/zero of=/dev/sdc bs=1M count=512
dd if=/dev/zero of=/dev/sdd bs=1M count=512

# create new partition table
sgdisk -og /dev/sda

# create (u)efi-boot partition
sgdisk --new 1:0:+100M --type 1:ef00 --change-name "EFI System" /dev/sda

# create root partition
sgdisk --new 2:0:0 --type 2:fd00 --change-name "Linux RAID" /dev/sda

# mirror partition table to second disk
sgdisk --replicate /dev/sdb /dev/sda
# unique drive-specific IDs will never be the same anyway
sgdisk --regenerate-guids /dev/sdb

# inform kernel on partition table change
# ehhhh.....
partprobe

# mdadm --zero-superblock /dev/sd[abcd][12]
# create new raid1
mdadm --create /dev/md0 --metadata=1.2 --level=1 --assume-clean --raid-devices=2 /dev/sd[ab]2

# setup encryption on root partition
cryptsetup --cipher aes-xts-plain --verify-passphrase --key-size 512 --hash sha512 luksFormat /dev/md0
cryptsetup luksOpen /dev/md0 cryptroot

# create lvm
pvcreate /dev/mapper/cryptroot
vgcreate vg0 /dev/mapper/cryptroot
lvcreate --size 64G --name swap vg0
lvcreate --extents 100%FREE --name root vg0

# format partitions
mkfs.ext4 -L root /dev/vg0/root
mkswap -L swap /dev/vg0/swap

# FAT32 for UEFI
mkfs.fat -F 32 /dev/sda1

# mount root partition
mount /dev/vg0/root /mnt

# mount other partitions
mkdir -p /mnt/boot/efi
mount -t vfat /dev/sda1 /mnt/boot/efi
mkdir /mnt/boot/efi/EFI
swapon -L swap /dev/vg0/swap

# install minimal ubuntu
debootstrap --arch=amd64 buster /mnt http://ftp.se.debian.org/debian

# resolv.conf / hostname
echo "nameserver 1.1.1.1" > /mnt/etc/resolv.conf
echo "test" > /mnt/etc/hostname

# crypttab
echo "cryptroot UUID=$(blkid -s UUID -o value /dev/md0) none luks" > /mnt/etc/crypttab

# fstab
cat > /mnt/etc/fstab << EOF
proc                        /proc   proc    defaults    0 0
UUID=$(blkid -s UUID -o value /dev/sda1)                    /boot   ext2    defaults    0 0
UUID=$(blkid -s UUID -o value /dev/mapper/vg0-root) /       ext4    defaults    0 1
UUID=$(blkid -s UUID -o value /dev/mapper/vg0-swap)  none    swap defaults          0 0
EOF

# mount devices to new ubuntu installation
mount -o bind /dev /mnt/dev
mount -o bind /dev/pts /mnt/dev/pts
mount -o bind /run /mnt/run
mount -t sysfs /sys /mnt/sys
mount -t proc /proc /mnt/proc

# chroot to new ubuntu installation
chroot /mnt /bin/bash

# set root password
passwd

# fix raid device files
mkdir /dev/md
ln -s /dev/md0 /dev/md/0

# mtab
cp /proc/mounts /etc/mtab

# add backports for newer shinier things
echo 'deb http://deb.debian.org/debian/ buster-backports main' | tee /etc/apt/sources.list

# finish installing system
apt-get update

# install locales first (if not en_US.UTF-8)
apt-get install locales
dpkg-reconfigure locales

# install packages / kernel
## NOTE: if you care about signing: grub-efi-amd64-signed
apt-get upgrade -y
DEBIAN_FRONTEND=noninteractive apt-get install -y \
 vim \
 linux-base \
 linux-image-5.8.0-0.bpo.2-amd64 \
 linux-headers-5.8.0-0.bpo.2-amd64 \
 grub-efi-amd64 \
 mdadm \
 cryptsetup \
 lvm2 \
 initramfs-tools \
 openssh-server \
 dropbear \
 efibootmgr \
 dosfstools

# remove any label references from mdadm.conf to prevent raid assembly name instability errors during boot
sed -i 's/name=debian:[0-9]*//' /etc/mdadm/mdadm.conf

##
## NOTE: if using dropbear for remote ssh luks unlock, run those commands listed below:
##

# "boot with eyes open" to remove "splash quiet" from boot opts
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT/#GRUB_CMDLINE_LINUX_DEFAULT/' /etc/default/grub

# wait for raid assembly
sed -i 's/GRUB_CMDLINE_LINUX=""/GRUB_CMDLINE_LINUX="rootdelay=30"/' /etc/default/grub

# tell grub about luks
echo "GRUB_ENABLE_CRYPTODISK=y" >> /etc/default/grub

# update grub with new config changes
update-grub
# update initramfs
update-initramfs -u -k all

# https://www.timoschindler.de/arch-linux-uefi-boot-mit-grub-und-verschluesseltem-lvm/
grub-install --target=x86_64-efi --efi-directory=/boot/efi --boot-directory=/boot --bootloader-id=Debian --recheck --debug
grub-mkconfig -o /boot/grub/grub.cfg

# exit our chroot
exit

# copy EFI bootloader over to EFI partition on second drive
dd if=/dev/sda1 of=/dev/sdb1
# load the second drive's EFI partition into EFI bootloader
efibootmgr -c -g -d /dev/sdb -p 1 -L "Debian" -l '\EFI\Debian\grubx64.efi'

# unmount all
umount /mnt/boot
sync
swapoff -L swap
reboot
exit



###
### BEGIN DROPBEAR CRYPTO UNLOCK
###
# disable dropbear after boot
update-rc.d dropbear disable

# enable dropbear for headless boot
sed -i "s/NO_START=1/NO_START=0/" /etc/default/dropbear

# change dropbear port
sed -i "s/DROPBEAR_OPTIONS=/DROPBEAR_OPTIONS=\"-p 2201\"/" /etc/dropbear-initramfs/config

# set initramfs parameters
echo "DEVICE=eth0" >> /etc/initramfs-tools/initramfs.conf
echo "export CRYPTSETUP=y" > /usr/share/initramfs-tools/conf-hooks.d/forcecryptsetup
echo "CRYPTOPTS=target=debian,source=UUID=$(blkid -s UUID -o value /dev/md0),lvm=debian--vg-root" > /etc/initramfs-tools/conf.d/cryptroot

# set ssh public key
mkdir /root/.ssh
echo "$SSH_PUBLIC_KEY" > /root/.ssh/authorized_keys

# copy ssh public key to initramfs
cp /root/.ssh/authorized_keys /etc/dropbear-initramfs/authorized_keys

# enable ssh
systemctl enable ssh

# https://askubuntu.com/questions/771362/ubuntu-will-not-boot-into-busybox-for-remote-luks-decryption-using-dropbear
# Add hook to create unlocker script
f=/usr/share/initramfs-tools/hooks/dropbear-unlocker
cat <<\END > "$f"
#!/bin/sh

PREREQ="dropbear"

prereqs() {
    echo "$PREREQ"
}

case "$1" in
    prereqs)
        prereqs
        exit 0
    ;;
esac

. "$CONFDIR/initramfs.conf"
. /usr/share/initramfs-tools/hook-functions

# Copy dropbear if explicitly enabled, or in case of a cryptroot setup if not explicitly disabled
[ "$DROPBEAR" = y ] || [ "$DROPBEAR" != n -a -r /etc/crypttab ] || exit 0

if [ ! -x "/usr/sbin/dropbear" ]; then
    if [ "$DROPBEAR" = y ]; then
        echo "dropbear-unlock: FAILURE: Dropbear not found, script wont start!" >&2
    else
        echo "dropbear-unlock: WARNING: Dropbear not found, script wont start" >&2
    fi
    exit 0
fi

# Copy the unlock script
s="$DESTDIR/$(ls $DESTDIR | grep root)/unlocker"
echo "#!/bin/sh

# Ask for decrypt key with one disk
/scripts/local-top/cryptroot
# With Multiple Disks
#/sbin/cryptsetup luksOpen /dev/sda3 sda3_crypt
#/sbin/cryptsetup luksOpen /dev/sdb3 sdb3_crypt
#/sbin/cryptsetup luksOpen /dev/sdc3 sdc3_crypt

# Kill these programs to keep 'init' moving.
echo "Loading OS..."
kill -9 \$(ps | grep cryptsetup | grep askpass | awk '{print \$1}') > /dev/null
kill -9 \$(ps | grep /bin/sh | grep cryptroot | awk '{print \$1}') > /dev/null
exit 0
" > "$s"

chmod +x "$s"

echo "unlocker: loaded"
END

chmod +x "$f"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment