fix: xorriso append_partition for real USB boot + grub-mkstandalone
Root cause of USB boot failure: our xorriso used -e boot/grub/efi.img to embed the EFI image inside the ISO. This works for CD-ROM and QEMU but NOT for USB on real UEFI hardware. Fix: use the Will Haley / Debian live-build approach: - -append_partition 2 (GPT type EFI) appends efi.img AFTER ISO data - -e --interval:appended_partition_2:all:: references the appended partition - --mbr-force-bootable forces MBR active flag - grub-mkstandalone with embedded bootstrap config (searches for grub.cfg) - grub.cfg placed in both /boot/grub/ AND /EFI/BOOT/ on ISO - grub.cfg uses search --label ARCHIPELAGO to find the ISO root This is the exact approach used by StartOS, TAILS, and every production custom Debian live ISO that boots from USB. Also: iso-debug, iso-branding skills + reference docs, dev-start.sh option 0 for branding dev, improved dev-branding.sh and test-iso-qemu.sh. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
parent
013b724e02
commit
34a476d0a1
@@ -1,87 +1,121 @@
|
||||
---
|
||||
name: build-iso
|
||||
description: Build a new Archipelago auto-installer ISO image (bundled or unbundled)
|
||||
disable-model-invocation: true
|
||||
allowed-tools: Bash, Read
|
||||
description: Build Archipelago auto-installer ISOs. Custom debootstrap base (no Debian Live dependency), live-boot for squashfs root, hybrid BIOS+UEFI boot, Archipelago branding. Use when user says "build ISO", "build image", "create installer", or needs to work on the ISO build pipeline.
|
||||
allowed-tools: Bash, Read, Edit, Write, Grep, Glob, Agent
|
||||
---
|
||||
|
||||
Build a new Archipelago auto-installer ISO.
|
||||
# Build Archipelago ISO
|
||||
|
||||
## Pre-build checklist
|
||||
## Architecture (dev-iso branch)
|
||||
|
||||
1. Latest code deployed to server (`/deploy` first)
|
||||
2. System configs synced (`/sync-configs` first)
|
||||
3. Everything tested and working on live server
|
||||
4. Sync build scripts to server before building:
|
||||
```bash
|
||||
rsync -avz -e "ssh -i ~/.ssh/archipelago-deploy" \
|
||||
/Users/dorian/Projects/archy/image-recipe/build-auto-installer-iso.sh \
|
||||
/Users/dorian/Projects/archy/image-recipe/build-unbundled-iso.sh \
|
||||
archipelago@192.168.1.228:~/archy/image-recipe/
|
||||
```
|
||||
Custom debootstrap-based installer. NO Debian Live ISO download.
|
||||
|
||||
## Build variants
|
||||
| Component | Source | Size |
|
||||
|-----------|--------|------|
|
||||
| Installer squashfs | debootstrap --variant=minbase + live-boot | ~180MB |
|
||||
| Target rootfs | Docker build (Debian bookworm, full stack) | ~1.5GB compressed |
|
||||
| Kernel + initramfs | From debootstrap, with live-boot hooks | ~50MB |
|
||||
| GRUB + ISOLINUX | Built from packages during Step 2 | ~1MB |
|
||||
| **Total ISO** | **Unbundled** | **~2.2GB** |
|
||||
|
||||
### Unbundled ISO (recommended for distribution — ~3GB)
|
||||
No pre-bundled container images. Apps install on-demand from Marketplace (requires internet).
|
||||
## Build Pipeline (6 Steps)
|
||||
|
||||
**Step 1** (lines ~200-430): Build target rootfs via Docker
|
||||
- Debian bookworm + all runtime packages (podman, nginx, tor, chromium, etc.)
|
||||
- `--no-install-recommends` for size reduction
|
||||
- Strips docs/man/locales
|
||||
- Output: `archipelago-rootfs.tar` (~1.5GB)
|
||||
|
||||
**Step 2** (lines ~430-710): Build installer environment via debootstrap
|
||||
- `debootstrap --variant=minbase` inside a container
|
||||
- Installs live-boot via chroot (NOT --include — minbase can't resolve it)
|
||||
- Custom initramfs with live-boot hooks
|
||||
- Builds GRUB EFI image with grub-mkimage
|
||||
- Creates ISOLINUX files, EFI boot image
|
||||
- Installs GRUB theme + background
|
||||
- Output: vmlinuz, initrd.img, filesystem.squashfs, BOOTX64.EFI, efi.img, isolinux.bin
|
||||
|
||||
**Step 3** (lines ~710-850): Add Archipelago components
|
||||
- Backend binary, web UI, rootfs.tar, scripts, Plymouth theme
|
||||
|
||||
**Step 3b** (lines ~850-1230): Bundle container images (skipped if UNBUNDLED=1)
|
||||
|
||||
**Step 4** (lines ~1230-2380): Generate auto-install.sh
|
||||
- Embedded installer script (~1100 lines)
|
||||
- Disk detection, partitioning, LUKS encryption, GRUB install
|
||||
- Installs GRUB + Plymouth theme on target
|
||||
|
||||
**Step 5** (lines ~2380-2460): Configure boot loaders
|
||||
- Write GRUB config (boot=live components)
|
||||
- Write ISOLINUX config
|
||||
- Both reference kernel at /live/vmlinuz
|
||||
|
||||
**Step 6** (lines ~2460-2540): Create final ISO
|
||||
- xorriso with hybrid BIOS+UEFI boot
|
||||
- Uses proven MBR from `branding/isohdpfx.bin`
|
||||
- `-partition_offset 16` for UEFI compatibility
|
||||
|
||||
## CI Workflow
|
||||
|
||||
**Branch**: `dev-iso` → `.gitea/workflows/build-iso-dev.yml`
|
||||
**Branch**: `main` → `.gitea/workflows/build-iso.yml`
|
||||
|
||||
Dev CI includes a smoke test step that verifies:
|
||||
- All critical files present in ISO
|
||||
- Initrd contains live-boot scripts
|
||||
- grub.cfg has boot=live
|
||||
- Fails build before copying to Builds if any check fails
|
||||
|
||||
## Critical Rules
|
||||
|
||||
1. **MBR**: Always use `branding/isohdpfx.bin` (Debian Live MBR, starts with `4552`). The ISOLINUX generic MBR (`33ed`) doesn't boot on all hardware.
|
||||
|
||||
2. **live-boot**: Must be installed via `chroot /installer apt-get install` AFTER debootstrap completes. The `--include` flag silently fails for live-boot.
|
||||
|
||||
3. **Initramfs**: `update-initramfs` needs `/proc`, `/sys`, `/dev` bind-mounted in the chroot. Without them, the initramfs is broken.
|
||||
|
||||
4. **scripts/live is a FILE**: Verify with `[ -e ]` not `[ -d ]`.
|
||||
|
||||
5. **Kernel params**: Must include `boot=live components`. Without `boot=live`, live-boot hooks never activate.
|
||||
|
||||
6. **partition_offset 16**: Required in xorriso for UEFI firmware to recognize the USB.
|
||||
|
||||
7. **Never push during a running CI build**: The gitea-runner kills in-progress builds when a new commit arrives on the same branch.
|
||||
|
||||
## Quick Commands
|
||||
|
||||
```bash
|
||||
# Build locally (on .228):
|
||||
ssh -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228
|
||||
cd ~/archy/image-recipe
|
||||
sudo UNBUNDLED=1 DEV_SERVER=localhost BUILD_FROM_SOURCE=0 ./build-auto-installer-iso.sh
|
||||
|
||||
# Check build status:
|
||||
ssh -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228 \
|
||||
'cd ~/archy/image-recipe && sudo ./build-unbundled-iso.sh'
|
||||
"ps aux | grep build-auto | grep -v grep"
|
||||
|
||||
# Check latest ISO:
|
||||
ssh -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228 \
|
||||
"ls -lt /var/lib/archipelago/filebrowser/Builds/archipelago-dev-*.iso | head -3"
|
||||
|
||||
# Verify ISO:
|
||||
# See /iso-debug skill for the full verification checklist
|
||||
|
||||
# Iterate on branding without rebuilding:
|
||||
./image-recipe/dev-branding.sh [path-to-iso]
|
||||
# Or: ./scripts/dev-start.sh → option 0
|
||||
```
|
||||
|
||||
Output: `results/archipelago-installer-unbundled-x86_64.iso`
|
||||
## Key Files
|
||||
|
||||
### Full bundled ISO (~11GB)
|
||||
All container images pre-bundled for offline install.
|
||||
|
||||
```bash
|
||||
ssh -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228 \
|
||||
'cd ~/archy/image-recipe && sudo ./build-auto-installer-iso.sh'
|
||||
```
|
||||
|
||||
Output: `results/archipelago-installer-x86_64.iso`
|
||||
|
||||
## Post-build: ALWAYS publish to FileBrowser
|
||||
|
||||
After EVERY successful build, copy the ISO to the FileBrowser `Builds` folder so it's downloadable from the web UI. This is mandatory — do not skip.
|
||||
|
||||
**FileBrowser data root**: `/var/lib/archipelago/filebrowser/`
|
||||
|
||||
```bash
|
||||
# For unbundled:
|
||||
ssh -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228 \
|
||||
'sudo mkdir -p /var/lib/archipelago/filebrowser/Builds && \
|
||||
sudo cp ~/archy/image-recipe/results/archipelago-installer-unbundled-x86_64.iso /var/lib/archipelago/filebrowser/Builds/ && \
|
||||
sudo chown 1000:1000 /var/lib/archipelago/filebrowser/Builds/archipelago-installer-unbundled-x86_64.iso'
|
||||
|
||||
# For bundled:
|
||||
ssh -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228 \
|
||||
'sudo mkdir -p /var/lib/archipelago/filebrowser/Builds && \
|
||||
sudo cp ~/archy/image-recipe/results/archipelago-installer-x86_64.iso /var/lib/archipelago/filebrowser/Builds/ && \
|
||||
sudo chown 1000:1000 /var/lib/archipelago/filebrowser/Builds/archipelago-installer-x86_64.iso'
|
||||
```
|
||||
|
||||
## Post-build: Download to Mac (optional)
|
||||
|
||||
```bash
|
||||
# Unbundled:
|
||||
scp -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228:~/archy/image-recipe/results/archipelago-installer-unbundled-x86_64.iso ~/Downloads/
|
||||
|
||||
# Bundled:
|
||||
scp -i ~/.ssh/archipelago-deploy archipelago@192.168.1.228:~/archy/image-recipe/results/archipelago-installer-x86_64.iso ~/Downloads/
|
||||
```
|
||||
|
||||
## Key paths on server
|
||||
|
||||
- Build scripts: `~/archy/image-recipe/build-auto-installer-iso.sh`, `build-unbundled-iso.sh`
|
||||
- Build output: `~/archy/image-recipe/results/`
|
||||
- Build cache (rootfs, base ISO): `~/archy/image-recipe/build/auto-installer/`
|
||||
- FileBrowser Builds: `/var/lib/archipelago/filebrowser/Builds/`
|
||||
|
||||
## Notes
|
||||
|
||||
- Use `--rebuild` flag to force rootfs rebuild (otherwise uses cached)
|
||||
- FileBrowser container mounts `/var/lib/archipelago/filebrowser` → `/srv`
|
||||
- Always `chown 1000:1000` files in FileBrowser so the app can serve them
|
||||
- **IMPORTANT**: Use `build-auto-installer-iso.sh` (or `build-unbundled-iso.sh`) only. The deprecated `build-debian-iso.sh` causes boot-to-prompt issues.
|
||||
| File | Role |
|
||||
|------|------|
|
||||
| `image-recipe/build-auto-installer-iso.sh` | Main build script (~2600 lines) |
|
||||
| `image-recipe/build-unbundled-iso.sh` | Wrapper: sets UNBUNDLED=1 |
|
||||
| `image-recipe/branding/isohdpfx.bin` | Proven MBR (432 bytes) |
|
||||
| `image-recipe/branding/grub-theme/` | GRUB theme + background |
|
||||
| `image-recipe/branding/plymouth-theme/` | Plymouth boot splash |
|
||||
| `scripts/image-versions.sh` | Pinned container image versions |
|
||||
| `.gitea/workflows/build-iso-dev.yml` | CI for dev-iso branch |
|
||||
| `image-recipe/test-iso-qemu.sh` | QEMU test script |
|
||||
| `image-recipe/dev-branding.sh` | Quick branding iteration |
|
||||
|
||||
Reference in New Issue
Block a user