Skip to main content

Relocate the gateway role

Problem

Bootstrap puts gateway and vpn on one Node. Later you may want the Gateway on a new machine while the WireGuard hub and private DNS stay where they are. node:role:relocate moves websocket and metrics with the same command.

Cause

vpn never moves. gateway is a singleton. Removing it and adding it again would drop the only active Gateway assignment, so the next request would lose its Gateway authority and gateway.orbit would leave private DNS. Relocate keeps one active assignment for the whole move.

Solution

Rename first

A Node name is a unique identifier. It is not the WireGuard key or address. When the old Node is named gateway and the new machine must use that name, rename the old Node first:
node:add finds an existing record by name, so the rename avoids a collision.

Prepare the target

The target must not hold app-dev, app-prod, database, analytics, or ingress, because they conflict with gateway. Install PHP-FPM and Caddy there. Copy the Gateway checkout, ORBIT_HOME with the Orbit CA and Gateway SSH keys, and the Gateway .env.

Move the assignment

Relocate opens orbit:gateway-https on the target and moves the assignment. It grants the new Gateway access to the vpn Node and the metrics Node, when they are other Nodes. It publishes private DNS on the vpn Node, so gateway.orbit answers with the target’s WireGuard address. It adds the private DNS route on the target, so the new Gateway resolves names such as reverb.orbit. Then it removes that route and the firewall rule from the source. A failed route on the target does not stop the move, and follow_up names the retry command. A failed removal on the source leaves the move incomplete. The error names the --from command that finishes it. Relocate moves no files. It does not stop Caddy or PHP-FPM on the source, so the old address keeps working during the cutover.

After the move

  1. Confirm that orbit node:role:list gateway shows gateway and orbit node:role:list vpn still shows vpn.
  2. Confirm that orbit node:show gateway lists access to the vpn Node and, when Metrics exists, the Metrics Node.
  3. Relocate wrote the new assignment to the SQLite database on the machine that ran it. Copy that database to the target, then start Caddy and PHP-FPM there.
  4. From a peer that trusts the Orbit CA, run curl https://<new-wireguard-ip>/up, then curl https://gateway.orbit/up.
  5. Point CLI profiles that name the old WireGuard address at the new one.
  6. The gateway.serving_node_id setting still names the old Node, so that Node keeps Gateway authority. Only a Gateway bootstrap records a new serving Node.
  7. Run orbit node:add <node> or a role converge on each Node, so its Node agent learns the new Gateway address.
  8. Stop Caddy and PHP-FPM on the old Node once the new /up answers.
After the split, private DNS publication runs over SSH on the vpn Node. Inspect the catalog and the listener there, not on the Gateway. The publication installs the listener release from the Gateway’s own code, so the vpn Node needs no Orbit checkout. The WireGuard hub keys stay on the vpn Node in /etc/wireguard/orbit.conf. A Metrics converge that fails while it publishes DNS keeps Grafana, Prometheus, and /etc/orbit/metrics in place.

Limits

Relocate does not install Laravel on the target and does not copy the SQLite database or the Orbit CA. This page does not cover pointing public clients at a new machine.

Verification

After relocate, orbit node:show on the new Gateway must list access to the vpn Node. To prove the split DNS path, converge a Route or Metrics from the new Gateway and confirm that /var/lib/orbit/private-dns/catalog.json changes on the vpn Node, not on the Gateway.