omaserver/README.md
28allday 3b2707a8bd omaserver v0.1.0: one-shot hardened Arch VPS + native OMATERM
Single SSH session takes a fresh Arch box to a locked-down server running
native OMATERM (28allday/omaterm@native-frozen, fetched read-only at runtime).

- Phase A: hardening (deploy user, key-only SSH, ufw 22+tailscale0, fail2ban,
  weekly updates, swap, journal cap) — proven on tyler + durden 2026-06-06
- Phase B: hands off to install-native.sh as the deploy user with a real TTY;
  recovery net resumes first-run setup and lands in a shell if the chain
  exits early instead of dropping the SSH session
- Every answer asked once: machine name = hostname + tailnet name + ssh
  alias; git identity pre-seeds ~/.gitconfig so omaterm setup skips it;
  answers survive the kernel-upgrade reboot
- Kernel-upgrade guard offers the reboot in-script with exact resume command

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-06 16:35:23 +01:00

54 lines
2.8 KiB
Markdown

# omaserver
One-shot bootstrap for a fresh Arch Linux VPS: **hardened server + native [OMATERM](https://omaterm.org)**, in a single SSH session.
Part of the oma-family: [omalocal](https://github.com/28allday/omalocal) installs OMATERM on local hardware via a custom ISO — **omaserver** does the same job for a remote box you can only reach over SSH.
## Usage
Run as root on a fresh Arch VPS, **with a TTY** (the install ends in an interactive omaterm session):
```bash
ssh -t root@YOUR_SERVER 'bash <(curl -fsSL https://raw.githubusercontent.com/28allday/omaserver/main/install-server.sh)'
```
Answer four questions up front (machine name, deploy user, optional git identity) — each is asked **once** and reused everywhere:
| Answer | Used for |
|---|---|
| Machine name | hostname, Tailscale machine name, your local `ssh <name>` alias |
| Deploy user | the locked-down account that replaces root |
| Git identity | pre-seeds `~/.gitconfig` so omaterm's setup skips its git prompts |
If the first `pacman -Syu` upgrades the kernel, the script offers to reboot and your answers survive — reconnect, re-run the same command, and it picks up where it left off.
## What it does
**Phase A — hardening (as root)**
- Deploy user with key-only SSH (root's `authorized_keys` copied over), passwordless sudo
- Root SSH login disabled, password auth disabled, `AllowUsers <deploy-user>`
- UFW: deny incoming, allow 22/tcp + the `tailscale0` interface only
- fail2ban (systemd journal backend, ufw banaction)
- Weekly `pacman -Syu` timer, weekly package-cache pruning, 50MB journal cap
- 2GB swap (btrfs-aware; skipped if the image ships its own)
- Hostname, timezone, locale
**Phase B — OMATERM (as the deploy user)**
Hands off to the native OMATERM installer — packages, dotfiles, AI agents (claude, codex, gemini, opencode via mise), tmux workspace — then runs OMATERM's interactive first-run setup (GitHub, Tailscale, 1Password). The Tailscale hostname comes pre-filled with your machine name.
You end up inside a tmux session on a hardened box. If any part of the interactive setup bails early, the installer wrapper catches it, resumes setup, and lands you in a shell — the session is never just dropped.
To re-run or resume the OMATERM part later: `ssh -t <name> ./install-omaterm`
## Notes
- **Arch only** — refuses to run elsewhere.
- OMATERM is installed **natively** (no container) from the pinned fork [`28allday/omaterm@native-frozen`](https://github.com/28allday/omaterm/tree/native-frozen), which preserves the last upstream native install path. The fork is read-only at runtime; nothing is ever pushed to it.
- Want hardening without OMATERM? That's [arch-boot-strap](https://github.com/28allday/arch-boot-strap).
- Safe to re-run; completed steps skip themselves. After the first run root SSH login is disabled, so re-run as the deploy user with `sudo`.
## License
MIT