Fix install-breaking and live-boot bugs, verified on real hardware
All checks were successful
Mirror to GitHub / mirror (push) Successful in 3s

Boot-critical (each confirmed with a real boot/install cycle, not just
code review):

- Live ISO's liveuser shell is zsh, but Hyprland autostart was written
  to .bash_profile (never runs) — moved to .zprofile, and switched to
  start-hyprland (Hyprland's own watchdog wrapper; raw `exec Hyprland`
  is no longer the recommended launch method).
- copytoram (self-enables on most real hardware: non-optical boot +
  image < 4GiB + enough free RAM) unmounts /run/archiso/bootmnt, which
  unpackfs.conf and bos-copy-kernel both hardcoded as their source —
  broke the installer outright on real hardware, confirmed by forcing
  copytoram=y. Added a resolver step for unpackfs, and switched the
  kernel copy to /usr/lib/modules/$(uname -r)/vmlinuz (part of the live
  squashfs itself, unaffected by copytoram).
- BIOS installs got no bootloader — post-install.sh only ever ran the
  UEFI grub-install path despite BOS shipping bios.syslinux. Added a
  BIOS branch with disk auto-detection.
- @snapshots/@log/@cache were never real: iso/partition.conf's
  btrfsSubvolumes key isn't part of this Calamares version's partition
  module schema at all (same class of bug as the userShell fix below —
  silently ignored). Calamares only natively creates @ and @home.
  post-install.sh now creates the three subvolumes by hand after
  unpackfs, migrates existing /var/log + /var/cache content into them
  before mounting over, and adds the fstab entries — verified end to
  end on real hardware, including grub-btrfs generating bootable
  snapshot menu entries. The unmount step in the existing snapper
  create-config dance also gained retry + lazy-unmount fallback after
  a real chroot run hit a transient busy-mount race.
- Default shell was bash instead of zsh post-install: users.conf's
  top-level `userShell` key isn't part of this Calamares version's
  users module schema either — the real key is nested (user.shell).
- graphical-session.target ships RefuseManualStart=yes (systemd
  convention), so the earlier attempt to activate it from hyprland.lua
  silently failed and breadclipd (WantedBy=graphical-session.target)
  never started. Starts breadclipd.service directly instead.
- /etc/os-release was never set (showed "Arch Linux"); live boot never
  had quiet/splash/plymouth wired in (raw kernel scroll the whole
  time) despite BOS already shipping a complete bread-logo+spinner
  plymouth theme for the installed system.

Also: generalized build-local.sh's per-service skel baking (previously
only breadd.service was hand-committed; breadbox-sync/breadmill/
breadclipd never shipped), added the four new bakery packages to
BREAD_BINS, removed the redundant cliphist/fzf clipboard pipeline in
favor of breadclip, mirrored fastfetch's bread-logo config into skel,
and fixed a stale bos-update comment.
This commit is contained in:
Breadway 2026-07-03 13:31:40 +08:00
parent 81f2f3545a
commit a8f1592e75
24 changed files with 373 additions and 56 deletions

View file

@ -7,19 +7,40 @@
# (the stock linux.preset points ALL_kver at /boot/vmlinuz-linux) and before the
# `bootloader` module runs grub — otherwise the installed system is unbootable.
#
# Runs in the LIVE environment (Calamares shellprocess, dontChroot) so it can
# read /run/archiso/bootmnt; the target root mount point is passed as $1.
# Runs in the LIVE environment (Calamares shellprocess, dontChroot); the
# target root mount point is passed as $1.
#
# The kernel is read from /usr/lib/modules/$(uname -r)/vmlinuz — part of the
# live squashfs itself (the linux package always installs it there), not from
# the ISO's separate arch/boot/x86_64/ dir under /run/archiso/bootmnt. That
# mount gets torn down by archiso's own copytoram handling, which self-enables
# on most real hardware, so depending on it here would leave $ROOT/boot empty
# and the install unbootable on exactly the machines this is meant to run on.
set -uo pipefail
ROOT="${1:?target root required}"
SRC="/run/archiso/bootmnt/arch/boot/x86_64"
KVER="$(uname -r)"
SRC_KERNEL="/usr/lib/modules/${KVER}/vmlinuz"
SRC_BOOT="/run/archiso/bootmnt/arch/boot/x86_64"
install -d -m 0755 "$ROOT/boot"
cp -f "$SRC/vmlinuz-linux" "$ROOT/boot/vmlinuz-linux"
# Microcode, if the live medium carries it (grub-mkconfig picks it up).
if [ -f "$SRC_KERNEL" ]; then
cp -f "$SRC_KERNEL" "$ROOT/boot/vmlinuz-linux"
elif [ -f "$SRC_BOOT/vmlinuz-linux" ]; then
echo "WARN: $SRC_KERNEL missing, falling back to $SRC_BOOT"
cp -f "$SRC_BOOT/vmlinuz-linux" "$ROOT/boot/vmlinuz-linux"
else
echo "ERROR: no kernel image found (checked $SRC_KERNEL and $SRC_BOOT/vmlinuz-linux) — install would be unbootable" >&2
exit 1
fi
# Microcode, if the live medium carries it (grub-mkconfig picks it up). This
# is best-effort: post-install.sh's mkinitcpio `microcode` HOOKS entry embeds
# microcode from /usr/lib/firmware directly, so a missing standalone ucode.img
# here is not boot-critical, unlike the kernel image above.
for u in amd-ucode.img intel-ucode.img; do
[ -f "$SRC/$u" ] && cp -f "$SRC/$u" "$ROOT/boot/$u"
[ -f "$SRC_BOOT/$u" ] && cp -f "$SRC_BOOT/$u" "$ROOT/boot/$u"
done
# Replace the archiso initramfs setup that unpackfs copied from the live medium.

View file

@ -34,15 +34,18 @@ fi
# Start Hyprland on tty1 login; capture output and fall back to a shell so a
# failed compositor start is visible rather than a blank looping cursor.
cat >/home/liveuser/.bash_profile <<'EOF'
# liveuser's shell is zsh (see useradd above), which never sources
# .bash_profile — this must be .zprofile (zsh's login-shell hook) or it never
# runs at all and the live session boots to a bare console.
cat >/home/liveuser/.zprofile <<'EOF'
if [[ "$(tty)" == /dev/tty1 ]] && [[ -z "$WAYLAND_DISPLAY" ]]; then
export WLR_RENDERER_ALLOW_SOFTWARE=1
export WLR_NO_HARDWARE_CURSORS=1
# Log to a user-writable path (/var/log is root-only; redirecting there
# would fail and silently keep the compositor from ever launching).
Hyprland &>/tmp/hyprland-live.log
start-hyprland &>/tmp/hyprland-live.log
echo "Hyprland exited (rc=$?). Log: /tmp/hyprland-live.log"
exec bash -i
exec zsh -i
fi
EOF

View file

@ -0,0 +1,29 @@
#!/bin/bash
# Resolve the real location of the live squashfs before Calamares' unpackfs
# module runs, and leave a stable symlink for it to unpack from.
#
# archiso's own initcpio hook unmounts /run/archiso/bootmnt once copytoram has
# copied the image to a tmpfs (/run/archiso/copytoram/airootfs.sfs) — and
# copytoram=auto self-enables on most real hardware (non-optical boot device,
# image under 4 GiB, enough free RAM), not just when explicitly requested. A
# Calamares unpackfs.conf source path hardcoded to /run/archiso/bootmnt/...
# would then point at nothing. Check both locations here, in a real script,
# and hand unpackfs.conf one fixed path that always resolves.
set -uo pipefail
DEST="/run/archiso/resolved-airootfs.sfs"
CANDIDATES=(
"/run/archiso/copytoram/airootfs.sfs"
"/run/archiso/bootmnt/arch/x86_64/airootfs.sfs"
)
for c in "${CANDIDATES[@]}"; do
if [ -f "$c" ]; then
ln -sf "$c" "$DEST"
echo "resolved live squashfs: $c -> $DEST"
exit 0
fi
done
echo "ERROR: could not find the live squashfs in any known location (checked: ${CANDIDATES[*]})" >&2
exit 1

View file

@ -7,9 +7,14 @@
# breadbox-sync, …) would be missing from PATH and the Hyprland `exec-once`
# launches would fail. Source the login profile here so PATH is correct, set the
# Wayland session hints, then hand off to Hyprland.
#
# Launched via start-hyprland (ships with the hyprland package) rather than the
# raw Hyprland binary — Hyprland upstream no longer recommends exec'ing it
# directly; start-hyprland wraps it in a watchdog process that also gives us
# crash recovery for free.
source /etc/profile 2>/dev/null
export XDG_SESSION_TYPE=wayland
export XDG_CURRENT_DESKTOP=Hyprland
exec Hyprland
exec start-hyprland

View file

@ -5,8 +5,10 @@
# 1. pacman — Arch base/desktop + the [breadway] repo (bos-settings, etc.).
# Every transaction is snapshotted by snap-pac, so you can roll
# back from the GRUB "snapshots" submenu or BOS Settings.
# 2. bakery — the bread ecosystem apps in ~/.local/bin (bread, breadbar,
# breadbox, breadcrumbs, breadpad, breadman, bread-theme).
# 2. bakery — the bread ecosystem apps in ~/.local/bin (whatever `bakery list`
# reports as installed — bread, breadbar, breadbox, breadcrumbs,
# breadpad, breadman, bread-theme, breadpaper, breadmon,
# breadsearch, breadclip, breadshot, ...).
#
# Best-effort: a failure in one channel doesn't abort the other.
set -uo pipefail