Custom templates
Organizations can add their own templates next to the catalog. A custom template uses the same format as the catalog: a template.yaml describing the app and its inputs, plus a Docker Compose file.
Create one
Section titled “Create one”- Open Settings → Templates → Import.
- Paste or upload a template bundle (a
template.yamlwith acompose:key), or enter anhttps://URL to fetch it from. - Falak validates it and shows problems line by line. Save.
URL imports: https only, public addresses only, at most 3 redirects, 10-second timeout, 20 fetches per minute.
- Open a Compose site’s panel → ⋯ → Save as template.
- Falak drafts
template.yamlfrom the site: its public services, and inputs for its variables. - Review the name, slug, inputs and generators, then save.
Custom templates appear in the gallery next to catalog templates. Edit or delete them under Settings → Templates (templates.manage: owners, admins, developers). Each organization can have up to 200.
The format
Section titled “The format”name: Wiki.jsslug: wikijsversion: 1.0.0description: Modern wiki on Node.js with PostgreSQL.category: cmsicon: wikidotjs # a simple-icons key, or ./icon.svgdocs: https://docs.requarks.iostateful: true # warn when deploying to more than one servermin_memory_mb: 512popular: falsetags: [wiki, docs]public: - service: wiki port: 3000inputs: - key: DB_PASSWORD type: secret generate: password(32) label: Database password - key: SITE_TITLE type: string label: Site title default: Our wiki required: falsecompose: services: wiki: image: ghcr.io/requarks/wiki:2.5.300 expose: ["3000"] environment: DB_TYPE: postgres DB_HOST: db DB_USER: wiki DB_PASS: ${DB_PASSWORD} DB_NAME: wiki depends_on: [db] db: image: postgres:17.11-alpine environment: POSTGRES_USER: wiki POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_DB: wiki volumes: [wiki-db:/var/lib/postgresql/data] volumes: wiki-db:In the catalog, the Compose file lives next to template.yaml as compose.yaml (plus an optional icon.svg); an import bundle carries it under compose: (as a mapping or a string). Use one or the other, not both.
Top-level keys
Section titled “Top-level keys”| Key | Required | Rule |
|---|---|---|
name |
✓ | Up to 60 characters |
slug |
✓ | ^[a-z0-9][a-z0-9-]{0,49}$ |
version |
✓ | Semantic version, e.g. 1.0.0 |
description |
✓ | Up to 300 characters |
category |
✓ | automation, analytics, cms, databases, dev-tools, monitoring, storage, communication, ai |
icon |
A simple-icons key ([a-z0-9], up to 64) or ./icon.svg |
|
docs |
An https:// URL |
|
stateful |
Boolean; warns on multi-server deploys | |
min_memory_mb |
Integer 64–262144 | |
popular |
Boolean | |
tags |
Up to 10 lowercase words (up to 24 characters each) | |
public |
✓ | At least one {service, port} |
inputs |
List of inputs (below) | |
compose |
✓* | The Compose file (*or a separate compose.yaml) |
Unknown keys are errors, so typos never silently drop settings.
Inputs
Section titled “Inputs”| Key | Meaning |
|---|---|
key |
Variable name, ^[A-Z_][A-Z0-9_]{0,127}$ |
type |
string, secret, email, number, boolean, select, domain |
label, description, placeholder |
Form text |
default |
Default value. May contain references like ${{ postgres.DATABASE_URL }} or ${{ falak.url(web) }} |
generate |
secret(n), password(n), hex(n) (n = 8–128) or uuid |
options |
Choices for select |
required |
Default true |
Inputs become site variables (secrets encrypted). Generated values are created once when the site is created and never change on redeploy.
| Generator | Produces |
|---|---|
secret(n) |
n characters from A–Z, a–z, 0–9 |
password(n) |
n characters from an unambiguous alphabet with upper case, lower case and digits (URL and dotenv safe) |
hex(n) |
n lowercase hex characters |
uuid |
A random UUID v4 |
Falak placeholders
Section titled “Falak placeholders”Rendered once, when a site is created from the template:
| Placeholder | Becomes |
|---|---|
${{ falak.url(<service>) }} |
https://<domain of that public service> |
${{ falak.domain(<service>) }} |
The domain of that public service |
${{ falak.site }} |
The site slug |
Compose interpolation (${VAR}) stays Compose-native and reads the site’s variables at deploy time. Besides inputs, FALAK_SITE_ID, FALAK_SERVER_ID, FALAK_DEPLOYMENT_ID and FALAK_RELEASE_ID are available.
Validation rules
Section titled “Validation rules”A template is rejected when:
compose.yamldoes not parse, orinclude/extendsare used;- a service uses
build:(templates must reference published images); - an image is missing, interpolated (
${…}), untagged or taggedlatest(pin a version or a@sha256:digest); - a service sets
container_name(Falak names containers per site so a template can be deployed twice); - a
${VAR}is neither an input nor a Falak variable (use${VAR:-default}for optional ones); - a
${{ … }}incompose.yamlis not a Falak placeholder (variable references belong in input defaults); - a public service does not exist or does not expose its port (add
expose: ["3000"]); - the Compose security policy is violated.
Each of template.yaml and the Compose file may be up to 256 KiB.
Preview locally
Section titled “Preview locally”On the control plane host, render a catalog template with sample inputs to see what a site would get:
falak-ctl artisan templates:render n8n --domain=falak.test --env-file=/tmp/n8n.env