Templates
Use a canette-template.yaml file to create one or more apps at once from a single file.
A template is a YAML file that describes one or more apps to create in a project. It is the fastest way to get a full stack running — paste the file or give canette a URL, review the settings in the wizard, and all apps are created in one go.
Loading a template
- Open a project in the dashboard.
- Click From template next to the New app button.
- Paste the YAML directly, or enter a public URL (e.g. a raw GitHub link). The file is fetched server-side.
- Step through the wizard — one screen per app — to review or adjust any field.
- Click Create N apps on the summary screen.
File format
A template file is a superset of canette.yaml. It adds a top-level name, an optional description, and an apps array. Each entry in apps is a single-app configuration.
name: "Template display name" # required
description: "Optional subtitle"
apps:
- name: My App # display name — required
slug: my-app # suggested slug — required, lowercase alphanumeric + hyphens
# Source: git repo or Docker image
source_type: git # "git" (default) or "image"
git_url: https://github.com/org/repo
git_branch: main # optional, defaults to "main"
app_path: "" # optional, subdirectory within the repo
# Or for a Docker image:
# source_type: image
# image_url: nginx
# image_tag: latest
deployment_type: web # "web" (default), "private", or "cronjob" — see below
port: 3000 # not used for deployment_type: cronjob
# Only for deployment_type: cronjob — a standard 5-field cron expression
# or a predefined schedule (@hourly, @daily, @weekly, @monthly, @yearly, @midnight)
# schedule: "0 2 * * *"
# Env vars (plaintext, shown and editable in the wizard)
# PORT is reserved — canette injects it automatically from `port` above,
# so it cannot be set here or as a secret.
env:
KEY: value
# Secret names only — the wizard prompts for values.
# Optionally add a description to guide whoever fills in the value.
secrets:
- SECRET_NAME
- name: ANNOTATED_SECRET
description: "A 32-character random string — run: openssl rand -hex 16"
# Any canette.yaml runtime fields are accepted here too:
# runtime, resources, replicas, healthcheck, ingress, build
resources:
requests:
cpu: 100m
memory: 128MiCross-app references
When one app's env var needs to reference another app's slug (for example, a service hostname), use the {{apps.<slug>.slug}} syntax:
env:
DB_HOST: "{{apps.db.slug}}"The wizard shows a live preview of the resolved value as you type. At creation time, all references are substituted with the slugs the user confirmed in the wizard.
Field notes
nameandslugare the only required fields per app.slugis a suggestion — the wizard pre-fills it and lets you edit. If a slug is already taken in the project you will be asked to choose another.deployment_typecontrols what gets created.web(default) creates aDeployment+Service+HTTPRoute.privatecreates onlyDeployment+Service— the app is reachable inside the cluster at<slug>.<namespace>.svc.cluster.localbut has no public URL.cronjobcreates aCronJobinstead of aDeploymentand requiresschedule;portis ignored andPORTis not injected for cronjob apps. Useprivatefor databases and internal APIs, andcronjobfor scheduled batch jobs. See Apps — Deployment type.scheduleis required whendeployment_type: cronjoband ignored otherwise. It's a standard 5-field cron expression (e.g.0 2 * * *) or a predefined schedule (@hourly,@daily,@weekly,@monthly,@yearly,@midnight).PORTis a reserved env var. canette sets it automatically on the container from the app'sport(forweb/privateapps) — it cannot be set viaenvorsecretsin a template, and the API rejects it the same way it does outside of templates.- Env vars are shown in the wizard as editable key-value pairs. Values containing
{{apps.X.slug}}show a resolved preview. - Secrets listed under
secretsappear as required password fields in the wizard. Values are encrypted at rest and are never returned by the API. Each entry can be a plain string or an object withnameand an optionaldescriptionshown as hint text in the wizard. - Any field not recognised as an app-row field (
source_type,deployment_type,git_url, etc.) is passed through ascanette.yamlcontent and stored as the app's advanced configuration. Unknown fields are silently ignored for forward compatibility. - Volumes are not supported in templates. Volumes (PVC / emptyDir / configmap mounts) are always configured after the app exists, on its settings page — there's no
volumesfield in either a template orcanette.yaml. Add volumes to each app individually after running the wizard.
Examples
Minimal — single Git app
The simplest possible template. Good for sharing a repo with a one-click deploy link.
name: "Hello World"
apps:
- name: Hello World
slug: hello-world
source_type: git
git_url: https://github.com/org/hello-world
port: 3000Single Docker image
Deploy a pre-built image straight from a registry.
name: "Nginx static site"
apps:
- name: Web
slug: web
source_type: image
image_url: nginx
image_tag: "1.27"
port: 80Scheduled job (CronJob)
A batch job that runs on a schedule instead of serving traffic. port and env.PORT don't apply here — cronjob apps never get a PORT injected.
name: "Nightly report"
apps:
- name: Nightly Report
slug: nightly-report
source_type: git
git_url: https://github.com/org/nightly-report
git_branch: main
deployment_type: cronjob
schedule: "0 2 * * *" # every day at 02:00
env:
REPORT_RECIPIENTS: "team@example.com"
secrets:
- name: SMTP_PASSWORD
description: "SMTP relay password for sending the report"Node.js API + Postgres
A two-app stack where the API connects to the database over the cluster-internal hostname.
name: "Node API + Postgres"
description: "Express API backed by a Postgres database"
apps:
- name: API
slug: api
source_type: git
git_url: https://github.com/org/api
git_branch: main
port: 3000
env:
DATABASE_URL: "postgresql://app:{{apps.db.slug}}@{{apps.db.slug}}:5432/app"
NODE_ENV: production
secrets:
- name: SESSION_SECRET
description: "A 32-character random string — run: openssl rand -hex 16"
- name: Postgres
slug: db
source_type: image
deployment_type: private # no public URL — only reachable inside the cluster
image_url: postgres
image_tag: "16"
port: 5432
secrets:
- name: POSTGRES_PASSWORD
description: "Choose a strong password — must match DATABASE_URL above"
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512MiThe
{{apps.db.slug}}references inDATABASE_URLare resolved to the slug you confirm for the Postgres app in the wizard. The Postgres app usesdeployment_type: privateso it has no public URL and is only accessible from other apps inside the cluster.
Full-stack with resource limits and health checks
Demonstrates most template fields at once, including a cronjob app alongside the always-on ones.
name: "Full-stack starter"
description: "Next.js frontend, Go API, and Postgres"
apps:
- name: Frontend
slug: frontend
source_type: git
git_url: https://github.com/org/frontend
git_branch: main
port: 3000
env:
NEXT_PUBLIC_API_URL: "http://{{apps.api.slug}}:4000"
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
healthcheck:
path: /
port: 3000
initial_delay: 15
period: 30
- name: API
slug: api
source_type: git
git_url: https://github.com/org/api
git_branch: main
port: 4000
env:
DATABASE_URL: "postgresql://app:secret@{{apps.db.slug}}:5432/app"
ENVIRONMENT: production
secrets:
- JWT_SECRET
- DATABASE_PASSWORD
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 1000m
memory: 512Mi
healthcheck:
path: /healthz
port: 4000
initial_delay: 10
period: 15
- name: Postgres
slug: db
source_type: image
deployment_type: private
image_url: postgres
image_tag: "16"
port: 5432
secrets:
- POSTGRES_PASSWORD
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 1Gi
- name: DB Backup
slug: db-backup
source_type: git
git_url: https://github.com/org/db-backup
git_branch: main
deployment_type: cronjob
schedule: "0 3 * * *" # every day at 03:00
env:
DATABASE_URL: "postgresql://app:secret@{{apps.db.slug}}:5432/app"
secrets:
- name: BACKUP_BUCKET_KEY
description: "Write access key for the off-site backup bucket"
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi