|
| 1 | +# Incident notes: AMD mini-PC live-ISO boot hang + fresh-install Flatpak bake (June 2026) |
| 2 | + |
| 3 | +Two distinct bugs surfaced from the same uBlue forum thread |
| 4 | +([#12247](https://universal-blue.discourse.group/t/introducing-margine-os/12247)) |
| 5 | +by tester **CyberOto** on the same hardware class (AMD Ryzen 8000 / Radeon |
| 6 | +780M mini-PCs). They are unrelated in cause but share two themes worth |
| 7 | +recording: **the dev host masked both bugs**, and **CI never exercised the |
| 8 | +path that broke**. |
| 9 | + |
| 10 | +- **Incident 1 — live ISO hard-hangs on boot.** RESOLVED, PR #221. |
| 11 | +- **Incident 2 — fresh install lands with a broken /var/lib/flatpak.** Fixed |
| 12 | + PR #222 (upstream-alignment); definitive confirmation pending the |
| 13 | + real-install CI gate. |
| 14 | + |
| 15 | +--- |
| 16 | + |
| 17 | +## Incident 1 — AMD mini-PC live-ISO boot hang (baked `console=ttyS0`) |
| 18 | + |
| 19 | +### Affected hardware |
| 20 | +| Machine | CPU | iGPU | RAM | Result | |
| 21 | +|---|---|---|---|---| |
| 22 | +| Beelink SER8 (mini-PC) | Ryzen 7 8745(H) | Radeon 780M | 32 GB | **HANG** | |
| 23 | +| Second AMD desktop | Ryzen 7 8745 | Radeon 780M | — | **HANG** | |
| 24 | +| Tuxedo Pulse Gen3 (laptop) | Ryzen 7 7840 | Radeon 780M | — | boots fine | |
| 25 | + |
| 26 | +Discriminators: same 780M iGPU works on the laptop but not the desktops; |
| 27 | +**stock Bluefin DX live ISO booted fine on the same desktops.** |
| 28 | + |
| 29 | +### Symptoms |
| 30 | +- Margine live ISO: black screen shortly after peripheral init. |
| 31 | +- With `quiet rhgb` removed (verbose): the boot **crawls ~30x too slow** — |
| 32 | + every systemd step ~30 s apart, even trivial socket units — reaches the |
| 33 | + initramfs, and **hard-hangs at ~700 s** during `systemd-modules-load` |
| 34 | + (right after the SCSI device handlers emc/rdac/alua). Keyboard then dead, |
| 35 | + no VT switch, no Caps/Num-Lock LED, no SSH, no ping. |
| 36 | +- Early ACPI BIOS error: `\_SB.PCI0.GPP5.RTL8._S0W, AE_ALREADY_EXISTS`. |
| 37 | +- Rebase to the installed image reached GDM, then froze on login, then disk |
| 38 | + write errors, then unbootable. |
| 39 | + |
| 40 | +### Solutions tried |
| 41 | +| Attempt | Result | |
| 42 | +|---|---| |
| 43 | +| `amd_iommu=off` | no change | |
| 44 | +| `nomodeset` / `amdgpu.dc=0` | no change | |
| 45 | +| remove `quiet rhgb` | no fix, but revealed the verbose log (the 30x slowdown) | |
| 46 | +| Ctrl+Alt+F3 / Caps-Lock LED / SSH / ping | confirmed a true hard hang | |
| 47 | +| BIOS UMA = Auto / 8 GB / UMA_AUTO | no change (ruled out RAM/UMA) | |
| 48 | +| `processor.max_cstate=1` + remove `console=ttyS0` | booted | |
| 49 | +| **remove only `console=ttyS0,115200n8`** | **booted fully, no slowness — THE FIX** | |
| 50 | +| stock-Fedora-kernel test ISO, `console=ttyS0` removed | also booted (exonerates the kernel) | |
| 51 | + |
| 52 | +### Hypotheses (and their fate) |
| 53 | +1. **CachyOS kernel regression on Ryzen 8000** (amd_sfh GPF / amd_pstate / |
| 54 | + C-state). Investigated with two multi-agent research passes + a |
| 55 | + stock-kernel A/B test ISO. **REFUTED:** the stock-Fedora-kernel ISO hung |
| 56 | + identically and was fixed by the same param. |
| 57 | +2. **RAM / UMA-VRAM exhaustion on the 780M.** **REFUTED:** 32 GB RAM, and |
| 58 | + changing the BIOS UMA setting made no difference. |
| 59 | +3. **ACPI `_S0W` / Realtek.** Benign, common AM5 ACPI warning; red herring. |
| 60 | +4. **Baked `console=ttyS0` stalling on a phantom UART.** Raised early as the |
| 61 | + one karg our ISO bakes that Bluefin's does not. **CONFIRMED** by CyberOto. |
| 62 | + |
| 63 | +### Root cause |
| 64 | +The live ISO baked `console=tty0 console=ttyS0,115200n8 |
| 65 | +systemd.show_status=1` into the default GRUB entries. |
| 66 | +`console=ttyS0` was added only so the CI QEMU boot-test could watch the |
| 67 | +serial console. On a board that advertises a **phantom 8250 UART** (common |
| 68 | +on mini-PCs like the Beelink SER8) the device never drains its TX FIFO, so |
| 69 | +every kernel `printk` busy-waits in `serial8250` until a timeout; with |
| 70 | +`systemd.show_status` forcing per-unit output that drags the whole boot ~30x |
| 71 | +slower and eventually wedges. Bluefin's ISO does not bake `console=ttyS0`, |
| 72 | +which is why it booted. The CachyOS kernel was a coincidence, not a cause. |
| 73 | + |
| 74 | +### Resolution |
| 75 | +- **PR #221:** removed `console=ttyS0` + `systemd.show_status=1` from the two |
| 76 | + default ISO entries (now `console=tty0` only). CI keeps serial |
| 77 | + observability **without** the harmful karg by extracting the ISO's |
| 78 | + kernel+initrd and direct-booting them (`-kernel/-initrd/-append`, console |
| 79 | + injected there) while `-cdrom` serves the squashfs. |
| 80 | +- **PR #220 (audit hardening, same week):** a "verbose, no splash, no serial" |
| 81 | + recovery GRUB entry; bounded the live overlay (`rd.live.overlay.size`); |
| 82 | + refreshed `linux-firmware`/microcode after the kernel swap; zstd-guards on |
| 83 | + the initramfs regen; a squashfs-is-zstd CI assertion; a warn-only 2 GiB |
| 84 | + constrained CI boot pass. |
| 85 | +- Follow-up: republish a clean public ISO (the previously published one |
| 86 | + still carries the karg). |
| 87 | + |
| 88 | +--- |
| 89 | + |
| 90 | +## Incident 2 — fresh install lands with a broken /var/lib/flatpak |
| 91 | + |
| 92 | +### Affected hardware / scope |
| 93 | +Reported on the Beelink SER8 (Ryzen 8745, 32 GB) after a fresh ISO install, |
| 94 | +but the analysis concluded it affects **every fresh ISO install** on the |
| 95 | +default partitioning (dedicated `/var` btrfs subvol) — not SER8-specific. |
| 96 | + |
| 97 | +### Symptoms (installed system, post-boot) |
| 98 | +- `margine-validate-margine-system`: all ~42 BAKE/preinstall apps "NOT |
| 99 | + installed" — "kickstart %post bake silently failed AND preinstall fallback |
| 100 | + hasn't caught it yet". |
| 101 | +- `flatpak-preinstall.service`: failed (exit 1), "Start request repeated too |
| 102 | + quickly, restart counter at 3" → permanently failed. |
| 103 | +- `flatpak update`: `Warning/error: opendir(refs/remotes): No such file or |
| 104 | + directory`; apps won't start; `sudo flatpak update` hung. |
| 105 | + |
| 106 | +### Investigation + hypotheses |
| 107 | +A 24-agent analysis (with adversarial verification) found Margine **diverged |
| 108 | +from BOTH Bluefin and Bazzite** on four points of the bake/install path. The |
| 109 | +exact on-disk corruption mechanism did **not** fully converge — and, crucially, |
| 110 | +**it cannot be settled from the dev host because the host never exercised the |
| 111 | +bake path** (its Flatpaks came from the first-boot download fallback, which |
| 112 | +masks the bug). The four verified divergences (the actionable truth): |
| 113 | + |
| 114 | +1. **SELinux labels stripped, never restored.** `install-flatpaks.ks` used |
| 115 | + `rsync --filter='-x security.selinux'`. ostree relabels `/var` only once |
| 116 | + at deploy-finalize (before `%post`), so the rsynced repo kept a wrong |
| 117 | + context → confined flatpak denied access to `/var/lib/flatpak/repo`. |
| 118 | + Bluefin does NOT strip; Bazzite strips but then `restorecon`s. Margine did |
| 119 | + neither's safe half. |
| 120 | +2. **Bake rsync targeted the per-deployment `.0/var`**, which the booted |
| 121 | + system never mounts as `/var` (runtime `/var` is the stateroot var) — |
| 122 | + plausibly shadowing the bake. (Most-disputed of the four; upstream uses |
| 123 | + the same target but ALSO bakes into the committed image, which Margine |
| 124 | + does not.) |
| 125 | +3. **No `disable-fedora-flatpak.ks`** (both upstreams ship it) — Fedora's |
| 126 | + `flatpak-add-fedora-repos` can half-initialize/clobber the system repo. |
| 127 | +4. **`flatpak-preinstall.service` had a brittle 3-strike lockout** — one |
| 128 | + transient first-boot failure left it permanently `failed`, so the |
| 129 | + download fallback never recovered. |
| 130 | + |
| 131 | +### Resolution (PR #222 — align to Bluefin/Bazzite) |
| 132 | +- `install-flatpaks.ks`: target the real mounted runtime `/var` |
| 133 | + (`/mnt/sysimage/var`), drop the SELinux label-strip, add a loud |
| 134 | + `MARGINE-BAKE-OK/FAIL` marker. |
| 135 | +- New `disable-fedora-flatpak.ks` (mask `flatpak-add-fedora-repos`) BEFORE |
| 136 | + the bake; new `flatpak-restore-selinux-labels.ks` (`restorecon`) AFTER it. |
| 137 | +- `flatpak-preinstall.service` drop-in: `StartLimitIntervalSec=0` + |
| 138 | + ExecStartPre ensure-flathub + `flatpak repair` → self-healing fallback. |
| 139 | + |
| 140 | +**Honest status:** these are upstream-alignment fixes (verified divergences), |
| 141 | +not yet confirmed against a reproduced install. The definitive confirmation |
| 142 | +is the real-install CI gate (below). |
| 143 | + |
| 144 | +--- |
| 145 | + |
| 146 | +## Cross-cutting: why both shipped, and the CI gaps |
| 147 | + |
| 148 | +- **The dev host masks both bugs.** It has Secure Boot off, a real/normal |
| 149 | + UART (so `console=ttyS0` doesn't stall), and its Flatpaks came from the |
| 150 | + download fallback (not the bake). Never trust the dev host to validate |
| 151 | + either path. |
| 152 | +- **No CI ever did a real ISO install + first boot.** `smoke-boot` builds a |
| 153 | + qcow2 directly from the OCI image (skips Anaconda + the kickstart); |
| 154 | + `build-disk` only boots the LIVE session (where `/var/lib/flatpak` is a |
| 155 | + read-only mount that looks fine). `install-flatpaks.ks` had literally never |
| 156 | + run end-to-end in CI. |
| 157 | +- **A truncated local ISO sent the first repro attempts down a rabbit hole.** |
| 158 | + A `curl` that died at 6.5/7.9 GB produced an ISO that failed to boot in |
| 159 | + every local QEMU configuration — mistaken for OVMF / `-kernel` problems. |
| 160 | + The `-kernel/-initrd` boot method is fine; the dev host has 4M OVMF. |
| 161 | +- **The boot-test's own bug:** it loop-mounted the ISO with `sudo` then |
| 162 | + `cp`'d as the runner user → `Permission denied`. Fixed to extract with |
| 163 | + `xorriso` (no mount/sudo) in PR #221's follow-up. |
| 164 | + |
| 165 | +### Regression guards added |
| 166 | +- **Static guard** (`.github/scripts/check-flatpak-fixes.sh`, run in `lint`): |
| 167 | + asserts all four Flatpak invariants + the no-`console=ttyS0` invariant stay |
| 168 | + in place. Cheap, immediate. |
| 169 | +- **Real-install gate** (planned): a `build-disk.yml` job that boots the ISO, |
| 170 | + triggers an automated Anaconda install (a dormant `anaconda --kickstart` |
| 171 | + service gated by a CI-only `margine.autoinstall` karg — `inst.ks`/OEMDRV do |
| 172 | + NOT work on this live ISO, its initrd has no anaconda-dracut modules), then |
| 173 | + offline-verifies the installed disk via `qemu-nbd` |
| 174 | + (`/var/lib/flatpak/repo/refs/remotes/flathub` present, app count, SELinux |
| 175 | + labels). This reproduces + permanently guards the class. |
| 176 | + |
| 177 | +### Lessons |
| 178 | +- A knob added for **CI/dev convenience** (the serial console) broke **real |
| 179 | + hardware**. Inject test-only knobs at test time, never ship them. |
| 180 | +- "Works on our hardware + in CI" is not "works on arbitrary hardware": |
| 181 | + mini-PCs with phantom ACPI/firmware devices are a real, common class. |
| 182 | +- Atomic/ostree `/var` semantics + SELinux relabel timing are subtle; mirror |
| 183 | + what two working upstreams (Bluefin, Bazzite) do rather than inventing a |
| 184 | + third way. |
0 commit comments