#!/bin/bash
set -e
# Overview: Raspberry Pi OS will be installed on two uSD cards. Both will be
# booted up to expand the root partition to the size of the uSD card. Then, a
# system booted from one uSD card will be used to install the encrypted root on
# the other.

# Download Raspberry Pi OS Lite from
# https://www.raspberrypi.org/software/operating-systems/
# Copy the image to the uSD card with 
#   `dd if=rapsios.img of=/dev/sdb bs=4M status=progress`
# Boot up, login with default username 'pi' password 'raspberry', then enable
# ssh with `sudo systemctl enable --now ssh`
# Do the same for the second uSD card
# Once the second card is booted up, use a uSD-USB adapter to plug the other uSD
# card into pi.
# I recomment to change the variables SSH_PORT and DROPBEAR_PORT something
# random above 10000. It's also nice if DROPBEAR_PORT is different from
# SSH_PORT, avoids ssh warnings
# Adjust DEVICE to point to the uSD in the USB adapter, you can get a list of
# block devices with `lsblk` to double check it's right

# Port setup for ssh and dropbear. Dropbear unlocks root partition during boot
SSH_PORT=22
DROPBEAR_PORT=22 

# Device to partition
DEVICE=/dev/sdb
BOOT_PART="${DEVICE}1"
ROOT_PART="${DEVICE}2"
ROOT_PATH=vgroup
CRYPT_NAME=cryptroot

# Install needed packages
apt install -y cryptsetup lvm2 busybox

# Encrypted root partition
echo "Choose a password for unlocking the encrypted root partition"
cryptsetup luksFormat $ROOT_PART
echo "Enter previous password to unlock encrypted root partition"
cryptsetup open $ROOT_PART ${CRYPT_NAME}

# LVM setup
# not sure why these lvm commands say '/dev/sda open failed: No medium found',
# doesn't seem to be an issue
pvcreate /dev/mapper/${CRYPT_NAME}
vgcreate ${ROOT_PATH} /dev/mapper/${CRYPT_NAME}
# Calculate lvm size to fill root partition
LVM_SIZE="$(blockdev --getsz $ROOT_PART)"
let LVM_SIZE=LVM_SIZE/2/1024/1024
echo "size of lvm is ${LVM_SIZE}"
lvcreate -L ${LVM_SIZE}G ${ROOT_PATH} -n root

mkfs.ext4 /dev/mapper/${ROOT_PATH}-root

BOOT_UUID="$(blkid -o value -s UUID $BOOT_PART)"
echo "BOOT_UUID: $BOOT_UUID"
ROOT_UUID="$(blkid -o value -s UUID $ROOT_PART)"
echo "ROOT_UUID: $ROOT_UUID"

# Syncing the root fs to the 2nd uSD
mount /dev/mapper/${ROOT_PATH}-root /mnt/
mkdir /mnt/boot
mount $BOOT_PART /mnt/boot
rsync -a --info=progress2 --del --exclude '/dev/*' --exclude '/proc/*' --exclude '/sys/*' --exclude '/tmp/*' --exclude '/run/*' --exclude '/mnt/*' --exclude '/media/*' --exclude '/lost+found' / /mnt/
sync

# Changing boot parameters for the encrypted root
sed -i 's/root=\S\+/cryptdevice=${ROOT_UUID}:${ROOT_PATH}-root root=\/dev\/mapper\/'${ROOT_PATH}-root'/' /mnt/boot/cmdline.txt
echo "initramfs initramfs.gz followkernel" >> /mnt/boot/config.txt

# Prepare chroot
mount -o rbind /dev /mnt/dev/
mount -t proc /proc /mnt/proc
mount -t sysfs /sys /mnt/sys

# Change SSH port
sed -i 's/#Port .*/Port '$SSH_PORT'/' /mnt/etc/ssh/sshd_config

# Install, configure dropbear and copy over authorized ssh keys
chroot /mnt/ apt install -y dropbear-initramfs cryptsetup-initramfs
sed -i 's/#CRYPTSETUP=.*/CRYPTSETUP=Y/' /mnt/etc/cryptsetup-initramfs/conf-hook
sed -i 's/.*DROPBEAR_OPTIONS.*/DROPBEAR_OPTIONS="-p '$DROPBEAR_PORT'"/' /mnt/etc/dropbear-initramfs/config
cp ./authorized_keys /mnt/etc/dropbear-initramfs/

# Setup unlocking and mounting of root partition
echo "${CRYPT_NAME} UUID=${ROOT_UUID} none luks" >> /mnt/etc/crypttab
sed -i 's/PARTUUID=.*\/\s/\/dev\/mapper\/'${ROOT_PATH}-root'  \/ /' /mnt/etc/fstab

# Add mounting boot partition to fstab
sed -i 's/PARTUUID=.* \/boot/UUID='$BOOT_UUID'  \/boot/' /mnt/etc/fstab

# Rebuild initramfs in /boot
chroot /mnt/ mkinitramfs -o /boot/initramfs.gz
# Add script for initramfs rebuild following kernel upgrades
cp initramfs-rebuild.sh /mnt/etc/kernel/postinst.d/initramfs-rebuild
chmod +x /mnt/etc/kernel/postinst.d/initramfs-rebuild

# Flush filesystem buffers
sync
