"storage-${domain}" pushes the first DNS label of Dokploy's generated
sslip.io hosts past 63 characters, so the storage domain never resolves
and browser uploads can't reach it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MinIO images on quay.io/Docker Hub are no longer publicly pullable, so the
deploy failed at image pull. Storage now runs SeaweedFS (S3 on port 9000,
credentials orbit/MINIO_PASSWORD) and the bucket service uses mc from the
orbit-bucket image to create orbit-uploads and set its CORS rule for the
app origin (browser presigned PUT uploads).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Self-hosted OpenStatus (status pages + uptime monitoring) following the
official docker-compose.github-packages.yaml setup: local libSQL database,
one-shot migration runner built from the pinned upstream commit, workflows,
API server, dashboard, status-page, and the private-location ingest server.
All app images pinned to upstream commit e1a9825; Tinybird analytics run in
no-op mode by default.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Same root cause as odoo_19 (#1108, fixed in #1110): the compose file
bind-mounts ../files/config over /etc/odoo, but with mounts = [] the
directory is empty, hiding the image's /etc/odoo/odoo.conf. As a result
wait-for-psql.py crashes with configparser.NoSectionError: No section:
'options' and the web container never starts.
Ship odoo.conf through the template config mount instead, with
proxy_mode enabled so websocket/POS/livechat work behind Traefik.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix(postiz): pass all social provider env vars and fix Temporal healthcheck
* fix(postiz): drop env vars Postiz does not read, unset NOT_SECURED
- GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET are not read by Postiz:
the Google auth provider and GMB both use YOUTUBE_CLIENT_ID
(google.provider.ts, gmb.provider.ts).
- NEXT_PUBLIC_FRONTEND_URL does not exist in the Postiz codebase.
- Postiz checks NOT_SECURED for truthiness only, so the string
"false" still enables insecure mode; remove the variable so
secure cookies are actually on for the HTTPS deployment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Mauricio Siu <mauricio@dokploy.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* data permission right & Traefik configuration
Permession to write on data directory is mandatory for odoo server to run
Added Traefik configuration to allow POS and live chat to run
* fix(odoo_19): provide odoo.conf via config mount and enable proxy_mode
The empty ../files/config bind mount was hiding the image's
/etc/odoo/odoo.conf, crashing wait-for-psql.py (NoSectionError:
'options') in a restart loop. Ship odoo.conf through the template
mount instead, with proxy_mode enabled so websocket/POS/livechat
work behind Traefik (threaded mode serves /websocket on 8069, so
no extra routing is needed). Revert the manual Traefik labels
(invalid compose: labels must be a mapping; Dokploy generates
routing from template.toml) and the chown command (the named
volume already gets odoo ownership from the image).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Mauricio Siu <mauricio@dokploy.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
- ghcr.io/plausible/community-edition v2.1.5 -> v3.2.1 (latest stable release)
- clickhouse-server 24.3.3.102-alpine -> 24.12-alpine, matching the official
CE v3.2.1 compose.yml
- CLICKHOUSE_SKIP_USER_SETUP=1 on the events db: required by ClickHouse
24.11+ images so Plausible can connect as the passwordless default user
(without it the app crash-loops with AUTHENTICATION_FAILED)
- plausible-data volume + TMPDIR per the official v3 compose
Deploy-verified on a Dokploy instance: fresh import, all 3 containers
running, HTTP 200 on the domain with the Plausible login page.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
#1107 targeted main instead of canary and was squash-merged there. This merge
brings blueprints/openseo into canary and keeps both histories converged so
the next canary->main release stays conflict-free.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Add OpenSEO template
OpenSEO is an open source, self-hosted alternative to Semrush and
Ahrefs (keyword research, rank tracking, backlinks, site audits).
Requires a DataForSEO API key, which the template leaves blank for
the user to fill in via the Dokploy UI.
* openseo: pin image to v0.1.6 and set ALLOWED_HOST so Vite preview accepts the Dokploy domain
---------
Co-authored-by: Mauricio Siu <mauricio@dokploy.com>
* fix(appwrite): enable HTTPS for function API endpoint
* appwrite: document that _APP_OPTIONS_FORCE_HTTPS=enabled requires an HTTPS domain
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Mauricio Siu <mauricio@dokploy.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat: update calcom image version and add QOL Env Var for public signup
* fix: add quotes to env var definition
* fix: add more information for selfhosting
* feat: add env vars and config for Email SMTP Creds
* chore(calcom): bump meta.json version to v6.2.0 and fix ARM comment line reference
---------
Co-authored-by: Mauricio Siu <mauricio@dokploy.com>
* feat: add Instatic template
Instatic is a self-hosted, open-source visual CMS combining a canvas
editor, content engine, and static site publisher. Deployed as a
single container backed by SQLite, with uploads and DB on one
persistent volume.
Signed-off-by: Tekena Solomon <tekena157@gmail.com>
* fix: add init container to fix Instatic storage volume permissions
Signed-off-by: Tekena Solomon <tekena157@gmail.com>
* fix(instatic): accept both https and http public origins so the setup wizard works before HTTPS is enabled
---------
Signed-off-by: Tekena Solomon <tekena157@gmail.com>
Co-authored-by: Mauricio Siu <mauricio@dokploy.com>
- rustrak-full: the Next.js standalone UI bound to $HOSTNAME (container id),
so Traefik got connection refused and the UI domain returned 502 (pre-existing
on canary, confirmed by deploying both #1102 and canary). HOSTNAME=0.0.0.0
was deploy-verified: UI 200 "Rustrak - Error Tracking System".
- trmnl-larapaper: #1101 bumped to 0.33.0 (Apr 2026); upstream is at 0.40.0.
0.40.0 was deploy-verified on the same template: healthy, /, /login,
/register, /up all 200.
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Both Rustrak blueprints shipped abians7/* images pinned to v0.2.1, twelve
minor versions behind the current release, and linked to the old personal
repo. Updated to the official rustrak/* images on latest, refreshed the
metadata, and replaced the logo with the current mark.
The memory figure in the description is now measured rather than estimated:
32 MB resident at idle with SQLite, from docker stats on these images.
* feat: add postgres-pgadmin template
* feat: expose postgres via second domain
Add postgres_domain variable and second [[config.domains]] for
postgres:5432 alongside pgadmin:80, so both the DB and the web UI
are reachable via Dokploy domains.
* fix(postgres-pgadmin): drop HTTP domain on postgres:5432, pre-register server in pgAdmin, bump pgAdmin to 9.17
- Remove the second [[config.domains]] pointing an HTTP host at postgres:5432 (Traefik returned 502).
- Mount servers.json + pgpass via config.mounts so pgAdmin comes with the bundled PostgreSQL pre-registered and connects without a password prompt (pgpass is copied to the data volume with 0600 for uid 5050).
- Bump dpage/pgadmin4 8.13 -> 9.17.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Mauricio Siu <mauricio@dokploy.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
- ghcr.io/trixtylab/kotonoba:latest -> 1.0.19 (same digest as latest today); meta.json version 1.0.19.
- ADMIN_DOMAIN is documented upstream as a bare hostname, pass ${main_domain} without scheme.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add DockRoute template
* fix: pass template env vars through to the dockroute container
The compose file had no environment block, so the DOCKROUTE_*/CLOUDFLARE_*
variables defined in template.toml never reached the container - switching
the provider to cloudflare from the Dokploy environment tab would have
silently stayed in the log dry-run mode.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Mauricio Siu <mauricio@dokploy.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Louez is an open-source equipment rental platform (AGPL-3.0): a booking
storefront with live availability plus a back office for reservations,
customers, PDF contracts and statistics.
The blueprint brings up the app, MySQL 8.4 and a private MinIO bucket for
product images. Louez installs its own database schema on first boot.
Didacta is a fair-code self-hosted LMS. The blueprint ships the app image
alongside a pgvector-enabled Postgres (the baseline migration runs
CREATE EXTENSION "vector", so a plain postgres image fails on first boot)
and Redis.
A single domain is enough: the container runs the API on :4000 and the web
on :3000, and Next.js rewrites /api/*, /healthz and /readyz to the internal
API, so the domain only targets port 3000.
* Add Langfuse template
Open-source LLM engineering platform: tracing, prompt management,
evaluation and cost/usage analytics for LLM apps.
Stack: langfuse-web + langfuse-worker (image tag 4), Postgres 17,
ClickHouse 25.12, Redis 7, MinIO. Adapted from the official
docker-compose.yml at https://github.com/langfuse/langfuse/blob/main/docker-compose.yml,
with all secrets generated via Dokploy's template.toml helpers instead
of the upstream hardcoded defaults.
MinIO gets its own domain because Langfuse's web UI issues presigned
S3 URLs that the browser fetches directly (media attached to traces),
so that endpoint has to be reachable from outside the internal network.
Validated locally with build-scripts/validate-template.ts,
validate-docker-compose.ts and generate-meta.js --check (all pass),
plus `docker compose config` with sample secrets to confirm the
langfuse-web override of LANGFUSE_S3_MEDIA_UPLOAD_ENDPOINT resolves
correctly. Not yet deployed on a live Dokploy instance.
* fix: bind langfuse-web to 0.0.0.0 so Traefik can reach it
Docker sets HOSTNAME to the container id, and Next.js standalone binds to
it, which resolves to a single network's IP. With Dokploy's proxy network
attached as a second network, Traefik got connection refused (502).
Setting HOSTNAME=0.0.0.0 fixes routing; verified with a live deploy.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Mauricio Siu <mauricio@dokploy.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat: add Waxum template
* fix(waxum): pin SQLITE_PATH inside the mounted session volume
Waxum's default SQLite path already resolves inside
WHATSAPP_STORAGE_PATH, so this was already persisted, but make it
explicit so it doesn't depend on undocumented default derivation
surviving a redeploy.
Addresses: https://github.com/Dokploy/templates/pull/1074#pullrequestreview-4883962555
---------
Co-authored-by: fdciabdul <taqin2731@gmail.com>
* fix(supabase): generate the new API keys and wire up JWKS verification
The template has carried the plumbing for Supabase's new opaque API keys
since #872 — kong-entrypoint.sh builds the Lua translation expressions and
kong.yml registers the keys as key-auth credentials — and #1068 added the
studio/kong compose references while aligning with upstream.
But four of the variables that plumbing reads have never been declared in
template.toml, so they never reached the Environment tab:
SUPABASE_PUBLISHABLE_KEY, SUPABASE_SECRET_KEY,
ANON_KEY_ASYMMETRIC, SERVICE_ROLE_KEY_ASYMMETRIC
kong-entrypoint.sh gates on the first two being non-empty, so every deploy
silently took the legacy-only branch and users had no field to fill in.
Generate them from [variables] instead:
- SUPABASE_PUBLISHABLE_KEY / SUPABASE_SECRET_KEY as opaque sb_* strings
- ANON_KEY / SERVICE_ROLE_KEY move to [variables] so ANON_KEY_ASYMMETRIC
and SERVICE_ROLE_KEY_ASYMMETRIC can reuse the same JWT
Kong substitutes whatever token those hold and every backend already
verifies HS256 with JWT_SECRET, so the opaque keys work without an EC
keypair (which the dokploy helpers cannot generate). Clients still only
ever hold an opaque string. JWT_KEYS / JWT_JWKS stay empty as a
documented opt-in for real ES256.
Also fixed while in here:
- JWT_JWKS was missing entirely. GOTRUE_JWT_KEYS was already enabled, so
anyone setting a real JWKS got Auth signing ES256 tokens that PostgREST,
Storage, Realtime and Functions had no way to verify. Wire it into all
four verifiers.
- Restore two routes kong.yml dropped: /realtime/v1/api/tenants and
/realtime/v1/api/openapi were reachable with the anon key, and the
PostgREST OpenAPI root at /rest/v1/ was anon-readable (supabase#42949).
Needs KONG_ROUTER_FLAVOR: expressions, as upstream sets.
- graphql-v1 had key-auth hide_credentials: true. key-auth runs before
request-transformer, so the apikey header was stripped before the Lua
expression could read it and service_role GraphQL requests were
silently downgraded to anon.
- DB_ENC_KEY was hardcoded to the well-known "supabaserealtime" default;
generate REALTIME_DB_ENC_KEY instead.
- functions/main/index.ts was the old remote-JWKS version pinned to
deno.land/x/jose@4.14.4; sync with upstream (jsr:@panva/jose@6 and
local SUPABASE_JWKS).
Verified against all 11 services running locally: an RLS-protected table
confirms anon and publishable keys are blocked while service_role and
secret keys read the row, so the opaque keys really are translated and
not downgraded. Storage and Realtime still verify HS256 with JWT_JWKS
empty. 21/22 end-to-end checks pass; the last was the test not following
Studio's redirect.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(supabase): match dokploy hash helper semantics (length = chars, not bytes)
Dokploy's generateHash(length) returns exactly `length` hex characters,
not `length` random bytes hex-encoded. Realtime requires DB_ENC_KEY to be
exactly 16 characters (AES-128), so ${hash:8} produced an 8-char key and
the realtime container crash-looped. Bump to ${hash:16}, and bump the
opaque API key segments to ${hash:22}/${hash:8} to match the intended
sb_<role>_<22>_<8> shape.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Mauricio Siu <mauricio@dokploy.com>
* feat: add NaviMusic blueprint template with docker-compose and configuration support for NaviMusic #1058
* fix: align NaviMusic blueprint metadata
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix: remove invalid NaviMusic env comment
* fix: pin NaviMusic to 4.1.0 and keep container alive without credentials
4.1.1+ throws at startup unless a valid YouTube OAuth2 refresh token
(interactive device-code flow) is provided, so no placeholder config can
ever boot those tags. 4.1.0 is the newest release that boots without it.
Also wrap the entrypoint so a clean exit (empty/invalid DISCORD_TOKEN is
logged, not thrown) idles with instructions in the logs instead of
restart-looping; non-zero exits still hit the restart policy.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Mauricio Siu <siumauricio@icloud.com>
Co-authored-by: Mauricio Siu <mauricio@dokploy.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat: add Novu self-hosted notification template
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat: enhance Novu template with comprehensive environment variable configuration
Added a detailed environment variable section to the Novu template, including secrets, feature flags, service URLs, and database configurations. This update improves clarity and usability for self-hosted deployments.
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* Update forgejo template; bumps Forgejo version to 15; fixes git push over ssh
* updates template compose and toml to use internal port mapping
* fix: bump Forgejo to 16, use expose per repo convention, drop HTTP domain on SSH port
- codeberg.org/forgejo/forgejo:15 -> :16 (current stable, 16.0.2)
- ports -> expose (repo convention since #1053; Traefik reaches the
container over the docker network, no host port publishing needed)
- remove the [[config.domains]] entry on port 22: Dokploy domains are
Traefik HTTP routers and cannot proxy SSH (returned 500 in testing)
- drop empty FORGEJO__server__SSH_PORT= and SSH_LISTEN_PORT overrides
(image defaults already listen on 22)
- clean comment/blank entries from template.toml env array
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Mauricio Siu <siumauricio@icloud.com>
Co-authored-by: Mauricio Siu <mauricio@dokploy.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* fix: normalize template.toml mounts across all blueprints (closes#1047)
- 79 blueprints declared a bare [[config.mounts]] header (one empty array
element in TOML) -> replaced with the repo idiom 'mounts = []'
- 38 blueprints carried doc-style mount blocks (name/mountPath/description)
that don't match the schema (filePath/content) and are inert in Dokploy's
template processor -> removed; their named volumes already live in each
docker-compose.yml
- penpot: duplicate 'expose' map key made its docker-compose.yml invalid
YAML -> merged into one expose list
After this, validate-template.ts passes for all 502 blueprints. The
remaining validate-docker-compose.ts flags are the intentional host-port
templates (mail/game/streaming protocols: poste.io, mailu, oryx, fivem,
lodestone, etc.) which the validator does not yet model as exceptions.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: validator opt-out marker for intentional host ports + annotate rustdesk
The validate-docker-compose CI on this PR was failing on rustdesk's
hbbs/hbbr port mappings (21115-21119) — intentional host-published ports
for the RustDesk relay/rendezvous protocol, which Traefik cannot route.
Adds a '# dokploy: allow-host-ports' top-of-file marker that downgrades
the port-mapping errors to warnings for such protocol templates
(mail/game/streaming/VPN/remote-desktop), and annotates rustdesk.
Other exception templates (poste.io, mailu, oryx, fivem...) can be
annotated case-by-case as the weekly audit (#1049) surfaces them.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Align the template with the current upstream self-hosted stack
(supabase/postgres 17.6.1.136, studio 2026.08.03, kong 3.9.3),
remove the deprecated analytics/vector services and switch
Studio/pg-meta to the postgres role per upstream guidance.
Closes#1067
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* Add Yuvomi template
Privacy-first, self-hosted family planner.
- Image pinned to 0.71.10 (latest stable GHCR tag)
- 4 named volumes (data/backups/modules/documents)
- SESSION_SECRET via ${password:64} helper
- Single domain on port 3000
- Healthcheck wired
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* chore(yuvomi): bump image to 1.85.0
The PR pinned ghcr.io/ulsklyc/yuvomi:0.71.10, but upstream's latest
stable release is v1.85.0. Bump the compose image tag and meta.json
version to match.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Mauricio Siu <siumauricio@icloud.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* feat(templates): add Creed self-host template
Adds a Dokploy blueprint for Creed (creed.md), built from source since
no official Docker image exists yet. Requires an external Supabase
project (schema pushed via the Supabase CLI), so only what can be
generated locally (CREED_ENCRYPTION_SECRET) is auto-filled; Supabase,
Stripe, OpenRouter, Resend, and GitHub OAuth vars are left blank with
setup steps documented in the mounted README.
NEXT_PUBLIC_* vars are threaded through as Docker build args (not just
runtime env), since Next.js inlines them at build time and the app
hard-fails the build if NEXT_PUBLIC_SITE_URL is unset — this was
caught by an actual `docker compose build` run against the upstream
repo, not just template validation.
Verified with docker compose build/up: image builds cleanly, container
boots, / returns 200, and /api/health correctly reports "degraded"
with Supabase unconfigured as expected.
* Pin creed build context and refactor env
- Pin creed docker-compose build context to a specific commit
hash to ensure reproducible builds
- Expose port 3000 in docker-compose (use expose instead of ports)
- Update meta.json version from latest to the pinned hash e9b096d
- Convert template.toml env block from [config.env] to a single env
array
- Keep the README.md mount in place
* Modify docker-compose build context URL
Updated the build context URL to the main branch.
* fix(creed): pin build context and move env under [config]
Restore the commit pin so the inline Dockerfile matches the pre-monorepo
layout, and place env under [config] before domains so Dokploy imports
the environment correctly.
* Add Open Design template
Open Design is a local-first, open-source design tool that ships as a
single self-contained container (no external DB or cache). Adds the
blueprint (docker-compose.yml + template.toml + logo) and a meta.json entry.
* Use node-based healthcheck for Open Design template (matches upstream; verified locally)
* Pin Open Design image to 0.16.1 for reproducible deploys
Replace :latest with the immutable released tag ghcr.io/nexu-io/od:0.16.1
in docker-compose.yml and set the matching version in meta.json, per the
repo pinning convention (AGENTS.md). Tag 0.16.1 verified: /api/health
returns 200 and the node-based healthcheck passes.
* Allow both http and https origins for Open Design template
Dokploy's auto-generated domain is served over plain HTTP by default (no
cert), so OD_ALLOWED_ORIGINS=https://${main_domain} alone made the daemon
reject the browser's http origin with 403, breaking the app after the
onboarding shell loaded. List both schemes so the template works on the
default HTTP domain and after a user adds an HTTPS certificate. Verified
against a live deploy: listed origin -> 200, unlisted -> 403; the daemon
supports comma-separated multi-origin per deploy/README.md.
* Disable daemon API auth so the Open Design web UI loads
The daemon token-gates its API when bound to 0.0.0.0 (every container),
and a browser has no way to present that bearer token, so the web UI's
bootstrap calls all returned 401 and the app failed to load. Set
OD_DISABLE_API_AUTH=1 (the daemon's documented escape hatch) so the UI
works on deploy. Add a README noting the instance is then open (front it
with auth/HTTPS if internet-facing) and how to enable AI features.
Verified end to end against a live deploy on a real domain.
---------
Co-authored-by: Abhiigg <abhi@incrediblegoodguys.com>
Co-authored-by: Mauricio Siu <siumauricio@icloud.com>
- Point the image at ghcr.io/arkhe-systems/senddock:latest so fresh
deploys always get the current release without a per-release PR.
- Remove DEPLOYMENT_MODE (self-host is the default now; the cloud flag
became the boolean CLOUD).
- Remove SENDDOCK_LICENSE_KEY (Pro license is activated from the
dashboard in 0.8; the env var is removed in 0.9).
* feat: add 9Router template (#1040)
* fix: pin the headroom sidecar instead of :latest
* fix: use http for BASE_URL per the repo URL convention
* fix: set NEXT_PUBLIC_BASE_URL so the browser hits the deployed domain
* feat(fmd-server): bump to version 0.16.0
* fix: use expose instead of ports
* fix: fmd-server image tag is 0.16.0 (upstream dropped the v prefix)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Mauricio Siu <siumauricio@icloud.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
* ci: audit every blueprint on a schedule (#1047)
* ci: use RUNNER_TEMP and gate the fail step on the dispatch event
* ci: bound the step summary and publish the full report as an artifact
* ci: treat a missing file as a finding, and never truncate mid-fence
* feat: Add Fluxer template
* fix: populate config.env in template.toml
* fix: syntax in template.toml for config.env
* fix: use multiline string for config.env in template.toml
* fix: format config.env as valid string array in template.toml
* fix: update template.toml format to match standard env array structure
* add: template.toml with optional env vars and http guidance
* fix: change wording to avoid confusion
* fix: add more missing instructions
* fix: more wording changes
* fix: final wording improvements
* fix: comma missing from previous commit
* fix: drop no-op container_name from three blueprints (#1047)
* fix: drop the empty [[config.mounts]] block from vault
* fix: pin vault and scrutiny images, add the missing version header
* fix: meta.json of Poke blueprint
The current github/docs links was broken
before:
https://codeberg.org/ashley/poke
after:
https://codeberg.org/ashleyirispuppy/poke
* fix: broken links in some blueprints
* Add openhabittracker blueprint
* fix(affinepro): update to current AFFiNE images
The template pinned ghcr.io/toeverything/affine-graphql:stable-780dd83,
an ephemeral per-commit tag on the old image name that has since been
removed from GHCR, so the template could no longer pull and deploy.
- Switch both app and migration services to ghcr.io/toeverything/affine:stable,
the rolling stable tag recommended by the official self-host compose,
so the template no longer rots when per-commit tags are garbage-collected
- Move postgres to pgvector/pgvector:pg16 and set AFFINE_INDEXER_ENABLED=false,
matching the current upstream self-host compose requirements
- Add postgres/redis healthchecks and proper depends_on conditions so the
self-host-predeploy migration job runs only once the database is ready,
and the server starts only after migrations complete successfully
Closes#777
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(cockpit): persist config and storage volumes per upstream docs
The template mounted `html:/var/www/html` (freezing the app code from the
first deploy) and `data:/var/www/html/storage/data`, which misses uploaded
assets (stored under `storage/uploads`) and cache. Per the official Cockpit
persistent-storage docs, mount `config:/var/www/html/config` and
`storage:/var/www/html/storage` instead.
Closes#549
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(kener): define REDIS_URL and drop unused databases
Kener v4 requires Redis for its BullMQ queues, caching and scheduler,
so the app crashed on startup with "REDIS_URL is not defined in
environment variables" right after printing that it was running
(issue #976). The template also spun up both a postgres and a mariadb
container while DATABASE_URL pointed at SQLite, so neither database
was ever used (issue #282).
Changes, aligned with the upstream docker-compose.yml
(rajnandan1/kener):
- Add a redis:7-alpine service with a healthcheck and persistent
volume, wire REDIS_URL=redis://redis:6379 and make kener depend on
redis being healthy
- Remove the unused postgres and mysql services plus their env vars
and generated passwords; keep SQLite (upstream default) persisted
in the kener_db volume
- Set ORIGIN to https://<domain> instead of http://localhost:3000 so
CSRF protection works behind the generated domain
- Drop the stale /app/uploads bind mount (kener v4 only persists
/app/database) and the obsolete compose version key
Deploy-tested on a Dokploy instance: migrations and seed complete,
schedulers start, "Kener version 4.1.2 is running!", HTTP 200 on the
generated domain, both containers stable.
Closes#976Closes#282
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(homarr): use named volume for /appdata and hex encryption key
- Replace the relative bind mount `../homarr/appdata:/appdata` with a
named volume `homarr_appdata:/appdata` so the data survives cleanups
and can be backed up through Dokploy volume backups.
- Generate SECRET_ENCRYPTION_KEY with `${hash:64}` instead of
`${password:64}`: homarr requires a 64-character hex string
(`openssl rand -hex 32`) and the password helper emits non-hex
characters (g-z).
Closes#738
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(logto): fix postgres role error and update to 1.41.0
The postgres healthcheck ran pg_isready without -U while POSTGRES_USER
was set to logto, so every probe attempted to connect as role
"postgres" and spammed FATAL: role "postgres" does not exist.
Pass -U logto -d logto explicitly and set POSTGRES_DB.
Also fix LOGTO_ENDPOINT pointing at the admin domain instead of the
main domain, update Logto 1.27.0 -> 1.41.0, use ${password:32} for the
generated password, drop the ephemeral host port publishing and add
restart policies.
Closes#130
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(gitlab-ce): serve on the generated domain (remove removed unicorn config, pin omnibus)
The template set unicorn['worker_processes'] / unicorn['worker_timeout'] in
GITLAB_OMNIBUS_CONFIG. Unicorn was removed in GitLab 14.0, so on current
gitlab-ce images `gitlab-ctl reconfigure` aborts with "Removed configurations
found in gitlab.rb" and GitLab never starts serving — the generated domain
returned 502 Bad Gateway (issue #380).
Rewrite the template as the official all-in-one Omnibus setup:
- pin gitlab/gitlab-ce:19.1.2-ce.0 instead of :latest
- external_url http://<domain> with nginx listen_port 80 / listen_https false
(TLS terminates at Traefik)
- set gitlab_rails['initial_root_password'] from a generated template password
- puma single mode + prometheus monitoring off to keep memory reasonable
- drop the external postgres/redis containers (Omnibus bundles and manages
its own) and the broken ports entries ("2224" published a random host port
while sshd listens on 22)
Verified on a live Dokploy instance: domain serves the GitLab sign-in page
and root login with the generated password works.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(zitadel): wire EXTERNALDOMAIN/PORT/SECURE to the generated domain
Zitadel resolves its instance from the external domain/port/scheme, so the
template's ZITADEL_EXTERNALPORT=8080 made every generated URL (OIDC issuer,
login redirects) point at http://<domain>:8080 instead of the domain served
by Traefik, ending in {"code":5,"message":"Not Found"} (#516).
- Expose ZITADEL_EXTERNALDOMAIN / ZITADEL_EXTERNALPORT / ZITADEL_EXTERNALSECURE
as template env vars, defaulting to the generated domain over HTTP
(port 80, secure=false) so the routed domain and Zitadel's external config
always match; HTTPS users flip them to 443/true in the Env tab.
- Pin image to v4.16.0 (was latest) and keep the built-in login v1 via
ZITADEL_DEFAULTINSTANCE_FEATURES_LOGINV2_REQUIRED=false so no separate
login-v2 container is needed.
- Add the official readiness healthcheck, drop the unused /app/data volume,
bogus SMTP env keys, published port and obsolete compose version key.
Closes#516
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(immich): update to v3.0.2
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(automatisch): switch to official image and wire up DOMAIN to fix Bad Gateway
- Replace unofficial dockeriddonuts/automatisch:2.0 mirror (stale since Nov 2024)
with the official automatischio/automatisch:0.15.0 image
- Define DOMAIN in template.toml [config.env]: the compose referenced ${DOMAIN}
but it was never provided, so HOST resolved empty and the app generated
localhost URLs for the web app and webhooks
- Set API_URL/WEB_APP_URL so generated URLs don't carry the internal :3000 port
behind Traefik
- Add postgres healthcheck and gate the app on service_healthy to avoid the
boot-time migration race; worker now starts after main (official compose order)
- Drop unnecessary published port and no-op REDIS_* env on the redis service
- Bump meta.json version to 0.15.0
Closes#97
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(signoz): fix ClickHouse hostname resolution and IPv6 binding
- Override the ClickHouse image's config.d/docker_related_config.xml,
which listens on the IPv6 wildcard address ([::]) first and fails to
bind on hosts without IPv6 support; listen on 0.0.0.0 (IPv4) only and
disable the internal DNS cache so transient startup DNS failures for
zookeeper-1/clickhouse are not cached (issue #534).
- Set hostname: clickhouse (instead of container_name) so the server
identifies itself as the cluster host declared in cluster.xml.
- Remove the explicit signoz-net network: Dokploy attaches its own
networks automatically and the repo validator rejects explicit
networks; a fixed-name shared network also breaks service DNS across
deployments.
- Fix mount mismatch: template.toml created files/signoz/prometheus.xml
while the compose mounts ../files/signoz/prometheus.yml, so Docker
silently mounted a directory as the signoz prometheus config.
- Give the otel-collector domain its own generated host: both domains
previously shared the same host and path "/", creating two conflicting
Traefik routers where one service randomly won.
Closes#534
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(infisical): update to v0.162.6
- Bump image from v0.135.0-postgres to v0.162.6 (upstream dropped the
-postgres tag suffix after v0.146.0; plain tags are the postgres build)
- Remove the db-migration service: the standalone image runs database
migrations automatically on boot (auto-start-migrations), matching the
official docker-compose.prod.yml which no longer ships that service
- Generate ENCRYPTION_KEY (${hash:32}) and AUTH_SECRET (${base64:32})
per deployment instead of shipping hardcoded example secrets
- Fix SITE_URL to http://${main_domain} (no :8080; the domain is proxied)
- Refresh SMTP env names (SMTP_FROM_ADDRESS/SMTP_FROM_NAME; SMTP_SECURE
was removed upstream) and drop unused CLIENT_* env placeholders that
were never passed to the container
Closes#215
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix: add databasus (postgresus renamed upstream)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(evolutionapi): enable integration flags and update version
Adds the integration enable env flags introduced in Evolution API v2.3.x
(N8N_ENABLED, OPENAI_ENABLED, EVOAI_ENABLED, DIFY_ENABLED, TYPEBOT_ENABLED,
CHATWOOT_ENABLED) so integrations no longer fail with 'N8n is disabled',
and pins the image to v2.3.7 instead of latest.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(rybbit): update to v2.7.0
The template shipped rybbit v1.5.1, which is no longer supported and is
vulnerable to known React2Shell exploits (see #659). Update to the
latest stable release v2.7.0 and align the stack with the upstream
docker-compose:
- Pin ghcr.io/rybbit-io/rybbit-backend and rybbit-client to v2.7.0
- Add the redis service now required by the backend (session tracking
and BullMQ queues), with password auth, AOF persistence and
noeviction policy per upstream
- Drop the DOMAIN_NAME env var (only used by the upstream Caddy
webserver, which Dokploy replaces with Traefik)
- Add DISABLE_TELEMETRY env and generate BETTER_AUTH_SECRET as base64
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(phpmyadmin): raise PHP upload limit so SQL imports over 2MB work
Without UPLOAD_LIMIT the phpMyAdmin image keeps PHP's default 2M
post_max_size/upload_max_filesize, so importing any SQL file larger
than 2MB fails with 'POST Content-Length exceeds the limit of
2097152 bytes' followed by a session_start error page.
- Add UPLOAD_LIMIT (512M) and MAX_EXECUTION_TIME (600) env vars,
configurable from the template env
- Wire the previously unused MYSQL_DATABASE env var into the compose
file, replacing the hardcoded 'tu_base_de_datos' placeholder, and
default it to 'phpmyadmin' instead of the system 'mysql' schema
Closes#236
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(openpanel): pin verified 2.2.1 images and fix ClickHouse interserver host
- Pin lindesvard/openpanel-api|dashboard|worker to 2.2.1 (verified working
end-to-end on a Dokploy instance) instead of the mutable :2 tag, so a
future broken 2.x release cannot silently break the template again —
which is how #615 originated when 2.0.0 shipped.
- Fix interserver_http_host to match the actual service name (op-ch),
aligning with upstream self-hosting config.
- Set meta.json version to the pinned 2.2.1.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(wordpress): route loopback requests through Traefik to fix cURL error 28
WordPress resolves its own public domain to the server's public IP from
inside the container, so REST API / WP-Cron / Site Health loopback
requests depend on hairpin NAT, which times out (cURL error 28) on many
hosts. Pin the site domain to the dokploy-traefik container IP in
/etc/hosts at startup (with retries, since Traefik joins the compose
network shortly after the container starts) so loopback traffic stays
inside the Docker network for both HTTP and HTTPS. No-op fallback when
dokploy-traefik is not resolvable.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(minio): migrate to pgsty/minio community fork (upstream is source-only and archived)
MinIO Inc. stopped publishing Docker images and pre-built binaries in
October 2025 and archived the minio/minio repository in February 2026.
The official minio/minio image is frozen at RELEASE.2025-09-07T16-13-09Z
and no longer receives security fixes (the fix for CVE-2025-62506 was
never published as an image).
- Switch image to pgsty/minio:RELEASE.2026-06-18T00-00-00Z, the actively
maintained community fork (drop-in replacement, AGPLv3, same env vars,
same /data on-disk format, restores the full web console)
- Route the S3 API (port 9000) through its own generated domain instead
of publishing host port 9000, per repo conventions
- Update meta.json links/description to point at the maintained fork
Closes#469
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(nextcloud-aio): drop AIO branding, keep template id, pin nextcloud 33.0.6
The template ships plain nextcloud + mariadb + redis + cron, not the
nextcloud/all-in-one mastercontainer. Display name and description no
longer claim AIO; folder id is kept as nextcloud-aio to avoid breaking
existing installs. Image pinned to the current stable tag (33.0.6).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add MailCatcher NG template
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* docs: add per-template setup instructions (supabase, trigger.dev)
Adds instructions.md files for the Supabase and Trigger.dev templates and
renders them in the template browser as a new Instructions tab in the
template dialog (fetched from blueprints/<id>/instructions.md, rendered
with a small dependency-free markdown component).
Also removes the placeholder blueprints/ackee/instructions.md so it does
not surface as an empty Instructions tab.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add Weblate template
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add Synapse (Matrix homeserver) template
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add Dify template
Dify 1.15.0 (open-source LLM app development platform): api + worker +
worker_beat + web + pgvector PostgreSQL (also used as the vector store) +
redis + sandbox + ssrf_proxy (squid) + plugin_daemon, fronted by an
internal nginx gateway that mirrors the upstream path routing.
Closes#88
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add Sim Studio template
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add Steedos template
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add Silex template
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add SpacetimeDB template
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add CertMate template
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add PostHog template
Based on the official hobby deployment, trimmed to run on a single
server: Django web + Celery worker, Node plugin-server (CDP, ingestion,
session replay, recording API), Rust capture/replay-capture/
feature-flags/hypercache, livestream, Caddy path router, Postgres,
Redis, Redpanda (Kafka), ZooKeeper, ClickHouse and MinIO.
Images are pinned to a tested master commit (PostHog no longer
publishes tagged releases); an init container fetches the matching
ClickHouse configuration, Kafka table schemas, funnel UDF binaries and
the GeoIP database at the same pinned ref.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add Markup template
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add Frappe LMS template
Adds a Frappe LMS (Frappe Learning) template based on the erpnext-v16
blueprint pattern (configurator + create-site + workers + scheduler +
websocket + mariadb + 3x redis).
Pins ghcr.io/frappe/lms:v2.52.0, the latest upstream image that ships
the lms app (v2.52.1+ images are currently published without any apps
baked in). The image does not bundle the payments app, so create-site
clears lms's required_apps before install; paid-course checkout is
unavailable, everything else works. The backend is gated on a
create-site completion marker so gunicorn workers never serve (and
cache) a half-installed site during the 3-6 minute first boot.
Closes#517
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add TREK template
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add Oryx (SRS) media streaming template
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix: stop plugins service crash loop (logs-redis TLS default)
In production images LOGS_REDIS_TLS/TRACES_REDIS_TLS default to true, so
the logs-ingestion consumer (part of the plugin-server default mode) kept
attempting a TLS handshake against the plaintext Redis, timed out every
~11s and killed the process after 10 errors (restart loop every ~2.5 min).
Constrain the plugins service to the capability groups this template
ships (cdp_workflows, realtime_cohorts, feature_flags) and pin the redis
TLS flags to false as belt-and-braces.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add n8n queue mode template
n8n running in queue mode (EXECUTIONS_MODE=queue): main instance for the
editor/webhooks, a scalable pool of workers (deploy.replicas driven by the
N8N_WORKER_REPLICAS env var), Redis (Bull) as the queue broker and
PostgreSQL as the database. Pinned to the current stable n8nio/n8n:2.30.4.
Closes#455
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add bonfire template
Bonfire (social flavour) — federated social networking toolkit.
App + PostGIS + Meilisearch, mirroring upstream's reference deployments.
Closes#125
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add dagu blueprint
Dagu is a self-contained workflow engine with a Web UI for scheduling and
orchestrating jobs as DAGs defined in declarative YAML.
- Pin ghcr.io/dagucloud/dagu:2.10.7 and expose the Web UI on port 8080
- Set DAGU_HOST=0.0.0.0 so the service is reachable through the proxy
- Enable basic auth with a generated per-deploy admin password
- Persist /var/lib/dagu (DAGs, logs, run history) in a named volume
Claude-Session: https://claude.ai/code/session_01CRNT6sa2q2P9rUTokeoGhQ
* feat: add OneUptime template
Adds OneUptime (open-source observability platform: uptime monitoring,
status pages, incident management, on-call, logs/traces/metrics) as a
template, following upstream's current single-app architecture
(app + nginx ingress + postgres + redis + clickhouse + probe).
Closes#514
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat: add Mailu template
Mailu 2024.06 mail server: front (nginx), admin, imap (dovecot),
smtp (postfix), antispam (rspamd), Roundcube webmail and redis.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* feat(templates): add systemprompt (#1032)
* feat(templates): add systemprompt
* fix header comment: accurate in both repos
* chore: normalize template tags to kebab-case (#987)
* feat: adds `check-links.js` to find broken links (#983)
* feat: add struxa template (#1037)
* feat: add struxa template
Adds a Dokploy blueprint for Struxa (github.com/struxadotcloud/struxa),
a self-hosted, open-source server management panel. Deploys the
published GHCR images (dashboard, watchkeeper, migrate) plus MySQL
and MinIO sidecars. The web service generates its RS256 JWT keypair
at startup via Node's built-in crypto module, since no Dokploy
template helper covers RSA key generation.
* fix: pin struxa images to latest floating tag
struxa's release workflow pushes a latest floating tag alongside
version tags on every stable release, matching the convention used
by ~44% of existing blueprints (version: "latest" in meta.json).
* fix: generate a 64-char DATABASE_ENCRYPTION_KEY
Dokploy's runtime \${hash:N} helper produces N hex characters, not N
bytes (the templates repo's local preview helpers.ts models it as
byte count, which is inconsistent with the platform). struxa's env
schema requires DATABASE_ENCRYPTION_KEY to be >=64 chars (it's hex
decoded to a 32-byte AES-256 key), so \${hash:32} only produced half
the required length. Confirmed against other blueprints (sim,
chatwoot, outline) which all use \${hash:64} for 64-char secrets.
* fix: address Copilot review comments
- Add explicit \`version: "3.8"\` to docker-compose.yml, matching the
documented template format.
- Pin minio/minio to a specific RELEASE tag (used elsewhere in the
repo: plane, posthog) instead of the floating latest tag.
- Default BETTER_AUTH_URL/APP_URL/CORS_ORIGIN to http://, matching
repo convention for Dokploy-fronted apps (TLS terminates at the
proxy).
* fix: rename web service to struxa
AGENTS.md convention: the primary Docker service name should match
the blueprint folder name. Renamed the web/dashboard service from
"web" to "struxa" in docker-compose.yml and updated
template.toml's config.domains.serviceName to match.
* Add PodFetch template (#1035)
* Add PodFetch template
* Use env array syntax in template.toml
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Address review: match version to image tag, expose admin_username variable, dark-mode friendly logo
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* fix(docker): share plugins and themes volumes across containers (#990)
* feat(directus): upgrade template to Directus 12.1.1 (#986)
* feat(directus): upgrade template to Directus 12.1.1
* feat(directus): add commented S3 env variables to template.toml
---------
Co-authored-by: Zakher Masri <46135573+zaaakher@users.noreply.github.com>
Co-authored-by: zakher <zakhermasri@gmail.com>
Co-authored-by: Jinjinov <dzindzinovic@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Stephan Fitzpatrick <stephan@knowsuchagency.com>
Co-authored-by: Mauricio Siu <mauricio@dokploy.com>
Co-authored-by: Edward Burton <ejb503@gmail.com>
Co-authored-by: Marko Kostich <markokosticdev@gmail.com>
Co-authored-by: Jakub Krzyżanowski <jakubkrzyz.kontakt@gmail.com>
Co-authored-by: SamTV12345 <40429738+SamTV12345@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Mafly <110502739+Nekoplii@users.noreply.github.com>
* Add PodFetch template
* Use env array syntax in template.toml
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* Address review: match version to image tag, expose admin_username variable, dark-mode friendly logo
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* feat: add struxa template
Adds a Dokploy blueprint for Struxa (github.com/struxadotcloud/struxa),
a self-hosted, open-source server management panel. Deploys the
published GHCR images (dashboard, watchkeeper, migrate) plus MySQL
and MinIO sidecars. The web service generates its RS256 JWT keypair
at startup via Node's built-in crypto module, since no Dokploy
template helper covers RSA key generation.
* fix: pin struxa images to latest floating tag
struxa's release workflow pushes a latest floating tag alongside
version tags on every stable release, matching the convention used
by ~44% of existing blueprints (version: "latest" in meta.json).
* fix: generate a 64-char DATABASE_ENCRYPTION_KEY
Dokploy's runtime \${hash:N} helper produces N hex characters, not N
bytes (the templates repo's local preview helpers.ts models it as
byte count, which is inconsistent with the platform). struxa's env
schema requires DATABASE_ENCRYPTION_KEY to be >=64 chars (it's hex
decoded to a 32-byte AES-256 key), so \${hash:32} only produced half
the required length. Confirmed against other blueprints (sim,
chatwoot, outline) which all use \${hash:64} for 64-char secrets.
* fix: address Copilot review comments
- Add explicit \`version: "3.8"\` to docker-compose.yml, matching the
documented template format.
- Pin minio/minio to a specific RELEASE tag (used elsewhere in the
repo: plane, posthog) instead of the floating latest tag.
- Default BETTER_AUTH_URL/APP_URL/CORS_ORIGIN to http://, matching
repo convention for Dokploy-fronted apps (TLS terminates at the
proxy).
* fix: rename web service to struxa
AGENTS.md convention: the primary Docker service name should match
the blueprint folder name. Renamed the web/dashboard service from
"web" to "struxa" in docker-compose.yml and updated
template.toml's config.domains.serviceName to match.
Dagu is a self-contained workflow engine with a Web UI for scheduling and
orchestrating jobs as DAGs defined in declarative YAML.
- Pin ghcr.io/dagucloud/dagu:2.10.7 and expose the Web UI on port 8080
- Set DAGU_HOST=0.0.0.0 so the service is reachable through the proxy
- Enable basic auth with a generated per-deploy admin password
- Persist /var/lib/dagu (DAGs, logs, run history) in a named volume
Claude-Session: https://claude.ai/code/session_01CRNT6sa2q2P9rUTokeoGhQ
n8n running in queue mode (EXECUTIONS_MODE=queue): main instance for the
editor/webhooks, a scalable pool of workers (deploy.replicas driven by the
N8N_WORKER_REPLICAS env var), Redis (Bull) as the queue broker and
PostgreSQL as the database. Pinned to the current stable n8nio/n8n:2.30.4.
Closes#455
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
In production images LOGS_REDIS_TLS/TRACES_REDIS_TLS default to true, so
the logs-ingestion consumer (part of the plugin-server default mode) kept
attempting a TLS handshake against the plaintext Redis, timed out every
~11s and killed the process after 10 errors (restart loop every ~2.5 min).
Constrain the plugins service to the capability groups this template
ships (cdp_workflows, realtime_cohorts, feature_flags) and pin the redis
TLS flags to false as belt-and-braces.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds a Frappe LMS (Frappe Learning) template based on the erpnext-v16
blueprint pattern (configurator + create-site + workers + scheduler +
websocket + mariadb + 3x redis).
Pins ghcr.io/frappe/lms:v2.52.0, the latest upstream image that ships
the lms app (v2.52.1+ images are currently published without any apps
baked in). The image does not bundle the payments app, so create-site
clears lms's required_apps before install; paid-course checkout is
unavailable, everything else works. The backend is gated on a
create-site completion marker so gunicorn workers never serve (and
cache) a half-installed site during the 3-6 minute first boot.
Closes#517
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Based on the official hobby deployment, trimmed to run on a single
server: Django web + Celery worker, Node plugin-server (CDP, ingestion,
session replay, recording API), Rust capture/replay-capture/
feature-flags/hypercache, livestream, Caddy path router, Postgres,
Redis, Redpanda (Kafka), ZooKeeper, ClickHouse and MinIO.
Images are pinned to a tested master commit (PostHog no longer
publishes tagged releases); an init container fetches the matching
ClickHouse configuration, Kafka table schemas, funnel UDF binaries and
the GeoIP database at the same pinned ref.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds instructions.md files for the Supabase and Trigger.dev templates and
renders them in the template browser as a new Instructions tab in the
template dialog (fetched from blueprints/<id>/instructions.md, rendered
with a small dependency-free markdown component).
Also removes the placeholder blueprints/ackee/instructions.md so it does
not surface as an empty Instructions tab.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The template ships plain nextcloud + mariadb + redis + cron, not the
nextcloud/all-in-one mastercontainer. Display name and description no
longer claim AIO; folder id is kept as nextcloud-aio to avoid breaking
existing installs. Image pinned to the current stable tag (33.0.6).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MinIO Inc. stopped publishing Docker images and pre-built binaries in
October 2025 and archived the minio/minio repository in February 2026.
The official minio/minio image is frozen at RELEASE.2025-09-07T16-13-09Z
and no longer receives security fixes (the fix for CVE-2025-62506 was
never published as an image).
- Switch image to pgsty/minio:RELEASE.2026-06-18T00-00-00Z, the actively
maintained community fork (drop-in replacement, AGPLv3, same env vars,
same /data on-disk format, restores the full web console)
- Route the S3 API (port 9000) through its own generated domain instead
of publishing host port 9000, per repo conventions
- Update meta.json links/description to point at the maintained fork
Closes#469
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
WordPress resolves its own public domain to the server's public IP from
inside the container, so REST API / WP-Cron / Site Health loopback
requests depend on hairpin NAT, which times out (cURL error 28) on many
hosts. Pin the site domain to the dokploy-traefik container IP in
/etc/hosts at startup (with retries, since Traefik joins the compose
network shortly after the container starts) so loopback traffic stays
inside the Docker network for both HTTP and HTTPS. No-op fallback when
dokploy-traefik is not resolvable.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Pin lindesvard/openpanel-api|dashboard|worker to 2.2.1 (verified working
end-to-end on a Dokploy instance) instead of the mutable :2 tag, so a
future broken 2.x release cannot silently break the template again —
which is how #615 originated when 2.0.0 shipped.
- Fix interserver_http_host to match the actual service name (op-ch),
aligning with upstream self-hosting config.
- Set meta.json version to the pinned 2.2.1.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Without UPLOAD_LIMIT the phpMyAdmin image keeps PHP's default 2M
post_max_size/upload_max_filesize, so importing any SQL file larger
than 2MB fails with 'POST Content-Length exceeds the limit of
2097152 bytes' followed by a session_start error page.
- Add UPLOAD_LIMIT (512M) and MAX_EXECUTION_TIME (600) env vars,
configurable from the template env
- Wire the previously unused MYSQL_DATABASE env var into the compose
file, replacing the hardcoded 'tu_base_de_datos' placeholder, and
default it to 'phpmyadmin' instead of the system 'mysql' schema
Closes#236
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The template shipped rybbit v1.5.1, which is no longer supported and is
vulnerable to known React2Shell exploits (see #659). Update to the
latest stable release v2.7.0 and align the stack with the upstream
docker-compose:
- Pin ghcr.io/rybbit-io/rybbit-backend and rybbit-client to v2.7.0
- Add the redis service now required by the backend (session tracking
and BullMQ queues), with password auth, AOF persistence and
noeviction policy per upstream
- Drop the DOMAIN_NAME env var (only used by the upstream Caddy
webserver, which Dokploy replaces with Traefik)
- Add DISABLE_TELEMETRY env and generate BETTER_AUTH_SECRET as base64
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds the integration enable env flags introduced in Evolution API v2.3.x
(N8N_ENABLED, OPENAI_ENABLED, EVOAI_ENABLED, DIFY_ENABLED, TYPEBOT_ENABLED,
CHATWOOT_ENABLED) so integrations no longer fail with 'N8n is disabled',
and pins the image to v2.3.7 instead of latest.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Bump image from v0.135.0-postgres to v0.162.6 (upstream dropped the
-postgres tag suffix after v0.146.0; plain tags are the postgres build)
- Remove the db-migration service: the standalone image runs database
migrations automatically on boot (auto-start-migrations), matching the
official docker-compose.prod.yml which no longer ships that service
- Generate ENCRYPTION_KEY (${hash:32}) and AUTH_SECRET (${base64:32})
per deployment instead of shipping hardcoded example secrets
- Fix SITE_URL to http://${main_domain} (no :8080; the domain is proxied)
- Refresh SMTP env names (SMTP_FROM_ADDRESS/SMTP_FROM_NAME; SMTP_SECURE
was removed upstream) and drop unused CLIENT_* env placeholders that
were never passed to the container
Closes#215
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Override the ClickHouse image's config.d/docker_related_config.xml,
which listens on the IPv6 wildcard address ([::]) first and fails to
bind on hosts without IPv6 support; listen on 0.0.0.0 (IPv4) only and
disable the internal DNS cache so transient startup DNS failures for
zookeeper-1/clickhouse are not cached (issue #534).
- Set hostname: clickhouse (instead of container_name) so the server
identifies itself as the cluster host declared in cluster.xml.
- Remove the explicit signoz-net network: Dokploy attaches its own
networks automatically and the repo validator rejects explicit
networks; a fixed-name shared network also breaks service DNS across
deployments.
- Fix mount mismatch: template.toml created files/signoz/prometheus.xml
while the compose mounts ../files/signoz/prometheus.yml, so Docker
silently mounted a directory as the signoz prometheus config.
- Give the otel-collector domain its own generated host: both domains
previously shared the same host and path "/", creating two conflicting
Traefik routers where one service randomly won.
Closes#534
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Replace unofficial dockeriddonuts/automatisch:2.0 mirror (stale since Nov 2024)
with the official automatischio/automatisch:0.15.0 image
- Define DOMAIN in template.toml [config.env]: the compose referenced ${DOMAIN}
but it was never provided, so HOST resolved empty and the app generated
localhost URLs for the web app and webhooks
- Set API_URL/WEB_APP_URL so generated URLs don't carry the internal :3000 port
behind Traefik
- Add postgres healthcheck and gate the app on service_healthy to avoid the
boot-time migration race; worker now starts after main (official compose order)
- Drop unnecessary published port and no-op REDIS_* env on the redis service
- Bump meta.json version to 0.15.0
Closes#97
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Zitadel resolves its instance from the external domain/port/scheme, so the
template's ZITADEL_EXTERNALPORT=8080 made every generated URL (OIDC issuer,
login redirects) point at http://<domain>:8080 instead of the domain served
by Traefik, ending in {"code":5,"message":"Not Found"} (#516).
- Expose ZITADEL_EXTERNALDOMAIN / ZITADEL_EXTERNALPORT / ZITADEL_EXTERNALSECURE
as template env vars, defaulting to the generated domain over HTTP
(port 80, secure=false) so the routed domain and Zitadel's external config
always match; HTTPS users flip them to 443/true in the Env tab.
- Pin image to v4.16.0 (was latest) and keep the built-in login v1 via
ZITADEL_DEFAULTINSTANCE_FEATURES_LOGINV2_REQUIRED=false so no separate
login-v2 container is needed.
- Add the official readiness healthcheck, drop the unused /app/data volume,
bogus SMTP env keys, published port and obsolete compose version key.
Closes#516
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The template set unicorn['worker_processes'] / unicorn['worker_timeout'] in
GITLAB_OMNIBUS_CONFIG. Unicorn was removed in GitLab 14.0, so on current
gitlab-ce images `gitlab-ctl reconfigure` aborts with "Removed configurations
found in gitlab.rb" and GitLab never starts serving — the generated domain
returned 502 Bad Gateway (issue #380).
Rewrite the template as the official all-in-one Omnibus setup:
- pin gitlab/gitlab-ce:19.1.2-ce.0 instead of :latest
- external_url http://<domain> with nginx listen_port 80 / listen_https false
(TLS terminates at Traefik)
- set gitlab_rails['initial_root_password'] from a generated template password
- puma single mode + prometheus monitoring off to keep memory reasonable
- drop the external postgres/redis containers (Omnibus bundles and manages
its own) and the broken ports entries ("2224" published a random host port
while sshd listens on 22)
Verified on a live Dokploy instance: domain serves the GitLab sign-in page
and root login with the generated password works.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The postgres healthcheck ran pg_isready without -U while POSTGRES_USER
was set to logto, so every probe attempted to connect as role
"postgres" and spammed FATAL: role "postgres" does not exist.
Pass -U logto -d logto explicitly and set POSTGRES_DB.
Also fix LOGTO_ENDPOINT pointing at the admin domain instead of the
main domain, update Logto 1.27.0 -> 1.41.0, use ${password:32} for the
generated password, drop the ephemeral host port publishing and add
restart policies.
Closes#130
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Replace the relative bind mount `../homarr/appdata:/appdata` with a
named volume `homarr_appdata:/appdata` so the data survives cleanups
and can be backed up through Dokploy volume backups.
- Generate SECRET_ENCRYPTION_KEY with `${hash:64}` instead of
`${password:64}`: homarr requires a 64-character hex string
(`openssl rand -hex 32`) and the password helper emits non-hex
characters (g-z).
Closes#738
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kener v4 requires Redis for its BullMQ queues, caching and scheduler,
so the app crashed on startup with "REDIS_URL is not defined in
environment variables" right after printing that it was running
(issue #976). The template also spun up both a postgres and a mariadb
container while DATABASE_URL pointed at SQLite, so neither database
was ever used (issue #282).
Changes, aligned with the upstream docker-compose.yml
(rajnandan1/kener):
- Add a redis:7-alpine service with a healthcheck and persistent
volume, wire REDIS_URL=redis://redis:6379 and make kener depend on
redis being healthy
- Remove the unused postgres and mysql services plus their env vars
and generated passwords; keep SQLite (upstream default) persisted
in the kener_db volume
- Set ORIGIN to https://<domain> instead of http://localhost:3000 so
CSRF protection works behind the generated domain
- Drop the stale /app/uploads bind mount (kener v4 only persists
/app/database) and the obsolete compose version key
Deploy-tested on a Dokploy instance: migrations and seed complete,
schedulers start, "Kener version 4.1.2 is running!", HTTP 200 on the
generated domain, both containers stable.
Closes#976Closes#282
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The template mounted `html:/var/www/html` (freezing the app code from the
first deploy) and `data:/var/www/html/storage/data`, which misses uploaded
assets (stored under `storage/uploads`) and cache. Per the official Cockpit
persistent-storage docs, mount `config:/var/www/html/config` and
`storage:/var/www/html/storage` instead.
Closes#549
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The template pinned ghcr.io/toeverything/affine-graphql:stable-780dd83,
an ephemeral per-commit tag on the old image name that has since been
removed from GHCR, so the template could no longer pull and deploy.
- Switch both app and migration services to ghcr.io/toeverything/affine:stable,
the rolling stable tag recommended by the official self-host compose,
so the template no longer rots when per-commit tags are garbage-collected
- Move postgres to pgvector/pgvector:pg16 and set AFFINE_INDEXER_ENABLED=false,
matching the current upstream self-host compose requirements
- Add postgres/redis healthchecks and proper depends_on conditions so the
self-host-predeploy migration job runs only once the database is ready,
and the server starts only after migrations complete successfully
Closes#777
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kener v4 requires Redis for BullMQ background queues. Without it, the
application crashes on startup with 'REDIS_URL is not defined' error.
Changes:
- Add Redis 7 Alpine service with healthcheck
- Pin Kener image to v4.1.1 (was 'latest')
- Add REDIS_URL env var pointing to redis://redis:6379
- Remove unused postgres and mysql services (SQLite is the default)
- Remove unused env vars for removed DB services
- Use expose instead of ports (Dokploy convention)
- Add depends_on with service_healthy condition for Redis
Fixes https://github.com/Dokploy/templates/issues/976
"description":"Self-hosted AI model router that rotates requests across 40+ providers with automatic fallback, exposing an OpenAI-compatible endpoint for coding agents.",
# dokploy: allow-host-ports — DNS (53/tcp+udp), DHCP (67/68) and DNS-over-TLS/QUIC (853) are not HTTP protocols; clients must reach them directly on the host, Traefik cannot route them.
version:"3.8"
services:
adguardhome:
@@ -10,11 +11,12 @@ services:
- "68:68/tcp"# DHCP Client
- "853:853/tcp"# DNS over TLS, DNS-over-QUIC
- "853:853/udp"# DNS over TLS, DNS-over-QUIC
- "6060:6060/tcp"# HTTP (pprof)
expose:
- 6060# HTTP (pprof) — debug endpoint, no need to publish it on the host
"description":"Affine Pro is a modern, self-hosted platform designed for collaborative content creation and project management. It offers an intuitive interface, seamless real-time collaboration, and powerful tools for organizing tasks, notes, and ideas.",
# dokploy: allow-host-ports — Anytype clients speak the any-sync protocol (TCP 33010, UDP/QUIC 33020) directly against the server; it is not HTTP, so Traefik cannot route it.
# Example: Any-Sync-Bundle with embedded MongoDB and Redis (all-in-one image)
"description":"Automatisch is a powerful, self-hosted workflow automation tool designed for connecting your apps and automating repetitive tasks. With Automatisch, you can create workflows to sync data, send notifications, and perform various actions seamlessly across different services.",
Dokploy creates independent database, storage, JWT, encryption, and scheduler secrets during import. Only the `web` service receives a public domain; the API, scheduler, PostgreSQL, and MinIO remain private.
## First administrator
1. Open the Compose service's environment settings and copy the generated `ADMIN_EMAILS` value.
2. Open the generated BlogFactory domain and register with that exact email address.
3. Return to the Compose environment settings, change `BLOGFACTORY_ALLOW_SIGNUP` to `false`, and redeploy.
4. Add OpenRouter, CMS, or Google Search Console credentials from BlogFactory only when you need those optional integrations.
BlogFactory sends reviewed content to connected CMS providers as drafts. The template does not grant live-publish or delete authority.
"description":"Federated social networking toolkit for communities: customizable digital spaces with ActivityPub federation, flexible boundaries and moderation tools.",
2. Log in with the **API bearer token**: it is auto-generated by the template and stored in the `API_BEARER_TOKEN` environment variable (Dokploy → your service → Environment). The same token authenticates REST API requests (`Authorization: Bearer <token>`).
3. In **Settings**, set your Let's Encrypt email and add credentials for your DNS provider (Cloudflare, Route53, etc.) to issue certificates through DNS-01 challenges.
## Notes
-`CLOUDFLARE_TOKEN` can optionally be set as an environment variable instead of configuring it in the UI.
- Certificates, application data and backups are persisted in the `certmate_certificates`, `certmate_data` and `certmate_backups` volumes.
- API documentation is available at `/docs/` (Swagger) and `/redoc/` on your domain.
"description":"CertMate is an SSL certificate management system with a web UI and REST API. It automates issuing and renewing Let's Encrypt certificates via DNS-01 challenges across 20+ DNS providers, with unified backups and multi-account support.",
"description":"A fully-featured real-time chat application for teams and communities. This template deploys the single Chatto binary with embedded NATS. Note: email/password registration requires SMTP to be configured after deployment; voice/video calls are not included in the single-binary setup.",
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.