#!/usr/bin/env bash # Copyright (C) 2023 Umorpha Systems # SPDX-License-Identifier: AGPL-3.0-or-later # Dependencies: # - /usr/bin/env (coreutils, busybox) # - cat (coreutils, busybox) # - dd (coreutils, busybox) # - install (coreutils, busybox) # - mkdir (coreutils, busybox) # - mktemp (coreutils, busybox) # - rm (coreutils, busybox) # - rmdir (coreutils, busybox) # - losetup (optional) (util-linux; the busybox one doesn't work) # - umount (util-linux, busybox) # - blkid (util-linux) # - mount (util-linux) # - bash (bash) # - systemd-repart (systemd) # - lvcreate (lvm2) # - pvcreate (lvm2) # - vgchange (lvm2) # - vgcreate (lvm2) # - pv (pv) # - mkfs.ext4 (e2fsprogs) # - mkfs.vfat (dosfstools) # - arch-chroot (arch-install-scripts) # # Dependencies of arch-chroot (as of v28): # - cat (coreutils, busybox) # - install (coreutils, busybox) # - ln (coreutils, busybox) # - touch (coreutils, busybox) # - chroot (coreutils; the busybox one doesn't work) # - readlink (coreutils; the busybox one doesn't work) # - mountpoint (util-linux, busybox) # - umount (util-linux, busybox) # - unshare (util-linux, busybox) # - mount (util-linux) # - grep (grep, busybox) # - bash (bash) # # Of those, these are the ones that aren't already in an initcpio: # - arch-chroot (arch-install-scripts) # - bash (bash) # - chroot (coreutils) # - readlink (coreutils) # - pv (pv) # - systemd-repart (systemd) # - mkfs.ext4 (e2fsprogs) # - mkfs.vfat (dosfstools) # - pvcreate (lvm2) # - vgchange (lvm2) # - vgcreate (lvm2) # - lvcreate (lvm2) set -euE -o pipefail v() { printf ' $ %s\n' "${*@Q}" "$@" } main() { local device rootfs rootfs=$1 device=$2 echo ":: Installing '${rootfs}' to '${device}'" cleanup=() #trap 'for (( i=${#cleanup[@]}-1; i >= 0; i-- )); do eval "${cleanup[$i]}"; done' EXIT local tmpdir tmpdir="$(mktemp -dt "${0##*/}.XXXXXXXXXX")" cleanup+="rmdir -- ${tmpdir@Q}" ######################################################################## local is_loop=false if [[ -f "$device" ]]; then echo " file '${device}' is not a block device, setting up a loopback device..." device=$(v losetup --find --show --partscan -- "$device") echo " ... '${device}'" cleanup+=("v losetup --detach ${device@Q}") is_loop=true fi local devicep="$device" if [[ "$devicep" == *[0-9] ]]; then devicep+='p' fi v vgchange --activate=n vg_umorpha || true ######################################################################## echo ":: Setting up GPT" #dd if=/dev/zero of="$device" bs=512 count=4 cat >"$tmpdir/00-esp.conf" <<-EOF [Partition] Type=esp Format=vfat Label=Umorpha EFI System Partition SizeMinBytes=512M SizeMaxBytes=512M EOF cat >"$tmpdir/10-lvm.conf" <<-EOF [Partition] # https://en.wikipedia.org/w/index.php?title=User_talk:Claunia&diff=prev&oldid=1182832243 Type=E6D6D379-F507-44C2-A23C-238F2A3DF928 Label=Umorpha LVM Partition EOF v systemd-repart \ --empty=allow --dry-run=no \ --no-pager \ --definitions="$tmpdir" \ "$device" rm -- "$tmpdir"/*.conf ######################################################################## echo ":: Setting up LVM" v pvcreate "${devicep}2" v vgcreate vg_umorpha "${devicep}2" if $is_loop; then cleanup+=("v vgchange --activate=n vg_umorpha") fi # Use short `-c` instead of `--format` so this works with busybox. v lvcreate --name=lv_root_a --size="$(stat -c '%s' -- "$rootfs")b" vg_umorpha v pv -- "$rootfs" >/dev/mapper/vg_umorpha-lv_root_a v lvcreate --name=lv_root_overlay --size=1G vg_umorpha v mkfs.ext4 /dev/mapper/vg_umorpha-lv_root_overlay ######################################################################## echo ":: Configuring boot" local selector_boot selector_root selector_overlay selector_boot="$( blkid --output=export "${devicep}1" | grep ^UUID=)" selector_root="$( blkid --output=export /dev/mapper/vg_umorpha-lv_root_a | grep ^UUID=)" selector_overlay="$(blkid --output=export /dev/mapper/vg_umorpha-lv_root_overlay | grep ^UUID=)" v declare -p selector_boot selector_root selector_overlay mkdir "$tmpdir/root" cleanup+=("rmdir -- ${tmpdir@Q}/root") v mount -o ro -- /dev/mapper/vg_umorpha-lv_root_a "$tmpdir/root" cleanup+=("v umount ${tmpdir@Q}/root") mkdir "$tmpdir/overlay" cleanup+=("rmdir -- ${tmpdir@Q}/overlay") v mount -- /dev/mapper/vg_umorpha-lv_root_overlay "$tmpdir/overlay" cleanup+=("v umount ${tmpdir@Q}/overlay") mkdir "$tmpdir/mnt" "$tmpdir/overlay/upperdir" "$tmpdir/overlay/workdir" cleanup+=("rmdir -- ${tmpdir@Q}/mnt") v mount -t overlay -o "lowerdir=${tmpdir}/root,upperdir=${tmpdir}/overlay/upperdir,workdir=${tmpdir}/overlay/workdir" umorpha-rootfs \ "${tmpdir}/mnt" cleanup+=("v umount ${tmpdir@Q}/mnt") v mount -- "${devicep}1" "$tmpdir/mnt/boot" cleanup+=("v umount ${tmpdir@Q}/mnt/boot") mkdir -p "$tmpdir/mnt/etc/kernel" echo root=$selector_root overlay_root=$selector_overlay boot=$selector_boot rw >"$tmpdir/mnt/etc/kernel/cmdline" mkdir -p -- "$tmpdir/mnt/boot/EFI/Linux" v arch-chroot -- "$tmpdir/mnt" sh -c "printf '%s\n' usr/lib/modules/*/vmlinuz | /usr/share/libalpm/scripts/mkinitcpio install" v install -D "$tmpdir/mnt/usr/lib/systemd/boot/efi/systemd-bootx64.efi" "$tmpdir/mnt/boot/EFI/BOOT/BOOTX64.EFI" v arch-chroot -- "$tmpdir/mnt" ldconfig v arch-chroot -- "$tmpdir/mnt" systemd-machine-id-setup v arch-chroot -- "$tmpdir/mnt" update-ca-trust } main "$@"