+++ /dev/null
-SUBSYSTEM=="backlight", ACTION=="add", \
- RUN+="/bin/chgrp video $sys$devpath/brightness", \
- RUN+="/bin/chmod g+w $sys$devpath/brightness"
+++ /dev/null
-set -Ceu
-SCRIPT_NAME=$0
-cd "$(dirname "${SCRIPT_NAME}")"
-
-# constants unlikely to change
-FNAME_PROFILE=.profile
-NAME_DEV=dev
-PATH_DEV="/${NAME_DEV}"
-PATH_MNT=/mnt
-TO_RBIND="${NAME_DEV} proc sys"
-
-# constants we might want to change at some point
-NAME_DATA=data
-NAME_LUKSVG=cryptolvm
-NAME_SWAP=swap
-PATH_MNT_ROOT="${PATH_MNT}/root"
-
-# constants derived from changeables
-PATH_PROFILE="${HOME}/${FNAME_PROFILE}"
-
-# path constructors
-path_luks_mapper() {
- printf '%s/mapper/%s' "${PATH_DEV}" "$1"
-}
-path_vg() {
- printf '%s/%s' "${PATH_DEV}" "$1"
-}
-
-# helpers: logging, testing, failing basics
-msg_nonl() {
- printf '[## %s ##] ' "${SCRIPT_NAME}"
- # shellcheck disable=SC2059
- # (assume we'll always pass a literal format string)
- printf -- "$@"
-}
-msg() {
- msg_nonl "$@"
- printf '\n'
-}
-die() {
- msg '%s' "$*" >&2
- exit 1
-}
-error() {
- die "error: $*"
-}
-try_quiet() {
- "$@" >/dev/null 2>&1
-}
-
-# helpers: more involved testing
-check_tools() {
- for CMD in "$@"; do
- try_quiet command -v "${CMD}"\
- || error "required tool not found: ${CMD}"
- done
-}
-check_input_partition_mountable() {
- local PARTITION=$1
- [ -b "${PARTITION}" ]\
- || error "${PARTITION} is not a block device"
- try_quiet findmnt --source "${PARTITION}"\
- && error "${PARTITION} is already mounted"
- true
-}
-check_new_luksvg() {
- local PATH_LUKS_MAPPER
- PATH_LUKS_MAPPER=$(path_luks_mapper "${NAME_LUKSVG}")
- try_quiet vgs "${NAME_LUKSVG}"\
- && error "volume group '${NAME_LUKSVG}' already exists"
- [ -e "${PATH_LUKS_MAPPER}" ]\
- && error "${PATH_LUKS_MAPPER} already exists"
- true
-}
-check_input_openable_luksvg() {
- local PARTITION=$1
- check_new_luksvg
- try_quiet cryptsetup isLuks "${PARTITION}"\
- || error "${PARTITION} not a LUKS container"
-}
-
-# helpers: luks open/close
-open_luksvg() {
- local PARTITION=$1
- msg 'Opening LUKS container as "%s" …' "${NAME_LUKSVG}"
- cryptsetup luksOpen "${PARTITION}" "${NAME_LUKSVG}"
-}
-close_luksvg() {
- msg 'Deactivating volume group and closing LUKS container …'
- vgchange -an "${NAME_LUKSVG}"
- cryptsetup luksClose "${NAME_LUKSVG}"
-}
-
-# helpers: mount/unmount root
-mount_privately() {
- local TO_MOUNT=$1
- local DEST=$2
- # to facilitate later unmounting of the chrooted system: isolate our mounts
- # against propagation to services sandboxed with PrivateMounts=yes (e.g.
- # systemd-udevd), into whose private namespaces our later umount might fail
- # to reach for closing their references e.g. into what we'll want to
- # vgchange -an, only to be blocked by referenced devices claimed as "busy"
- msg "Privatize script's process' mount namespace …"
- mount --make-rprivate /
-
- # mount and install base
- msg 'Mounting %s at %s …' "${TO_MOUNT}" "${DEST}"
- mkdir -p "${DEST}"
- mount "${TO_MOUNT}" "${DEST}"
-}
-await_path() {
- local TO_AWAIT=$1
- msg_nonl 'Waiting for %s to appear …' "${TO_AWAIT}"
- while [ ! -e "${TO_AWAIT}" ]; do
- printf " …"
- sleep 0.5
- done
- printf ' there it is!\n'
-}
-rbind_mnt() {
- for NAME in ${TO_RBIND}; do
- local PATH_NAME="/${NAME}"
- local SLAVE="${PATH_MNT_ROOT}${PATH_NAME}"
- msg 'For working chroot also mounting %s into there …' "${PATH_NAME}"
- mount --rbind "${PATH_NAME}" "${SLAVE}"
- mount --make-rslave "${SLAVE}"
- done
-}
-unmount_unrbind() {
- msg 'Unmounting chroot environment …'
- for NAME in ${TO_RBIND}; do
- umount -R "${PATH_MNT_ROOT}/${NAME}"
- done
- umount "${PATH_MNT_ROOT}"
-}
-
-# helpers: miscellaneous
-chroot_sh() {
- LANG=C.UTF-8 chroot "${PATH_MNT_ROOT}" /bin/sh -c "$@"
-}
-create_lv() {
- local VG=$1
- local LV=$2
- local SIZE=$3
- msg 'Creating logical volume "%s" inside volume group …' "${LV}"
- lvcreate -L "${SIZE}" -n "${LV}" "${VG}"
-}
-usage() {
- local COUNT_INPUTS=$1
- shift
- local MSG="usage: ${SCRIPT_NAME}"
- for PARAMETER in "$@"; do
- MSG="${MSG} <${PARAMETER}>"
- done
- [ "${COUNT_INPUTS}" -eq $# ]\
- || die "${MSG}"
-}
-augment_profile() {
- msg 'Augmenting user %s …' "${FNAME_PROFILE}"
- echo 'alias ls="ls --color=auto"' >> "${PATH_PROFILE}"
-}
+++ /dev/null
-#!/bin/sh
-. "$(dirname "$0")/_lib.sh"
-
-# inputs to confirm
-usage $# "partition" "root-name" "command"
-PARTITION=$1
-NAME_ROOT=$2
-COMMAND=$3
-
-# constants derived from changeables
-PATH_VG_ROOT=$(path_vg "${NAME_LUKSVG}")/${NAME_ROOT}
-
-# sanity checks
-check_tools cryptsetup vgchange vgs
-check_input_partition_mountable "${PARTITION}"
-check_input_openable_luksvg "${PARTITION}"
-
-# mount
-open_luksvg "${PARTITION}"
-await_path "${PATH_VG_ROOT}"
-mount_privately "${PATH_VG_ROOT}" "${PATH_MNT_ROOT}"
-rbind_mnt
-
-# enact command
-RC=0
-chroot_sh "${COMMAND}" || RC=$?
-
-# clean up mounts
-unmount_unrbind
-close_luksvg
-msg 'Finished! (command exit status: %s)' "${RC}"
-exit "${RC}"
+++ /dev/null
-#!/bin/sh
-. "$(dirname "$0")/_lib.sh"
-
-# constants unlikely to change
-FNAME_INITRD=initrd.img
-FNAME_NM_CONN=wifi.nmconnection
-FNAME_VMLINUZ=vmlinuz
-PATH_CRYPTTAB=/etc/crypttab
-PATH_EFI=/boot/efi
-PATH_FSTAB=/etc/fstab
-PATH_INTERFACES=/etc/network/interfaces
-PATH_NM_CONNECTIONS=/etc/NetworkManager/system-connections
-
-# constants we might want to change at some point
-DEB_SUITE=trixie
-IDX_BOOT_PARTITION=1
-PATH_BOOT_DEVICE="${PATH_DEV}/nvme0n1"
-
-# inputs to confirm
-usage $# "partition" "boot-name"
-PARTITION=$1
-NAME_BOOT=$2
-NAME_ROOT="${NAME_BOOT}"
-
-# constants derived from changeables
-PATH_EFI_NAME_BOOT="${PATH_EFI}/${NAME_BOOT}"
-PATH_MNT_APT_SOURCES="${PATH_MNT_ROOT}/etc/apt/sources.list"
-PATH_MNT_CRYPTTAB="${PATH_MNT_ROOT}${PATH_CRYPTTAB}"
-PATH_MNT_FSTAB="${PATH_MNT_ROOT}${PATH_FSTAB}"
-PATH_MNT_NM_CONN="${PATH_MNT_ROOT}${PATH_NM_CONNECTIONS}/${FNAME_NM_CONN}"
-PATH_MNT_NM_CONNECTIONS="${PATH_MNT_ROOT}${PATH_NM_CONNECTIONS}"
-PATH_VG=$(path_vg "${NAME_LUKSVG}")
-PATH_VG_DATA=${PATH_VG}/${NAME_DATA}
-PATH_VG_ROOT=${PATH_VG}/${NAME_ROOT}
-PATH_VG_SWAP=${PATH_VG}/${NAME_SWAP}
-
-# sanity checks
-check_tools cryptsetup debootstrap efibootmgr lvcreate mkfs.ext4 vgchange vgs
-check_input_partition_mountable "${PARTITION}"
-check_input_openable_luksvg "${PARTITION}"
-case "${NAME_BOOT}" in *[!A-Za-z0-9_.-]*|"")
- error "illegal characters in boot label '${NAME_BOOT}'" ;;
-esac
-[ -e "${PATH_EFI}/${NAME_BOOT}" ]\
- && error "${PATH_EFI}/${NAME_BOOT} already exists"
-efibootmgr \
- | sed -n 's/^Boot[0-9A-Fa-f]\{4\}[* ] //p' \
- | awk '{print $1}' \
- | grep -Fxq "${NAME_BOOT}"\
- && error "an EFI boot entry named '${NAME_BOOT}' already exists"
-
-# run inputs by user and ask for confirmation
-msg 'Your installation choices:'
-msg '- target partition: [ %s ]' "${PARTITION}"
-msg '- name for new boot option: [ %s ]' "${NAME_BOOT}"
-
-# set up logival volume and filesystem
-open_luksvg "${PARTITION}"
-create_lv "${NAME_LUKSVG}" "${NAME_ROOT}" 10G
-await_path "${PATH_VG_ROOT}"
-msg 'Creating EXT4 filesystem …'
-mkfs.ext4 -q "${PATH_VG_ROOT}"
-
-# mount and install base
-mount_privately "${PATH_VG_ROOT}" "${PATH_MNT_ROOT}"
-msg 'Installing Debian Suite "%s" there via debootstrap …' "${DEB_SUITE}"
-debootstrap "${DEB_SUITE}" "${PATH_MNT_ROOT}"
-rbind_mnt
-
-# set up minimal fstab
-msg 'Writing fstab …'
-cat <<EOF >| "${PATH_MNT_FSTAB}"
-${PATH_VG_ROOT} / ext4 errors=remount-ro 0 1
-${PATH_VG_DATA} /${NAME_DATA} ext4 errors=remount-ro 0 2
-${PATH_VG_SWAP} none swap sw 0 0
-EOF
-
-# set up crypttab
-msg 'Writing crypttab …'
-printf '%s UUID=%s none luks\n' \
- "${NAME_LUKSVG}" "$(cryptsetup luksUUID "${PARTITION}")" \
- >| "${PATH_MNT_CRYPTTAB}"
-
-# enable non-free-firmware component for firmware-iwlwifi below (as debootstrap
-# only enables "main" by default)
-msg 'Enabling non-free-firmware component in target sources.list …'
-sed -i 's/ main$/ main non-free-firmware/' "${PATH_MNT_APT_SOURCES}"
-
-# set up kernel, initrd etc.
-msg 'Into chroot environment installing LVM tools, kernel, initrd etc. …'
-chroot_sh "apt-get -qq update"
-chroot_sh \
- "DEBIAN_FRONTEND=noninteractive apt-get -qq install -y \
- linux-image-amd64 \
- cryptsetup cryptsetup-initramfs lvm2 \
- firmware-iwlwifi network-manager wpasupplicant"
-
-# pre-seed known wifi network into NetworkManager
-msg 'Extracting wifi credentials from %s …' "${PATH_INTERFACES}"
-NAME_WIFI_SSID=$(sed -n 's/^[[:space:]]*wpa-ssid[[:space:]]*//p' \
- "${PATH_INTERFACES}" | sed 's/[[:space:]]*$//')
-NAME_WIFI_PSK=$(sed -n 's/^[[:space:]]*wpa-psk[[:space:]]*//p' \
- "${PATH_INTERFACES}" | sed 's/[[:space:]]*$//')
-if [ -z "${NAME_WIFI_SSID}" ] || [ -z "${NAME_WIFI_PSK}" ]; then
- error "could not extract wifi SSID/PSK from ${PATH_INTERFACES}"
-fi
-msg 'Writing NetworkManager connection profile for "%s" …' \
- "${NAME_WIFI_SSID}"
-mkdir -p "${PATH_MNT_NM_CONNECTIONS}"
-chmod 700 "${PATH_MNT_NM_CONNECTIONS}"
-cat <<EOF >| "${PATH_MNT_NM_CONN}"
-[connection]
-id=${NAME_WIFI_SSID}
-uuid=$(cat /proc/sys/kernel/random/uuid)
-type=wifi
-
-[wifi]
-mode=infrastructure
-ssid=${NAME_WIFI_SSID}
-
-[wifi-security]
-key-mgmt=wpa-psk
-psk=${NAME_WIFI_PSK}
-
-[ipv4]
-method=auto
-
-[ipv6]
-method=auto
-EOF
-chmod 600 "${PATH_MNT_NM_CONN}"
-
-# install kernel and initrd into EFI tree/vars
-msg 'EFI setup: copying kernel and initrd into %s …' "${PATH_EFI_NAME_BOOT}"
-mkdir "${PATH_EFI_NAME_BOOT}"
-for FILENAME in "${FNAME_INITRD}" "${FNAME_VMLINUZ}"; do
- cp "${PATH_MNT_ROOT}/${FILENAME}" "${PATH_EFI_NAME_BOOT}/"
-done
-msg 'EFI setup: adding boot entry %s …' "${NAME_BOOT}"
-efibootmgr \
- --create \
- --quiet \
- --disk "${PATH_BOOT_DEVICE}" \
- --part "${IDX_BOOT_PARTITION}" \
- --label "${NAME_BOOT}" \
- --loader "${NAME_BOOT}/${FNAME_VMLINUZ}" \
- --unicode "root=${PATH_VG_ROOT} ro initrd=${NAME_BOOT}\\${FNAME_INITRD}"
-
-# ask root login at latest possible moment, so that on fails: less left undone
-msg 'Setting up root login …'
-chroot_sh "passwd"
-
-# clean up mounts
-unmount_unrbind
-close_luksvg
-msg 'Finished!'
+++ /dev/null
-#!/bin/sh
-. "$(dirname "$0")/_lib.sh"
-
-# inputs to confirm
-usage $# "partition"
-PARTITION=$1
-
-# constants derived from changeables
-PATH_LUKS_MAPPER=$(path_luks_mapper "${NAME_LUKSVG}")
-PATH_MNT_DATA="${PATH_MNT}/${NAME_DATA}"
-PATH_VG=$(path_vg "${NAME_LUKSVG}")
-PATH_VG_DATA=${PATH_VG}/${NAME_DATA}
-PATH_VG_SWAP=${PATH_VG}/${NAME_SWAP}
-
-# sanity checks
-check_tools cryptsetup lvcreate mkfs.ext4 mkswap vgchange vgcreate vgs
-check_input_partition_mountable "${PARTITION}"
-check_new_luksvg
-try_quiet cryptsetup isLuks "${PARTITION}"\
- && error "${PARTITION} is already a LUKS container"
-
-# run inputs by user and ask for confirmation
-msg 'Your target partition (WILL BE ERASED!): [ %s ]' "${PARTITION}"
-msg_nonl 'To continue, type "YES!" (all caps, exclamation mark, no quotes): '
-read -r CONFIRM; [ "${CONFIRM}" = 'YES!' ]\
- || die 'ABORTED: expected confirmation not given.'
-
-# encrypt partition
-msg 'Formatting %s as LUKS container …' "${PARTITION}"
-cryptsetup luksFormat --batch-mode "${PARTITION}"
-open_luksvg "${PARTITION}"
-
-# set up LVM and filesystems
-msg 'Creating volume group "%s" inside LUKS container …' "${NAME_LUKSVG}"
-vgcreate "${NAME_LUKSVG}" "${PATH_LUKS_MAPPER}"
-create_lv "${NAME_LUKSVG}" "${NAME_SWAP}" 64G
-msg 'Configuring as swap area …'
-mkswap "${PATH_VG_SWAP}"
-create_lv "${NAME_LUKSVG}" "${NAME_DATA}" 256G
-msg 'Creating EXT4 filesystem …'
-mkfs.ext4 -q "${PATH_VG_DATA}"
-
-# place repo copy
-mount_privately "${PATH_VG_DATA}" "${PATH_MNT_DATA}"
-msg 'Copying repo …'
-cp -a "$(pwd)" "${PATH_MNT_DATA}"
-
-# clean-up
-msg 'Unmounting …'
-umount "${PATH_MNT_DATA}"
-close_luksvg
-msg 'Finished!'
--- /dev/null
+set -Ceu
+SCRIPT_NAME=$0
+cd "$(dirname "${SCRIPT_NAME}")"
+
+# constants unlikely to change
+FNAME_PROFILE=.profile
+NAME_DEV=dev
+PATH_DEV="/${NAME_DEV}"
+PATH_MNT=/mnt
+TO_RBIND="${NAME_DEV} proc sys"
+
+# constants we might want to change at some point
+NAME_DATA=data
+NAME_LUKSVG=cryptolvm
+NAME_SWAP=swap
+PATH_MNT_ROOT="${PATH_MNT}/root"
+
+# constants derived from changeables
+PATH_PROFILE="${HOME}/${FNAME_PROFILE}"
+PATH_REPO=$(cd .. && pwd)
+
+# path constructors
+path_luks_mapper() {
+ printf '%s/mapper/%s' "${PATH_DEV}" "$1"
+}
+path_vg() {
+ printf '%s/%s' "${PATH_DEV}" "$1"
+}
+
+# helpers: logging, testing, failing basics
+msg_nonl() {
+ printf '[## %s ##] ' "${SCRIPT_NAME}"
+ # shellcheck disable=SC2059
+ # (assume we'll always pass a literal format string)
+ printf -- "$@"
+}
+msg() {
+ msg_nonl "$@"
+ printf '\n'
+}
+die() {
+ msg '%s' "$*" >&2
+ exit 1
+}
+error() {
+ die "error: $*"
+}
+try_quiet() {
+ "$@" >/dev/null 2>&1
+}
+
+# helpers: more involved testing
+check_tools() {
+ for CMD in "$@"; do
+ try_quiet command -v "${CMD}"\
+ || error "required tool not found: ${CMD}"
+ done
+}
+check_input_partition_mountable() {
+ local PARTITION=$1
+ [ -b "${PARTITION}" ]\
+ || error "${PARTITION} is not a block device"
+ try_quiet findmnt --source "${PARTITION}"\
+ && error "${PARTITION} is already mounted"
+ true
+}
+check_new_luksvg() {
+ local PATH_LUKS_MAPPER
+ PATH_LUKS_MAPPER=$(path_luks_mapper "${NAME_LUKSVG}")
+ try_quiet vgs "${NAME_LUKSVG}"\
+ && error "volume group '${NAME_LUKSVG}' already exists"
+ [ -e "${PATH_LUKS_MAPPER}" ]\
+ && error "${PATH_LUKS_MAPPER} already exists"
+ true
+}
+check_input_openable_luksvg() {
+ local PARTITION=$1
+ check_new_luksvg
+ try_quiet cryptsetup isLuks "${PARTITION}"\
+ || error "${PARTITION} not a LUKS container"
+}
+
+# helpers: luks open/close
+open_luksvg() {
+ local PARTITION=$1
+ msg 'Opening LUKS container as "%s" …' "${NAME_LUKSVG}"
+ cryptsetup luksOpen "${PARTITION}" "${NAME_LUKSVG}"
+}
+close_luksvg() {
+ msg 'Deactivating volume group and closing LUKS container …'
+ vgchange -an "${NAME_LUKSVG}"
+ cryptsetup luksClose "${NAME_LUKSVG}"
+}
+
+# helpers: mount/unmount root
+mount_privately() {
+ local TO_MOUNT=$1
+ local DEST=$2
+ # to facilitate later unmounting of the chrooted system: isolate our mounts
+ # against propagation to services sandboxed with PrivateMounts=yes (e.g.
+ # systemd-udevd), into whose private namespaces our later umount might fail
+ # to reach for closing their references e.g. into what we'll want to
+ # vgchange -an, only to be blocked by referenced devices claimed as "busy"
+ msg "Privatize script's process' mount namespace …"
+ mount --make-rprivate /
+
+ # mount and install base
+ msg 'Mounting %s at %s …' "${TO_MOUNT}" "${DEST}"
+ mkdir -p "${DEST}"
+ mount "${TO_MOUNT}" "${DEST}"
+}
+await_path() {
+ local TO_AWAIT=$1
+ msg_nonl 'Waiting for %s to appear …' "${TO_AWAIT}"
+ while [ ! -e "${TO_AWAIT}" ]; do
+ printf " …"
+ sleep 0.5
+ done
+ printf ' there it is!\n'
+}
+rbind_mnt() {
+ for NAME in ${TO_RBIND}; do
+ local PATH_NAME="/${NAME}"
+ local SLAVE="${PATH_MNT_ROOT}${PATH_NAME}"
+ msg 'For working chroot also mounting %s into there …' "${PATH_NAME}"
+ mount --rbind "${PATH_NAME}" "${SLAVE}"
+ mount --make-rslave "${SLAVE}"
+ done
+}
+unmount_unrbind() {
+ msg 'Unmounting chroot environment …'
+ for NAME in ${TO_RBIND}; do
+ umount -R "${PATH_MNT_ROOT}/${NAME}"
+ done
+ umount "${PATH_MNT_ROOT}"
+}
+
+# helpers: miscellaneous
+chroot_sh() {
+ LANG=C.UTF-8 chroot "${PATH_MNT_ROOT}" /bin/sh -c "$@"
+}
+create_lv() {
+ local VG=$1
+ local LV=$2
+ local SIZE=$3
+ msg 'Creating logical volume "%s" inside volume group …' "${LV}"
+ lvcreate -L "${SIZE}" -n "${LV}" "${VG}"
+}
+usage() {
+ local COUNT_INPUTS=$1
+ shift
+ local MSG="usage: ${SCRIPT_NAME}"
+ for PARAMETER in "$@"; do
+ MSG="${MSG} <${PARAMETER}>"
+ done
+ [ "${COUNT_INPUTS}" -eq $# ]\
+ || die "${MSG}"
+}
+augment_profile() {
+ msg 'Augmenting user %s …' "${FNAME_PROFILE}"
+ echo 'alias ls="ls --color=auto"' >> "${PATH_PROFILE}"
+}
--- /dev/null
+#!/bin/sh
+. "$(dirname "$0")/_lib.sh"
+
+# inputs to confirm
+usage $# "partition" "root-name" "command"
+PARTITION=$1
+NAME_ROOT=$2
+COMMAND=$3
+
+# constants derived from changeables
+PATH_VG_ROOT=$(path_vg "${NAME_LUKSVG}")/${NAME_ROOT}
+
+# sanity checks
+check_tools cryptsetup vgchange vgs
+check_input_partition_mountable "${PARTITION}"
+check_input_openable_luksvg "${PARTITION}"
+
+# mount
+open_luksvg "${PARTITION}"
+await_path "${PATH_VG_ROOT}"
+mount_privately "${PATH_VG_ROOT}" "${PATH_MNT_ROOT}"
+rbind_mnt
+
+# enact command
+RC=0
+chroot_sh "${COMMAND}" || RC=$?
+
+# clean up mounts
+unmount_unrbind
+close_luksvg
+msg 'Finished! (command exit status: %s)' "${RC}"
+exit "${RC}"
--- /dev/null
+#!/bin/sh
+. "$(dirname "$0")/_lib.sh"
+
+# constants unlikely to change
+FNAME_INITRD=initrd.img
+FNAME_NM_CONN=wifi.nmconnection
+FNAME_VMLINUZ=vmlinuz
+PATH_CRYPTTAB=/etc/crypttab
+PATH_EFI=/boot/efi
+PATH_FSTAB=/etc/fstab
+PATH_INTERFACES=/etc/network/interfaces
+PATH_NM_CONNECTIONS=/etc/NetworkManager/system-connections
+
+# constants we might want to change at some point
+DEB_SUITE=trixie
+IDX_BOOT_PARTITION=1
+PATH_BOOT_DEVICE="${PATH_DEV}/nvme0n1"
+
+# inputs to confirm
+usage $# "partition" "boot-name"
+PARTITION=$1
+NAME_BOOT=$2
+NAME_ROOT="${NAME_BOOT}"
+
+# constants derived from changeables
+PATH_EFI_NAME_BOOT="${PATH_EFI}/${NAME_BOOT}"
+PATH_MNT_APT_SOURCES="${PATH_MNT_ROOT}/etc/apt/sources.list"
+PATH_MNT_CRYPTTAB="${PATH_MNT_ROOT}${PATH_CRYPTTAB}"
+PATH_MNT_FSTAB="${PATH_MNT_ROOT}${PATH_FSTAB}"
+PATH_MNT_NM_CONN="${PATH_MNT_ROOT}${PATH_NM_CONNECTIONS}/${FNAME_NM_CONN}"
+PATH_MNT_NM_CONNECTIONS="${PATH_MNT_ROOT}${PATH_NM_CONNECTIONS}"
+PATH_VG=$(path_vg "${NAME_LUKSVG}")
+PATH_VG_DATA=${PATH_VG}/${NAME_DATA}
+PATH_VG_ROOT=${PATH_VG}/${NAME_ROOT}
+PATH_VG_SWAP=${PATH_VG}/${NAME_SWAP}
+
+# sanity checks
+check_tools cryptsetup debootstrap efibootmgr lvcreate mkfs.ext4 vgchange vgs
+check_input_partition_mountable "${PARTITION}"
+check_input_openable_luksvg "${PARTITION}"
+case "${NAME_BOOT}" in *[!A-Za-z0-9_.-]*|"")
+ error "illegal characters in boot label '${NAME_BOOT}'" ;;
+esac
+[ -e "${PATH_EFI}/${NAME_BOOT}" ]\
+ && error "${PATH_EFI}/${NAME_BOOT} already exists"
+efibootmgr \
+ | sed -n 's/^Boot[0-9A-Fa-f]\{4\}[* ] //p' \
+ | awk '{print $1}' \
+ | grep -Fxq "${NAME_BOOT}"\
+ && error "an EFI boot entry named '${NAME_BOOT}' already exists"
+
+# run inputs by user and ask for confirmation
+msg 'Your installation choices:'
+msg '- target partition: [ %s ]' "${PARTITION}"
+msg '- name for new boot option: [ %s ]' "${NAME_BOOT}"
+
+# set up logival volume and filesystem
+open_luksvg "${PARTITION}"
+create_lv "${NAME_LUKSVG}" "${NAME_ROOT}" 10G
+await_path "${PATH_VG_ROOT}"
+msg 'Creating EXT4 filesystem …'
+mkfs.ext4 -q "${PATH_VG_ROOT}"
+
+# mount and install base
+mount_privately "${PATH_VG_ROOT}" "${PATH_MNT_ROOT}"
+msg 'Installing Debian Suite "%s" there via debootstrap …' "${DEB_SUITE}"
+debootstrap "${DEB_SUITE}" "${PATH_MNT_ROOT}"
+rbind_mnt
+
+# set up minimal fstab
+msg 'Writing fstab …'
+cat <<EOF >| "${PATH_MNT_FSTAB}"
+${PATH_VG_ROOT} / ext4 errors=remount-ro 0 1
+${PATH_VG_DATA} /${NAME_DATA} ext4 errors=remount-ro 0 2
+${PATH_VG_SWAP} none swap sw 0 0
+EOF
+
+# set up crypttab
+msg 'Writing crypttab …'
+printf '%s UUID=%s none luks\n' \
+ "${NAME_LUKSVG}" "$(cryptsetup luksUUID "${PARTITION}")" \
+ >| "${PATH_MNT_CRYPTTAB}"
+
+# enable non-free-firmware component for firmware-iwlwifi below (as debootstrap
+# only enables "main" by default)
+msg 'Enabling non-free-firmware component in target sources.list …'
+sed -i 's/ main$/ main non-free-firmware/' "${PATH_MNT_APT_SOURCES}"
+
+# set up kernel, initrd etc.
+msg 'Into chroot environment installing LVM tools, kernel, initrd etc. …'
+chroot_sh "apt-get -qq update"
+chroot_sh \
+ "DEBIAN_FRONTEND=noninteractive apt-get -qq install -y \
+ linux-image-amd64 \
+ cryptsetup cryptsetup-initramfs lvm2 \
+ firmware-iwlwifi network-manager wpasupplicant"
+
+# pre-seed known wifi network into NetworkManager
+msg 'Extracting wifi credentials from %s …' "${PATH_INTERFACES}"
+NAME_WIFI_SSID=$(sed -n 's/^[[:space:]]*wpa-ssid[[:space:]]*//p' \
+ "${PATH_INTERFACES}" | sed 's/[[:space:]]*$//')
+NAME_WIFI_PSK=$(sed -n 's/^[[:space:]]*wpa-psk[[:space:]]*//p' \
+ "${PATH_INTERFACES}" | sed 's/[[:space:]]*$//')
+if [ -z "${NAME_WIFI_SSID}" ] || [ -z "${NAME_WIFI_PSK}" ]; then
+ error "could not extract wifi SSID/PSK from ${PATH_INTERFACES}"
+fi
+msg 'Writing NetworkManager connection profile for "%s" …' \
+ "${NAME_WIFI_SSID}"
+mkdir -p "${PATH_MNT_NM_CONNECTIONS}"
+chmod 700 "${PATH_MNT_NM_CONNECTIONS}"
+cat <<EOF >| "${PATH_MNT_NM_CONN}"
+[connection]
+id=${NAME_WIFI_SSID}
+uuid=$(cat /proc/sys/kernel/random/uuid)
+type=wifi
+
+[wifi]
+mode=infrastructure
+ssid=${NAME_WIFI_SSID}
+
+[wifi-security]
+key-mgmt=wpa-psk
+psk=${NAME_WIFI_PSK}
+
+[ipv4]
+method=auto
+
+[ipv6]
+method=auto
+EOF
+chmod 600 "${PATH_MNT_NM_CONN}"
+
+# install kernel and initrd into EFI tree/vars
+msg 'EFI setup: copying kernel and initrd into %s …' "${PATH_EFI_NAME_BOOT}"
+mkdir "${PATH_EFI_NAME_BOOT}"
+for FILENAME in "${FNAME_INITRD}" "${FNAME_VMLINUZ}"; do
+ cp "${PATH_MNT_ROOT}/${FILENAME}" "${PATH_EFI_NAME_BOOT}/"
+done
+msg 'EFI setup: adding boot entry %s …' "${NAME_BOOT}"
+efibootmgr \
+ --create \
+ --quiet \
+ --disk "${PATH_BOOT_DEVICE}" \
+ --part "${IDX_BOOT_PARTITION}" \
+ --label "${NAME_BOOT}" \
+ --loader "${NAME_BOOT}/${FNAME_VMLINUZ}" \
+ --unicode "root=${PATH_VG_ROOT} ro initrd=${NAME_BOOT}\\${FNAME_INITRD}"
+
+# ask root login at latest possible moment, so that on fails: less left undone
+msg 'Setting up root login …'
+chroot_sh "passwd"
+
+# clean up mounts
+unmount_unrbind
+close_luksvg
+msg 'Finished!'
--- /dev/null
+#!/bin/sh
+. "$(dirname "$0")/_lib.sh"
+
+# inputs to confirm
+usage $# "partition"
+PARTITION=$1
+
+# constants derived from changeables
+PATH_LUKS_MAPPER=$(path_luks_mapper "${NAME_LUKSVG}")
+PATH_MNT_DATA="${PATH_MNT}/${NAME_DATA}"
+PATH_VG=$(path_vg "${NAME_LUKSVG}")
+PATH_VG_DATA=${PATH_VG}/${NAME_DATA}
+PATH_VG_SWAP=${PATH_VG}/${NAME_SWAP}
+
+# sanity checks
+check_tools cryptsetup lvcreate mkfs.ext4 mkswap vgchange vgcreate vgs
+check_input_partition_mountable "${PARTITION}"
+check_new_luksvg
+try_quiet cryptsetup isLuks "${PARTITION}"\
+ && error "${PARTITION} is already a LUKS container"
+
+# run inputs by user and ask for confirmation
+msg 'Your target partition (WILL BE ERASED!): [ %s ]' "${PARTITION}"
+msg_nonl 'To continue, type "YES!" (all caps, exclamation mark, no quotes): '
+read -r CONFIRM; [ "${CONFIRM}" = 'YES!' ]\
+ || die 'ABORTED: expected confirmation not given.'
+
+# encrypt partition
+msg 'Formatting %s as LUKS container …' "${PARTITION}"
+cryptsetup luksFormat --batch-mode "${PARTITION}"
+open_luksvg "${PARTITION}"
+
+# set up LVM and filesystems
+msg 'Creating volume group "%s" inside LUKS container …' "${NAME_LUKSVG}"
+vgcreate "${NAME_LUKSVG}" "${PATH_LUKS_MAPPER}"
+create_lv "${NAME_LUKSVG}" "${NAME_SWAP}" 64G
+msg 'Configuring as swap area …'
+mkswap "${PATH_VG_SWAP}"
+create_lv "${NAME_LUKSVG}" "${NAME_DATA}" 256G
+msg 'Creating EXT4 filesystem …'
+mkfs.ext4 -q "${PATH_VG_DATA}"
+
+# place repo copy
+mount_privately "${PATH_VG_DATA}" "${PATH_MNT_DATA}"
+msg 'Copying repo …'
+cp -a "${PATH_REPO}" "${PATH_MNT_DATA}"
+
+# clean-up
+msg 'Unmounting …'
+umount "${PATH_MNT_DATA}"
+close_luksvg
+msg 'Finished!'
--- /dev/null
+#!/bin/sh
+. "$(dirname "$0")/_lib.sh"
+
+# constants unlikely to change
+PATH_DEFAULT_LOCALE=/etc/default/locale
+PATH_SYSCTL_PRINTK=/etc/sysctl.d/60-printk-console.conf
+PATH_TLP_THRESH_CONF=/etc/tlp.conf.d/60-thresholds.conf
+PATH_UDEV_RULES=/etc/udev/rules.d
+
+# constants we might want to change at some point
+FNAME_UDEV_RULES_BACKLIGHT=90-backlight.rules
+LOCALE=C.UTF-8
+TO_INSTALL="ack man-db ntpsec-ntpdate sudo sway tlp vim-gtk3 wmenu xwayland"
+USERNAME=plom
+PRINTK_LEVELS="4 4 1 7"
+TLP_THRESH_START=40
+TLP_THRESH_STOP=80
+
+# constants derived from changeables
+PATH_TO_COPY="${PATH_REPO}/to_copy"
+
+augment_profile
+
+msg 'Ensuring packages: %s' "${TO_INSTALL}"
+apt-get -y update
+apt-get -y install ${TO_INSTALL}
+
+# C.UTF-8 is built into glibc itself (unlike e.g. en_US.UTF-8), so no
+# "locales" package / locale-gen is needed to make it available — writing
+# it here is enough for it to apply system-wide from the next login on.
+msg 'Setting system locale to %s …' "${LOCALE}"
+printf 'LANG=%s\n' "${LOCALE}" >| "${PATH_DEFAULT_LOCALE}"
+
+msg 'Quieting routine kernel messages on the console …'
+printf 'kernel.printk = %s\n' "${PRINTK_LEVELS}" >| "${PATH_SYSCTL_PRINTK}"
+sysctl -p "${PATH_SYSCTL_PRINTK}"
+
+msg 'Setting TLP battery charge thresholds: start %s%%, stop %s%% …' \
+ "${TLP_THRESH_START}" "${TLP_THRESH_STOP}"
+mkdir -p "$(dirname "${PATH_TLP_THRESH_CONF}")"
+printf 'START_CHARGE_THRESH_BAT0=%s\nSTOP_CHARGE_THRESH_BAT0=%s\n' \
+ "${TLP_THRESH_START}" "${TLP_THRESH_STOP}" >| "${PATH_TLP_THRESH_CONF}"
+tlp start
+
+msg 'Making backlight devices available to user-run backlight script …'
+cp "${PATH_TO_COPY}/${FNAME_UDEV_RULES_BACKLIGHT}" "${PATH_UDEV_RULES}/"
+udevadm control --reload-rules
+udevadm trigger --action=add --subsystem-match=backlight
+
+msg 'Setting up user: %s' "${USERNAME}"
+adduser --comment "" "${USERNAME}"
+usermod -a -G sudo,video "${USERNAME}"
+
+msg 'Synchronizing clock …'
+ntpdate-debian
--- /dev/null
+#!/bin/sh
+. "$(dirname "$0")/_lib.sh"
+
+# constants we might want to change at some point
+PATH_SKEL_USER="${PATH_REPO}/home_user"
+
+augment_profile
+
+msg 'Linking %s files into home directory …' "${PATH_SKEL_USER}"
+find "${PATH_SKEL_USER}" -mindepth 1 -maxdepth 1\
+ -exec ln -v -s {} "${HOME}/" \;
+++ /dev/null
-#!/bin/sh
-. "$(dirname "$0")/_lib.sh"
-
-# constants unlikely to change
-PATH_DEFAULT_LOCALE=/etc/default/locale
-PATH_SYSCTL_PRINTK=/etc/sysctl.d/60-printk-console.conf
-PATH_TLP_THRESH_CONF=/etc/tlp.conf.d/60-thresholds.conf
-PATH_UDEV_RULES=/etc/udev/rules.d
-
-# constants we might want to change at some point
-FNAME_UDEV_RULES_BACKLIGHT=90-backlight.rules
-LOCALE=C.UTF-8
-TO_INSTALL="ack man-db ntpsec-ntpdate sudo sway tlp vim-gtk3 wmenu xwayland"
-USERNAME=plom
-PRINTK_LEVELS="4 4 1 7"
-TLP_THRESH_START=40
-TLP_THRESH_STOP=80
-
-augment_profile
-
-msg 'Ensuring packages: %s' "${TO_INSTALL}"
-apt-get -y update
-apt-get -y install ${TO_INSTALL}
-
-# C.UTF-8 is built into glibc itself (unlike e.g. en_US.UTF-8), so no
-# "locales" package / locale-gen is needed to make it available — writing
-# it here is enough for it to apply system-wide from the next login on.
-msg 'Setting system locale to %s …' "${LOCALE}"
-printf 'LANG=%s\n' "${LOCALE}" >| "${PATH_DEFAULT_LOCALE}"
-
-msg 'Quieting routine kernel messages on the console …'
-printf 'kernel.printk = %s\n' "${PRINTK_LEVELS}" >| "${PATH_SYSCTL_PRINTK}"
-sysctl -p "${PATH_SYSCTL_PRINTK}"
-
-msg 'Setting TLP battery charge thresholds: start %s%%, stop %s%% …' \
- "${TLP_THRESH_START}" "${TLP_THRESH_STOP}"
-mkdir -p "$(dirname "${PATH_TLP_THRESH_CONF}")"
-printf 'START_CHARGE_THRESH_BAT0=%s\nSTOP_CHARGE_THRESH_BAT0=%s\n' \
- "${TLP_THRESH_START}" "${TLP_THRESH_STOP}" >| "${PATH_TLP_THRESH_CONF}"
-tlp start
-
-msg 'Making backlight devices available to user-run backlight.py script …'
-cp "${FNAME_UDEV_RULES_BACKLIGHT}" "${PATH_UDEV_RULES}/"
-udevadm control --reload-rules
-udevadm trigger --action=add --subsystem-match=backlight
-
-msg 'Setting up user: %s' "${USERNAME}"
-adduser --comment "" "${USERNAME}"
-usermod -a -G sudo,video "${USERNAME}"
-
-msg 'Synchronizing clock …'
-ntpdate-debian
+++ /dev/null
-#!/bin/sh
-. "$(dirname "$0")/_lib.sh"
-
-# constants we might want to change at some point
-PATH_SKEL_USER="$(pwd)/home_user"
-
-augment_profile
-
-msg 'Linking %s files into home directory …' "${PATH_SKEL_USER}"
-find "${PATH_SKEL_USER}" -mindepth 1 -maxdepth 1\
- -exec ln -v -s {} "${HOME}/" \;
--- /dev/null
+SUBSYSTEM=="backlight", ACTION=="add", \
+ RUN+="/bin/chgrp video $sys$devpath/brightness", \
+ RUN+="/bin/chmod g+w $sys$devpath/brightness"