deploy-enc-arch/deploy.sh

308 lines
8.8 KiB
Bash

#!/bin/bash
# Author: Wallun <wallun@disroot.org>
# This script has to be run from archlinux iso.
# It allows a fast encrypted VM deployment with almost nothing but the
# essential.
# Variables
SWAP=true
# Check arguments
if [[ "${#}" -lt "4" ]]; then
echo "Usage: ${0} -h MACHINE_HOSTNAME -d DEVICE"
exit 1;
else
while getopts ":h:d:s" OPTION; do
case "${OPTION}" in
h)
MACHINE_HOSTNAME="${OPTARG}";
;;
d)
DEVICE="${OPTARG}";
;;
s)
SWAP=false
;;
*)
;;
esac;
done
if [[ -z "${MACHINE_HOSTNAME}" ]]; then
echo "MACHINE_HOSTNAME is not defined";
exit 2;
fi;
if [[ -z "${DEVICE}" ]]; then
echo "DEVICE is not defined";
exit 3;
fi;
if [[ ! -b "${DEVICE}" ]]; then
echo "${DEVICE} is not a block device"
exit 4;
fi;
fi;
# Check configuration
CONFIG_FILE=$(dirname "${0}")/config
if [[ ! -f "${CONFIG_FILE}" ]]; then
echo "${CONFIG_FILE} does not exist"
exit 10;
else
# shellcheck source=config
source "${CONFIG_FILE}";
if [[ -z "${PASSPHRASE}" ]]; then
echo "PASSPHRASE is not defined";
exit 11
fi;
if [[ -z "${ADMIN_NAME}" ]]; then
echo "ADMIN_NAME is not defined in config file"
exit 12;
fi;
if [[ -z "${AUTHORIZED_KEY}" ]]; then
echo "AUTHORIZED_KEY is not defined in config file"
fi
fi;
# Check if BIOS or UEFI
if [[ -d /sys/firmware/efi/efivars ]]; then
readonly MODE="uefi";
else
readonly MODE="bios";
fi;
# Enable NTP
timedatectl set-ntp on;
# Create partitions
SWAP_SIZE=$(free -m | grep "Mem" | awk '{print $2}')
parted -s -a optimal "${DEVICE}" mklabel gpt;
if [[ "${MODE}" == bios ]]; then
parted -s -a optimal "${DEVICE}" unit mib mkpart primary 1 3
parted -s -a optimal "${DEVICE}" name 1 grub;
parted -s -a optimal "${DEVICE}" set 1 bios on;
parted -s -a optimal "${DEVICE}" unit mib mkpart primary 3 515;
parted -s -a optimal "${DEVICE}" name 2 boot;
parted -s -a optimal "${DEVICE}" unit mib mkpart primary 515 100%;
parted -s -a optimal "${DEVICE}" name 3 lvmcrypt;
readonly BOOT_PARTITION="${DEVICE}2"
readonly ENCRYPTED_PARTITION="${DEVICE}3"
else
parted -s -a optimal "${DEVICE}" unit mib mkpart primary 1 513
parted -s -a optimal "${DEVICE}" name 1 boot
parted -s -a optimal "${DEVICE}" set 1 esp on
parted -s -a optimal "${DEVICE}" unit mib mkpart primary 513 100%
parted -s -a optimal "${DEVICE}" name 2 lvmcrypt;
readonly BOOT_PARTITION="${DEVICE}1"
readonly ENCRYPTED_PARTITION="${DEVICE}2"
fi;
# Create LUKS partition
echo "${PASSPHRASE}" |\
cryptsetup -q luksFormat "${ENCRYPTED_PARTITION}";
echo "${PASSPHRASE}" | \
cryptsetup -q open "${ENCRYPTED_PARTITION}" cryptlvm
# Create PV
pvcreate /dev/mapper/cryptlvm
# Create VG
vgcreate vgos /dev/mapper/cryptlvm;
# Optional: create and enable swap partition
if ${SWAP}; then
lvcreate -L "${SWAP_SIZE}m" vgos -n swap
mkswap -f /dev/vgos/swap;
swapon /dev/vgos/swap
fi
# Create LV
lvcreate -l 100%FREE vgos -n root
# Create filesystems
mkfs.ext4 -F /dev/vgos/root;
if [[ "${MODE}" == "bios" ]]; then
mkfs.ext2 -F "${BOOT_PARTITION}";
else
mkfs.fat -F32 "${BOOT_PARTITION}"
fi;
# Mount filesystems
mount /dev/vgos/root /mnt;
mkdir /mnt/boot;
mount "${BOOT_PARTITION}" /mnt/boot;
# /etc/login.defs
sed -i "s/UID_MIN.*1000$/UID_MIN\t\t\t10000/g;\
s/UID_MAX.*60000$/UID_MAX\t\t\t11000/g;\
s/SYS_UID_MIN.*500$/SYS_UID_MIN\t\t 600/g;\
s/SYS_UID_MAX.*999$/SYS_UID_MAX\t\t 700/g;\
s/GID_MIN.*1000$/GID_MIN\t\t\t10000/g;\
s/GID_MAX.*60000$/GID_MAX\t\t\t11000/g;\
s/SYS_GID_MIN.*500$/SYS_GID_MIN\t\t 600/g;\
s/SYS_GID_MAX.*999$/SYS_GID_MAX\t\t 700/g;" /etc/login.defs
# Change pacman mirrorlist
curl -L "www.archlinux.org/mirrorlist/?country=FR&protocol=https\
&ip_version=4&use_mirror_status=on" \
| sed "s/#Server/Server/g" \
| tee /etc/pacman.d/mirrorlist > /dev/null
# Populate /mnt
pacstrap /mnt base base-devel linux linux-firmware \
nano git man-db man-pages texinfo lvm2
# Generate fstab
genfstab -U /mnt >> /mnt/etc/fstab
# Configure system-resolved
cd /mnt/etc || exit;
rm -f resolv.conf;
ln -sf ../run/systemd/resolve/resolv.conf resolv.conf
# Configure timezone
arch-chroot /mnt ln -sf /usr/share/zoneinfo/Europe/Paris /etc/localtime;
# Localization
arch-chroot /mnt sed -i "s/#en_US.UTF-8/en_US.UTF-8/g; \
s/#fr_FR.UTF-8/fr_FR.UTF-8/g" /etc/locale.gen;
arch-chroot /mnt locale-gen;
echo "LANG=en_US.UTF-8
LC_CTYPE=fr_FR.UTF-8
LC_NUMERIC=fr_FR.UTF-8
LC_TIME=fr_FR.UTF-8
LC_COLLATE=fr_FR.UTF-8
LC_MONETARY=fr_FR.UTF-8
LC_MESSAGES=en_US.UTF-8
LC_PAPER=fr_FR.UTF-8
LC_NAME=fr_FR.UTF-8
LC_ADDRESS=fr_FR.UTF-8
LC_TELEPHONE=fr_FR.UTF-8
LC_MEASUREMENT=fr_FR.UTF-8
LC_IDENTIFICATION=fr_FR.UTF-8"\
| arch-chroot tee /etc/locale.conf > /dev/null
echo "KEYMAP=fr-latin1" \
| arch-chroot /mnt tee /etc/vconsole.conf > /dev/null;
# Network
## Hostname
echo "${MACHINE_HOSTNAME}" \
| arch-chroot /mnt tee /etc/hostname > /dev/null;
## Localhost
echo "127.0.0.1 localhost" \
| arch-chroot /mnt tee -a /etc/hosts > /dev/null;
## Disable interface renaming
arch-chroot /mnt ln -sf /dev/null /etc/udev/rules.d/80-net-setup-link.rules;
## Configure eth0 DHCP
echo "[Match]
Name=eth0
[Network]
DHCP=ipv4
[DHCP]
UseDNS=true
UseDomains=true" \
| arch-chroot /mnt tee /etc/systemd/network/eth0.network > /dev/null;
## Enable systemd-networkd and systemd-resolved
arch-chroot /mnt systemctl enable systemd-networkd systemd-resolved
# /etc/logins/def
arch-chroot /mnt sed -i "s/UID_MIN.*1000$/UID_MIN\t\t\t10000/g;\
s/UID_MAX.*60000$/UID_MAX\t\t\t11000/g;\
s/SYS_UID_MIN.*500$/SYS_UID_MIN\t\t 600/g;\
s/SYS_UID_MAX.*999$/SYS_UID_MAX\t\t 700/g;\
s/GID_MIN.*1000$/GID_MIN\t\t\t10000/g;\
s/GID_MAX.*60000$/GID_MAX\t\t\t11000/g;\
s/SYS_GID_MIN.*500$/SYS_GID_MIN\t\t 600/g;\
s/SYS_GID_MAX.*999$/SYS_GID_MAX\t\t 700/g;"\
/etc/login.defs
# Create local admin account
arch-chroot /mnt useradd "${ADMIN_NAME}"
arch-chroot /mnt usermod -aG wheel "${ADMIN_NAME}";
arch-chroot /mnt mkdir -p "/home/${ADMIN_NAME}/.ssh"
arch-chroot /mnt chmod -R 700 "/home/${ADMIN_NAME}"
echo "# User rules for ${ADMIN_NAME}
${ADMIN_NAME} ALL=(ALL) NOPASSWD:ALL" \
| arch-chroot /mnt tee "/etc/sudoers.d/${ADMIN_NAME}" > /dev/null;
# Bootloader
arch-chroot /mnt pacman -S --noconfirm grub;
if [[ "${MODE}" == "bios" ]]; then
arch-chroot /mnt grub-install "${DEVICE}";
else
arch-chroot /mnt pacman -S --noconfirm efibootmgr
arch-chroot /mnt grub-install \
--target=x86_64-efi \
--efi-directory=/boot \
--bootloader-id=GRUB
fi;
arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg;
# /etc/default/grub
CRYPTDEVICE=""
DISK_UUID_LIST=$(find /dev/disk/by-uuid -type l)
for DISK_UUID in ${DISK_UUID_LIST}; do
if [[ "$(realpath "$DISK_UUID")" == "${ENCRYPTED_PARTITION}" ]]; then
CRYPTDEVICE="cryptdevice=UUID=$(basename "${DISK_UUID}"):cryplvm"
fi;
done
IP="ip=::::${HOSTNAME}:eth0:dhcp netconf_timeout=10"
ROOT="root=/dev/vgos/root"
PRELOAD_MODULES="part_gpt part_msdos lvm"
arch-chroot /mnt sed -i "s|CMDLINE_LINUX=.*|CMDLINE_LINUX=\"${IP} ${CRYPTDEVICE} ${ROOT}\"|g;\
s|PRELOAD_MODULES=.*|PRELOAD_MODULES=\"${PRELOAD_MODULES}\"|g;\
s|^#GRUB_ENABLE_CRYPTODISK|GRUB_ENABLE_CRYPTODISK|g;" /etc/default/grub;
# Openssh
arch-chroot /mnt pacman -S --noconfirm openssh;
arch-chroot /mnt sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin no/g" /etc/ssh/sshd_config;
arch-chroot /mnt sed -i "s/#PasswordAuthentication yes/PasswordAuthentication no/g" /etc/ssh/sshd_config;
echo "${AUTHORIZED_KEY}" \
| arch-chroot /mnt tee "/home/${ADMIN_NAME}/.ssh/authorized_keys" > /dev/null
arch-chroot /mnt chown -R "${ADMIN_NAME}": "/home/${ADMIN_NAME}"
arch-chroot /mnt systemctl enable sshd
# /etc/mkinitcpio.conf
HOOKS="base udev autodetect keyboard keymap consolefont modconf block \
lvm2 netconf dropbear encryptssh filesystems fsck"
arch-chroot /mnt sed -i "s/^HOOKS=.*/HOOKS=(${HOOKS})/" /etc/mkinitcpio.conf
arch-chroot /mnt pacman -S --noconfirm \
mkinitcpio-dropbear mkinitcpio-netconf mkinitcpio-utils;
arch-chroot /mnt cp "/home/${ADMIN_NAME}/.ssh/authorized_keys" /etc/dropbear/root_key;
arch-chroot /mnt dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
arch-chroot /mnt dropbearkey -t ecdsa -f /etc/dropbear/dropbear_ecdsa_host_key
arch-chroot /mnt dropbearkey -t ed25519 -f /etc/dropbear/dropbear_ed25519_host_key
arch-chroot /mnt sed -i "s/-E -s -j -k/-E -s -j -k -p 222/g" /usr/lib/initcpio/hooks/dropbear
NET_MODULE=$(realpath /sys/class/net/eth0/device/driver | awk -F"/" '{print $NF}')
arch-chroot /mnt sed -i "s/^MODULES=()/MODULES=(${NET_MODULE})/g" /etc/mkinitcpio.conf
arch-chroot /mnt mkinitcpio -P;
arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg;