levelrail-cli apps deploy-compose. There is no separate template deploy path, so a template-deployed app behaves like any other Compose app.
Some templates also come with an install manifest: a short list of settings (generated secrets, values with defaults, required values) and the services you can put behind a domain. Their template page shows an Install form, and levelrail-cli templates install <id> does the same from the CLI. See Compose apps.
This page covers how to deploy templates, how $SERVICE_... variables work, and how to save your own apps as templates. To see what is in the catalog, read the template catalog. The seven multi-service wiring examples are described in Starter kit templates.
Deploy a template
- Dashboard
- CLI
- API
Open Apps, choose New app, then Browse templates. Search by name, slogan or category, or pick a category. Selecting a card pre-fills the app name (the template ID) and an editable Compose body. Review it, replace any
$SERVICE_... token you want to set yourself, and deploy. The result lists each deployed service with a link to its app page.How templates are defined
The built-in catalog is compiled into the control plane binary and served from memory: there is no catalog table and no admin screen. Adding or changing a built-in template means shipping a new control plane build. Each entry has an ID, name, slogan, category, documentation link, a Compose body, and two optional hints:- Recommended memory: a static hint shown as a badge (for example “~6 GiB RAM recommended”). It is a rule of thumb and is not checked against any node’s free memory.
- Requires GPU: the entry reserves an NVIDIA GPU through
deploy.resources.reservations.devices. It needs a node with a GPU and the NVIDIA container runtime; see AI models.
resources.reservations.devices and replicas keys of a Compose deploy: block are read. Other Swarm-only keys are reported rather than silently ignored.
Magic variables
Templates use$SERVICE_<KIND>_<NAME> tokens in place of literal secrets. At deploy time:
PASSWORD,USER,BASE64,HEXandREALBASE64tokens are generated and stored as secrets. Every reference to the same name gets the same value, so an app and its database agree on$SERVICE_PASSWORD_DB. A generated value is never written into the stored Compose body.FQDNtokens resolve tohttps://plus the service’s assigned domain, when the Compose file assigns one.- Any token written with a default (
${SERVICE_FOO:-value}) uses that default. - Anything else has no value and is reported as unresolved. A template with an unresolved token is marked
requires_configuration, and the one-click route refuses it. Deploy it through the dashboard’s Compose editor, or withapps deploy-compose, after filling the value in.
Save an app as a template
Custom templates turn an app you already run into a reusable one-click template. They are stored in the database, not in the binary.1
Save the app
On the app’s detail page, open the overflow menu and choose Save as template, or run:Levelrail derives a Compose body from the app’s current desired state (one service, or every service of a multi-service app) and saves it with an ID of the form
custom- plus 16 hex characters.2
Find it
In the dashboard it appears under Your templates in the same template grid. From the CLI,
levelrail-cli templates list --custom.3
Deploy or delete it
A custom ID works anywhere a catalog ID does:Deleting removes only the saved template. The source app and apps already deployed from it are untouched.
${SERVICE_SECRET_<key>} placeholder. SECRET is not a generated kind, so such a template always has requires_configuration set and must be deployed through the Compose editor, where you supply the real values.
The saved Compose body does not capture everything about the app:
- Domains stay with the source app. A new app starts with none, as with
apps clone. - Host port, bind address and bind mounts are specific to the source machine.
- Resources and health checks have no Compose representation Levelrail can read back, so they are dropped.
Static sites
An app whoseapp.yaml sets build.type: static has no container. The control plane copies the built output to a directory on its own host and Caddy serves it directly. These sites are created only by a git push to such an app. levelrail-cli static-sites list (and GET /api/v1/static-sites) lists their names and domains, and the Apps page shows a read-only Static sites card when any exist. See app.yaml reference for the build types.
API and CLI reference
templates delete only removes custom templates; the built-in catalog is read-only.
Limits
- There is no versioning. A template’s Compose body can change between control plane releases, and nothing records what an already-deployed app was created from.
- Importing a catalog from an external source is not supported: the built-in set is the one in the template catalog. The reasoning is in ADR 015.
Next steps
Template catalog
Every built-in template by category.
Starter kit templates
Seven multi-service wiring patterns.
Deploying apps
Roll out, roll back and operate what you deployed.
app.yaml reference
Build types and service settings.