Zomg gives you instant Linux sandbox environments. Each environment is a box: a persistent, isolated Linux system you create in seconds, run commands in, snapshot, and reach over the network. You drive Zomg with the zomg CLI, which talks to a server called zomg-api. The server manages the underlying Kubernetes and filesystem state so you work with boxes, not infrastructure.
The user-facing noun for a sandbox is box. The --fork flag is reserved for one action: clone an existing box’s filesystem into a new box.

The mental model

You create a box, run commands in it, and reach it over the web. It behaves like a fresh Linux machine: install packages, edit files, start services. The default image is ubuntu:24.04, and anything you write survives across stops and resumes. Under the hood, a box is a Kubernetes Deployment running a single privileged runner container. When the box starts, the runner sets up a persistent root filesystem, chroots into it, and starts PID 1:
1

Mount the kernel interfaces

The runner mounts proc, sysfs, and the host /dev into the box’s filesystem, and bind-mounts /tmp, /run, /etc/resolv.conf, and /etc/hosts.
2

Set the hostname

The box hostname is set to <box>.<project>.
3

chroot and start PID 1

The runner runs chroot /volumes and starts tini as PID 1:
exec chroot /volumes /usr/bin/tini -s -- /bin/bash -lc "sleep infinity"
That persistent root lives at /volumes.

Persistent filesystems

Zomg keeps box state on a btrfs mount on the node. The layers build on each other with copy-on-write snapshots:
LayerRole
basesRead-only template subvolumes. A new box starts from a base.
rootsWritable btrfs snapshots created from a base — your box’s live root.
checkpointsRoot snapshots you capture and restore.
volumes, volume-checkpoints, volume-backupsData-volume state for disks you mount into boxes.
Because roots are snapshots of a base, creating a box is fast: you get a writable copy of a template without duplicating it.

The zomg-api server

zomg-api is an HTTP server that owns the Kubernetes and btrfs state and serves interactive transports:
  • REST routes under /v1/projects/{project}/boxes/{name} for box lifecycle.
  • WebSocket exec at …/exec/ws and console at …/console for running commands and attaching an interactive terminal. A non-WebSocket POST …/exec is also available.
For running commands inside a box, the server prefers a container-runtime path and falls back to Kubernetes exec. See the API reference for the full route surface.

Reaching boxes

Each box is published at a stable HTTPS hostname:
https://{box_name}.{domain}
That exact form applies to the default project. Boxes in other projects get a project-qualified hostname instead.
The deployment domain is set on the server via ZOMG_DOMAIN (required; falls back to localhost only for local dev defaults).

Box-to-box networking

Boxes in the same project reach each other over DNS without publishing anything. Box Services are headless, so a box name resolves directly to the pod and any port is reachable:
  • Same project: reach another box by its bare name.
  • Different project: reach it by name.project.
Publishing is only for exposing a box to the public internet. In-cluster, box-to-box traffic needs no publishing.

Common commands

Once you have a target configured, the everyday workflow is:
# Create a box from the default base
zomg create myapp

# Run a command in it
zomg exec myapp -- echo hello

# List your boxes
zomg list

# Open an interactive console
zomg console myapp

# Delete it
zomg delete myapp
A few flags worth knowing on zomg create:
  • --base / -b — start from a specific base (default base is box-base).
  • --fork / -f — clone an existing box’s filesystem instead of a base (cannot combine with --base).
  • --data / -d — mount a data volume as NAME=/path[:ro|:rw].
  • --env / -e, --cpu, --memory, --project / -p.
The zomg docs command prints the full “Using zomg” guide in your terminal.

Projects

Boxes live in a project. The CLI resolves the project in this order:
  1. --project / -p flag
  2. ZOMG_PROJECT environment variable
  3. The current git repository’s root directory name
  4. default
You can address a box in another project with project:box (canonical) or project.box (shorthand).

Where to next

Quickstart

Install zomg, deploy an environment, and publish your first box.

Boxes

The box lifecycle: create, exec, stop, resume, delete.

Environment

The runtime inside a box: filesystem layout, PID 1, DNS, and injected env vars.

Snapshots and bases

Capture box state as checkpoints and turn it into reusable bases.

Data volumes

Persistent disks you mount into one or more boxes.

Services

Run long-lived services and expose them at a public URL.