`cat > "$WORK_DIR/Dockerfile.rootfs" <<DOCKERFILE` was unquoted, so the build shell performed command substitution on the Dockerfile body. Any backtick in a Dockerfile COMMENT was executed on the build host and its output spliced into the generated file. Six comments did this. One of them ran `systemctl start archipelago-fips.service` against the build machine on every ISO build; the others were harmless only by accident of being command-not-found. Fixes the class, not the six instances. The delimiter is now quoted, so the body is emitted verbatim and a future backticked comment is inert. Verified the boundary by line range first: the other backticked comments in this file (:264, :809, :1188, :1289, :1506, :1605, :3597, :3651) are ordinary shell comments outside any unquoted heredoc and were never at risk — they are untouched. The body needs exactly four build-time values and they are all package names (LINUX_IMAGE_PKG, GRUB_EFI_PKG, GRUB_EFI_SIGNED_PKG, GRUB_PC_PKG), on four consecutive lines. So quoting was practical: the heredoc is split into DOCKERFILE_HEAD and DOCKERFILE_TAIL, both quoted, with a single explicit printf interpolating those four names between them. Escapes that existed only because the heredoc was unquoted are undone in the same pass: six trailing `\\` become `\` (Docker line continuations) and four `\$` become `$` (RUN arguments reach the shell verbatim — Docker does not substitute variables in RUN). Verified by rendering the generated Dockerfile before and after with the same inputs and diffing them normalised (continuations joined, whitespace collapsed). Both are 190 normalised lines and the ONLY differences are the six comments regaining their text — every instruction is byte-identical. Before: "# the archipelago backend calls" / after: "# the archipelago backend calls `systemctl start archipelago-fips.service`". Test: case 7 asserts every heredoc writing Dockerfile.rootfs has a quoted delimiter, and when one is not, reports which body lines would execute. The assertion is on the delimiter, not on backticks — with quoting a backticked comment is legal and six of them are back in the body on purpose, so flagging backticks would flag a non-bug and fail on the very comments this restored. This bug is invisible to `bash -n`; an instance of it introduced earlier in this plan hung a syntactically-clean build for two minutes before being caught. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Archipelago OS Image Recipes
Build scripts for creating bootable Debian Linux OS images for Archipelago Bitcoin Node OS.
Quick Start
Build the ISO
# 1. Sync latest configs from live dev server
./sync-from-live.sh
# 2. Build components
./scripts/build-backend.sh
./scripts/build-frontend.sh
# 3. Build the ISO
./build-debian-iso.sh
This creates a bootable Debian Live ISO with Archipelago pre-installed.
Write to USB
# Using dd (recommended)
./write-usb-dd.sh /dev/diskN
# Or use Balena Etcher to flash the ISO
See the ISO-BUILD-CHECKLIST.md for a comprehensive build workflow.
See the Architecture documentation for detailed system information.
What's Included
- Debian Linux Base: Debian 13 (Trixie) with security updates applied during ISO/install creation
- Podman: Container runtime for apps (rootless by default)
- Archipelago Backend: Rust-based API server
- Archipelago Frontend: Vue.js web interface
- Systemd Services: Automatic service management
- Network Configuration: NetworkManager for easy setup
Build Output
results/archipelago-installer-x86_64.iso- Bootable hybrid ISO image
Supported Platforms
- x86_64: Dell OptiPlex, HP ProDesk 400 G4 DM, Start9 Server Pure, and other x86_64 machines
- Build Systems: macOS (requires Docker) and Linux (native or Docker)
Installation Methods
1. Live USB Boot
Boot from USB, run in live mode to test, or install to disk.
2. Full Disk Installation
From the live environment, run:
sudo /archipelago/install-to-disk.sh
This installs Archipelago to a target disk using debootstrap.
Directory Structure
image-recipe/
├── build-debian-iso.sh # Main ISO builder
├── write-usb-dd.sh # Write ISO to USB with dd
├── create-fat32-usb.sh # Alternative USB creation
├── archipelago-scripts/ # Scripts included in ISO
│ ├── install-to-disk.sh # Disk installer
│ └── setup-bitcoin.sh # Bitcoin Core setup
├── scripts/ # Build helper scripts
│ ├── build-backend.sh # Compile Rust backend
│ ├── build-frontend.sh # Build Vue.js frontend
│ └── check-dependencies.sh # Verify build requirements
└── results/ # Built ISO output
Requirements
- Docker (for macOS builds)
- xorriso (for ISO creation):
brew install xorriso - 7zip (for ISO extraction):
brew install p7zip