# omalocal **One script that turns a stock Arch Linux ISO into a headless, key-only-SSH Arch *server* installer ISO** — one that, on first login, offers to bootstrap the [OMATERM](https://omaterm.org) terminal toolkit and [Once](https://once.com) (Basecamp's self-hosted app deployment platform). Burn it to a USB stick (Ventoy or `dd`) and you get a reproducible, minimal Arch server that's ready for self-hosting in minutes. > **Not affiliated with OMATERM or Once.** `omalocal` is an *ISO builder*. It > bundles and runs the official upstream installers; it does not vendor or fork > them. --- ## What you get Booting the generated ISO runs an automated installer that produces a **headless Arch Linux server**: - **UEFI-only**, systemd-boot, single 512 MB EFI partition + ext4 root. - **Key-only SSH** — your public key is baked in at build time; password auth and root login over SSH are disabled. - **Reachable on the LAN as `.local`** via Avahi/mDNS (`ssh you@host.local`). - **Docker** installed and enabled out of the box. - **ufw** firewall: deny incoming by default, allowing `22`, `80`, `443`, `5353/udp` (mDNS) and `53317` (LocalSend). - On **first interactive login**, a one-time prompt offers to install Once, [Omarchy-Send](https://github.com/28allday/omarchy-send) (optional), and OMATERM — after which you're dropped straight into your new tmux session. - A small `once-mdns-sync` daemon that auto-publishes `.local` for each Once app you deploy, so they're reachable across the LAN with no per-app setup. --- ## Requirements (on the build machine) - A Linux box with: `xorriso`, `squashfs-tools`, `git`, `sha512sum`, `sudo`. - A **stock Arch ISO** (filename starting with `archlinux-`) from , placed next to the script. - An SSH public key (used for the headless server's only login method). ## Build the ISO ```sh # 1. Drop a stock Arch ISO into this folder: # archlinux-x86_64.iso # 2. Run the builder (it needs sudo for squashfs work): ./omalocal.sh # 3. Output: # omalocal-arch-YYYYMMDD.iso (Ventoy-compatible, dd-bootable) ``` By default the builder uses `~/.ssh/id_ed25519.pub` (falling back to `~/.ssh/id_rsa.pub`) as the server's authorized key. Override with: ```sh SSH_PUBKEY=/path/to/key.pub ./omalocal.sh ``` ## Install onto a machine Either drop `omalocal-arch-*.iso` onto a [Ventoy](https://www.ventoy.net/) USB, or write it to a stick directly: ```sh sudo dd if=omalocal-arch-YYYYMMDD.iso of=/dev/sdX bs=4M status=progress conv=fsync ``` Boot the target in **UEFI** mode. The installer auto-starts on the console: it brings up networking (wired or Wi-Fi), prompts for hostname / user / password / target disk (with a type-to-confirm guard before it wipes anything), installs the base system, and reboots into your headless server. ## First login SSH in with the key you baked in: ```sh ssh @.local ``` You'll be asked once whether to set the server up. Saying yes installs **Once**, optionally **Omarchy-Send**, then **OMATERM**, and leaves you in tmux. ### Deploying a Once app reachable on the LAN Use the bundled `once-add` helper (single-label `.local` name, served over HTTP): ```sh once-add # interactive wizard once-add book ghcr.io/basecamp/writebook # non-interactive # -> reachable at http://book.local from any machine on the LAN ``` --- ## How it works `omalocal.sh` is self-contained. It: 1. Extracts `airootfs.sfs` from the stock ISO and unsquashes it. 2. Injects an installer payload (auto-launched on `tty1`) plus your SSH key. 3. Patches boot cmdlines (`rootdelay=60` for slow USB enumeration) and re-squashes. 4. Repacks the ISO, preserving the stock boot config, hybrid MBR and volume UUID so it stays bootable and Ventoy-friendly. The installed system's first-login helper, the LAN-deploy recipe, and a bundled Claude Code skill / `CLAUDE.md` are all embedded in the single script. ## Notes & caveats - **UEFI only** — the installer aborts on legacy BIOS boot. - The installer **wipes the disk you select** (it asks you to type the path to confirm). Double-check the target. - The build needs `sudo` to manipulate the squashfs image. ## License MIT — see [`LICENSE`](LICENSE).