# once-add Deploy and remove a [Once](https://once.com) app at a single-label `.local` host. Adds the right `/etc/hosts` entry, runs `once deploy --disable-tls`, and (on removal) cleans the `/etc/hosts` line that the Once UI orphans. ## Why it's needed Once's binary is statically linked (pure-Go resolver), so its post-deploy `GET /up` verify resolves `/etc/hosts` + real DNS only — never mDNS — and the TUI install forces TLS on (no Let's Encrypt cert for a private `.local`). Either one makes Once roll back the container. `once-add` runs the working recipe: ```sh echo "127.0.0.1 .local" | sudo tee -a /etc/hosts # so Once's verify resolves it once deploy --host .local --disable-tls # TLS off; http verify passes ``` For other machines on your LAN to reach the site you'll also need an mDNS publisher running on the box (something that announces `.local` over Avahi). Without one, the site is only reachable from the hosting box itself. ## Install ```sh curl -fsSL https://github.com/28allday/once-add/releases/latest/download/once-add \ -o once-add && sudo install -m 755 once-add /usr/local/bin/once-add && rm once-add ``` ## Usage Runs as root (it edits `/etc/hosts`); self-elevates with `sudo` if needed. ```sh once-add # interactive wizard (Add / Remove) once-add book ghcr.io/basecamp/writebook # add (non-interactive) once-add remove book # remove app + its /etc/hosts entry once-add remove book --data # also delete the data volume (irreversible) once-add remove # interactive remove picker ``` **Add** wizard: pick a curated app (or a custom image) → name it → deploy → reachable at `http://.local`. **Remove** runs `once remove ` and then clears the `/etc/hosts` line once-add added (the Once UI removes the container but orphans that line). Data volumes are kept by default — pass `--data` (or tick the toggle in the wizard) to delete them too. If the app is already gone, the orphaned `/etc/hosts` line is cleaned up anyway. ## Curated apps Edit `/etc/once-add/apps.toml` to add entries — no rebuild needed. `once-add` seeds a default file (Writebook, Campfire) on first run if it's missing. ```toml [[app]] name = "Writebook" image = "ghcr.io/basecamp/writebook" description = "Books & documentation" suggested = "book" ``` ## Build ```sh CGO_ENABLED=0 go build -o once-add ./cmd/once-add # static binary go test ./... ``` ## Licence MIT.