Skip to main content
Templates are the base images that sandboxes boot from. Each template is a Docker-to-ext4 converted filesystem image containing an operating system, language runtime, tools, and default configuration. ZWRM ships with built-in templates and supports custom templates.

Built-in templates

These templates are automatically registered and built when the control plane starts:
TemplateDescriptionSource
pythonPython 3.12 with pip and common packagesgithub.com/zwrm-eu/templates/python-api
nodeNode.js 22 with npmgithub.com/zwrm-eu/templates/web
goGo toolchaingithub.com/zwrm-eu/templates/go

Template lifecycle

  1. Pending — Template record created in database
  2. Building — Docker image is being built and converted to ext4
  3. Ready — Image is built and available for sandbox creation
  4. Failed — Build failed (error stored in build_error field)

Listing templates

zwrm templates list
Output shows both built-in and custom templates with their status:
NAME      STATUS   VERSION  BUILT-IN  DESCRIPTION
python    ready    1        yes       Python 3.12 environment
node      ready    1        yes       Node.js 22 environment
go        ready    1        yes       Go development environment
my-ml     ready    2        no        Custom ML template

Creating custom templates

Custom templates are built from a Dockerfile. The Dockerfile defines the complete environment — OS packages, language runtimes, tools, and default configuration.
zwrm templates create my-ml --dockerfile ./Dockerfile
The build runs asynchronously. Check progress with:
zwrm templates list
To set a default egress policy for all sandboxes created from this template:
zwrm templates create my-ml --dockerfile ./Dockerfile \
  --egress-mode deny_all \
  --egress-allow-cidr 0.0.0.0/0 \
  --egress-deny-cidr 10.0.0.0/8
Egress flags:
  • --egress-modeallow_all or deny_all default for sandboxes from this template
  • --egress-allow-cidr CIDR — Default allowed outbound CIDR (repeatable; implies deny_all)
  • --egress-deny-cidr CIDR — Default denied outbound CIDR (repeatable)
  • --egress-allow-port PORT — Default TCP port restriction for --egress-allow-cidr (repeatable)

Template metadata

Templates can include a zwrm-template.toml file in their repository root with metadata:
name = "my-ml"
description = "Machine learning environment"
author = "your-org"
icon = "brain"
tags = ["python", "ml", "data-science"]
default_size = "performance-2x"
min_size = "shared-cpu-4x"

[env]
PYTHONUNBUFFERED = "1"
OMP_NUM_THREADS = "2"

Build pipeline

The template build pipeline converts a Dockerfile into a Firecracker-bootable ext4 filesystem:
  1. Docker build — Standard docker build using the provided Dockerfile
  2. Container export — Export the built image as a tar archive
  3. ext4 creation — Create an ext4 filesystem and extract the tar contents into it
  4. Init injection — Inject init scripts for VM boot (networking, overlayfs setup)
  5. Daemon injection — Install zwrm-sandboxd, the in-VM agent daemon that the host communicates with for command execution and file operations
  6. Agent skeleton — Copy /home/agent to /etc/skel/agent-skel/ for user provisioning
  7. Cache — Store the result with a content-addressed cache key
After a template image is built, the control plane creates a golden snapshot in the background: a pre-taken Firecracker memory+state snapshot for each VM size. When a warm-pool slot isn’t available, cold-starting from a golden snapshot is faster than a full kernel boot.
Build caching is content-addressed. The cache key includes the repository URL and commit hash. Rebuilding with no upstream changes is a no-op.

Rebuilding templates

When you update a template’s Dockerfile, rebuild it to create a new version:
zwrm templates rebuild my-ml
Rebuilding increments the template version, invalidates any existing golden snapshots, and triggers a new build. Existing sandboxes continue using their current image — only new sandboxes use the updated template.

Deleting custom templates

zwrm templates delete my-ml
Built-in templates cannot be deleted. Only custom templates can be removed.

Template resolution

When creating a sandbox, the template field is resolved in this order:
  1. By ID — Exact match on template ID (e.g., tmpl_abc123)
  2. By name (org-scoped) — Match on name within the requesting organization’s custom templates
  3. By name (built-in) — Match on name among built-in templates
This means custom templates with the same name as a built-in template take precedence for that organization.