cubeship
Templates

The template file

Every block a template may contain, and the defaults for the ones it leaves out

A template is one YAML file, template.yaml at the root of its repository — see Publishing. This is the worked example the validator's own tests run against — Umami, one app and one database:

version: 1
minCubeship: "0.6.0"
project: umami            # suggested slug; the installer may change it

inputs:                   # what the template cannot know
  - key: domain
    type: domain
    label: Where the dashboard answers
  - key: appSecret
    type: secret
    label: The app's session secret
    generate: 32          # the instance generates it and shows it once

databases:
  - key: db                # template-local; what references name
    name: umami-db         # suggested instance name, renamable at install
    engine: postgres
    version: "18"
    database: umami        # the password is generated, never written here

apps:
  - key: web
    name: web
    image: ghcr.io/umami-software/umami
    tag: postgresql-v2
    port: 3000
    health: /api/heartbeat
    domains:
      - host: ${input.domain}
    attach:
      - database: db      # contributes DATABASE_URL and friends
        prefix: ""
    limits: { cpu: 1, memory: 1Gi }
    scale: 1
    env:
      APP_SECRET: ${input.appSecret}
      DATABASE_TYPE: postgresql

Every key not shown below is optional and takes the default listed. Unknown keys are refused — see schema.unknown-key.

Top level

KeyDefaultMeaning
versionAlways 1. The only value the validator speaks right now.
minCubeshipnoneA semver range the installing instance must satisfy, e.g. ">=0.6.0".
projectThe suggested project slug. The installer may rename it.
environmentproductionThe suggested environment inside that project.
inputs[]What the installer is asked. See Inputs.
databases[]The managed databases this template needs.
stores[]The managed object stores this template needs.
appsAt least one. What actually runs.

Keys and names are two different things

Every input, database, store and app has a key — lowercase or mixed case, letters/digits/dash/underscore, starting with a letter — which never leaves the file. It is what a reference like ${db.db.host} names, and what attach.database or attach.store names, and it is how one part of the template points at another. See References.

A database, store or app also has a name, which defaults to its key and is what appears on the instance. The installer may change any name, and for databases and stores it sometimes has to: their names are unique across the whole instance, so two installs of one template would collide on the first one otherwise.

Databases

KeyDefaultMeaning
keyRequired. What attach and ${db.<key>.…} name.
namethe keyThe suggested instance name.
engineRequired. One of postgres, mysql, mariadb, redis, mongodb.
versionthe newest offeredPinning it is advised but not required.
usernamethe engine's defaultRedis is always default; MySQL and MariaDB refuse root.
databasenoneThe database name inside the engine. Ignored on engines with none, like Redis.
exposenot exposednull (the default) keeps it internal only; 0 asks for a port picked for you; a number asks for that port.
limitsnoneSee Limits.

There is no password field. A database's password is generated by the instance and handed to an app through an attachment — a template that could write one down would be a template that could steal one.

Stores

KeyDefaultMeaning
keyRequired. What attach names.
namethe keyThe suggested instance name.
versionnoneThe MinIO version, unvalidated here — the instance decides what a missing one means.
buckets[]The buckets to create inside it.
limitsnoneSee Limits.

A template cannot declare a linked S3 endpoint — that would be somebody's credential. A template that wants one asks for an input of type store instead, and the installer picks a store that already exists on the instance.

Apps

Source

An app is exactly one of an image or a build — never neither, never both:

KeyDefaultMeaning
imagenoneA public image, with no tag in the string — tag is its own field.
tagnoneThe tag for image. Refused on a build: a built app is tagged by its deploy, not by you.
repononeAn http, https or git URL, with the branch in ref, never after a #.
refthe repo's default branchThe branch or tag to build.
buildnonedockerfile or railpack. Required once repo is set.
dockerfileDockerfileOnly meaningful with build: dockerfile.

Network

KeyDefaultMeaning
portnoneThe port the app listens on. Also the default for a domain that names none.
healthoffA path starting with /, no ? or #, at most 255 characters. Strongly advised — see advice.no-health.
domains[]See below.

Each entry under domains is { host, port }. host must come from exactly one input of type domain${input.<key>} and nothing else, never a literal hostname. port defaults to the app's own port, and beneath that to 8080.

Attach

Each entry under attach wires one database or one store into the app's environment — exactly one of database or store per entry, naming its key:

KeyDefaultMeaning
databaseA database's key, exclusive with store.
storeA store's key, or the key of an input of type store, exclusive with database.
bucketRequired with store: which bucket the app gets.
prefix""Upper case, ending in _, like ANALYTICS_. Distinguishes two attachments that would otherwise write the same variable names.

A database attachment contributes <PREFIX><STEM>_URL, _HOST, _PORT, _USER, _PASSWORD, and _NAME unless the engine has no named databases — STEM is DATABASE for postgres, mysql and mariadb, REDIS for redis, MONGO for mongodb. A store attachment contributes <PREFIX>S3_ENDPOINT, _REGION, _BUCKET, _ACCESS_KEY_ID, _SECRET_ACCESS_KEY, _PATH_STYLE.

Environment

env is a map of names to values, merged into the app on top of whatever attach already wrote — an app's own env wins on a collision, which is how you point at a different target without detaching anything. A value may itself be a reference, like ${input.appSecret} above.

Limits and scaling

KeyDefaultMeaning
limits.cpunoneCores, at least 0.01.
limits.memorynoneA size — 512Mi, 2Gi, 1500M — at least 6Mi.
scalenoneHow many copies, at least 1.
spreadfalseSpread copies across machines rather than pack them onto one.
autoscale.min1The floor, at least 1 and at most max.
autoscale.maxRequired with autoscale. At most 100.
autoscale.cpuRequired with autoscale. A target above 0, where 100 means one whole core.

limits and stores/databases' own limits share the same shape.

On this page