Contributing a Recipe
Recipes live in vazra/simpledeploy-recipes, a separate public repo. Anyone can submit one via PR. CI validates schema, parses compose, and resolves every image manifest before a maintainer reviews. Once merged, your recipe appears in every SimpleDeploy server’s deploy wizard within minutes.
Anatomy of a recipe
Section titled “Anatomy of a recipe”A recipe is a folder under recipes/<slug>/ with four files:
recipes/<slug>/ recipe.yml metadata compose.yml paste-ready Docker Compose with simpledeploy labels README.md what it does, env vars, post-deploy notes screenshot.png optional preview image (max ~1MB)The <slug> is a stable identifier (lowercase, kebab-case). It must match recipe.yml’s id field. Once published, never rename a slug; users may have deployed something that references it.
Step-by-step
Section titled “Step-by-step”# 1. Fork & clonegh repo fork vazra/simpledeploy-recipes --clonecd simpledeploy-recipesnpm install
# 2. Scaffold a recipe foldermkdir -p recipes/my-app$EDITOR recipes/my-app/recipe.yml$EDITOR recipes/my-app/compose.yml$EDITOR recipes/my-app/README.md
# 3. Validate locallynode scripts/validate.mjs recipes/my-app
# 4. Open a PRgit checkout -b add-my-appgit add recipes/my-appgit commit -m "feat: add my-app recipe"gh pr create --title "Add my-app recipe" --body "..."CI runs schema validation, compose parse, and docker manifest inspect on every image. A maintainer reviews and merges; the publish workflow rebuilds the index on main and deploys to GitHub Pages.
recipe.yml reference
Section titled “recipe.yml reference”schema_version: 1id: my-app # required, kebab-case, must match folder namename: My App # required, human-readable title (≤80 chars)icon: "🚀" # optional emojicategory: web # required, see belowdescription: One-line summary shown on the card.tags: [analytics, dashboard] # optional, max 10author: yourgithubhandle # optional but encouragedhomepage: https://example.commin_simpledeploy_version: 0.5.0 # optional, used to gate against old binariesCategories (pick the closest fit):
web, dev-tools, databases, storage, productivity, observability, auth, mail, ci.
If your app spans categories, choose the user’s primary mental model: “what would I search for?” Plausible is observability, not web.
compose.yml requirements
Section titled “compose.yml requirements”It must:
- Be a valid Docker Compose file. CI runs
js-yamland asserts a non-emptyservices:map. - Reference images that resolve via
docker manifest inspect. Avoidlatest; pin to a specific tag. - Be paste-ready. A user clicks Use Recipe, edits a domain or two, and clicks Deploy. No external setup steps.
It should:
-
Include
simpledeploy.*labels for at least one HTTP endpoint. Without these the user gets no public URL.labels:simpledeploy.endpoints.0.domain: "${DOMAIN:-example.com}"simpledeploy.endpoints.0.port: "8080"simpledeploy.endpoints.0.tls: "auto" -
Use
${VAR:-default}env interpolation for anything the user must change. Use placeholder defaults, never real secrets. -
Set resource limits under
deploy.resources.limits(cpus and memory). Pick caps a low-end VPS can handle. -
Define healthchecks for every long-running service so SimpleDeploy can show health status.
-
Use named volumes for persistence and document them in the README.
-
Set
restart: unless-stoppedunless there’s a reason not to.
It must not:
- Bake real secrets into the file.
- Require host-level mounts (
/var/run/docker.sock,/etc,/sys) without a clear, documented reason. - Run privileged containers without justification in the README.
- Require
network_mode: host(incompatible with SimpleDeploy’s reverse proxy).
README.md template
Section titled “README.md template”# My App
One-paragraph description: what it is, who it's for, when to use it.
## Variables
- `DOMAIN`: public domain pointing at this server.- `ADMIN_EMAIL`: receives bootstrap admin invitation.- `SECRET_KEY`: 32+ random characters; generate with `openssl rand -hex 32`.
## Post-deploy
1. Visit `https://<DOMAIN>`.2. Sign in with the admin email; check inbox for the invite.3. Configure ... (anything app-specific).
## Backups
Persistent data lives in the `data` named volume. Recommended backup: a SimpleDeploy "volume" backup config, daily.
## Resources
This recipe runs comfortably with 1 vCPU and 1GB RAM. For >100 active users, raise the memory limit to 2GB.
## Links
- Project: https://...- Docs: https://...- License: AGPL-3.0Keep it short. The detail screen renders the README inline, so a wall of text hurts UX. If you have a lot to say, link out.
Screenshots
Section titled “Screenshots”Optional. If included:
- 1280x720 or larger, max ~1MB.
- Show the running app’s main UI, not the install/setup wizard.
- PNG or compressed JPEG.
Validation locally
Section titled “Validation locally”# One recipenode scripts/validate.mjs recipes/my-app
# All recipesnode scripts/validate.mjs
# Build the catalog index (catches things validation alone misses)node scripts/build-index.mjsValidation checks:
- All four required files present.
recipe.ymlmatches the JSON schema (schema/recipe.schema.json).recipe.idequals the folder name.compose.ymlparses and has aservices:map.
CI additionally runs docker manifest inspect for every image; you can do the same locally:
docker manifest inspect plausible/analytics:v2.1.0Image hosting and the GHCR mirror
Section titled “Image hosting and the GHCR mirror”When your recipe merges, a workflow mirrors every image it references into ghcr.io/vazra/simpledeploy-mirror/<image> so SimpleDeploy E2E tests and users behind Docker Hub rate limits can still pull it. You don’t need to do anything; the mirror is automatic.
If your recipe references a private image, mirroring will fail and CI will block the merge. Either move the image to a public registry or open an issue to discuss.
Versioning and updates
Section titled “Versioning and updates”Recipes evolve. To update:
- Bump image tags in
compose.yml. Test locally if you can. - Edit the README for any new env vars or steps.
- Open a PR; the same CI gate applies.
There is no per-recipe semver. Users always pull the latest version of a recipe; if you ship a breaking change (e.g. requiring a new env var), call it out clearly in the README.
What makes a great recipe
Section titled “What makes a great recipe”- Solves a complete user need. “Run Plausible Analytics” beats “Run Postgres” (which the user could have figured out from a template).
- Sensible defaults. A user with a domain and 30 seconds gets a working app.
- Documents the trade-offs. Memory needs, persistence, backup story, what to do for production.
- Stays simple. A recipe with 12 services and 200 lines of compose is hard to review and rarely deploys cleanly. If your stack is that complex, ship it as a single image with internal services or upstream a Helm-style installer.
License
Section titled “License”The recipes repo is MIT-licensed. By submitting a recipe, you agree to license your contribution under MIT. The apps you reference keep their own licenses; cite them in the README.
Where to ask questions
Section titled “Where to ask questions”- Issue on vazra/simpledeploy-recipes for catalog-specific questions.
- Issue on vazra/simpledeploy for SimpleDeploy itself.