> ## Documentation Index
> Fetch the complete documentation index at: https://orbit.nckrtl.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Relocate the gateway role

> Move the Gateway to another Node while vpn and private DNS stay on the original Node.

# 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`](/docs/cli/node#orbit-noderolerelocate) 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:

```bash theme={"dark"}
orbit node:rename gateway vpn
orbit node:add gateway <new-host>
```

`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

```bash theme={"dark"}
orbit node:role:relocate gateway gateway --force
```

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](/docs/reference/private-dns#the-gateway-machine) 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](/docs/reference/node-agent#how-it-connects) 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

```bash theme={"dark"}
orbit node:role:list <old-node>
orbit node:role:list <new-node>
orbit doctor --node=<new-node-id>
curl --fail https://gateway.orbit/up
```

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.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.