Networking
How Cubicle networking works, covering each Box's private IPv4 address, the WireGuard path from the cubicle CLI through Gateway, private DNS names under cubicle.internal, expiring access sessions, grants, SSH host-key pinning, outbound internet access and when to use SSH, the private network or the exec API.
Every Box has a private IPv4 address and no public one. You reach a Box from your workstation
through Cubicle's private network: the cubicle CLI opens a WireGuard tunnel to Gateway, and
Gateway forwards your traffic to the Boxes you have access to. Boxes can open connections to
the public internet, but nothing on the internet can connect to a Box.
- On your workstation, the
cubicleCLI and its tunnel helper hold a WireGuard tunnel to Gateway over UDP. - Gateway answers DNS for
cubicle.internalnames and checks every packet against your expiring access rules. - Allowed traffic reaches the Box's private IPv4 address on any port.
To set this up, see Reach a Box over the private network and SSH into a Box.
Private IPv4 addresses
- Each Box gets one IPv4 address from its Node's subnet. Every Node has its own subnet.
- The Box object's
privateIpfield holds the address. The Box's Node assigns it when it first takes on the Box, shortly after the Box is created, even if it is created stopped. Until thenprivateIpisnull. - A Box never moves to another Node, so its address stays the same for its whole life: across stop, start, hibernation and restore.
- The address is released when the Box's deletion completes, and a later Box can get it.
- A Box created from a snapshot is a new Box with its own address.
- Boxes have no public IPv4 address and no IPv6. IPv6 is disabled inside the Box.
To look up a Box's address and DNS name, see Reach a Box over the private network.
The path from your workstation
The private network needs the cubicle CLI with its tunnel helper, on macOS or Linux.
Platform requirements lists what the helper
needs.
| Part | What it does |
|---|---|
cubicle CLI | Signs you in, registers your workstation as a device and keeps an access session open while you are connected. |
| Tunnel helper | A root service installed by cubicle tunnel install. It runs the WireGuard interface and adds routes and DNS settings for cubicle.internal. |
| WireGuard | An encrypted tunnel over UDP from your workstation to Gateway, with an MTU of 1280 bytes. It carries IPv4 only. |
| Gateway | Terminates the tunnel, serves private DNS and forwards traffic only to Boxes your current access session allows. |
| Box | Receives the traffic on its private address. Services in the Box see Gateway's private address as the client address, not your workstation's. |
- The CLI registers a WireGuard device for your account, named after the workstation's
hostname, and the device gets a tunnel address from Gateway's address range.
cubicle devices listshows your devices. Revoking a device withcubicle devices revokeis permanent. - The helper adds a
/32route for each reachable Box's address and one for Gateway's DNS address. Your default route and other traffic are not changed. - Connections start from your workstation. A Box can only reply; it cannot open connections to your workstation.
Private DNS names
Each Box you can reach has a private DNS name, built from the Box's name and its organization's name:
<box>.<org>.cubicle.internalFor example, Box job-1 in organization acme is job-1.acme.cubicle.internal. The name
resolves to the Box's privateIp.
- If a Box or organization name is not a valid DNS label (for example, it ends with
-), that label becomesbox-<boxId>ororg-<orgId>instead. - Only
cubicle.internalis sent to Gateway. On Linux the helper sets a systemd-resolved routing domain (~cubicle.internal); on macOS it writes/etc/resolver/cubicle.internal. - Gateway serves only
Arecords, with a TTL of at most 10 s. It does not resolve other names. - The answers depend on who asks. Gateway resolves a name only for devices whose access session can reach that Box.
- Private names resolve only on connected workstations. They do not resolve inside Boxes.
- The Box's own hostname is
box-<name>, which is not its private DNS name.
| Query | Answer |
|---|---|
| A Box your session can reach | Its private IPv4 address |
Another name under cubicle.internal, such as a stopped Box or one without a grant | NXDOMAIN |
A name outside cubicle.internal | REFUSED |
Gateway answers DNS only for devices with a live access session. A DNS answer never grants access by itself: Gateway checks every packet separately.
Access sessions and expiry
Access to Boxes over the private network is short-lived and renewed continuously while you are
connected. cubicle connect and cubicle ssh open an access session for your device using your
sign-in session.
| Timer | Value |
|---|---|
| Access session lease | 30 s, and never past the expiry of your sign-in session |
| CLI refresh | Every 10 s while you are connected |
| Gateway re-check | Every 10 s, and right away when grants, SSH keys, memberships or devices change |
| Gateway's firewall entries | Expire with the lease, so access lapses even if Gateway stops renewing it |
| Helper's routes and DNS | Removed by the helper itself if refreshes stop for more than 30 s |
| DNS answer TTL | At most 10 s |
- Each refresh returns the current list of reachable Boxes, so a new grant or a Box that has just started appears within about 10 s.
- Revoking a grant, revoking the device, signing out, revoking the sign-in session and a disabled account all end access, including connections that are already open.
- Stopping, hibernating or deleting a Box removes it from your session.
- A start, stop, hibernation or restore advances the Box's
connectionGeneration, and Gateway drops the Box from your session until it runs at the new value. See Generations. - Access sessions need an interactive sign-in. API keys cannot open them. See Sign in and API keys.
Which Boxes a session can reach
A session reaches every Box, in all of your organizations, that meets all of these conditions:
- You hold an active grant on the Box. The owner or admin role is not enough by itself.
- Your membership in the Box's organization is active and your account is not disabled.
- The Box's desired state is
running, it is not waiting for an explicit start after a host reboot, its Node is healthy and the Box reportsrunningat its current generation. Every Box whosessh.readyistruemeets this.
An SSH key is not needed for the private network. See Organizations and access for how grants work.
SSH and host-key pinning
SSH runs over the private network to port 22 on the Box's private address. It needs a grant, an
ssh-ed25519 public key added to your account and a Box that is ready.
- Cubicle generates each Box's SSH host key when it provisions the Box, and the Cubicle API
publishes it.
cubicle sshandcubicle ssh-configfetch the key from the API and pin it per Box ID withStrictHostKeyChecking yes, sosshnever asks you to trust a key and never silently accepts a new one. Host-key checking is never turned off. What the CLI writes lists the files and theHostblock. - You log in as your own guest account.
- The guest SSH server accepts key logins only: no passwords and no root login. Agent forwarding, X11 forwarding and remote forwarding are off. Local forwarding works only to the Box's own localhost, which is enough for editors such as VS Code Remote SSH.
| Event | Host key |
|---|---|
| Stop, start, hibernation or restore | Unchanged. The key belongs to the Box for its whole life. |
| Right after any start, stop or restore | Not published until the Box runs at its new generation. The CLI reports "box has no trusted host key or guest account yet". |
| A new Box, including one created from a snapshot or with a reused name | A new key, pinned under the new Box ID. No warning. |
| The API publishes a different key for the same Box ID | The CLI stops with the host key for jevbox-<box ID> changed until you pass --accept-new-host-key. |
| The Box's SSH server presents a key that differs from the pinned one | OpenSSH refuses to connect with WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! |
Treat a changed key for the same Box as a security event, and find out why before you accept it. SSH troubleshooting has the fix for each message.
Outbound traffic from a Box
| Destination | Allowed |
|---|---|
| Public IPv4 internet (TCP, UDP, ICMP) | Yes. Traffic leaves from the Node's address, not a per-Box address. |
| DNS (port 53, UDP and TCP) on the resolver the Node configures | Yes. This is how a Box resolves public names. |
| Other Boxes, including Boxes in the same organization | No |
| Private and reserved IPv4 ranges (listed below) | No |
| Other services on the Node | No |
| Your workstation | No. A Box can only reply to connections you open. |
| IPv6 | No |
The blocked private and reserved ranges are 0.0.0.0/8, 10.0.0.0/8, 100.64.0.0/10,
127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.168.0.0/16, multicast (224.0.0.0/4)
and 240.0.0.0/4.
Inbound traffic to a Box
- Boxes have no public IP address and no public ports. The only network path to a Box is through Gateway, from a workstation with an access session that can reach the Box.
- Over the private network, any IPv4 protocol and port works: SSH, HTTP, databases, UDP and ICMP.
- A service must listen on the Box's network interface (for example
0.0.0.0), not only on127.0.0.1. Use SSH local forwarding for services that listen only on localhost. - Private DNS names have no HTTPS certificates.
- TCP port 5900 on a Box's address reaches the Box's console display (VNC), not a service in the Box. See Use the desktop console.
Not available yet
Public URLs, public ports, and Cubicle-managed port forwarding or proxies to Boxes are not available yet. The SDK and API keys have no private network access: from code, use the exec API.
SSH, the private network or the exec API
| SSH | Private network | Exec API | |
|---|---|---|---|
Needs the cubicle CLI | Yes. It connects the tunnel and pins the host key. | Yes | No. Use the SDK, the HTTP API or the CLI. |
| Needs the tunnel | Yes | Yes | No |
| Works with API keys | No | No | Yes, with the write scope |
| Needs a Box grant | Yes | Yes | Yes |
| Needs an SSH key | Yes, ssh-ed25519 | No | No |
| Protocols | SSH on port 22: interactive shells, remote commands, local forwarding to the Box's localhost | Any IPv4 TCP, UDP or ICMP traffic to the Box's private address | HTTPS to the Cubicle API. One command per request, with no shell, stdin, TTY or streamed output. |
| Runs as | Your guest account | No account: services see connections from Gateway's address | Your guest account, or the service account's |
| Good for | Interactive work and remote editors | Using services you run in the Box from your workstation | Automation, CI and AI agents |
See Commands and operations for how exec works and its limits.
Related
Reach a Box over the private network
Install the tunnel, connect and use private DNS names.
SSH into a Box
Add a key, connect and configure SSH clients.
Networking and SSH commands
cubicle tunnel, connect, ssh, ssh-config and devices.
Organizations and access
Roles, Box grants, service accounts and API keys.
Snapshots
Cubicle snapshots are offline, disk-only copies of a stopped Box stored on its Node, used to restore the Box in place or create new Boxes, with rules for status, sizing, organization snapshots, hibernation and retention.
Limits and defaults
Every Cubicle limit and default in one place, covering Box vCPU, memory and disk ranges and base image sizes, name rules, exec timeouts and output limits, request body size, rate limits, auto-hibernation, SDK and CLI wait timeouts, API key expiry, session lifetimes, private network sessions and what is not available yet.

