diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5acd172 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Gavin Nugent + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..4ad59b6 --- /dev/null +++ b/README.md @@ -0,0 +1,120 @@ +# 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).