Skip to main content
A template is a single orgo.ai/v1 document, written in YAML or JSON. This page is the field-by-field reference. The canonical machine-readable contract is the JSON Schema at GET /api/template-schema. Point your editor at it for autocomplete and inline validation.
The published JSON Schema describes the canonical form only. It requires api_version and template, and it rejects unknown top-level keys. An editor validating against it therefore flags every sugar document as invalid on two counts. Sugar is desugared server-side, so check a sugar template with Validate template instead of relying on editor validation.

Two forms

Templates accept a canonical form and a shorter sugar form. Both normalize to the same document and the same digest.

Sugar → canonical

api_version has no sugar: every document needs it, in either form. Don’t mix the forms: a document with a canonical template: block that otherwise parses as canonical is read as canonical, and its top-level sugar keys, such as cpu or on_every_boot, are ignored. In a sugar document, a canonical hardware value wins over its flat key: if a document sets both hardware.cpu and top-level cpu, the hardware value is used and the sugar key is ignored. ram and disk accept 4gb, 4g, or a bare 4; a sub-gigabyte size such as 512mb resolves to 0, which is the same as omitting it.

Top-level fields

Every field except api_version and template is optional, so the smallest valid template is a name, a version, and the API version.

template

Identity and provenance. name and version are required.

hardware

The computer’s resource shape. Every field is optional; omit one and the platform default applies. A Create computer request’s cpu, ram, and disk override these at launch. The template’s resolution always wins over the request’s, because the golden snapshot was captured at it.

vars and interpolation

vars are compile-time strings, interpolated across the document before build.
  • ${var.X} resolves from vars.
  • ${env.X} resolves from a literal env value (not secret-backed ones).
  • $${var.X} escapes to a literal ${var.X}.
  • Only the var. and env. forms are substituted, so a shell variable such as ${HOME} passes through unchanged.
  • An unknown reference is not caught by Validate template or at publish. It fails the build, and the build’s error names the exact field path.

env

Environment variables written to the computer. Keys must be UPPER_SNAKE_CASE. Each value is a literal string, or a {secret: <name>} reference resolved from the launching user’s vault at create time. A value cannot be both.
A {secret: …} reference to a name you never declared under secrets is a validation error (unknown_reference). Literal values are written to /root/.env, which is sourced at boot before services, terminal sessions, and boot hooks start, and by new interactive shells. Two caveats apply at launch, both covered in Secrets:
  • A {secret: …} reference is not applied. The value arrives only under the secret’s own UPPER_SNAKE_CASE name, so the example above works because ANTHROPIC_API_KEY is that name.
  • A launch that injects secrets rewrites /root/.env with only the secrets, so literal values are not set on that computer. Put a value a service needs in that service’s own env.

build

Package and command steps run once when baking the golden snapshot, before app installs. This is where dependencies get pre-installed so launches are instant.

files

Files materialized into the computer. Each entry sets exactly one of from or inline. Setting both, or neither, is a validation error.

File sources

Sources are fetched once, on the build machine, and the result is baked in.
  • http and https download the URL.
  • git clones over HTTPS: git://github.com/owner/repo#path/to/file writes that file, and a directory is written as a tar archive.
  • s3 works only for a public AWS bucket.
  • file is accepted by validation, but the build cannot read it and fails.
  • secret://<name> must name a declared secret, but the file is never written. See Secrets.
to must be an absolute path with no ... Reserved system paths are rejected: /proc, /sys, /boot, /dev, /tmp, /run, plus the Orgo runtime (/etc/orgo, /var/orgo, /orgo, /etc/supervisor, and Orgo’s own binaries under /opt and /usr/local/sbin). Your apps can still write under /opt and elsewhere. Only Orgo’s own runtime files are off-limits.

apps

An app bundles an install step with the long-running services, health checks, and ports it needs. Services are managed by supervisord, so they start at boot and respawn on crash.
App name is required and must be unique kebab-case. requires lists other app names this one depends on, and data lists persistent data paths, validated the same way as files[].to.

services

health

A polled liveness check. After retries consecutive failures, on_fail runs. This is the per-app watchdog. type is required, and so is the field that type checks (url, port, command, or process). The other fields are optional. every defaults to 30s, timeout to 5s, and retries to 3. All durations are Go duration strings (30s, 2m, 1h). on_fail is one of restart_service:<name>, restart_vm, alert, or none. Only restart_service acts: restart_vm and alert write a log line and do nothing else.

ports

terminal

Pre-staged tmux sessions. Each one is created detached on every cold boot unless it already exists, and its run, if set, is typed into it as the first command. A launch that restores the golden snapshot’s memory keeps the sessions the build left running. Orgo’s browser terminal attaches to them by name. name is required and must be unique.
Sessions are not auto-restarted. For a process that must respawn, use an app service instead.

hooks

Shell that runs at lifecycle points. Each runs with set -e and times out after 10 minutes.
Only on_first_boot and on_every_boot run today. Validation accepts on_pre_snapshot, on_resume, and on_shutdown, but Orgo’s builds do not run on_pre_snapshot, and launched computers do not run on_resume or on_shutdown.
Work that should be baked into the image belongs in build or an app’s install, not in a boot hook. To start a program with a launch-time secret, use a terminal session’s run or an app service. See Secrets.

telemetry

Metrics go to <otel_endpoint>/v1/metrics and logs to <otel_endpoint>/v1/logs, as OTLP JSON. Each logs entry names a service, whose log is /var/log/orgo/<service>.log.

egress_policy

Per-computer network filtering, applied on the host when the computer is created. mode is allow or block (allowlist and denylist also work), and rules lists domains, IPs, or CIDRs. The JSON Schema requires both fields, but publish does not check them: a policy with no rules, or with any other mode, leaves the computer unfiltered.
  • Domain rules filter DNS lookups only. A rule matches any lookup whose name contains its second-level label, so *.github.com, github.com, and api.github.com all match every name containing github.
  • IP and CIDR rules filter traffic to those addresses.
  • block drops lookups that match a domain rule and traffic to a listed address. Everything else is allowed.
  • allow accepts traffic to listed addresses and lookups that match a domain rule, and drops all other lookups. With at least one domain rule, only lookups are filtered, so a connection made by IP address is not blocked. With only IP or CIDR rules, all other traffic is dropped.
The VNC and Desktop API paths are always reachable. Omit the block entirely for no filtering.

streaming

Outbound RTMP(S) streams of the desktop. name, url, and key are required; url must start with rtmp:// or rtmps://.
streaming is parsed and validated, but no runtime streamer is wired up yet. A declared stream does not broadcast.

Next steps

Secrets

The full secret-injection model.

Triggers

Sources, actions, and dedup.

Examples

Annotated real templates.

Publish API

Ship a template over HTTP.