System preparation script
#!/usr/bin/env bash
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# Copyright (c) 2021 @linux-aarhus
#
# The target device is cleaned and
# repurposed to hold default LUKS encrypted installation.
# The bootloader installed is systemd-boot.
# The target device can only be booted on EFI enabled systems.
# The filesystem is f2fs targeting flash devices.
# Possible improvements
# Fill device with random chars : dd if=/dev/urandom of=/dev/nvme
#
set -euxo pipefail
TROOTFS="f2fs"
TARGET="/dev/nvme0n1" # target device
TP1="$TARGET"p1 # partition 1 (EFI)
TP2="$TARGET"p2 # partition 2 (ROOT)
KERNEL="linux-lts" # linux kernel
MIRROR='https://repos.nix.dk/archlinux' # build mirror
TKEYMAP='dk-latin1' # target keyboard layout
TLOCALE_CONF='en_DK.UTF-8' # target locale.conf
TLOCALE_PRIMARY='en_DK.UTF-8 UTF-8' # target primary locale
TLOCALE_FALLBACK='en_US.UTF-8 UTF-8' # target fallback locale
TTIMEZONE='Europe/Copenhagen' # target timezone
THOSTNAME='panther' # target hostname
ITER_TIME="10000" # luks iteration time
RETRIES="5" # luks decryption retries
BASE_PKGS="base f2fs-tools $KERNEL mkinitcpio networkmanager bash-completion"
echo "==> Unmounting $TARGET"
umount -f "$TARGET"
echo "==> Preparing disk $TARGET"
sgdisk --zap-all "$TARGET"
sgdisk --mbrtogpt "$TARGET"
echo "==> Creating EFI partition"
sgdisk --new 1::+512M \
--typecode 1:ef00 \
--change-name 1:"EFI System" \
"$TARGET"
echo "==> Creating root partition"
sgdisk --new 2::: \
--typecode 2:8304 \
--change-name 2:"Linux x86-64 root" \
"$TARGET"
echo "==> wiping fs strings for EFI partition"
wipefs -af "$TP1"
echo "==> wiping fs strings for root partition"
wipefs -af "$TP2"
echo "==> formatting EFI partition"
mkfs.vfat -F32 "$TP1"
echo "==> ------------------------------------------"
echo "==> Setting up root LUKS container"
echo " -> WATCHOUT FOR THE UPPERCASE CONFIRMATION"
echo " -> If using CapsLock remember to toggle back"
cryptsetup --type luks2 \
--hash sha512 \
--iter-time $ITER_TIME \
--tries $RETRIES \
--use-urandom luksFormat \
"$TP2"
echo "==> ------------------------------------------"
echo "==> Open LUKS container"
cryptsetup open "$TP2" cryptroot
echo "==> Formatting LUKS using $TROOTFS"
fscmd="mkfs.$TROOTFS -f"
$fscmd /dev/mapper/cryptroot
echo "==> Mounting root partition"
mount /dev/mapper/cryptroot /mnt
echo "==> Creating /boot"
mkdir /mnt/boot
echo "==> Mounting EFI on boot"
mount "$TP1" /mnt/boot
echo "==> Setting installer mirror"
echo "Server = $MIRROR/\$repo/os/\$arch" > /etc/pacman.d/mirrorlist
echo "==> Syncronizing pacman databases"
pacman -Syy
echo "==> installing base system with kernel: $KERNEL"
pacstrap /mnt $BASE_PKGS
echo "==> Configure base ..."
echo " -> Creating file: vconsole.conf"
echo "KEYMAP=$TKEYMAP" > /mnt/etc/vconsole.conf
echo " -> Creating file: locale.conf"
echo "LANG=$TLOCALE_CONF" > /mnt/etc/locale.conf
echo " -> Creating file: hostname"
echo "$THOSTNAME" > /mnt/etc/hostname
echo " -> Creating file: hosts"
cat > /mnt/etc/hosts <<EOF
127.0.0.1 localhost
127.0.1.1 $THOSTNAME.localdomain $THOSTNAME
EOF
echo " -> Creating symlink: localtime"
arch-chroot /mnt ln -sf /usr/share/zoneinfo/$TTIMEZONE /etc/localtime
echo " -> Setting hardware clock"
arch-chroot /mnt hwclock --systohc
echo " -> Enabling services"
arch-chroot /mnt systemctl enable NetworkManager systemd-timesyncd
echo " -> Modifying file: locale.gen"
echo "$TLOCALE_PRIMARY" >> /mnt/etc/locale.gen
echo "$TLOCALE_FALLBACK" >> /mnt/etc/locale.gen
echo " -> Generating locale"
arch-chroot /mnt locale-gen
echo " -> Setting up mkinitcpio.conf"
sed -i '/MODULES=/c\MODULES=(f2fs)' \
/mnt/etc/mkinitcpio.conf
sed -i '/HOOKS=/c\HOOKS=(base systemd keyboard keymap sd-vconsole block sd-encrypt autodetect modconf filesystems fsck)' \
/mnt/etc/mkinitcpio.conf
echo " -> Generating initrd"
arch-chroot /mnt mkinitcpio -P
echo " -> Installing bootloader"
bootctl --path=/mnt/boot install
echo " -> Updating entries with device UUID"
devuuid=$(lsblk -no uuid "$TP2" | tail -1)
echo " -> Creating loader entry: panther.conf"
cat > /mnt/boot/loader/entries/panther.conf <<EOF
title Panther
linux /vmlinuz-$KERNEL
initrd /initramfs-$KERNEL.img
options root=/dev/mapper/cryptroot rd.luks.name=$devuuid=cryptroot
EOF
echo " -> Creating fallback entry: panther-fallback.conf"
cat > /mnt/boot/loader/entries/panther-fallback.conf <<EOF
title Panther (fallback)
linux /vmlinuz-$KERNEL
initrd /initramfs-$KERNEL.img
options root=/dev/mapper/cryptroot rd.luks.name=$devuuid=cryptroot
EOF
echo " -> Setting default loader"
sed -i '/default/c\/default @saved\*/' /mnt/boot/loader/loader.conf
echo "==> Setting target mirror $MIRROR"
echo "Server = $MIRROR/\$repo/os/\$arch" > /mnt/etc/pacman.d/mirrorlist
echo " -> Setup your root password"
arch-chroot /mnt passwd
echo "==> Cleaning up"
echo " -> Unmounting partitions"
umount -R /mnt
echo " -> Closing LUKS container"
cryptsetup close /dev/mapper/cryptroot
sync
echo "==> Done! Minimal base is now installed and configured"
echo "==> TODO: Install GUI - configure swap ..."
echo ""
echo "=== REBOOT TO TEST SYSTEM ==="
echo ""