Skip to content

Catalog and recipes

The catalog lives in api/internal/catalog/templates.json, embedded in the binary. Each entry is a template: the defaults Deployer uses to write the compose file, the nginx site and the access suggestion for one app, plus an optional single sign-on recipe.

Template format

{
  "id": "linkding",
  "name": "linkding",
  "category": "Productivity",
  "icon": "bookmark",
  "website": "https://github.com/sissbruecker/linkding",
  "description": "Bookmark manager.",
  "image": "sissbruecker/linkding",
  "tag": "latest",
  "port": 9090,
  "auth": "app",
  "secrets": { "ADMIN_PASSWORD": "password" },
  "env": [
    { "key": "LD_SUPERUSER_NAME", "value": "admin" },
    { "key": "LD_SUPERUSER_PASSWORD", "value": "{{SECRET:ADMIN_PASSWORD}}", "secret": true }
  ],
  "volumes": [ { "name": "data", "target": "/etc/linkding/data" } ],
  "notes": "Log in as admin with the generated password (shown in the Secrets panel).",
  "aliases": [],
  "sso": { "method": "header", "env": [ … ], "remove": [ … ], "notes": "…" }
}
Field Meaning
id, name, category, icon, website, description, tags catalog display (icons are lucide names)
image, tag main image; aliases lists other image names of the same app (mirrors, forks)
port container port nginx proxies to
env variables; secret: true puts them in secrets/app.env
secrets generated values, name → generator (password, hex16, hex32), used as {{SECRET:NAME}}
volumes {name, target, readOnly, uid, gid} becomes ./data/<name>:<target>; {hostPath, target} mounts a host path (flagged as risky outside the stack)
services extra services (databases, caches) with their own image, tag, env, volumes, health check
command, user, health, memLimit, noNewPrivileges main service options
websocket, maxBodyMB, readTimeout, buffering nginx defaults
auth suggested access: authentik, app (has its own login) or none (public)
notes shown in the wizard and the stack README
sso single sign-on recipe (below)

Placeholders in templates: {{URL}}, {{FQDN}}, {{NAME}}, {{TZ}}, {{SECRET:NAME}}.

Sign-in recipe format

"sso": {
  "method": "oidc",
  "env": [
    { "key": "OIDC_AUTH_ENABLED", "value": "true" },
    { "key": "OIDC_CONFIGURATION_URL", "value": "{{OIDC_CONFIG_URL}}" },
    { "key": "OIDC_CLIENT_ID", "value": "{{OIDC_CLIENT_ID}}" },
    { "key": "OIDC_CLIENT_SECRET", "value": "{{OIDC_CLIENT_SECRET}}", "secret": true },
    { "key": "OIDC_GROUPS_CLAIM", "value": "deployer_groups" },
    { "key": "OIDC_ADMIN_GROUP", "value": "admin" }
  ],
  "remove": [],
  "adminClaim": true,
  "notes": "Mealie signs you in with Authentik; your account is the admin."
}
Field Meaning
method oidc, saml, header, none, basic or autologin
env / remove variables added to / removed from the main service while the recipe is on; removed values come back when it is turned off
steps steps to do once in the app (placeholders allowed), shown on the app page
redirect the app's OIDC callback, for display
notes shown under the choice
adminClaim add the deployer_groups claim (["admin"] for the admin account) to the app's OIDC client
init [{service, user, args, done}]: commands run once in the container after it is healthy
ownDoor no forward auth in front; the app's OIDC sign-in is the door
login {adapter: "form" \| "uptime-kuma", path, next} for auto-login

Sign-in placeholders: {{URL}} {{FQDN}} {{OIDC_ISSUER}} {{OIDC_CONFIG_URL}} {{OIDC_LOGOUT_URL}} {{OIDC_CLIENT_ID}} {{OIDC_CLIENT_SECRET}} {{GATEWAY}} {{AUTHENTIK_URL}} {{ADMIN_USER}} {{ADMIN_EMAIL}}.

Applying a recipe is idempotent and exactly reversible: Deployer records what it added and what it replaced (SSOState) and restores it when the account method changes or Authentik is turned off. A test applies and removes every recipe of the catalog against its template.

Adding an app

  1. Add the template to templates.json (keep categories and icons consistent).
  2. go test ./internal/catalog/ (every template must build, every recipe must apply and undo cleanly).
  3. Deploy it in fake mode through the wizard; check the compose file and the lint result.
  4. If it supports single sign-on, write the recipe and verify it with a real login in the lab (Development → The real-login lab).
  5. Add the result to the table in Single sign-on.

Knowledge used by detection

File Content
api/internal/ssodetect/known.json popular apps outside the catalog: names (image names, or owner/name for generic ones), method, how, link, paid
api/internal/ssodetect/authentik_guides.json generated from Authentik's integration guides: slug, name, provider types, guide URL

Contributions to known.json are the easiest way to help: one entry per app, with a link to the documentation that proves it.