From 2116b7cd7be889a40f138622d7595500ebbc1e75 Mon Sep 17 00:00:00 2001 From: Breadway Date: Sun, 14 Jun 2026 13:29:49 +0800 Subject: [PATCH] Add rsync and make the installed system bootable/clean unpackfs runs unsquashfs then rsync to copy the rootfs onto the target; rsync was missing (error code 127), so add it alongside squashfs-tools. unpackfs also copies the live filesystem verbatim, so the installed system would inherit the archiso initramfs hooks (booting into the live path) plus the live autologin/user/sudoers. Rework post-install.sh to run in the target chroot as a resilient best-effort script that: - removes the live autologin drop-in, bos-live-setup service/scripts and the liveuser sudoers file, and locks root (sudo model; the live medium left root passwordless), - drops the archiso mkinitcpio config, installs the stock linux.preset and regenerates the initramfs, then refreshes grub.cfg, - keeps the snapper/services/dotfiles setup, with the network-dependent bakery install made non-fatal so offline installs still complete. --- iso/airootfs/etc/calamares/post-install.sh | 105 +++++++++++++++------ iso/packages.x86_64 | 2 + 2 files changed, 76 insertions(+), 31 deletions(-) diff --git a/iso/airootfs/etc/calamares/post-install.sh b/iso/airootfs/etc/calamares/post-install.sh index 967292b..1a81b5a 100644 --- a/iso/airootfs/etc/calamares/post-install.sh +++ b/iso/airootfs/etc/calamares/post-install.sh @@ -1,41 +1,84 @@ #!/bin/bash -set -euo pipefail +# Runs inside the installed-system chroot (Calamares shellprocess, after the +# bootloader step). Best-effort: a single failure must not abort the rest, so +# we deliberately do NOT use `set -e`. +set -uo pipefail -# --- Snapper root config --- -snapper -c root create-config / -sed -i 's/TIMELINE_CREATE="yes"/TIMELINE_CREATE="no"/' /etc/snapper/configs/root -sed -i 's/NUMBER_CLEANUP="no"/NUMBER_CLEANUP="yes"/' /etc/snapper/configs/root -sed -i 's/NUMBER_MIN_AGE="[^"]*"/NUMBER_MIN_AGE="1800"/' /etc/snapper/configs/root -sed -i 's/NUMBER_LIMIT="[^"]*"/NUMBER_LIMIT="10"/' /etc/snapper/configs/root -sed -i 's/NUMBER_LIMIT_IMPORTANT="[^"]*"/NUMBER_LIMIT_IMPORTANT="5"/' /etc/snapper/configs/root +MAIN_USER="$(getent passwd 1000 | cut -d: -f1 || true)" -# Allow main user to list/create/delete snapshots without sudo -MAIN_USER=$(getent passwd 1000 | cut -d: -f1) -sed -i "s/ALLOW_USERS=\"\"/ALLOW_USERS=\"$MAIN_USER\"/" /etc/snapper/configs/root +# --------------------------------------------------------------------------- +# Strip live-only bits that unpackfs copied verbatim from the live medium. +# --------------------------------------------------------------------------- +rm -f /etc/systemd/system/getty@tty1.service.d/autologin.conf +rm -f /etc/systemd/system/bos-live-setup.service \ + /etc/systemd/system/multi-user.target.wants/bos-live-setup.service +rm -f /usr/local/bin/bos-live-setup /usr/local/bin/bos-launch-calamares +rm -f /etc/sudoers.d/99-bos-live +userdel -r liveuser 2>/dev/null || true -# --- System services --- -systemctl enable NetworkManager -systemctl enable bluetooth -systemctl enable snapper-cleanup.timer -systemctl enable grub-btrfs.path +# Root used a passwordless entry on the live medium; lock it (sudo model). +passwd -l root || true -# --- Bakery: install bread ecosystem --- -# Requires [breadway] repo in /etc/pacman.conf — see iso/pacman.conf -if command -v bakery &>/dev/null; then - sudo -u "$MAIN_USER" bakery install bread breadbar breadbox breadcrumbs breadpad bos-settings +# --------------------------------------------------------------------------- +# Rebuild the initramfs for a real install — the live image ships the archiso +# hooks, which would send the installed system into the live-boot path. +# --------------------------------------------------------------------------- +rm -f /etc/mkinitcpio.conf.d/archiso.conf +cat >/etc/mkinitcpio.d/linux.preset <<'PRESET' +# mkinitcpio preset file for the 'linux' package +ALL_config="/etc/mkinitcpio.conf" +ALL_kver="/boot/vmlinuz-linux" +PRESETS=('default' 'fallback') +default_image="/boot/initramfs-linux.img" +fallback_image="/boot/initramfs-linux-fallback.img" +fallback_options="-S autodetect" +PRESET +mkinitcpio -P || echo "WARN: mkinitcpio regeneration failed" + +# Refresh GRUB so it references the rebuilt initramfs (and the new fallback). +if command -v grub-mkconfig &>/dev/null; then + grub-mkconfig -o /boot/grub/grub.cfg || echo "WARN: grub-mkconfig failed" fi -# --- Deploy dotfiles into user home (skip any file that already exists) --- -SKEL_SRC="/etc/skel/.config" -DOTFILES_DEST="/home/$MAIN_USER/.config" - -if [[ -d "$SKEL_SRC" ]]; then - mkdir -p "$DOTFILES_DEST" - cp -rn "$SKEL_SRC/." "$DOTFILES_DEST/" - chown -R "$MAIN_USER:$MAIN_USER" "$DOTFILES_DEST" +# --------------------------------------------------------------------------- +# Snapper root config (root is btrfs). +# --------------------------------------------------------------------------- +if command -v snapper &>/dev/null; then + snapper -c root create-config / || echo "WARN: snapper create-config failed" + if [[ -f /etc/snapper/configs/root ]]; then + sed -i 's/TIMELINE_CREATE="yes"/TIMELINE_CREATE="no"/' /etc/snapper/configs/root + sed -i 's/NUMBER_CLEANUP="no"/NUMBER_CLEANUP="yes"/' /etc/snapper/configs/root + sed -i 's/NUMBER_MIN_AGE="[^"]*"/NUMBER_MIN_AGE="1800"/' /etc/snapper/configs/root + sed -i 's/NUMBER_LIMIT="[^"]*"/NUMBER_LIMIT="10"/' /etc/snapper/configs/root + sed -i 's/NUMBER_LIMIT_IMPORTANT="[^"]*"/NUMBER_LIMIT_IMPORTANT="5"/' /etc/snapper/configs/root + [[ -n "$MAIN_USER" ]] && \ + sed -i "s/ALLOW_USERS=\"\"/ALLOW_USERS=\"$MAIN_USER\"/" /etc/snapper/configs/root + fi fi -# --- XDG user dirs --- -sudo -u "$MAIN_USER" xdg-user-dirs-update +# --------------------------------------------------------------------------- +# System services. +# --------------------------------------------------------------------------- +systemctl enable NetworkManager bluetooth snapper-cleanup.timer grub-btrfs.path \ + || echo "WARN: enabling some services failed" -echo "BOS post-install complete. Reboot to start your system." +# --------------------------------------------------------------------------- +# Bread ecosystem via bakery (needs network — non-fatal so an offline install +# still completes; the user can run it after first boot). +# --------------------------------------------------------------------------- +if [[ -n "$MAIN_USER" ]] && command -v bakery &>/dev/null; then + sudo -u "$MAIN_USER" bakery install bread breadbar breadbox breadcrumbs breadpad bos-settings \ + || echo "WARN: bakery install failed (no network during install?); run it after first boot" +fi + +# --------------------------------------------------------------------------- +# Deploy dotfiles into the user's home (don't clobber existing files). +# --------------------------------------------------------------------------- +if [[ -n "$MAIN_USER" && -d /etc/skel/.config ]]; then + mkdir -p "/home/$MAIN_USER/.config" + cp -rn /etc/skel/.config/. "/home/$MAIN_USER/.config/" || true + chown -R "$MAIN_USER:$MAIN_USER" "/home/$MAIN_USER/.config" || true + sudo -u "$MAIN_USER" xdg-user-dirs-update || true +fi + +echo "BOS post-install complete." diff --git a/iso/packages.x86_64 b/iso/packages.x86_64 index c89e69e..f49eeb8 100644 --- a/iso/packages.x86_64 +++ b/iso/packages.x86_64 @@ -14,6 +14,8 @@ mtools # squashfs-tools: provides unsquashfs, which Calamares' unpackfs module uses # to extract airootfs.sfs onto the target during install. squashfs-tools +# rsync: unpackfs copies the unpacked rootfs onto the target with rsync. +rsync # Live-ISO boot (archiso bootmodes: bios.syslinux + uefi.systemd-boot) # mkinitcpio-archiso provides the initramfs hooks that find and mount # airootfs.sfs and switch root into it — without it the live ISO drops