Major ISO build overhaul on dev-iso branch: - Replace ~800MB Debian Live download with debootstrap --variant=minbase (~150MB installer squashfs built from scratch) - Custom initramfs with archipelago-mount hook for boot media detection - Systemd service auto-starts installer (replaces profile.d hack) - GRUB + ISOLINUX configs written from scratch (no Debian Live dependency) - EFI boot image built with grub-mkimage (no more MBR extraction) - Archipelago GRUB theme: dark background, Bitcoin orange accents - Theme installed on both installer ISO and target system - Rootfs optimizations: --no-install-recommends, strip docs/man/locales, remove firmware-misc-nonfree/wget/htop, add explicit font deps - Separate CI workflow (build-iso-dev.yml) for dev-iso branch - Includes pre-existing fixes from main (build-iso.yml, middleware, Login) Target: sub-2GB unbundled ISO (down from 3.9GB) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
244 lines
9.4 KiB
Markdown
244 lines
9.4 KiB
Markdown
# ISO Overhaul: Custom Minimal Base + Branding + Size Optimization
|
|
|
|
## Context
|
|
|
|
The Archipelago ISO is ~3.9GB — too large. The root cause is a ~800MB Debian Live ISO used as the boot base, plus a ~2.1GB rootfs with no `--no-install-recommends`. We're replacing the Debian Live dependency entirely with a custom debootstrap-built installer, adding full Archipelago branding to the boot chain, and stripping the rootfs. Target: sub-2GB ISO.
|
|
|
|
All work on `dev-iso` branch with its own CI workflow. Main branch stays untouched.
|
|
|
|
---
|
|
|
|
## Phase 0: Branch + CI Setup
|
|
|
|
**Create `dev-iso` branch and separate CI workflow.**
|
|
|
|
1. Branch from current `main`
|
|
2. Create `.gitea/workflows/build-iso-dev.yml`:
|
|
- Trigger: `push: branches: [dev-iso]` + `workflow_dispatch`
|
|
- Same structure as `build-iso.yml` (131 lines) but:
|
|
- Remove "Cache Debian Live ISO" step (no longer needed)
|
|
- Add `debootstrap`, `squashfs-tools`, `isolinux`, `syslinux-common`, `mtools`, `grub-efi-amd64-bin`, `grub-pc-bin` to tool dependencies
|
|
- Output naming: `archipelago-dev-unbundled-{date}.iso`
|
|
- Keep: backend build, frontend build, type check, tests, build report
|
|
3. Push and verify CI triggers on .228 runner
|
|
|
|
**Files:**
|
|
- New: `.gitea/workflows/build-iso-dev.yml`
|
|
|
|
---
|
|
|
|
## Phase 1: Rootfs Size Optimizations
|
|
|
|
**Shrink rootfs.tar from ~2.1GB to ~1.5GB. Only touches the Dockerfile heredoc in Step 1 (lines 210-335).**
|
|
|
|
### 1.1 Add `--no-install-recommends`
|
|
- Line 229: `apt-get install -y` → `apt-get install -y --no-install-recommends`
|
|
- Line 269: Same for Tailscale install
|
|
- Explicitly add packages that may be needed as recommends: `fonts-liberation`, `xfonts-base` (for Chromium kiosk)
|
|
- **Saves: ~150-300MB**
|
|
|
|
### 1.2 Remove `firmware-misc-nonfree`
|
|
- Line 257: Remove `firmware-misc-nonfree` from package list
|
|
- Keep: `firmware-realtek`, `firmware-iwlwifi`, `intel-microcode`, `amd64-microcode`
|
|
- **Saves: ~50-80MB**
|
|
|
|
### 1.3 Strip docs/man/locales
|
|
- Add after line 264 (after apt-get clean):
|
|
```dockerfile
|
|
RUN find /usr/share/doc -depth -type f ! -name copyright -delete 2>/dev/null; \
|
|
find /usr/share/doc -empty -delete 2>/dev/null; \
|
|
rm -rf /usr/share/man /usr/share/info /usr/share/lintian /usr/share/linda; \
|
|
find /usr/share/locale -maxdepth 1 -mindepth 1 ! -name 'en_US' ! -name 'locale.alias' -exec rm -rf {} +
|
|
```
|
|
- **Saves: ~50-80MB**
|
|
|
|
### 1.4 Remove `wget` and `htop`
|
|
- Lines 244, 246: Remove `wget` (curl covers it) and `htop` (luxury tool)
|
|
- Keep `git` (used by self-update system)
|
|
- **Saves: ~5MB** (minor but removes unnecessary surface)
|
|
|
|
### Verification
|
|
- Build ISO, compare rootfs.tar size
|
|
- Boot in QEMU, verify: kiosk renders, SSH works, nginx serves UI, podman runs
|
|
|
|
**Files modified:**
|
|
- `image-recipe/build-auto-installer-iso.sh` (Step 1 Dockerfile heredoc, lines 210-335)
|
|
|
|
---
|
|
|
|
## Phase 2: Replace Debian Live with Custom Debootstrap Base
|
|
|
|
**The big one. Replaces Steps 2, 5, and parts of 4 and 6.**
|
|
|
|
### 2.1 New Step 2: Build Minimal Installer Environment
|
|
|
|
Replace lines 420-502 entirely. Run debootstrap inside a container to produce:
|
|
- `vmlinuz` — kernel (reused from linux-image-amd64)
|
|
- `initrd.img` — custom initramfs with ISO-mount hook
|
|
- `filesystem.squashfs` — minimal Debian root (~120-180MB)
|
|
|
|
The installer squashfs contains only what's needed to run the auto-install script:
|
|
- `debootstrap --variant=minbase --include=systemd,systemd-sysv,udev,bash,coreutils,mount,util-linux,cryptsetup,parted,dosfstools,e2fsprogs,kmod,procps,iproute2,ca-certificates,gdisk`
|
|
- Auto-login on tty1 via getty override
|
|
- systemd service that auto-starts the installer (replaces profile.d hack)
|
|
|
|
**Key: Custom initramfs hook** (`local-bottom/archipelago-mount`) that:
|
|
1. Scans `/dev/sr0`, `/dev/sd*` for a partition containing `archipelago/auto-install.sh`
|
|
2. Mounts it read-only at `/run/archiso`
|
|
3. This replaces Debian Live's `boot=live components` mechanism
|
|
|
|
### 2.2 New Step 5: Assemble ISO Directory
|
|
|
|
Replace lines 2236-2448 entirely. Much simpler — no squashfs overlay mechanism, no tools extraction (tools are in the squashfs), no profile.d manipulation.
|
|
|
|
New Step 5 just assembles the directory structure:
|
|
```
|
|
$INSTALLER_ISO/
|
|
live/
|
|
vmlinuz
|
|
initrd.img
|
|
filesystem.squashfs
|
|
boot/grub/
|
|
grub.cfg
|
|
themes/archipelago/ (Phase 3)
|
|
efi.img (built with grub-mkimage)
|
|
isolinux/
|
|
isolinux.bin
|
|
ldlinux.c32
|
|
isolinux.cfg
|
|
EFI/BOOT/
|
|
BOOTX64.EFI (built with grub-mkimage)
|
|
archipelago/
|
|
auto-install.sh
|
|
rootfs.tar
|
|
bin/archipelago
|
|
web-ui/
|
|
scripts/
|
|
container-images/ (if bundled)
|
|
```
|
|
|
|
Generate EFI boot image with `grub-mkimage` and ISOLINUX files from the `isolinux` package. No more extracting MBR from Debian Live.
|
|
|
|
### 2.3 Updated Step 6: ISO Creation
|
|
|
|
Replace lines 2461-2511 (MBR extraction + EFI image search). Use:
|
|
- MBR: `/usr/lib/ISOLINUX/isohdpfx.bin` (from `isolinux` package)
|
|
- EFI: `boot/grub/efi.img` (built in Step 5)
|
|
- xorriso command stays the same structure
|
|
|
|
### 2.4 Update Boot Media Paths in Step 4 (auto-install.sh)
|
|
|
|
Lines 1154-1155: Add `/run/archiso` as first search path:
|
|
```bash
|
|
for dev in /run/archiso /cdrom /media/cdrom /run/live/medium /lib/live/mount/medium; do
|
|
```
|
|
|
|
Also update lines 2326, 2377 (no longer needed — replaced by systemd service in installer squashfs).
|
|
|
|
### 2.5 Remove Debian Live cleanup from auto-install.sh
|
|
|
|
The installed system's auto-install script currently removes `live-boot`, `live-boot-initramfs-tools`, `live-config` (around line 1872). With the custom base, these packages won't exist in the rootfs, so this cleanup becomes a harmless no-op — but should be cleaned up for clarity.
|
|
|
|
### Verification
|
|
- Build ISO, verify size < 2GB
|
|
- Boot in QEMU (UEFI mode): verify GRUB menu → installer → full install → reboot
|
|
- Boot in QEMU (BIOS mode): verify ISOLINUX → installer → full install → reboot
|
|
- After install: SSH, web UI, kiosk, container loading all work
|
|
- Test `test-iso-qemu.sh` (may need minor path updates)
|
|
|
|
**Files modified:**
|
|
- `image-recipe/build-auto-installer-iso.sh` (Steps 2, 4, 5, 6 — major rewrite)
|
|
|
|
---
|
|
|
|
## Phase 3: Archipelago Boot Branding
|
|
|
|
**Custom GRUB theme, installer banner, installed system GRUB.**
|
|
|
|
### 3.1 Create GRUB Theme
|
|
|
|
New directory: `image-recipe/branding/grub-theme/`
|
|
- `theme.txt` — dark background (#0a0a0a), white text, Bitcoin orange (#f7931a) highlight
|
|
- `background.png` — 1920x1080 dark with subtle Archipelago logo watermark
|
|
- Font files (`.pf2`) — generated with `grub-mkfont` from DejaVu Sans during build
|
|
|
|
GRUB menu entries:
|
|
- "Install Archipelago" (default, quiet boot)
|
|
- "Install Archipelago (verbose)" (no `quiet`, for debugging)
|
|
- "Boot from local disk" (chainloader)
|
|
|
|
### 3.2 Create ISOLINUX Theme
|
|
|
|
New file: `image-recipe/branding/isolinux.cfg`
|
|
- Matching dark theme for legacy BIOS boot
|
|
- Same menu entries as GRUB
|
|
|
|
### 3.3 Branded Installer Banner
|
|
|
|
The systemd service's start script displays:
|
|
```
|
|
ARCHIPELAGO BITCOIN NODE OS
|
|
Automatic Installer v0.1.0
|
|
|
|
Press Enter to start installation...
|
|
```
|
|
|
|
### 3.4 Install GRUB Theme to Target System
|
|
|
|
In Step 4 (auto-install.sh), before `update-grub` (around line 1888):
|
|
- Copy GRUB theme from ISO to `/mnt/target/boot/grub/themes/archipelago/`
|
|
- Add `GRUB_THEME="/boot/grub/themes/archipelago/theme.txt"` to `/mnt/target/etc/default/grub`
|
|
- The installed system boots with Archipelago branding, not Debian default
|
|
|
|
### 3.5 Create Background Image
|
|
|
|
Render from existing SVG favicon (`neode-ui/public/assets/icon/favico-black-v2.svg`) to PNG at appropriate sizes. Dark background with subtle centered logo.
|
|
|
|
### Verification
|
|
- Boot ISO: GRUB shows Archipelago theme (dark + orange)
|
|
- No Debian branding visible anywhere
|
|
- After install: target system GRUB also shows Archipelago theme
|
|
|
|
**Files:**
|
|
- New: `image-recipe/branding/grub-theme/theme.txt`
|
|
- New: `image-recipe/branding/grub-theme/background.png`
|
|
- New: `image-recipe/branding/isolinux.cfg`
|
|
- Modified: `image-recipe/build-auto-installer-iso.sh` (Steps 5, 4)
|
|
|
|
---
|
|
|
|
## Risk Areas
|
|
|
|
| Risk | Severity | Mitigation |
|
|
|------|----------|------------|
|
|
| Custom initramfs fails to find USB media | High | Test multiple USB controller types in QEMU; add verbose fallback boot option |
|
|
| Missing packages in minbase break install | Medium | Trace auto-install.sh dependencies; test full install flow |
|
|
| GRUB EFI image missing modules | High | Include all common modules in grub-mkimage; test UEFI + BIOS |
|
|
| Kiosk breaks without recommends | Medium | Explicitly add Chromium/X11 font deps; test kiosk before merge |
|
|
| initramfs overlayfs mount fails | High | Follow well-established patterns from Arch/Ubuntu live ISOs |
|
|
|
|
---
|
|
|
|
## Implementation Order
|
|
|
|
1. **Phase 0** — branch + CI (~1 hour)
|
|
2. **Phase 1** — rootfs size opts (~2 hours, push + verify)
|
|
3. **Phase 2** — custom base (~8-10 hours, iterative QEMU testing)
|
|
4. **Phase 3** — branding (~3 hours)
|
|
|
|
Phases are sequential — each builds on the previous. Push after each phase, verify CI passes.
|
|
|
|
---
|
|
|
|
## Key Files
|
|
|
|
| File | Role |
|
|
|------|------|
|
|
| `image-recipe/build-auto-installer-iso.sh` | Main build script — most changes here |
|
|
| `.gitea/workflows/build-iso-dev.yml` | New CI workflow for dev-iso branch |
|
|
| `image-recipe/branding/grub-theme/*` | New GRUB theme assets |
|
|
| `image-recipe/branding/isolinux.cfg` | New ISOLINUX config |
|
|
| `image-recipe/test-iso-qemu.sh` | QEMU test script (minor updates) |
|
|
| `.gitea/workflows/build-iso.yml` | Reference for new CI workflow |
|
|
| `scripts/image-versions.sh` | Unchanged — container image versions |
|