Templates
Deploy one of the 171 templates built into sh0: a ready-made set of containers, volumes and generated secrets, described in a YAML file.
The catalog
Version 1.10.2 ships 171 templates, compiled into the sh0 binary: the catalog is the same on every server running that version, and it changes only with an update of sh0. They are grouped in 24 categories:
| Category | Templates | Examples |
|---|---|---|
| devtools | 20 | gitea-runner, dozzle, hoppscotch, code-server |
| productivity | 18 | baserow, excalidraw, homepage, docuseal |
| database | 17 | chroma, couchdb, cockroachdb, cassandra |
| media | 16 | immich, filebrowser, lidarr, jellyseerr |
| cms | 12 | ghost, laravel, october-cms, pocketbase |
| runtime | 10 | php-8.0, php-7.4, php-8.1, php-7.3 |
| networking | 9 | adguard-home, headscale, nginx-pm, netmaker |
| analytics | 9 | influxdb, posthog, questdb, clickhouse |
| ai | 9 | anything-llm, dify, langfuse, n8n |
| communication | 7 | cal-com, chatwoot, zulip, matrix-synapse |
| auth | 7 | authentik, authelia, keycloak, logto |
| finance | 6 | akaunting, actual-budget, invoice-ninja, erp-next |
| service | 4 | homebridge, node-red, duplicati, restic-server |
| queue | 4 | kafka, nats, rabbitmq, redpanda |
| monitoring | 4 | changedetection, uptime-kuma, jaeger, loki |
| storage | 3 | minio, seaweedfs, garage |
| search | 3 | meilisearch, opensearch, typesense |
| forum | 3 | flarum, discourse, nodebb |
| cache | 3 | dragonfly, memcached, keydb |
| 2 | stalwart, docker-mailserver | |
| ecommerce | 2 | saleor, prestashop |
| marketing | 1 | postiz |
| education | 1 | moodle |
| ai-ml | 1 | mindsdb |
sh0 templates list prints the whole catalog with each template's category and description. In version 1.10.2 its SERVICES column always shows 0; use sh0 templates info <name> to see the services.
Some templates carry a notice in the dashboard: Frozen image when they use bitnamilegacy/* images, a frozen archive that no longer receives security patches, and Community image for the community rebuild of MinIO.
Deploying a template
In the dashboard, open Templates, find the template with the search box, and click Deploy. Give the Application Name, review the Variables (secrets marked Auto-generated are created for you), then confirm with Deploy Template.
From the CLI, sh0 templates info shows what a template will create:
$ sh0 templates info ghost
Template: ghost
Description: Ghost publishing platform with MySQL database
Category: cms
Tags: cms, blog, publishing
Services:
- ghost (image: ghost:6-alpine, port: 2368, exposed)
- mysql (image: mysql:8, port: 3306)
Variables:
KEY REQUIRED DEFAULT DESCRIPTION
----------- -------- ------- ---------------------------
DB_PASSWORD auto - Database password for GhostThen sh0 templates deploy <template> --app-name <name> deploys it, with --var KEY=VALUE (repeatable) to set a variable yourself:
$ sh0 templates deploy it-tools --app-name my-tools
[*] Deploying template 'it-tools' as 'my-tools'...
Error: Failed to parse response
Caused by:
missing field `app_id` at line 1 column 650
$ sh0 apps
NAME STATUS BRANCH PORT REPLICAS UPDATED
-------- ------- ------ ---- -------- -------
my-tools running main 80 1 14s agosh0 templates deploy ends with Failed to parse response although the server has accepted the request and the deployment goes on. Check the result with sh0 apps or in the dashboard rather than relying on the exit code.A deployed template becomes one app whose services are listed in its page. Redeploying such an app (Deploy button or sh0 deploy) fails in version 1.10.2 with App has no repository URL configured; the services already running are not affected.
Variables
Values in a template may contain ${NAME} placeholders, resolved at deployment time from the template's variables list:
generated: secret_32orsecret_64creates a random secret of that length (143 and 26 templates use them);passwordis also accepted.defaultgives a value used when you set none;required: truemakes the variable mandatory.${DOMAIN}needs no declaration: sh0 replaces it with the domain it assigns to the app.
Template format
Each template is one YAML file in the templates/ directory of the sh0 source. Here is ghost.yaml as shipped in version 1.10.2:
# Ghost -- Modern publishing platform with MySQL backend
name: ghost
description: Ghost publishing platform with MySQL database
icon: ghost
category: cms
tags:
- cms
- blog
- publishing
services:
- name: ghost
image: ghost:6-alpine
port: 2368
expose: true
env:
url: "https://${DOMAIN}"
database__client: mysql
database__connection__host: mysql
database__connection__user: ghost
database__connection__password: "${DB_PASSWORD}"
database__connection__database: ghost
NODE_ENV: production
volumes:
- ghost-data:/var/lib/ghost/content
depends_on:
- mysql
memory_mb: 512
cpu_cores: 0.5
- name: mysql
image: mysql:8
port: 3306
expose: false
env:
MYSQL_ROOT_PASSWORD: "${DB_PASSWORD}"
MYSQL_DATABASE: ghost
MYSQL_USER: ghost
MYSQL_PASSWORD: "${DB_PASSWORD}"
volumes:
- db-data:/var/lib/mysql
memory_mb: 512
cpu_cores: 0.5
volumes:
- name: ghost-data
- name: db-data
variables:
- name: DB_PASSWORD
description: Database password for Ghost
required: true
generated: secret_32Besides name, image, port, env, volumes, depends_on, memory_mb and cpu_cores, a service accepts command and entrypoint. expose: true marks the primary service, the one that receives the app's public address; a secondary service gets its own public address only with route: true. Services without either stay internal and are reached by their name, as mysql above.
Your own templates
Version 1.10.2 cannot load a template from a file or a URL: the catalog is the one compiled into the binary. To deploy your own multi-container stack, use a Docker Compose file.