Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save nupplaphil/d55e81bd5f9c9c9111d570c7efff7ca7 to your computer and use it in GitHub Desktop.
Save nupplaphil/d55e81bd5f9c9c9111d570c7efff7ca7 to your computer and use it in GitHub Desktop.
Headless LUKS encrypted Debian Server with UEFI
# 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 -n 1:2048:+512M -t 1:b000 /dev/sda

# create root partition
sgdisk -n 2:0:0 -t 2:fd00 /dev/sda

# mirror partition table to second disk
sgdisk -R /dev/sdb /dev/sda
sgdisk -G /dev/sdb

# inform kernel on partition table change
partprobe

# mdadm --zero-superblock /dev/sd[abcd][12]

# create new raid1
mdadm --create /dev/md0 --metadata=1.2 --level=10 --assume-clean --raid-devices=4 /dev/sd[abcd]2

# setup encryption on root partition
cryptsetup -c aes-xts-plain -y -s 512 -h sha512 luksFormat /dev/md0
cryptsetup luksOpen /dev/md0 cryptroot

# create lvm
pvcreate /dev/mapper/cryptroot
vgcreate vg0 /dev/mapper/cryptroot
lvcreate -L 100GB -n root vg0
lvcreate -L 32GB -n swap 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 /mnt/boot
mount /dev/sda1 /mnt/boot
swapon -L swap /dev/vg0/swap

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

# resolv.conf / hostname
echo "nameserver 8.8.8.8" > /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 -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

apt-get update

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

# install packages / kernel
apt-get upgrade -y
DEBIAN_FRONTEND=noninteractive apt-get install -y \
 vim \
 linux-base \
 linux-image-amd64 \
 linux-headers-amd64 \
 grub-efi-amd64 \
 btrfs-tools \
 mdadm \
 cryptsetup \
 lvm2 \
 initramfs-tools \
 openssh-server \
 dropbear \
 efibootmgr \
 dosfstools

# 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

# Hack to address https://goo.gl/2fGjCY
mknod /dev/btrfs-control c 10 234
btrfs device scan

# 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"

# 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 --bootloader-id=arch_grub --recheck --debug
grub-mkconfig -o /boot/grub/grub.cfg

exit

# unmount all
umount /mnt/boot
sync
swapoff -L swap
reboot
exit
@Heziode
Copy link

Heziode commented Jun 21, 2020

@nupplaphil

Any reason to choose stretch instead of buster ?
I have tried to install with buster, without success (unable to connect to dropbear), with stretch I can access to Dropbear to unlock partitions.

However, I have a setup with 2 LUKS partition, one for the system and another for data (that prevent system issues, and allow to change OS more quickly).

On the other hand, after unlocking the partitions, I am unable to connect to the server (no ping response).
There is something that I have missed ?

I have tried on an OVH RISE-1 dedicated server.

@derbckr
Copy link

derbckr commented Jul 16, 2023

Hello,

I tried to port the whole thing to a fresh Debian 12 system. This works well so far, but I have a problem with the unlock script, or with the unlocking of the hard drives.

To the setting:
A raid in md1 (/home) and a partition (/) of the NVMe SSD are decrypted.

Efi bios and boot are not, of course.

I have changed the script to this:

`

With Multiple Disks

/sbin/cryptsetup luksOpen /dev/nvme0n1p3 nvm_crypt
/sbin/cryptsetup luksOpen /dev/md1 md1_crypt
`

As an error message I get as an example that:

update-initramfs: Generating /boot/initrd.img-6.1.0-10-amd64 /usr/share/initramfs-tools/hooks/dropbear-unlocker: 33: cannot create /var/tmp/mkinitramfs_heMOuW/cryptroot root-StUYyjVc3j/unlocker: Directory nonexistent chmod: cannot access '/var/tmp/mkinitramfs_heMOuW/cryptroot'$'\n''root-StUYyjVc3j/unlocker': No such file or directory unlocker: loaded

and I have no idea how to solve this problem, because the script is not established for multiple disks, or do I see it wrong?

any ideas how to solve this?

Greetings
derbckr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment