OXYGENHUB
◆ v0.3.0 oxygenhub / docs / deploy.md
4.1 KiB · Markdown · last changed Earth serves the hub on localhost only, behind the tunnel 1 month ago renderedsource blame history raw

Deploying the developer edition on Earth

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.

The host

Nameearth (earth.andymccall.xyz, IPv6 ULA; 192.168.1.6 on the LAN)
OSUbuntu 26.04.1 LTS, x86_64, 4 cores, 31 GiB RAM
Disk/ 251 GB (95 GB free), /home 1 TB (944 GB free)
Already runningsshd :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
Not installedRust toolchain, sqlite3 CLI, nginx or caddy, certbot
Accessssh -i ~/.ssh/earth_claude claude@earth; claude has passwordless sudo

Ports 7300 (HTTP) and 7343 (HTTPS) are free and are the hub's.

Steps

  1. Toolchain (as claude): curl https://sh.rustup.rs -sSf | sh -s -- -y --profile minimal, then sudo apt-get install -y build-essential pkg-config git.
  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.
  3. Build: cd ~/src/oxygenhub && cargo build --release.
  4. System user and data: sudo useradd --system --home /home/oxygenhub --create-home oxygenhub, sudo install -o oxygenhub -g oxygenhub -m 0755 target/release/oxygenhub /usr/local/bin/, sudo -u oxygenhub oxygenhub init --data /home/oxygenhub/data --admin andymccall (prints the first admin's one-time password).
  5. Service: /etc/systemd/system/oxygenhub.service running oxygenhub serve --data /home/oxygenhub/data as oxygenhub, Restart=on-failure, ProtectSystem=strict, ReadWritePaths=/home/oxygenhub/data, NoNewPrivileges=yes; sudo systemctl enable --now oxygenhub.
  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.
  8. Updates: rsync, build, sudo install, sudo systemctl restart oxygenhub. make deploy in the hub wraps steps 2, 3 and 8.
  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.
  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.

Where things are on Earth

Binaries/usr/local/bin/oxygenhub, /usr/local/bin/oxy
Sources/home/claude/src/oxygen, /home/claude/src/oxygenhub (rsync targets; the hub itself is the canonical remote)
Data/home/oxygenhub/data (hub.toml, hub.db, keys/, repos/andymccall/*)
Push token/home/oxygenhub/push-token (also in hub.toml); each local checkout has it as remote.earth.token
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
Servicesudo systemctl status oxygenhub, sudo journalctl -u oxygenhub