Skip to main content
Orbit is built to be run by your coding agent. This page is written for both of you. Your agent reads it and does the work. You read it to know what happens, what your agent needs from you, and how to check the result. At the end you have a Gateway, one development Node, and a Project at https://hello.test.

Hand this page to your agent

Open this page in your agent from the menu at the top, or paste its link into the agent you already use with a prompt like this:
Your agent needs a shell that can reach both machines over SSH. Your own laptop is fine. Every command below names the machine and the account it runs on.

Your part

  • Two fresh Ubuntu 26.04 machines that you reach over SSH as root. One becomes the Gateway, the other a development Node. Both need outbound access to package sources and GitHub.
  • Open UDP port 51820 to the Gateway machine in the provider firewall. WireGuard uses it.
  • Keep the provider console open for both machines. Orbit closes public SSH on a Node once its role is active, and one host fingerprint has to come from the console, not from the network.
  • The WireGuard range 10.44.0.0/24 must be free on your network. If it is in use, tell your agent which range to use instead.
Each step marks the moments that need you with You:.

Your agent’s part

Everything else. Before you run anything:
  • Confirm with the user which machine becomes the Gateway and which becomes the Node. The machine that runs you is usually neither.
  • Check for an existing installation on the Gateway machine with id orbit and systemctl is-active wg-quick@orbit. If either succeeds, reuse that installation. Do not bootstrap over it.
  • Run every command on the machine and account named in its title.
  • If a command fails, read the error code, fix the cause, and run the same command again. Do not rename records or add a machine under a new name to get past a failure.
  • Never skip certificate verification. No --insecure, no disabled TLS checks.
  • Keep keys, tokens, and .env values out of the chat and out of every repository.
Check each checkpoint before you continue to the next step.
1

Prepare the Gateway machine

Install the packages Orbit needs and create the orbit account that owns the Gateway:
Gateway machine · root
The orbit account has passwordless sudo because bootstrap configures Caddy, WireGuard, dnsmasq, and the firewall. The rest of the Gateway steps run as orbit, for example through sudo -iu orbit or ssh orbit@<GATEWAY_IP> after you add a key for it.Checkpoint: sudo -iu orbit whoami prints orbit.
2

Install Orbit

Clone the repository under /home/orbit/orbit and install the CLI and the Gateway:
Gateway machine · orbit
This installs the current main. When a release tag exists, check it out with git checkout --detach <TAG> before you run Composer. Record the commit from git rev-parse HEAD and report it to the user at the end; it belongs in every bug report.If a platform check fails, for example because the package source has no PHP 8.5, stop and report the error. Do not install with --ignore-platform-reqs.Configure the Gateway:
Gateway machine · orbit
Set these values in .env and keep the rest as they are:
apps/gateway/.env
APP_URL is the Gateway’s WireGuard address; change it if the user chose another range. ORBIT_GATEWAY_CHECKOUT points at apps/gateway, not at the repository root.Keep CACHE_STORE=file. The Gateway holds its locks in that cache store, and they must exclude other processes. It starts only with a file, redis, memcached, or dynamodb store; it has no cache tables for database, and array or null locks do not span processes. When a line is missing, the Gateway uses files for the cache, an in-memory session, and synchronous jobs.Create the state directory and the database:
Gateway machine · orbit
The application key encrypts stored secrets. It belongs in every backup together with the database; Update and recover a Gateway lists what a backup needs.Checkpoint: orbit --version prints a version and php artisan migrate --force reports its migrations without an error.
3

Bootstrap the Gateway

You: confirm that UDP port 51820 is open to the Gateway machine.Bootstrap with the public address that the Node will use to reach the Gateway:
Gateway machine · orbit
Bootstrap creates the Gateway’s SSH key, WireGuard key, and root certificate authority. It registers the Gateway as the first Node with the gateway and vpn roles and starts the private HTTPS endpoint and DNS. It installs Caddy from the Caddy project’s own package source, not the Ubuntu archive, because Orbit renders directives the archive release does not know. Node provisioning describes the pinned key and the release floor. php artisan orbit:bootstrap --help lists the range, address, port, and DNS options. A failure names its step and an error code; fix the cause and run the same command again.Checkpoint: every service reports active, and caddy version reports 2.9.0 or newer:
Gateway machine · orbit
4

Use Orbit DNS on the Gateway

Nodes receive Orbit DNS automatically. The Gateway itself does not, so point its resolver at the Gateway’s WireGuard address. This lets the Gateway resolve hello.test later.
Gateway machine · orbit
Orbit DNS forwards public names to upstream resolvers, so the machine keeps normal internet name resolution. See Private DNS.Checkpoint: both lookups return an address:
Gateway machine · orbit
5

Connect the CLI

Register the Gateway as a CLI profile. The CLI fetches the root certificate, checks it against the file bootstrap wrote, and installs it in the trust store, so it can ask for sudo.
Gateway machine · orbit
The Gateway identifies callers by their WireGuard address, not by a token, and its own Node has authority over the whole fleet. Profiles live in ~/.orbit/config.json; the gateway family explains profiles and trust recovery.Checkpoint: gateway:status succeeds over HTTPS and node:list shows one Node, the Gateway.
6

Add a development Node

You: open the Node in the provider console, run ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub -E sha256, and give the SHA256: fingerprint to your agent. A fingerprint read over the network cannot prove which machine answered; the console can.Before the first connection to the Node, confirm that the machine on the network shows the same fingerprint:
Agent machine
The Gateway needs SSH access to the Node. Print the Gateway public key, then authorize it on the Node:
Gateway machine · orbit
Node machine · root
Add the Node with the app-dev role and a development TLD. Generated hostnames use that TLD.
Gateway machine · orbit
The Gateway connects as root, creates the managed orbit user, joins the machine to WireGuard, and installs the role. Pass --user if the provider uses another bootstrap account. Once the role is active, public SSH on the Node closes and the Gateway reaches it over WireGuard only. That is expected; tell the user. Node provisioning lists the error codes.Checkpoint: node:list shows dev with an active app-dev role. Record its numeric ID.
7

Create the Project and its Instance

A Project records one repository. An Instance is a checkout of that Project on one Node, with its own hostname. This guide uses MDN’s public learning repository because its static page needs no dependencies, application key, or database. The user’s own application comes after this page. For a private repository, keep credentials out of the URL and set up Git access on the Gateway and the Node first.
Gateway machine · orbit
project:create returns the Project ID; use it with the Node ID from the previous step. Orbit clones the repository on the Node, publishes the Route, and prints the URL. The name default gives the Project its <project>.test hostname; any other name gives <name>.<project>.test.
Active means Orbit prepared the source, runtime, and Route. For a real application, composer install, an application key, and a database are the next step. The Applications guide explains that boundary.
Checkpoint: instance:create returns https://hello.test and the Instance is active. Record the instance ID.
8

Open the page

Resolve the hostname and fetch the page with the Orbit root certificate:
Gateway machine · orbit
The first request can fail with HTTP 401 while Orbit wakes the Instance. Run the curl command again after a moment. See runtime wake.Then check the fleet:
Gateway machine · orbit
Doctor compares each Node with what the Gateway expects and exits 1 on drift, without changing anything. Activity shows who ran what, including you.If DNS fails, check the WireGuard link and Private DNS. If HTTPS fails, check the hostname, the certificate, Caddy, and orbit node:show <NODE_ID>. If the page is wrong, check the branch and the web root.Checkpoint: the response contains This is my page and orbit doctor exits 0.

Report back

Tell the user:
  • The URL, https://hello.test, and the Project, Node, and Instance IDs.
  • The source commit from git rev-parse HEAD.
  • What their own machine needs to open the URL in a browser: a route to the private network, Orbit DNS, and the Gateway root certificate in its trust store. orbit gateway:add installs the certificate on any machine that runs the CLI. A Mac also needs a route to the Node; orbit dns:resolve configures only its resolver.
  • That orbit instance:destroy <INSTANCE_ID> removes the example when they are done. The Node stays.

Next steps

Bring your own application

Create an Instance from your repository, register an existing checkout, and finish the application setup.

Run a development server

Record Vite or a queue worker as a Process. Idle Processes hibernate and wake on the next request.

Attach a database

Register a connection once and write its keys into any Instance.

Ship to production

Clone a candidate into a production Instance, configure deploy steps, and deploy.

Work from another machine

Provision a Linux operator Node from the Gateway and grant it access with node:access:add.

Every command

The conventions shared by all families, and the family pages.