Companion to `spec.md` §17.5. Status: **installed and running** since 2026-09-27 as the systemd service `oxygenhub` under the `oxygenhub` system user, data in `/home/oxygenhub/data`, HTTP on 7300 and HTTPS on 7343 with a self-signed certificate. `oxygen`, `oxygen-vscode` and `oxygenhub` are hosted under `andymccall/` and each checkout has an `earth` remote.
| Already running | sshd :22, a Python service :6400, `wren-nest` :7842, retroplay-manager in Docker (:8080, :6670) with Postgres and a tetriblox server, two GitHub Actions runners (`doomsdayonecom`), Docker, containerd |
13
| Not installed | Rust toolchain, sqlite3 CLI, nginx or caddy, certbot |
2.**Source**: from the development machine, `rsync -a --delete --exclude target --exclude node_modules ~/development/oxygen ~/development/oxygenhub claude@earth:~/src/`. Oxygen is never pushed to Git; rsync is the bootstrap, and after the hub runs, `oxy push` to the hub itself is the ongoing path.
6.**TLS**: the developer edition generates a self-signed certificate at `init`. Download the certificate from `https://earth.andymccall.xyz:7343/.well-known/oxyhub-ca.pem` (or over plain HTTP on port 7300) and point clients at it with `oxy config remote.<name>.ca <file>` or `OXY_CA`.
7.**First repositories**: on the development machine, `oxy remote add earth https://oxygenhub.io/andymccall/oxygen` in each of `oxygen`, `oxygen-vscode`, `oxygenhub`, then `oxy push earth`.
9.**Public address** (2026-09-30): a Cloudflare tunnel on Earth serves the hub as `https://oxygenhub.io`, with a publicly trusted certificate, and `base_url` in `hub.toml` is that address, so every link the hub writes uses it. Checkouts push there with no CA set, and subrepo URLs name it too.
29
10.**Localhost only** (2026-09-30): the tunnel connects to `127.0.0.1:7300`, so the hub binds `127.0.0.1:7300` and `127.0.0.1:7343` and nothing on the LAN reaches it directly; `behind_proxy = true` (the hub does not yet use client addresses). The Flow runner on Earth polls `http://127.0.0.1:7300`. Backups: `hub.toml.before-localhost`, `~/flow/flow.toml.before-localhost`.
`ListenStream` is the address `server.bind` names in `hub.toml` (Earth's is `127.0.0.1:7300`, behind cloudflared). Then give `oxygenhub.service``Requires=oxygenhub.socket`,
On Earth the three service lines are a drop-in, `/etc/systemd/system/oxygenhub.service.d/socket.conf` (installed 2026-10-17; a restart under 10 requests a second then answered all 120 with 200).
| Sources |`/home/claude/src/oxygen`, `/home/claude/src/oxygenhub` (rsync targets; the hub itself is the canonical remote) |
80
| Data |`/home/oxygenhub/data` (`hub.toml`, `hub.db`, `keys/`, `repos/andymccall/*`) |
81
| Push token |`/home/oxygenhub/push-token` (also in `hub.toml`); each local checkout has it as `remote.earth.token`|
82
| Certificate |`/home/oxygenhub/data/keys/tls.crt`, served at `/.well-known/oxyhub-ca.pem`; local copy `~/.config/oxy/earth-ca.pem` set as `remote.earth.ca`|
83
| Service |`sudo systemctl status oxygenhub`, `sudo journalctl -u oxygenhub`|