Boxes
What a Box is, a QEMU/KVM virtual machine with its own Linux kernel and disk, with its isolation boundary, Boxes vs containers, the default and omarchy base images, vCPUs, memory and disk and how they are placed and reserved, free Omarchy Boxes and their automatic deletion, names, IDs, Box references and the Box object's key fields.
A Box is a Linux virtual machine that Cubicle runs for you. You create and control it from the
TypeScript SDK, the HTTP API, the cubicle CLI or the Dashboard. You run commands in it with
exec, and you reach it over SSH and Cubicle's private network.
A Box is a virtual machine
- Each Box is a QEMU virtual machine accelerated by KVM. It uses QEMU's
microvmmachine type and the host's CPU model (-cpu host) on x86-64. - It boots its own Linux kernel, which Cubicle supplies from the host. There is no bootloader, so installing a kernel inside the Box does not change the kernel it boots.
- It runs a full Linux system with systemd, an SSH server and user accounts.
- It has one root disk (ext4), one network interface with a private IPv4 address, and a virtual display, keyboard and tablet for the desktop console.
- It lives on one Node, a Cubicle host, for its whole life. It never moves to another Node. The
Box's
nodefield names that Node.
The virtual machine is the isolation boundary
- Code in a Box, including code running as root, runs on the Box's own kernel. It does not share a kernel with the host or with other Boxes.
- On the host, each Box's QEMU process runs under its own unprivileged user, inside a seccomp sandbox, with CPU and memory limits taken from the Box's size.
- Boxes cannot reach each other over the network, even in the same organization. A Box reaches the public IPv4 internet, and connections into it come only over Cubicle's private network; see Outbound traffic from a Box for the rules.
- Inside a Box, users are not isolated from each other. Cubicle gives its
guest accounts and the desktop account passwordless
sudo, so anyone who signs in over SSH or opens the desktop console can become root in the Box and read the other users' files. Give separate users or tenants separate Boxes. - The guest account of someone without an SSH key, such as a service account, is locked and
expired in the Box. Exec still runs commands as it, but do not rely on
sudofrom it.
Boxes vs containers
| Box | Container | |
|---|---|---|
| Kernel | Its own Linux kernel, managed by Cubicle | The host's kernel, shared with other containers |
| Isolation boundary | Hardware virtualization (KVM) | Kernel namespaces and cgroups on the shared kernel |
| What runs inside | A full Linux system: systemd, sshd, user accounts | Usually one application process tree |
| Starting | Boots the guest operating system, or resumes it from hibernation | Starts a process on a kernel that is already running |
| Images | One of Cubicle's base images, or a snapshot of one of your Boxes | Any OCI image |
| Saved state | The disk persists across stop and start; hibernation also saves memory | Depends on the runtime and its volumes |
| How you get in | SSH, exec through the API, the desktop console, the private IPv4 network | The runtime's exec, and ports the host publishes |
Base images
Every Box starts from a base image, or from a snapshot of another Box.
There are two base images. baseImage defaults to default.
| ID | What it is |
|---|---|
default | A Debian-based Linux system with OpenSSH, sudo and Python 3. Its console desktop is Xfce, signed in automatically as sandbox. |
omarchy | Arch Linux with Omarchy. Its console desktop is Hyprland with software rendering, signed in automatically as cubicle. |
- Each image has its own default size; Limits and defaults lists them.
GET /v1/orgs/{org}/bases(reference),cubicle.listBases()andcubicle boxes bases --org acmelist the base images.- A base image is
availablewhen at least one healthy Node offers it.availabledoes not consider free capacity. - The desktop accounts (
sandbox,cubicle) are separate from the accounts you use for SSH and exec. See Use the desktop console. - Run
cat /etc/os-releasein a Box to see the exact distribution release. - There are no custom base images; create Boxes from a template Box's snapshot. See Build a template Box.
When Cubicle creates a Box's disk, it writes these into it, whatever the image, without running any program from the image:
- an SSH server policy: key login only, no passwords, no root login
- an SSH host key generated for this Box
- a helper that runs exec commands and manages accounts
- a
sudorule that gives Cubicle's accounts passwordlesssudo /etc/hostnameset tobox-<name>, and a DNS resolver in/etc/resolv.conf
Cubicle then creates one account in the Box for each person or service account with a grant on it. Guest accounts describes that account.
Resources
A Box has a fixed number of vCPUs (vcpus), an amount of memory (memoryMiB) and a disk size
(diskGiB), each a whole number. Limits and defaults gives the allowed
ranges and each base image's default size.
- Sizes you leave out come from the base image. For a Box created from a snapshot, they come from the source Box.
- Cubicle places a new Box on a healthy Node that offers its base image and has the free vCPUs,
memory and disk. A Box created from a snapshot goes on the Node that holds the snapshot. When no
Node fits, create fails with
503 capacity. - The Box's vCPUs, memory and disk stay reserved on its Node for its whole life, including while it is stopped or hibernated, so a lack of capacity never stops it from starting again. Free Omarchy Boxes are the exception. The reservation is released when deletion finishes.
- A Box cannot be resized yet. To change its size, snapshot it and create a new Box from the snapshot with the size you want; the new disk can be larger but not smaller.
Disk size and snapshots
- The disk keeps its contents across stop, start, hibernation and resume.
- When Cubicle creates the disk, it grows the disk and its filesystem to
diskGiB. - A
diskGiBsmaller than the base image itself fails at provisioning, not at request time: the Box goes tofailedwithdisk is smaller than its source image. - A Box created from a snapshot needs a disk at least as large as the source Box's. See Size rules for a Box created from a snapshot.
- Deleting a Box deletes its disk and every snapshot of it.
Free Omarchy Boxes
A free Omarchy Box comes from the free Omarchy sign-up in the Dashboard, not from a create
request. Its pooled field is true, and Cubicle deletes it if it stays stopped or hibernated.
- Getting one: enter your email address at
https://app.cubicle.sh/omarchy. Cubicle emails you a one-time sign-in link. Opening the link creates the Box, or starts it when it is not running, and shows its desktop console in your browser. - No invitation needed: for a new email address, the sign-up creates a Cubicle account. While the sign-up is closed, it says that free Omarchy Boxes are not available. A free Omarchy Box you already have keeps working.
- One per account: it is named
omarchy, lives in your personal organization and uses theomarchybase image at its default size. After it is deleted, the sign-up gives you a new one while it is open. - Not from a create request:
POST /v1/orgs/{org}/boxes, the SDK, the CLI and the Dashboard's create form always create ordinary Boxes. - Pooled vCPUs and memory: once its Node reports it stopped or hibernated, Cubicle gives its
vCPUs and memory back to the Node. Its disk stays reserved. A start reserves them again on the
same Node, and fails with
503 capacity(free boxes are at capacity right now; try again shortly) when they do not fit. - Automatic deletion: when Cubicle gives back the vCPUs and memory, it sets
expiresAt. If the Box is still stopped or hibernated at that time, Cubicle deletes it with its disk and snapshots. A start before then clearsexpiresAt.
Because every Box hibernates automatically,
a free Omarchy Box you leave alone is deleted at expiresAt unless you start it again. Keep
anything you need from it somewhere else.
Names and IDs
| Identifier | Form | Rules |
|---|---|---|
| ID | A UUID, such as 0b3f6c2e-8d4a-4f6e-9c1d-7a2b5e8f9d10 | Assigned at creation. It never changes. |
| Name | 1 to 63 lowercase letters, digits and -, starting with a letter or digit (^[a-z0-9][a-z0-9-]{0,62}$) | Unique among the organization's Boxes that are not deleted. It cannot be changed. |
| Hostname | box-<name>, such as box-job-1 | Written to /etc/hostname when the disk is created. |
| Private DNS name | <name>.<org>.cubicle.internal, such as job-1.acme.cubicle.internal | Resolves only over Cubicle's private network. See Private DNS names. |
- When you leave out the name, the API and the SDK generate one:
box-followed by six hex digits, such asbox-3fa9c1. The CLI requires a name. - Creating a second Box with a name that is in use returns
409 conflict, with the messagea box named job-1 already exists. - A deleted Box's name is free as soon as the deletion is accepted.
Box references
Every route, method and command that acts on one Box takes a Box reference.
| Reference | Example | HTTP API ({box}) | SDK | CLI |
|---|---|---|---|---|
| ID | 0b3f6c2e-8d4a-4f6e-9c1d-7a2b5e8f9d10 | Yes | Yes | Yes |
ORG/NAME | acme/job-1 | Yes, with the slash encoded: acme%2Fjob-1 | Yes | Yes |
NAME | job-1 | Yes | Yes | No |
ORGis the organization's name or ID.- A bare
NAMEis looked up in every organization where you are an active member. Narrow it with?org=acmein the API, the SDK client'sorgoption, or an API key, which only sees its own organization. - A bare
NAMEthat matches Boxes in several organizations returns409 ambiguous_box. A reference that matches nothing returns404 not_found. - In the API and the SDK, names never resolve to deleted Boxes or to Boxes in organizations you do not belong to.
- Use the ID in code that retries or runs for a long time. Once a Box is deleted, its name can belong to a new Box.
The Box object
GET /v1/boxes/{box} and the SDK's cubicle.boxes.get() return the Box object. These are the
fields that the concept pages explain. The API reference and
the SDK's BoxInfo type describe every field, including the
Box's identity, size, Node, private IP address and timestamps.
| Field | Meaning |
|---|---|
state | What the Box is doing, from its Node's latest report. See Box lifecycle. |
desired | What was last requested: { state, generation }. |
observed | The Node's latest report, { state, generation, observedAt, ageSeconds, fresh, error }, or null before the first one. |
ssh, console | { ready, reason }: whether exec and SSH, or the desktop console, can be used now. See When a Box is ready. |
restartRequired | true when the Node's host restarted while the Box should have been running, until you start or stop it. |
connectionGeneration | A counter that advances with lifecycle changes, restores and host restarts. SSH and private-network access from an earlier value no longer applies. See Generations. |
pooled | true for a free Omarchy Box, otherwise false. |
expiresAt | When Cubicle deletes a stopped or hibernated free Omarchy Box unless it is started first, otherwise null. |
deletion | pending from an accepted delete until its Node has removed the Box and listings stop showing it, otherwise null. See Deleting a Box. A create repeated with the same Idempotency-Key can return complete for a Box removed since; see Idempotency keys. |
When not to use a Box
- You need a public URL or inbound port from the internet. Public URLs, port forwarding and proxies are not available yet.
- Your code must connect to a service in the Box. API keys cannot use the private network, so a
program that holds only an API key cannot open a connection to a port in a Box. Run the client
inside the Box with exec instead, and connect to
localhost. See Networking. - You need an always-on service. Every Box hibernates automatically, whatever it is doing.
- You need a GPU. A Box has a virtual display only; its desktops render in software.
- You need Windows, macOS, another CPU architecture or your own kernel. Boxes run x86-64 Linux on a kernel that Cubicle manages.
- You need IPv6. It is disabled in every Box.
- You need to isolate several users or tenants inside one machine. Anyone who can sign in to a Box over SSH or open its desktop console can become root in it.
- The Box would hold the only copy of important data. A Box's disk and its snapshots live on one Node and are deleted with the Box. Keep important data somewhere else too.
Related
Box lifecycle
States, generations, readiness, hibernation and deletion.
Commands and operations
How exec runs a command and reports its result.
Snapshots
Save a stopped Box's disk and create Boxes from it.
Networking
Private IPv4, Gateway, private DNS and outbound traffic.
Organizations and access
Roles, grants, service accounts and API keys.
Limits and defaults
Every size, timeout and rate limit in one place.
Concepts
How Cubicle works, with a link to each concept page (Boxes, organizations and access, Box lifecycle, commands and operations, snapshots, networking) and a glossary of Box, Node, organization, personal organization, member, role, grant, guest account, service account, API key, session, exec, operation, generations, connection generation, Gateway, tunnel, device, access session, snapshot, hibernation, base image, template Box and free Omarchy Box.
Organizations and access
How Cubicle access control works, covering organizations and personal organizations, Box creation approval, the owner, admin and member roles, Box grants, guest accounts in a Box, revoking access and what service accounts can do.

