Skip to content

Commit

Permalink
run pacstrap only once, improved style
Browse files Browse the repository at this point in the history
  • Loading branch information
punoko committed Aug 5, 2024
1 parent da70a09 commit 04858b5
Showing 1 changed file with 95 additions and 68 deletions.
163 changes: 95 additions & 68 deletions build.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#!/usr/bin/env bash
set -euo pipefail

MOUNT="$(mktemp --directory)"

HOSTNAME="arch"
KEYMAP="us"
LOCALE="C.UTF-8"
Expand All @@ -12,17 +10,28 @@ IMG_SIZE="2G"
IMG_FILE="image.img"
QCOW_FILE="image.qcow2"

# This setup makes writing fstab unnecessary because :
# - root partition is automatically mounted according to its GPT partition type
# - rootflags including subvol are set with kernel cmdline
# https://uapi-group.org/specifications/specs/discoverable_partitions_specification/

ESP_GPT_TYPE="C12A7328-F81F-11D2-BA4B-00A0C93EC93B" # EFI System
ESP_LABEL="ESP"
ESP_SIZE="100M"
ESP_DIR="efi"
ESP_GPT_TYPE="C12A7328-F81F-11D2-BA4B-00A0C93EC93B" # EFI System

ROOT_LABEL="Arch Linux"
ROOT_GPT_TYPE="4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709" # Linux root (x86-64)
ROOT_LABEL="Arch"
ROOT_SUBVOL="@arch"
ROOT_FLAGS="compress=zstd,noatime,subvol=$ROOT_SUBVOL"
ROOT_GPT_TYPE="4F68BCE3-E8CD-4DB1-96E7-FBCAF984B709" # Linux root (x86-64)

PACKAGES=(
BUILD_DEPENDENCIES+=(
arch-install-scripts
btrfs-progs
dosfstools
qemu-img
util-linux
)
PACKAGES+=(
base
btrfs-progs
cloud-init
Expand All @@ -31,22 +40,20 @@ PACKAGES=(
grml-zsh-config
htop
iptables-nft
# linux
linux
man-db
mkinitcpio
neovim
openssh
pacman-contrib
polkit
reflector
sudo
systemd-ukify
zsh
zsh-autosuggestions
zsh-completions
zsh-syntax-highlighting
)
UNITS_ENABLE=(
UNITS_ENABLE+=(
cloud-init
cloud-init-local
cloud-config
Expand All @@ -62,11 +69,15 @@ UNITS_ENABLE=(
[email protected]
paccache.timer
)
UNITS_DISABLE=(
UNITS_MASK+=(
systemd-homed.service
systemd-nsresourced.socket
systemd-userdbd.socket
)

# Cleanup
MOUNT="$(mktemp --directory)"

# Cleanup trap
cleanup() {
if findmnt --mountpoint "$MOUNT" >/dev/null; then
umount --recursive "$MOUNT"
Expand All @@ -78,80 +89,84 @@ cleanup() {
}
trap cleanup ERR

# Image setup
echo "### DEPENDENCIES" >&2
sed -i 's/^#ParallelDownloads/ParallelDownloads/' "/etc/pacman.conf"
pacman -Syu --needed --noconfirm "${BUILD_DEPENDENCIES[@]}"

echo "### IMAGE SETUP" >&2
rm -f $IMG_FILE
truncate --size $IMG_SIZE $IMG_FILE

# Image format
echo "### PARTITIONING" >&2
# Flag 59 marks the partition for automatic growing of the contained file system
# https://uapi-group.org/specifications/specs/discoverable_partitions_specification/
sfdisk --label gpt $IMG_FILE <<EOF
type=$ESP_GPT_TYPE,name="$ESP_LABEL",size=$ESP_SIZE
type=$ROOT_GPT_TYPE,name="$ROOT_LABEL",attrs=59
EOF

echo "### LOOP DEVICE SETUP" >&2
LOOPDEV=$(losetup --find --partscan --show $IMG_FILE)
PART1="$LOOPDEV"p1
PART2="$LOOPDEV"p2
sleep 1

mkfs.vfat -F 32 -n "$ESP_LABEL" "$LOOPDEV"p1
mkfs.btrfs -L "$ROOT_LABEL" "$LOOPDEV"p2
echo "### FORMATTING" >&2
mkfs.vfat -F 32 -n "$ESP_LABEL" "$PART1"
mkfs.btrfs --label "$ROOT_LABEL" "$PART2"

# Image mount
mount "$LOOPDEV"p2 "$MOUNT"
echo "### MOUNTING" >&2
mount "$PART2" "$MOUNT"
btrfs subvolume create "$MOUNT/$ROOT_SUBVOL"
btrfs subvolume set-default "$MOUNT/$ROOT_SUBVOL"
umount "$MOUNT"
mount -o "$ROOT_FLAGS" "$LOOPDEV"p2 "$MOUNT"
mount --mkdir=700 "$LOOPDEV"p1 "$MOUNT/$ESP_DIR"
mount --options "$ROOT_FLAGS" "$PART2" "$MOUNT"
mount --mkdir=700 "$PART1" "$MOUNT/$ESP_DIR"

# Install
pacstrap -cGM "$MOUNT" "${PACKAGES[@]}"

# Setting fstab is unnecessary for the following reasons:
# root partition is automatically mounted with its GPT partition type
# root partition grows thanks to GPT flag 59 set with sfdisk earlier https://github.com/systemd/systemd/pull/30030
# subvol is implicit from `btrfs subvolume set-default` and set with cmdline anyway
# compress & noatime are set by cmdline
echo "### KERNEL CMDLINE CONFIG" >&2
# Not specifying `rw` in cmdline breaks boot
CMDLINE="rootflags=$ROOT_FLAGS rw"
systemd-firstboot \
--root="$MOUNT" \
--force \
--keymap="$KEYMAP" \
--locale="$LOCALE" \
--hostname="$HOSTNAME" \
--timezone="$TIMEZONE" \
--root-shell=/usr/bin/zsh \
--kernel-command-line="$CMDLINE" \
;
mkdir --parents "$MOUNT/etc/kernel"
cat <<EOF >"$MOUNT/etc/kernel/cmdline"
rootflags=$ROOT_FLAGS rw
EOF

# Bootloader
bootctl install --root "$MOUNT" --no-variables
echo "### INITRD CONFIG" >&2
mkdir --parents "$MOUNT/etc/mkinitcpio.conf.d"
cat <<EOF >"$MOUNT/etc/mkinitcpio.conf.d/custom.conf"
MODULES=(btrfs)
HOOKS=(systemd autodetect microcode modconf keyboard block)
EOF

echo "### UKI CONFIG" >&2
mkdir --parents "$MOUNT/etc/mkinitcpio.d"
mkdir --parents "$MOUNT/$ESP_DIR/EFI/Linux/"
cat <<EOF >"$MOUNT/etc/mkinitcpio.d/linux.preset"
PRESETS=('default')
default_kver="/boot/vmlinuz-linux"
default_uki="/$ESP_DIR/EFI/Linux/arch.efi"
default_options="--splash /usr/share/systemd/bootctl/splash-arch.bmp -S autodetect"
EOF

# Kernel
pacstrap -cGM "$MOUNT" linux
echo "### PACSTRAP" >&2
pacstrap -cGM "$MOUNT" "${PACKAGES[@]}"
sed -i "s/ -S autodetect//" "$MOUNT/etc/mkinitcpio.d/linux.preset"

# https://systemd.io/BUILDING_IMAGES/
rm -f "$MOUNT/etc/machine-id"
rm -f "$MOUNT/var/lib/systemd/random-seed"
rm -f "$MOUNT/$ESP_DIR/loader/random-seed"
echo "### BOOTLOADER INSTALL" >&2
bootctl install --root "$MOUNT" --no-variables

# Use systemd-repart to grow the root partition
mkdir "$MOUNT/etc/repart.d"
cat <<EOF >"$MOUNT/etc/repart.d/root.conf"
[Partition]
Type=root
EOF
echo "### FIRSTBOOT SETTINGS" >&2
systemd-firstboot \
--root="$MOUNT" \
--force \
--keymap="$KEYMAP" \
--locale="$LOCALE" \
--hostname="$HOSTNAME" \
--timezone="$TIMEZONE" \
--root-shell=/usr/bin/zsh \
;

# Basic Network DHCP Setup
echo "### NETWORK SETTINGS" >&2
ln -sf /run/systemd/resolve/stub-resolv.conf "$MOUNT/etc/resolv.conf"
cat <<EOF >"$MOUNT/etc/systemd/network/99-ethernet.network"
[Match]
Name=en*
Expand All @@ -160,8 +175,18 @@ Type=ether
[Network]
DHCP=yes
EOF
ln -sf /run/systemd/resolve/stub-resolv.conf "$MOUNT/etc/resolv.conf"

echo "### CLOUD IMAGE SETTINGS" >&2
# https://systemd.io/BUILDING_IMAGES/
rm -f "$MOUNT/etc/machine-id"
rm -f "$MOUNT/var/lib/systemd/random-seed"
rm -f "$MOUNT/$ESP_DIR/loader/random-seed"
# Use systemd-repart to grow the root partition
mkdir --parents "$MOUNT/etc/repart.d"
cat <<EOF >"$MOUNT/etc/repart.d/root.conf"
[Partition]
Type=root
EOF
# Pacman Keyring Initialization
cat <<EOF >"$MOUNT/etc/systemd/system/pacman-init.service"
[Unit]
Expand All @@ -179,7 +204,6 @@ ExecStart=/usr/bin/pacman-key --populate
[Install]
WantedBy=multi-user.target
EOF

# Cloud Init Settings
cat <<EOF >"$MOUNT/etc/cloud/cloud.cfg.d/custom.cfg"
system_info:
Expand All @@ -195,40 +219,43 @@ disable_root: true
disable_root_opts: "#"
EOF

# Services
systemctl --root="$MOUNT" enable "${UNITS_ENABLE[@]}"
systemctl --root="$MOUNT" disable "${UNITS_DISABLE[@]}"

echo "### MISC SETTINGS" >&2
# Pacman config
sed -i 's/^#Color/Color/' "$MOUNT/etc/pacman.conf"
sed -i 's/^#ParallelDownloads/ParallelDownloads/' "$MOUNT/etc/pacman.conf"
sed -i 's/^#VerbosePkgLists/VerbosePkgLists/' "$MOUNT/etc/pacman.conf"

# Mirror list
cat <<EOF >"$MOUNT/etc/pacman.d/mirrorlist"
Server = https://geo.mirror.pkgbuild.com/\$repo/os/\$arch
EOF

# Disable SSH password and root login
cat <<EOF >"$MOUNT/etc/ssh/sshd_config.d/custom.conf"
PermitRootLogin no
PasswordAuthentication no
EOF

# ZSH plugins
cat <<EOF >>"$MOUNT/etc/zsh/zshrc"
source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
source <(fzf --zsh)
EOF

# Neovim Symlinks
ln -sf /usr/bin/nvim "$MOUNT/usr/local/bin/vim"
ln -sf /usr/bin/nvim "$MOUNT/usr/local/bin/vi"
ln -s /usr/bin/nvim "$MOUNT/usr/local/bin/vim"
ln -s /usr/bin/nvim "$MOUNT/usr/local/bin/vi"

echo "### ENABLE UNITS" >&2
systemctl --root="$MOUNT" enable "${UNITS_ENABLE[@]}"

echo "### MASK UNITS" >&2
systemctl --root="$MOUNT" mask "${UNITS_MASK[@]}"

# Image cleanup
echo "### CLEANUP" >&2
sync -f "$MOUNT/etc/os-release"
fstrim --verbose "$MOUNT/$ESP_DIR"
fstrim --verbose "$MOUNT"
cleanup

echo "### CREATE QCOW2" >&2
qemu-img convert -f raw -O qcow2 "$IMG_FILE" "$QCOW_FILE"

echo "### FINISHED WITHOUT ERRORS" >&2

0 comments on commit 04858b5

Please sign in to comment.