> ## 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.

# gateway

> Register Gateway profiles on the operator machine, select the active one, pin the Gateway root certificate, check Gateway status, and release the Gateway itself.

Every command that manages remote resources sends its request to the active Gateway. The `gateway` family manages the local profiles that name a Gateway. It also pins the Gateway root certificate authority (CA), installs it in the operating-system trust store, and shows whether the Gateway answers. [Gateway trust](/docs/reference/gateway-trust) describes where profiles live, the trust sequence, and the profile guard.

## Commands

| Command | Result |
| - | - |
| [`gateway:add`](#orbit-gatewayadd) | Add a profile and trust the Gateway root CA. |
| [`gateway:use`](#orbit-gatewayuse) | Select the active profile. |
| [`gateway:status`](#orbit-gatewaystatus) | Show the status and version of the active Gateway. |
| [`gateway:trust`](#orbit-gatewaytrust) | Trust or check the active Gateway root CA. |
| [`gateway:remove`](#orbit-gatewayremove) | Remove a profile and its pinned certificate. |
| [`gateway:release:list`](#orbit-gatewayreleaselist) | List the Gateway's release records. |
| [`gateway:release:show`](#orbit-gatewayreleaseshow) | Show one release record. |
| [`gateway:release:deploy`](#orbit-gatewayreleasedeploy) | Release one commit to the Gateway and follow it. |
| [`gateway:release:rollback`](#orbit-gatewayreleaserollback) | Switch the Gateway back to a retained release and follow it. |
| [`gateway:release:auto:status`](#orbit-gatewayreleaseautostatus) | Show the automatic release state. |
| [`gateway:release:auto:enable`](#orbit-gatewayreleaseautoenable-and-disable), [`gateway:release:auto:disable`](#orbit-gatewayreleaseautoenable-and-disable) | Turn automatic releases on or off. |
| [`gateway:release:auto:resume`](#orbit-gatewayreleaseautoresume) | Clear a pause of automatic releases. |

Every command accepts `--json`. `gateway:use` and `gateway:remove` work locally. The other commands contact the Gateway. `gateway:add` and `gateway:trust` can change the operating-system trust store, which can ask for local administrator privileges.

## orbit gateway:add

Add a Gateway profile. The CLI trusts the Gateway root CA first and saves the profile after that. The first profile becomes the active profile.

```bash theme={"dark"}
orbit gateway:add <gateway> [--name=NAME] [--ca=PATH] [--accept-ca-change] [--use] [--json]
```

| Argument | Required | Meaning |
| - | - | - |
| `gateway` | yes | Gateway IPv4 or IPv6 address, or an HTTPS origin. The CLI turns a bare address into `https://<address>` and refuses any other scheme. |

| Option | Default | Meaning |
| - | - | - |
| `--name=NAME` | `default` | Local profile name. If the name already exists, a changed CA is refused with `gateway.ca_changed` unless `--accept-ca-change` is passed. |
| `--ca=PATH` | none | Absolute path to a root CA certificate that the fetched certificate must match. |
| `--accept-ca-change` | off | Accept a changed CA for an existing profile name after checking the new fingerprint. Does not override a mismatched `--ca` file. |
| `--use` | off | Make the profile active. |

```bash theme={"dark"}
orbit gateway:add 10.70.0.1 --use
orbit gateway:add https://gateway.example.com --name=production --ca=/etc/orbit/production-root.pem
```

When the profile name already exists, `gateway:add` compares the fetched certificate with that profile's pin, as `gateway:trust` does. A changed CA fails with `gateway.ca_changed` unless `--accept-ca-change` is passed. `--ca`, when supplied, must also match the fetched certificate.

JSON output returns the profile with its `url` and `ca_path`, whether it is active, `trust_status` (`trusted` or `already_trusted`), the certificate `sha256` fingerprint, and the Gateway `request_id`.

| Error code | Meaning |
| - | - |
| `gateway.profile_invalid` | The name, URL, or CA path is not valid. |
| `gateway.ca_unavailable`, `gateway.ca_fetch_failed` | The CLI could not reach or safely fetch the root CA endpoint. An error code from the Gateway's answer, such as `ca.unavailable`, passes through. |
| `gateway.ca_invalid` | The Gateway returned invalid certificate material, or a fingerprint that does not match. |
| `gateway.ca_pin_invalid` | The `--ca` file is not a readable certificate. |
| `gateway.ca_changed` | The fetched certificate differs from the `--ca` file or the existing profile pin. |
| `gateway.ca_verification_failed` | The pinned HTTPS request did not return the same certificate. |
| `gateway.ca_store_failed` | The CLI could not store the certificate under `ORBIT_HOME`. |
| `gateway.ca_install_failed` | The CLI could not check or update the operating-system trust store. |
| `gateway.ca_profile_update_failed` | The certificate is trusted, but the CLI could not save the profile. |
| `gateway.config_invalid` | `config.json` is not valid. |
| `gateway.config_not_private` | `config.json` is a symlink, belongs to another user, or has group or other permission bits. |

## orbit gateway:use

Select an existing profile as the active Gateway. The command changes no pin and no trust store.

```bash theme={"dark"}
orbit gateway:use <name> [--json]
```

```bash theme={"dark"}
orbit gateway:use production
```

An unknown name fails with `gateway.profile_not_found`. JSON returns `active_gateway` with the selected name.

## orbit gateway:status

Show the status and version that the active Gateway reports.

```bash theme={"dark"}
orbit gateway:status [--json]
```

Human output is a detail tree with the profile URL, the Gateway name, status, Orbit version, PHP version, Laravel version, the release it runs from, the automatic release state, and request ID. JSON returns the same values with the profile name and URL. `release` and `release_sha` are null outside the [release layout](/docs/reference/gateway-recovery#release-layout). `auto_release` holds `enabled`, `paused`, `last_checked_at`, and `last_result`. It is null for a caller that is not an active WireGuard peer, and when the Gateway could not read that state.

When this machine is an active WireGuard peer, the Gateway also returns its [desired fleet state](/docs/reference/self-update#desired-fleet-state), as last resolved. It is absent until the Gateway resolves it. Human output then adds `CLI release`, the version of the Gateway's CLI release or why it is unavailable, and `Agent version`, the pinned agent. JSON carries the whole state as `desired_fleet_state`, which is null for any other caller. [`self-update`](/docs/cli/self-update) installs that state.

The command fails with `gateway.profile_missing` when no profile is active and with `gateway.unreachable` when the Gateway does not answer. A Gateway response without an error code uses `gateway.request_failed`; transport failures use `gateway.unreachable`.

## orbit gateway:trust

Trust the root CA of the active Gateway in the operating-system trust store, or confirm that it is already trusted.

```bash theme={"dark"}
orbit gateway:trust [--accept-ca-change] [--json]
```

| Option | Meaning |
| - | - |
| `--accept-ca-change` | Accept a certificate that differs from the profile's pin. Use it only after you check the new fingerprint. |

```bash theme={"dark"}
orbit gateway:trust
orbit gateway:trust --accept-ca-change
```

JSON output returns `gateway`, `status`, `sha256`, `ca_path`, and `request_id`. The command uses the error codes of `gateway:add`, and fails with `gateway.profile_missing` when no profile is active. Without `--accept-ca-change`, a Gateway that presents another certificate fails with `gateway.ca_changed` before anything is installed.

<Note>
  `gateway.ca_profile_update_failed` means that the certificate is already in the trust store but the profile changed during the command. Check which profile is active and run `gateway:trust` again.
</Note>

## orbit gateway:remove

Remove a profile and delete its pinned certificate file. The operating-system trust store stays unchanged.

```bash theme={"dark"}
orbit gateway:remove <name> [--force] [--yes] [--json]
```

| Option | Meaning |
| - | - |
| `--force` | Allow removal of the active profile. The active selection is then cleared. |
| `--yes` | Confirm without a prompt. Required with `--json` and without a terminal. |

```bash theme={"dark"}
orbit gateway:remove staging
orbit gateway:remove default --force --yes
```

The CLI checks the name and the active profile before it asks for consent. The prompt defaults to No. `--force` allows the removal but does not give consent.

| Error code | Meaning |
| - | - |
| `gateway.profile_not_found` | No profile has this name. |
| `gateway.profile_active` | The profile is active and `--force` is missing. |
| `input.confirmation_required` | `--yes` is missing with `--json` or without a terminal. |
| `input.cancelled` | The prompt was declined or interrupted. |
| `gateway.config_invalid` | The configuration file is invalid, or the profile is removed but the CLI could not delete its certificate file. |

A refusal changes nothing. JSON returns `profile` with the removed name.

## Gateway releases

The `gateway:release` commands release the Gateway itself. [Update and recover a Gateway](/docs/reference/gateway-recovery#deploy-a-release) describes the release steps, the records, and the error codes. Access to the Gateway is fleet-wide, so any Node with access may run them.

### orbit gateway:release:list

List the 50 newest release records, newest first, including queued and running ones.

```bash theme={"dark"}
orbit gateway:release:list [--json]
```

The table shows the record id, the release, the trigger, the outcome, the error code, the duration, and the start time. JSON returns `releases` with every record field, and `request_id`.

### orbit gateway:release:show

Show one release record.

```bash theme={"dark"}
orbit gateway:release:show [<release>] [--json]
```

| Argument | Meaning |
| - | - |
| `release` | A record id of one to six digits, or a hex SHA of 7 to 40 characters for the newest record of that commit. In a terminal, an omitted value opens a list of the records. |

JSON returns the record. `gateway.release_not_found` means no record matches, and `gateway.release_id_invalid` means the selector has another form.

### orbit gateway:release:deploy

Release one commit to the active Gateway, then follow it until it is live, switched back, or paused.

```bash theme={"dark"}
orbit gateway:release:deploy [<commit>] [--json]
```

| Argument | Meaning |
| - | - |
| `commit` | A hex SHA of 7 to 40 characters. In a terminal, an omitted value is asked for. |

The Gateway queues the release and runs it in its own unit. The CLI reads the record every 2 seconds and shows each step as the Gateway records it: queue, prepare, migrate, switch, hand off, verify, move the scheduler, publish the web app, and smoke. The tree ends with the outcome, and the record id and request ID follow it. JSON prints the final record. The command exits 0 only when the outcome is `verified`.

Interrupting the CLI stops following, not the release. Read the outcome later with `gateway:release:show <id>`. The CLI keeps reading while the Gateway reloads. It gives up with `gateway.release_follow_failed` after 30 failed reads in a row, or once 65 minutes have passed, whatever the reads return.

| Error code | Meaning |
| - | - |
| `gateway.release_commit_invalid` | The commit is not a hex SHA of 7 to 40 characters. |
| `gateway.release_in_progress` | Another release step runs, or another requested release waits to start. |
| `gateway.release_not_adopted` | The Gateway does not run from a release yet. |
| `gateway.release_unit_failed` | systemd did not start the release unit. |
| `gateway.release_follow_failed` | The CLI stopped reading the record. The release continues on the Gateway. |

### orbit gateway:release:rollback

Switch the active Gateway back to a retained release, then follow it.

```bash theme={"dark"}
orbit gateway:release:rollback [<release>] [--yes] [--json]
```

| Argument or option | Meaning |
| - | - |
| `release` | The 12-digit id of a retained release. In a terminal, an omitted value opens a list of the releases that went live. |
| `--yes` | Confirm the code rollback without a prompt. Required with `--json` or without a terminal. |

The Gateway checks that the target is a retained release before it queues anything. Rollback switches code and leaves the database in place. Confirm with `--yes` for noninteractive or JSON calls; the interactive prompt defaults to No. Declining fails with `input.cancelled`, and nothing is queued. Database restore is an explicit operator step described in [Gateway recovery](/docs/reference/gateway-recovery#roll-back). Output and exit status follow `gateway:release:deploy`.

### orbit gateway:release:smoke

Run the [smoke tests](/docs/reference/gateway-recovery#smoke) of the current release against the live Gateway. Smoke changes nothing and writes no release record.

```bash theme={"dark"}
orbit gateway:release:smoke [<commit>] [--since=<time>] [--json]
```

| Argument or option | Meaning |
| - | - |
| `commit` | The hex SHA, 7 to 40 characters, that the live Gateway must serve. Without it, smoke expects the commit of the current release. |
| `--since` | The runtime handoff time, ISO 8601 with a zone, such as `2026-10-07T06:00:00Z`. The scheduler and agent view must have restarted after it. Smoke does not wait for a tick; [`orbit gateway:release:auto:status`](#orbit-gatewayreleaseautostatus) shows whether the current release's scheduler has ticked. |

The Gateway runs `bin/gateway-smoke` of the current release inside the request and answers when smoke ends, after about a minute by default. Meanwhile the CLI shows one running step. The detail tree shows the commit, the outcome, the check counts, the duration, and the start time. A failed run adds the smoke message and the next step. A table lists each check with its status, error, message, and duration. JSON returns `release`, `sha`, `outcome`, the smoke `report`, and `request_id`. The command exits 0 only when the outcome is `passed`.

Interrupting the CLI stops waiting, not smoke. Smoke ends on the Gateway within its own limit.

| Error code | Meaning |
| - | - |
| `gateway.release_commit_invalid` | The commit is not a hex SHA of 7 to 40 characters, or the current release reports no commit. |
| `gateway.release_since_invalid` | `--since` is not an ISO 8601 time with a zone. |
| `gateway.release_smoke_failed` | Smoke printed no report, or a report that is not a check failure, such as `terminated`. Checks that did not pass are the `failed` outcome, not this error. |
| `gateway.release_smoke_timeout` | Smoke ran past its limit and was stopped. |
| `gateway.release_smoke_killed` | Something else, such as the out-of-memory killer, killed smoke before its limit. |
| `gateway.release_smoke_missing` | The current release has no `bin/gateway-smoke`. |
| `gateway.release_smoke_in_progress` | Another smoke run is in progress. Only one runs at a time. |

### orbit gateway:release:auto:status

Show the [automatic release](/docs/reference/gateway-recovery#automatic-releases) state.

```bash theme={"dark"}
orbit gateway:release:auto:status [--json]
```

The detail tree shows whether automatic releases are enabled and paused, with the reason of a pause, the current release and commit, the branch and check, the last check and its result, the stalls, and whether the current release's scheduler has run `tasks:tick` ([post-release tick confirmation](/docs/reference/gateway-recovery#post-release-tick-confirmation)). JSON returns `enabled`, `paused`, `pause`, `current_release`, `current_sha`, `last_tick`, `stalled_since`, `branch_head`, `behind_since`, `branch`, `check`, `tick_confirmation`, and `request_id`.

### orbit gateway:release:auto:enable and disable

Turn automatic releases on or off.

```bash theme={"dark"}
orbit gateway:release:auto:enable [--json]
orbit gateway:release:auto:disable [--json]
```

Both print the resulting state like `gateway:release:auto:status`. Enabling does not clear a pause. Disabling lets a release that already runs finish.

### orbit gateway:release:auto:resume

Clear a pause after you decided how to recover from a failed release.

```bash theme={"dark"}
orbit gateway:release:auto:resume [--json]
```

It prints the resulting state. It fails with `gateway.release_not_paused` when automatic releases are not paused.

## Related

* [`extension`](/docs/cli/extension) describes the Gateway-owned switches and how unavailable state differs from a disabled extension.
* [`node`](/docs/cli/node) registers the machines that the active Gateway manages.
* [`activity`](/docs/cli/activity) lists the requests that the active Gateway recorded.


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