Networking and SSH commands
Reference for the cubicle commands tunnel install, uninstall and status, connect, disconnect, status, devices list and revoke, ssh-config and ssh, covering the root network helper, the private WireGuard network, JSON status fields, SSH aliases, host keys and exit codes.
These commands give your computer private network access to your Boxes and set up OpenSSH for
them. connect and ssh need the tunnel, an optional network helper that runs as root. Every
command here that calls the API needs your interactive login: API keys cannot use the private
network or SSH. Networking explains how the private network works.
BOX is a Box ID or ORG/NAME, such as acme/job-1; see Box arguments.
cubicle tunnel install
Installs the root network helper, or updates it to this CLI's version.
cubicle tunnel install [--yes]| Flag | Value | Default | Meaning |
|---|---|---|---|
--yes, -y | none | Off | Install without asking first. sudo may still ask for your password. |
- The command explains what it installs and asks
Install the tunnel? [y/N]. When the tunnel is already installed, it asksUpdate the tunnel? [y/N]instead and replaces the helper with this CLI version's copy. - Any answer other than
yoryesstops withCancelled.and exits 1. - Without a terminal, and without
--yes, it fails withconfirmation required; pass --yes. - It then runs the installer with
sudoand printsTunnel installed.If the installer fails, the command ends withtunnel install failed. - On Linux without an active systemd-resolved, it fails with
systemd-resolved is requiredorsystemd-resolved must be active; see platform requirements. --jsonhas no effect.
Files the CLI writes lists the paths the helper installs, and platform requirements the service it runs as on Linux and macOS.
cubicle tunnel installThe Cubicle tunnel gives this computer private network access to your Boxes
…
Install the tunnel? [y/N] y
Tunnel installed.cubicle tunnel uninstall
Disconnects the private network and removes the root network helper.
cubicle tunnel uninstall [--yes]| Flag | Value | Default | Meaning |
|---|---|---|---|
--yes, -y | none | Off | Remove without asking first. sudo may still ask for your password. |
- When the tunnel is not installed, it fails with
the tunnel is not installed. - It asks
Remove the tunnel? [y/N], with the same rules astunnel install. - It prints
Tunnel removed. Device identity is retained in /var/lib/cubicle/cli. - The CLI, your login and this computer's device keys stay. Reinstalling reuses the device keys.
--jsonhas no effect.
cubicle tunnel uninstall --yesTunnel removed. Device identity is retained in /var/lib/cubicle/cli.cubicle tunnel status
Prints whether the tunnel is installed and connected.
cubicle tunnel status [--json]No options besides --json.
- Output:
not installed; run `cubicle tunnel install`,installed, connectedorinstalled, disconnected. - Installed means the helper's file
/etc/cubicle/cli-helper.jsonexists. The command does not check that the helper answers. --jsonprintsinstalledand the fields ofcubicle status.
cubicle tunnel statusinstalled, connectedcubicle connect
Connects this computer to the private network, so that you can reach your Boxes by private address and DNS name.
cubicle connectNo options. The command always prints JSON: the state, as cubicle status
prints it.
- It starts a background process and waits up to 15 s for it to connect. The process keeps running after the command returns.
- The first time, the process registers this computer as a device. It then opens a session and refreshes it every 10 s. Each refresh updates the routed Boxes; see Which Boxes a session can reach.
- When already connected with the same login, it prints the current state. When connected with another login, it disconnects that one first.
- The connection ends with
disconnect,logoutortunnel uninstall, or when the computer restarts. It does not reconnect by itself.
| Error | Cause |
|---|---|
the Cubicle tunnel is not installed; run `cubicle tunnel install` | The helper is not installed. |
the Cubicle tunnel helper is not responding; reinstall it with `cubicle tunnel install` | The helper is installed but does not answer. |
VPN startup timed out; inspect vpn.log | No connection within 15 s, and no error was recorded. |
api_key_not_allowed: API keys cannot use this route | CB_CLI_API_KEY is set. |
key_unavailable: device key is already registered or revoked | This computer's device was revoked. |
vpn_unavailable: … | Cubicle cannot give this computer a network address right now. |
Other errors that the background process hits are printed as they are, and it logs to
~/.config/cubicle/vpn.log. The private network guide's
Troubleshooting has the fix for each error, and
Reach a service in a Box covers services on
other ports.
cubicle connect{
"connected": true,
"apiUrl": "https://api.cubicle.sh",
"identity": "dev@example.com",
"sessionId": "…",
"boxes": [
{
"boxId": "0b3f6c2e-8d4a-4f6e-9c1d-7a2b5e8f9d10",
"name": "job-1",
"org": "acme",
"address": "…",
"generation": 3,
"hostname": "job-1.acme.cubicle.internal"
}
],
"endpoint": "…",
"expiresAt": "…"
}cubicle disconnect
Leaves the private network.
cubicle disconnectNo options.
- It stops the background process, which closes the session, and the helper removes the routes and DNS settings.
- It always prints
{ "connected": false }, also when you were not connected.
cubicle disconnect{
"connected": false
}cubicle status
Prints the private network's state as JSON.
cubicle statusNo options. The command always prints JSON. It asks the background process and does not call
the API. Without a background process, it prints { "connected": false }.
| Field | Meaning |
|---|---|
connected | Whether the private network is up: the session is live and routes are in place. |
error | The last refresh's error, when it failed. For example login expired; run `cubicle login` . |
apiUrl | The API the connection belongs to. |
identity | The login the connection belongs to. |
sessionId | The current session's ID. |
boxes | The routed Boxes, each with boxId, name, org, address, generation and hostname. |
endpoint | The Gateway's WireGuard address, as host:port. |
expiresAt | When the current lease ends unless it is refreshed. A lease lasts 30 s and never outlives your login. |
- If refreshes stop for more than 30 s, the helper removes the routes and DNS settings on its own.
- While the computer sleeps, nothing refreshes the session, and its lease lapses. When the computer
wakes, the background process removes the routes and opens a new session. If that fails, it
tries again every 10 s, and
cubicle statusshows theerror.
cubicle devices
A device is a WireGuard key that the root helper keeps for this computer, one for each login (API
URL and identity). cubicle connect registers it, named after the computer's hostname.
cubicle devices list
Lists your devices, including revoked ones, oldest first.
cubicle devices listNo options. The command always prints JSON: an array with id, name, address (the device's
private network address), created_at and revoked_at.
cubicle devices list[
{
"id": "e2a4c6e8-0b1d-4f3a-8c5e-7a9b1c3d5e7f",
"name": "dev-laptop",
"address": "…",
"created_at": "2026-11-01T14:03:55.218Z",
"revoked_at": null
}
]cubicle devices revoke
Revokes a device permanently.
cubicle devices revoke DEVICE_IDNo options.
- Open connections from the device close, and its key can never connect again.
- An unknown ID fails with
not_found: device not found. - The command prints nothing.
cubicle connecton that computer then fails withkey_unavailable: device key is already registered or revoked; Devices explains how to enroll it again.
cubicle devices revoke e2a4c6e8-0b1d-4f3a-8c5e-7a9b1c3d5e7fcubicle ssh-config
Writes an OpenSSH alias and a pinned host key for a Box.
cubicle ssh-config BOX [--alias NAME] [--identity FILE] [--accept-new-host-key] [--json]| Flag | Value | Default | Meaning |
|---|---|---|---|
--alias | Name | cubicle-<org>-<box> | The Host name to write. For acme/job-1 the default is cubicle-acme-job-1. |
--identity | Path | ~/.ssh/id_ed25519 | The private key to write as IdentityFile. A path you pass is written as given, so use a full path. |
--accept-new-host-key | none | Off | Replace a pinned host key that no longer matches the key the API publishes. |
- The command reads the Box's SSH details from the API. It writes a
Hostblock to~/.ssh/cubicle_config, the host key to~/.ssh/cubicle_known_hosts, and anIncludeline to~/.ssh/configonce. Running it again replaces the alias's block. - It does not connect the private network. The alias works while
cubicle connectis connected. - The Box needs a published host key and a guest account for you, which a grant creates.
Otherwise it fails with
box has no trusted host key or guest account yet (<reason>); retry when it is running. - A host key that differs from the pinned one fails with
the host key for jevbox-<box ID> changed. Verify the box was restored or replaced, then rerun with --accept-new-host-key.jevbox-<box ID>is the name the Box's host key is pinned under; see SSH and host-key pinning. - Output:
configured: ssh <alias>. When SSH would not work yet, it adds(not ready: <reason>), for exampleno_active_keywhen your account has no SSH key. --jsonprintsconfigPath,knownHostsPathandhostAlias.
Calls GET /v1/boxes/{box} and
GET /v1/boxes/{box}/ssh.
What the CLI writes shows the block it writes.
Copy files over SSH and
Use the alias with other tools use the alias with
scp, rsync and editors.
cubicle ssh-config acme/job-1configured: ssh cubicle-acme-job-1cubicle ssh
Connects the private network, writes the Box's alias and opens SSH.
cubicle ssh BOX [--alias NAME] [--identity FILE] [--accept-new-host-key] [-- SSH_ARGS...]The options are the same as for cubicle ssh-config.
- It connects as
cubicle connectdoes, writes the alias asssh-configdoes, then runsssh <alias> SSH_ARGS...in your terminal. - Everything after
--is passed tosshafter the alias, for example a remote command. - It exits with
ssh's exit code, or255whensshreports none. - The private network stays connected after
sshexits. - It does not print the
configured:line, and--jsonhas no effect. - You need a grant on the Box and an
ssh-ed25519key on your account; seecubicle keys add.
cubicle ssh acme/job-1 -- uname -sLinux
