Skip to content

Scaffold Recipes

Griffen Fargo edited this page Jul 2, 2026 · 3 revisions

Scaffold Recipes

strut scaffold can generate a new stack from a recipe — a curated set of Dockerfile, compose, and config files for a common stack shape.

List available recipes

strut scaffold list
strut scaffold list --json

Output includes both official recipes (shipped with strut) and any user recipes under .strut/recipes/.

Scaffold from a recipe

strut scaffold my-api  --recipe python-api
strut scaffold my-site --recipe static-site
strut scaffold my-app  --recipe next-postgres

Each recipe copies a directory tree into stacks/<name>/ and runs the usual STACK_NAME_PLACEHOLDER and YOUR_ORG substitutions so the result is ready to customize.

Built-in recipes

Name Summary
static-site Static site served by Caddy with auto TLS (Let's Encrypt)
python-api FastAPI + Postgres with /health DB ping
next-postgres Next.js app + Postgres + Caddy reverse proxy
minecraft Minecraft Java server (itzg/minecraft-server)
pihole Pi-hole v6 network-wide DNS + ad blocker
nextcloud Nextcloud + Postgres with a nightly backup schedule
jellyfin Jellyfin media server (Plex alternative, FOSS)
immich Immich photo & video backup (Google Photos alternative) with Postgres + Redis + ML
vaultwarden Vaultwarden — Bitwarden-compatible password manager
n8n n8n workflow automation (Zapier / Make.com alternative)
uptime-kuma Uptime Kuma — self-hosted uptime monitor
homeassistant Home Assistant — open-source home automation
gitea Gitea — self-hosted Git service (lightweight GitHub alternative)
umami Umami — privacy-friendly analytics (Google Analytics alternative) with Postgres
wg-easy WireGuard Easy — self-hosted WireGuard VPN with a web UI
paperless-ngx Paperless-ngx — self-hosted document management with OCR (Postgres + Redis + Gotenberg + Tika)
audiobookshelf Audiobookshelf — self-hosted audiobook & podcast server
ghost Ghost — self-hosted blog + newsletter platform with MySQL

Each ships with a README.md that explains the specific setup steps (e.g. point DNS, set output: 'standalone' in Next.js config).

Custom / team recipes

Drop your own recipe under .strut/recipes/<name>/ at the project root. Strut picks them up automatically and scaffold list shows them alongside official recipes. User recipes win when they share a name with an official recipe, so teams can lock a flavor of a stack without forking strut.

Recipe structure

A recipe is a directory with:

<recipe-name>/
├── recipe.conf        # metadata (NAME, DESCRIPTION, TAGS, …)
├── docker-compose.yml # the stack
├── services.conf      # health-check wiring
├── required_vars      # env vars the stack needs
├── .env.template      # starter env file
└── README.md          # recipe-specific guidance (shown as next step)

Any other files in the recipe directory are copied verbatim into the new stack. The recipe.conf file itself is not copied.

recipe.conf

NAME=my-recipe
DESCRIPTION=One-line summary shown by `strut scaffold list`
SERVICES=web,postgres
REQUIRED_VARS=DATABASE_URL,APP_SECRET
DEFAULT_PORTS=8080
TAGS=web,python,postgres

Only NAME and DESCRIPTION are displayed today; the other fields are metadata for future tooling (filtering by tag, validating required_vars against the env template, etc.).

Substitutions

Two tokens are replaced across every file in the copied tree:

Token Replaced with
STACK_NAME_PLACEHOLDER The <name> you passed to strut scaffold
YOUR_ORG DEFAULT_ORG from strut.conf (skipped if unset)

This is a literal sed replacement — no templating language, no variable interpolation. Drop the tokens into docker-compose image refs, container names, README prose, etc.

Default scaffold (no recipe)

Running strut scaffold my-app without --recipe keeps the original behavior from v0.17.0 and earlier — it generates a generic single-service stack with an nginx or caddy proxy based on REVERSE_PROXY. Recipes are purely additive.

Clone this wiki locally