From 7c96fd96d50ccc2e7ed2700bd388b6ed9553cafb Mon Sep 17 00:00:00 2001 From: Daniel Langbein Date: Sat, 13 Nov 2021 13:56:47 +0100 Subject: [PATCH] installer: disalbe FDE; notes Add option to disalbe full-disk encryption (FDE) to de-p1st-installer and update notes.md --- notes.md | 7 -- pkg/de-p1st-installer/PKGBUILD | 12 +-- pkg/de-p1st-installer/de-p1st-installer.sh | 95 +++++++++++-------- .../example-headless-docker.cfg | 6 +- pkg/de-p1st-installer/example-vbox.cfg | 21 ++-- pkg/de-p1st-installer/lib/block-device.sh | 53 +++++++---- 6 files changed, 115 insertions(+), 79 deletions(-) diff --git a/notes.md b/notes.md index dd96e7a..e006eab 100644 --- a/notes.md +++ b/notes.md @@ -103,25 +103,18 @@ Enter a number (default=1): ## TODOs (Ordered by priority) -* installer: Option to disable full disk encryption - * Install more packages with a Makefile, see [toggle-bluetooth/Makefile](pkg/toggle-bluetooth/Makefile) * de-p1st-cups * qt-installer-framework * see https://codeberg.org/privacy1st/qt-installer-framework and https://bbs.archlinux.org/viewtopic.php?pid=1991208 -* split up the "base" package: - * base-headless (no fonts required) - * base-graphical (depends on base-headless) - * * remove "de-p1st-grub" from base * just one "base" package for both: BIOS and (U)EFI installation! * installer: support BIOS boot mode? Or drop BIOS support? * installer: systemd-boot as alternative to GRUB? * https://wiki.archlinux.org/title/systemd-boot -* AUR-API * for each PKG: built with docker then sign wit pgp * signed package db diff --git a/pkg/de-p1st-installer/PKGBUILD b/pkg/de-p1st-installer/PKGBUILD index 0c075e5..0eb5c03 100644 --- a/pkg/de-p1st-installer/PKGBUILD +++ b/pkg/de-p1st-installer/PKGBUILD @@ -2,9 +2,9 @@ _pkgname=installer _reponame=arch pkgname="de-p1st-$_pkgname" -pkgver=0.1.24 +pkgver=0.2.0 pkgrel=1 -pkgdesc="Bash script to install Arch Linux" +pkgdesc="Installer for Arch Linux written in Bash" arch=('any') url="https://codeberg.org/privacy1st/${_reponame}" license=('MIT') @@ -17,11 +17,11 @@ sha256sums=('SKIP') package() { cd "${_reponame}/pkg/${pkgname}" - install -Dm0544 de-p1st-installer.sh "$pkgdir"/usr/bin/"${pkgname}" + install -Dm0544 de-p1st-installer.sh "$pkgdir"/usr/bin/"${pkgname}" - install -Dm0644 lib/block-device.sh "$pkgdir"/usr/lib/"${pkgname}"/block-device.sh - install -Dm0644 lib/user-input.sh "$pkgdir"/usr/lib/"${pkgname}"/user-input.sh - install -Dm0644 lib/util.sh "$pkgdir"/usr/lib/"${pkgname}"/util.sh + install -Dm0644 lib/block-device.sh "$pkgdir"/usr/lib/"${pkgname}"/block-device.sh + install -Dm0644 lib/user-input.sh "$pkgdir"/usr/lib/"${pkgname}"/user-input.sh + install -Dm0644 lib/util.sh "$pkgdir"/usr/lib/"${pkgname}"/util.sh install -Dm0644 -o0 installer.cfg "$pkgdir"/etc/"${pkgname}"/installer.cfg install -Dm0644 -o0 example-vbox.cfg "$pkgdir"/etc/"${pkgname}"/example-vbox.cfg diff --git a/pkg/de-p1st-installer/de-p1st-installer.sh b/pkg/de-p1st-installer/de-p1st-installer.sh index 83db415..8db9e50 100755 --- a/pkg/de-p1st-installer/de-p1st-installer.sh +++ b/pkg/de-p1st-installer/de-p1st-installer.sh @@ -16,8 +16,8 @@ function main() { check_network || return $? system_time || return $? - # in: BOOT_FIRMWARE, FS, HOSTNAME, USERNAME, USER_PWD, LUKS_PWD (all optional) - # out: BOOT_FIRMWARE, FS, HOSTNAME, USERNAME, USER_PWD, LUKS_PWD + # in: BOOT_FIRMWARE, FS, HOSTNAME, USERNAME, USER_PWD, FDE, LUKS_PWD; (all variables are optional) + # out: BOOT_FIRMWARE, FS, HOSTNAME, USERNAME, USER_PWD, FDE, LUKS_PWD (if FDE='true') get_user_input || return $? # in: CPU_VENDOR (optional) # out: CPU_VENDOR @@ -25,16 +25,16 @@ function main() { # in: FS # out: FS_DEFAULT_MOUNT_OPTIONS - get_default_mount_options || return $? + get_default_mount_options || return $? # in: FS # out: FS_ADDITIONAL_MOUNT_OPTIONS - get_additional_mount_options || return $? + get_additional_mount_options || return $? # in: TARGET_BLOCK_DEVICE, BOOT_FIRMWARE # out: BOOT_PART, LUKS_PART partition || return $? - # in: BOOT_FIRMWARE, BOOT_PART, LUKS_PART, LUKS_PWD, FS - # out: LUKS_PART_UUID, DATA_PART + # in: BOOT_FIRMWARE, BOOT_PART, LUKS_PART, FDE, LUKS_PWD, FS + # out: LUKS_PART_UUID (if FDE='true'), DATA_PART format || return $? # Combine default and additional mount options @@ -47,7 +47,7 @@ function main() { mount_partitions || return $? - # in: BOOT_FIRMWARE + # in: BOOT_FIRMWARE, PACSTRAP_INTERACTIVE (optional) run_pacstrap || return $? # in: FS run_genfstab || return $? @@ -58,14 +58,16 @@ function main() { user_and_pwd || return $? sudo arch-chroot /mnt mkinitcpio -P || return $? - # in: TARGET_BLOCK_DEVICE, LUKS_PART_UUID - bootloader || return $? + # in: TARGET_BLOCK_DEVICE, FDE, LUKS_PART_UUID + bootloader || return $? - if [ "${LEAVE_MOUNTED}" -eq '1' ]; then + if [ "${LEAVE_MOUNTED}" = 'true' ]; then echo 'Leaving partitions below /mnt mounted and '"${DATA_PART}"' opened.' else sudo umount -R /mnt || return $? - sudo cryptsetup luksClose "$(basename "${DATA_PART}")" || return $? + if [ "${FDE}" = 'true' ] ; then + sudo cryptsetup luksClose "$(basename "${DATA_PART}")" || return $? + fi fi echo 'Finished installation without errors!' } @@ -99,12 +101,13 @@ function increase_cow_space() { function get_user_input() { # @post - # BOOT_FIRMWARE (uefi or bios) - # FS (BTRFS, EXT4, F2FS) - # FS_BTRFS_SUBVOL_LAYOUT (root_only, @root@home) + # BOOT_FIRMWARE: 'uefi' | 'bios' + # FS: 'BTRFS' | 'EXT4' | 'F2FS' + # FS_BTRFS_SUBVOL_LAYOUT: 'root_only' | '@root@home' # HOSTNAME # USERNAME, USER_PWD - # LUKS_PWD + # FDE: 'true' | 'false' + # LUKS_PWD: only set if FDE='true' get_block_devices_with_size || return $? single_choice_if_empty TARGET_BLOCK_DEVICE 'Select target device for installation' BLOCK_DEVICE_SIZES || return $? @@ -151,7 +154,11 @@ function get_user_input() { exit 1; } fi - if [ -z "${LUKS_PWD}" ]; then + + TMP1=('true' 'Yes' 'false' 'No') + single_choice_if_empty FDE 'Shall Full-Disk-Encryption be enabled?' TMP1 || return $? + + if [ "${FDE}" = 'true' ] && [ -z "${LUKS_PWD}" ]; then ask_user_if_empty LUKS_PWD 'Enter a disk encryption password:' || return $? ask_user_if_empty LUKS_PWD2 'Please enter the password again:' || return $? # shellcheck disable=SC2153 @@ -277,6 +284,7 @@ function mount_partitions() { function run_pacstrap() { # @pre # BOOT_FIRMWARE + # PACSTRAP_INTERACTIVE: optional, 'true' echo 'Running pacstrap ...' PKGS=("${ADDITIONAL_PKGS[@]}") @@ -315,7 +323,7 @@ function run_pacstrap() { fi local args=() - if [ "${PACSTRAP_INTERACTIVE}" = '1' ]; then + if [ "${PACSTRAP_INTERACTIVE}" = 'true' ]; then args+=('-i') # run interactively fi args+=('/mnt') @@ -359,9 +367,9 @@ function run_genfstab() { function config_hostname_and_hosts() { # @pre # HOSTNAME - # FQDN (optional, e.g. sub.domain.de) - # STATIC_IP (optional, e.g. 93.133.433.133) - # IPV6_CAPABLE (optional, e.g. 1) + # FQDN: optional, e.g. sub.domain.de + # STATIC_IP: optional, e.g. 93.133.433.133 + # IPV6_CAPABLE: optional, 'true' echo 'Set hostname ...' echo "${HOSTNAME}" | sudo tee /mnt/etc/hostname >/dev/null || return $? @@ -383,7 +391,7 @@ function config_hostname_and_hosts() { # 127.0.1.1 is often used for the FQDN of the machine '"${STATIC_IP} ${FQDN} ${HOSTNAME}" | sudo tee /mnt/etc/hosts >/dev/null || return $? - if [ "${IPV6_CAPABLE}" = '1' ]; then + if [ "${IPV6_CAPABLE}" = 'true' ]; then echo ' # The following lines are desirable for IPv6 capable hosts ::1 localhost ip6-localhost ip6-loopback @@ -414,7 +422,8 @@ function user_and_pwd() { function bootloader() { # @pre # TARGET_BLOCK_DEVICE - # LUKS_PART_UUID + # FDE: 'true' | 'false' + # LUKS_PART_UUID: required if FDE='true' echo 'Installing grub ...' case "${BOOT_FIRMWARE}" in @@ -435,23 +444,35 @@ function bootloader() { echo 'Generating /boot/grub/grub.cfg ...' { - # /etc/default/grub is managed by Holo. Therefore we should not manually modify it. - # Instead, we create a holosript which writes $LUKS_PART_UUID into GRUB_CMDLINE_LINUX of /etc/default/grub - { - # Assert - grep --quiet '^GRUB_CMDLINE_LINUX=""$' < /mnt/etc/default/grub || return + case "${FDE}" in + true) + # /etc/default/grub is managed by Holo. Therefore we should not manually modify it. + # Instead, we create a holosript which writes $LUKS_PART_UUID into GRUB_CMDLINE_LINUX of /etc/default/grub + { + # Assert + grep --quiet '^GRUB_CMDLINE_LINUX=""$' < /mnt/etc/default/grub || return - # Use filename .../20- for the holoscript so that it gets executed after the one from de-p1st-grub - local holoScriptDir=/mnt/usr/share/holo/files/20-de-p1st-installer/etc/default/ - # The holoscript shall contain one 'sed "..."' command - sudo mkdir -p "${holoScriptDir}" || return $? - sudo echo '#!/bin/sh + # Use filename .../20- for the holoscript so that it gets executed after the one from de-p1st-grub + local holoScriptDir=/mnt/usr/share/holo/files/20-de-p1st-installer/etc/default/ + # The holoscript shall contain one 'sed "..."' command + sudo mkdir -p "${holoScriptDir}" || return $? + sudo echo '#!/bin/sh sed "s|^GRUB_CMDLINE_LINUX=\"\"\$|GRUB_CMDLINE_LINUX=\"cryptdevice=/dev/disk/by-uuid/'"${LUKS_PART_UUID}"':crypt\"|"' \ - | sudo tee "${holoScriptDir}"/grub.holoscript || return $? - sudo chmod 0544 "${holoScriptDir}"/grub.holoscript || return $? - } - # Then we apply the holoscript - sudo arch-chroot /mnt holo apply --force file:/etc/default/grub || return $? + | sudo tee "${holoScriptDir}"/grub.holoscript || return $? + sudo chmod 0544 "${holoScriptDir}"/grub.holoscript || return $? + } + # Then we apply the holoscript + sudo arch-chroot /mnt holo apply --force file:/etc/default/grub || return $? + ;; + false) + true + ;; + *) + echo 'Invalid option: '"${FDE}" + return 1 + ;; + esac + # And finally run grub-mkconfig sudo arch-chroot /mnt grub-mkconfig -o /boot/grub/grub.cfg || return $? } diff --git a/pkg/de-p1st-installer/example-headless-docker.cfg b/pkg/de-p1st-installer/example-headless-docker.cfg index 12fa821..997648a 100644 --- a/pkg/de-p1st-installer/example-headless-docker.cfg +++ b/pkg/de-p1st-installer/example-headless-docker.cfg @@ -2,7 +2,7 @@ FQDN=v2202012136854137045.happysrv.de STATIC_IP=45.83.105.88 -IPV6_CAPABLE=1 +IPV6_CAPABLE=true HOSTNAME=p1st-arch-1 USERNAME=yoda @@ -16,9 +16,9 @@ BOOT_FIRMWARE=uefi # If set to "1", then the data, boot and luks partitions # will be left mounted/opened after installation -LEAVE_MOUNTED=0 +LEAVE_MOUNTED=false -PACSTRAP_INTERACTIVE=1 +PACSTRAP_INTERACTIVE=true ADDITIONAL_PKGS=() # to skip pacman selections diff --git a/pkg/de-p1st-installer/example-vbox.cfg b/pkg/de-p1st-installer/example-vbox.cfg index 36fd2d2..10d646d 100644 --- a/pkg/de-p1st-installer/example-vbox.cfg +++ b/pkg/de-p1st-installer/example-vbox.cfg @@ -2,35 +2,36 @@ # FQDN=domain.name.of.this.host.de # STATIC_IP=123.123.123.123 -# IPV6_CAPABLE=1 -HOSTNAME='yodaTest' -USERNAME='yoda' +# IPV6_CAPABLE=true +HOSTNAME=yodaTest +USERNAME=yoda # One should rather enter these interactively than saving in this cfg. USER_PWD='test' +FDE=true # enable FULL-DISK-ENCRYPTION LUKS_PWD='test' # If unset, then USER_PWD will be used for ROOT_PWD # ROOT_PWD=test -TARGET_BLOCK_DEVICE='/dev/sda' # /dev/vda for Virtual Machine Manager -BOOT_PART_SIZE='500' # MiB -FS='BTRFS' +TARGET_BLOCK_DEVICE=/dev/sda # /dev/vda for Virtual Machine Manager +BOOT_PART_SIZE=500 # MiB +FS=BTRFS FS_BTRFS_SUBVOL_LAYOUT='@root@home' # Subvolume layout that is supported by Timeshift FS_ADDITIONAL_MOUNT_OPTIONS=('noatime') # If not booted into the target system, these values should be set: # CPU_VENDOR: "autodetect", "amd", "intel" or "none" -CPU_VENDOR='autodetect' +CPU_VENDOR=autodetect # BOOT_FIRMWARE: "autodetect", "uefi" or "bios" -BOOT_FIRMWARE='uefi' +BOOT_FIRMWARE=uefi # If set to "1", then the data, boot and luks partitions # will be left mounted/opened for manual inspection # after the installation -LEAVE_MOUNTED='1' +LEAVE_MOUNTED=true -PACSTRAP_INTERACTIVE='1' +PACSTRAP_INTERACTIVE=true ############## ADDITIONAL_PKGS from here on ############## ADDITIONAL_PKGS=() diff --git a/pkg/de-p1st-installer/lib/block-device.sh b/pkg/de-p1st-installer/lib/block-device.sh index a981b67..31e5b91 100644 --- a/pkg/de-p1st-installer/lib/block-device.sh +++ b/pkg/de-p1st-installer/lib/block-device.sh @@ -51,6 +51,10 @@ function get_block_devices_with_size() { function partition() { + # Creates two partitions: + # - BOOT_PART by default 261mb + # - LUKS_PART rest of the device for (encrypted) data + # # @pre # TARGET_BLOCK_DEVICE # BOOT_FIRMWARE @@ -111,17 +115,23 @@ function partition() { } function format() { + # Formats BOOT_PART and LUKS_PART. + # If encryption is enabled (FDE='true'), then an encrypted partition will be created at LUKS_PART + # which can be accessed under DATA_PART. + # If encryption is disabled, then DATA_PART is identical to LUKS_PART. + # # @pre # BOOT_FIRMWARE # BOOT_PART # LUKS_PART # LUKS_PWD + # FDE: 'true' | 'false' # FS # @post - # LUKS_PART_UUID - # DATA_PART (variable set with value /dev/mapper/$(basename "${LUKS_PART}") + # LUKS_PART_UUID: only set if FDE='true' + # DATA_PART: if FDE='true', then set to /dev/mapper/$(basename "${LUKS_PART}") # boot partition formatted - # luks partition formatted and opened at DATA_PART + # luks partition formatted and accessible under DATA_PART echo 'Wiping old signatures from partitions ...' sudo wipefs "${BOOT_PART}" || return $? @@ -130,22 +140,33 @@ function format() { echo 'Formatting boot partition '"${BOOT_PART}"' ...' sudo mkfs.fat -F32 "${BOOT_PART}" || return $? - # Note: - # FDE: GRUB does support LUKS2 since this commit: https://git.savannah.gnu.org/cgit/grub.git/commit/?id=365e0cc3e7e44151c14dd29514c2f870b49f9755 - # -> Using "--type luks1" is no longer required. - echo 'Creating encrypted luks partition '"${LUKS_PART}"' ...' - printf '%s' "${LUKS_PWD}" | sudo cryptsetup luksFormat \ - --cipher aes-xts-plain64 --key-size 512 --hash sha512 \ - --iter-time 10000 --use-random "${LUKS_PART}" || return $? + case "${FDE}" in + true) + # Note: + # FDE: GRUB does support LUKS2 since this commit: https://git.savannah.gnu.org/cgit/grub.git/commit/?id=365e0cc3e7e44151c14dd29514c2f870b49f9755 + # -> Using "--type luks1" is no longer required. + echo 'Creating encrypted luks partition '"${LUKS_PART}"' ...' + printf '%s' "${LUKS_PWD}" | sudo cryptsetup luksFormat \ + --cipher aes-xts-plain64 --key-size 512 --hash sha512 \ + --iter-time 10000 --use-random "${LUKS_PART}" || return $? - get_uuid "${LUKS_PART}" LUKS_PART_UUID || return $? + get_uuid "${LUKS_PART}" LUKS_PART_UUID || return $? - local luks_name - luks_name=$(basename "${LUKS_PART}") - DATA_PART="/dev/mapper/${luks_name}" + local luks_name + luks_name=$(basename "${LUKS_PART}") + DATA_PART="/dev/mapper/${luks_name}" - # open luks partition - printf '%s' "${LUKS_PWD}" | sudo cryptsetup luksOpen "${LUKS_PART}" "${luks_name}" || return $? + # open luks partition + printf '%s' "${LUKS_PWD}" | sudo cryptsetup luksOpen "${LUKS_PART}" "${luks_name}" || return $? + ;; + false) + DATA_PART="${LUKS_PART}" + ;; + *) + echo 'Invalid option: '"${FDE}" + return 1 + ;; + esac echo 'Formatting the data partition '"${DATA_PART}"' ...' case "${FS}" in