# Live ISO build Builds a bootable Arch-based live ISO that auto-starts the Flask webinstaller from `../webinstaller/` on boot. User plugs in a USB, boots, and the installer wizard comes up on `http://proksi.local:5000` (or the raw IP shown on the console). Runnable locally (below) or through Forgejo Actions — `.forgejo/workflows/build-iso.yml` builds on every push to `main` and on manual `workflow_dispatch`. The ISO lands as an artifact named `furtka-iso`, retained for 14 days. Feature branches don't trigger the ISO build; see `memory/project_ci_branching` for why. ## Run a build locally Needs a host with Docker. Disk space required: ~15 GB scratch during the build, ~1.5 GB for the final ISO. ```bash ./iso/build.sh ``` Output ISO ends up in `iso/out/furtka--x86_64.iso`. Around 3–10 min on a 4-core VM. First run is slower because it pulls `archlinux:latest` and all packages from upstream. The script re-execs itself inside a privileged `archlinux:latest` container. That's so `mkarchiso` has root + loop-mount access without polluting the host — Ubuntu hosts don't ship archiso natively anyway. ## What gets baked in The build starts from Arch's stock `releng` profile (the same one used to build the official Arch ISO), then overlays our customizations from `overlay/`: | Overlay file | Effect | |----------------------------------------------|----------------------------------------------------------------------------------| | `overlay/packages.extra` | Appended to the package list. Adds `python`, `python-flask`, `avahi`, `nss-mdns` | | `overlay/profiledef.sh` | Appended to `profiledef.sh`. Renames the ISO to `furtka-*` with a dated version | | `overlay/airootfs/opt/furtka/` | Directory where `webinstaller/` is copied at build time | | `overlay/airootfs/etc/hostname` | Live-ISO hostname (`proksi`) so mDNS advertises the installer as `proksi.local` | | `overlay/airootfs/etc/issue` | Welcome banner on the TTY pointing users at `http://proksi.local:5000` | | `overlay/airootfs/usr/local/bin/furtka-update-issue` | Rewrites `/etc/issue` at runtime so the banner also shows the DHCP-assigned IP as a fallback URL | | `overlay/airootfs/etc/systemd/system/` | `furtka-webinstaller.service` (Flask on :5000) + `furtka-issue.service` (runs the banner-updater on network-online), each symlinked into `multi-user.target.wants/` to auto-start on boot | The systemd service runs `flask --app app run --host 0.0.0.0 --port 5000` under `/opt/furtka`. The `0.0.0.0` binding is important — the Flask default is localhost-only, which wouldn't be reachable from another machine on the LAN. mDNS is wired: `avahi-daemon` + `nss-mdns` come from `packages.extra`, the live ISO's hostname is `proksi`, and as soon as `systemd-networkd-wait-online` fires the installer is reachable at `http://proksi.local:5000`. The raw IP still shows on the console for fallback — some Windows clients need the Bonjour service for `.local` to resolve at all. ## Test flow 1. Build: `./iso/build.sh` 2. Copy the ISO to your Proxmox host's ISO storage (typically `/var/lib/vz/template/iso/`). Browser uploads of 1.5 GB truncate silently — prefer `scp` over the Proxmox WebUI. 3. Create a VM with: - 2 vCPU, 4 GB RAM, 20 GB disk (empty) - **BIOS: OVMF (UEFI)**, add EFI Disk on `local-lvm`. SeaBIOS fails to load `ldlinux.c32` from our ISO; only the UEFI path works reliably. - **Secure Boot disabled**. Our GRUB isn't signed, so Secure Boot rejects it with `Access Denied`. Either boot into OVMF setup (Esc during boot) → Device Manager → Secure Boot Configuration → Attempt Secure Boot [ ] → F10 → reboot. Or remove the EFI Disk and re-add it with "Pre-Enroll keys" unchecked. - CD-ROM attached with the Furtka ISO - Boot order: CD before disk - Network: same bridge as your LAN, DHCP 4. Start the VM. Wait ~30 s for boot. 5. Find its IP in Proxmox's VM summary (or your router's DHCP table) 6. Open `http://:5000` — the existing 3-screen wizard should be there ## What you see after install + reboot Once `archinstall` finishes and you click **Reboot now**, the VM comes up into the installed system. No more port `:5000` — the wizard ISO is gone. Instead: - **Console**: agetty shows `Furtka is ready. Open http://.local …` with the IP fallback underneath. - **Browser** at `http://.local` (default `http://furtka.local` — the form's default hostname is `furtka`; only the live-installer ISO uses `proksi`): Caddy-served landing page with three live status tiles (uptime, Docker version, free disk) refreshed every 30 s by `furtka-status.timer`. HTTPS is opt-in (26.15-alpha) — flip the toggle in `/settings` to switch on Caddy's `tls internal` on `:443`, then trust `rootCA.crt` from `/settings` to clear browser warnings. - **SSH**: `ssh @.local` works; `docker ps` works without `sudo` because the user is in the `docker` group. This is a demo shell — no Authentik, no app store yet. The landing page lives at `/srv/furtka/www/`, served by Caddy on `:80` per `/etc/caddy/Caddyfile`. All of this is written into the target by `webinstaller/app.py`'s `_post_install_commands` via archinstall's `custom_commands`. ## Known rough edges - **Disk space**: the first time you build on a fresh host, the squashfs/xorriso steps need ~15 GB free. If the host's LVM-root is smaller, `xorriso` silently dies at the very end with "Image size exceeds free space on media". - **Live-installer wizard is still HTTP-only**. `http://proksi.local:5000` during install has no TLS; once the box reboots, Caddy can serve `tls internal` on `:443` if the user opts in via `/settings` (26.15-alpha), but bringing TLS to the wizard itself is a later milestone.