RivetHub

// install · agent node

Install an agent node

An agent node runs the RivetOS runtime and enrolls against your datahub over SSH. You need a working datahub first.

Requirements

  • Debian 12 or Ubuntu LTS, x86_64 or aarch64, with systemd.
  • Root (sudo) and about 512 MiB free disk (2 GiB comfortable for npm ci).
  • An SSH login on the datahub that can run rivethub-hub — this is your --hub target.
  • The installer runs as root, so BatchMode SSH uses /root/.ssh — copy your key there (or ssh-copy-id as root) before a curl-pipe or sudo run.
  • curl, python3, tar, ssh, flock, and git (bare-metal) — missing ones are installed via apt-get when run as root.
  • docker in PATH only if you choose --docker.

// the command

Curl-pipe is supported

node installer — curl-pipe
$ curl -fsSL https://get.rivethub.io/node.sh | bash -s -- --hub owner@192.0.2.10

Or from a checkout of the rivethub-distro repository:

node installer — checkout
$ sudo bash install/node.sh [--docker] [--hub owner@192.0.2.10] [--name node-a] [--advertise-host 192.0.2.11]

Re-running is safe. Re-run without --hub and the installer resumes HUB_TARGET / NODE_NAME from $RIVETHUB_ROOT/node.env.

// the prompts

What the installer asks

On a TTY, unset fields are prompted:

  • Datahub SSH target — the user@host for --hub. Required when stdin is not a TTY and no node.env has one recorded.
  • Mesh node name — the certificate CN ([a-z0-9-], max 63). Default: the hostname, sanitized.
  • Advertise host — the address other nodes use to reach this node. Default: hostname -f.

Enrollment happens over SSH: the installer runs rivethub-hub enroll <node-name> <advertise-host> on the datahub, and stdout is only a base64 tarball (leaf cert + key, ca-chain.pem, current mesh.json, node config snippet), unpacked into the local shared dir. rivetos mesh enroll is not merged upstream yet — the installer implements the same tarball contract today.

// layout

What gets installed where

/opt/rivetos
RivetOS checkout at the pins/stable.json rivetos_tag (bare-metal; Node 22+ from NodeSource)
/var/lib/rivethub/shared
local mesh.json + rivet-ca (RIVETOS_SHARED_DIR)
/rivet-shared
symlink to the shared dir, so hardcoded RivetOS TLS paths work
/home/rivet/.rivetos
config.yaml + .env (mode 0600) for the rivet user (uid 2000 if free)
/var/lib/rivethub/node.env
recorded identity (node name, hub target) — no secrets
/etc/systemd/system/rivetos-agent.service
the agent unit (enabled + started)

Bare-metal (systemd) is the default. --docker runs the pinned GHCR image under systemd with host networking on mesh port 3000.

Pins are still placeholders. Every pin in pins/stable.json is UNPINNED: the clone falls back to the default branch with a loud warning, and --docker falls back to a floating GHCR tag, until the first stable tag is pinned. See Releases.

// verify

Verify

on the node
$ systemctl status rivetos-agent
$ journalctl -u rivetos-agent -n 50
$ sudo -u rivet -H rivetos status
$ sudo -u rivet -H rivetos doctor

The mesh certificate lives at /var/lib/rivethub/shared/rivet-ca/issued/<node-name>.crt.

// next

Add the next node

Run the same command on another host, with a fresh name and address:

second node
$ curl -fsSL https://get.rivethub.io/node.sh | bash -s -- --hub owner@192.0.2.10 --name node-b --advertise-host 192.0.2.11

Renew certificates

Renewal is driven from the datahub, which re-issues the node's leaf and emits the same tarball:

on the datahub
$ rivethub-hub renew <node-name>

To change a node's address, re-enroll it instead of renewing.