Compare commits

...
3 Commits
Author SHA1 Message Date
+28 b373a6b7c5 New Version (#1295)
* chore: remove compose version + add checks (#1268)

* fix: reject deprecated Docker Compose version field

* chore: remove deprecated version field in docker compose

* chore(orbit): drop the obsolete compose version key

orbit was merged after this PR was opened and still had version: '3.8' at
the end of the file, which the new validator check rejects.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Mauricio Siu <siumauricio@icloud.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Update Calcom Template to add all env vars (#1278)

* feat: add all env variables for calcom image and health checking for postgres + restart config for containers

* feat: add postgres var generators

* cachkey: bump version to 0.2.0 (#1277)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat: add PrivatePaste template (#1276)

* feat: add PrivatePaste template

Self-hosted clipboard sync with an encrypted, searchable history; apps for Windows, macOS, Linux and Android. Image ghcr.io/dynamicsninja/privatepaste:0.2.0 (linux/amd64, linux/arm64).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S7qnD4vNtkFtpTzPq1fw5R

* chore(privatepaste): use image 0.3.1

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(phpmyadmin): migrate to the official phpMyAdmin Docker image (#1275)

* fix(phpmyadmin): migrate to the official phpMyAdmin Docker image

See: https://github.com/phpmyadmin/docker/issues/363
Signed-off-by: William Desportes <williamdes@wdes.fr>

* fix(phpmyadmin): update phpMyAdmin to 5.2.3

Pin the official image to the current release instead of a floating reference.

See: https://github.com/phpmyadmin/docker/issues/363
Signed-off-by: William Desportes <williamdes@wdes.fr>

* fix(phpmyadmin): match meta.json version to the 5.2.3 image

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Signed-off-by: William Desportes <williamdes@wdes.fr>
Co-authored-by: Mauricio Siu <siumauricio@icloud.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Legejo: update to 1.33.0 (#1273)

Co-authored-by: Markus Rådberg <3110202+jularboolean@users.noreply.github.com>

* Add Uptime kotlin template (#1272)

* feat: add Uptime Kotlin Docker Compose setup

* fix: remove default timezone setting from Docker Compose

* fix: update Docker Compose configuration for uptime-kotlin service

* feat: add mcpspan template (#1270)

* feat: add mcpspan template

* chore(mcpspan): update to 0.13.0, with the dashboard's address for MCP clients signing in

* fix(junctio): update image to 0.2.6 (#1269)

* fix(junctio): update image to 0.2.5

* fix(junctio): update image to 0.2.6

* feat: add PostgreSQL with 80+ extensions (postgres-extensor) template (#1267)

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* fix(yuvomi): bump to 2.80.0 and generate DB_ENCRYPTION_KEY (#1266)

Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com>
Co-authored-by: Ulas Kalayci <ulas.kalayci@icloud.com>

* feat: add OpenTodo template (#1265)

* feat: add OpenTodo template

* OpenTodo: update to 0.12.0

* OpenTodo 0.13.0

* fix(ponos): update template to 0.2.0 and move to the hermez-agency image (#1263)

* Add Reelsaw template (#1262)

Signed-off-by: dillonstreator <dillonstreator@gmail.com>

* feat(blueprints): add maintenant template (#1261)

* fix(docuseal): correct PostgreSQL 18 volume mount (#1290)

* feat(blueprints): add Zeqqat template (#1288)

* feat(umami): bump to 3.4.1 (#1287)

* feat(umami): bump to 3.4.1

* feat(umami): bump to 3.4.1

* feat(privatepaste): bump to 0.5.0 (#1286)

* feat(privatepaste): bump to 0.5.0

* feat(privatepaste): bump to 0.5.0

* feat(privatepaste): bump to 0.5.0

* fix(libredb-studio): update the blueprint to 1.2.0 (#1283)

* chore(libredb-studio): bump image to 1.2.0

* fix(libredb-studio): set version to 1.2.0 and update the engine counts

meta.json still pinned 1.0.0 while docker-compose.yml pulls 1.2.0, which the
blueprint rules require to match. The description also carried the 0.18.2
driver and engine counts; 1.2.0 ships 42 drivers reaching 69 named engines.

* Update OpenTodo to 0.19.0 (#1281)

* feat(blueprints): add itsaplan template (#1282)

* Add Calnode template (#1280)

* feat: add calnode template

* feat: add commas to fix template

* feat: replace logo

* fix: add url prefix

* fix: Remove default value for litestream url when unconfigured

* fix(calnode): pin the exact 0.12.0 tag instead of the moving 0.12 tag

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Mauricio Siu <siumauricio@icloud.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat: add Customermates template (#1279)

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>

* feat: update openwa template to 0.25.0 (#1260)

* feat(openwa): bump template to 0.25.0

- Update OpenWA image to 0.25.0
- Add 75s stop grace period for the longer bounded teardown

* feat(openwa): enable the MCP server by default

- Add mcp_enabled and mcp_readonly template variables
- Pass MCP_ENABLED and MCP_READONLY to the container
- Keep the read-only tool tier as the safe default

* feat(openwa): enable Swagger UI by default

Add an enable_swagger variable, wired to ENABLE_SWAGGER, so /api/docs is
served despite the upstream production default.

* chore: update the dossier version and disable germany's BA (#1258)

* chore: update the dossier version and disable germany's BA

* fix(dossier): match meta.json version to the v1.9.0 image

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Mauricio Siu <siumauricio@icloud.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Add Container Monitoring template (cAdvisor, Prometheus, Grafana) (#1257)

* Add container-monitoring template

* Default container detail dashboard to a single container

* Update SolidPing to 0.41.0 (#1256)

* feat: update appwrite template to 2.7.0 (#1259)

* feat(appwrite): bump template to 2.6.1

- Update appwrite/appwrite images to 2.6.1 and console to 1.2.97
- Add ExifTool service for image metadata stripping
- Add S3 path-style, VCS Entire, and maintenance queue variables
- Add maintenance scheduler interval and worker pool sizing
- Harden healthcheck with readiness marker and raise PostgreSQL shm
- Bump orchestrator to 2.2.4
- Remove duplicate _APP_CONSOLE_HOSTNAMES entry

* feat(appwrite): bump template to 2.6.2

* fix(appwrite): keep wildcard routers below console

Dokploy generates the console/API routers without a priority, so Traefik
falls back to rule length. A Sites/Functions HostRegexp rooted at the apex
also matches the console host and is longer, so it 404s the console.

The generated router names include a per-domain serial, so the template
cannot set their priority. Pin the template-owned wildcard routers to the
lowest priority instead, for both web and websecure.

* feat(appwrite): bump template to 2.7.0

- appwrite/appwrite 2.6.2 -> 2.7.0 across all services
- Console 1.2.108 -> 1.2.138 (and fix VITE_APPWRITE_VERSION default)
- browser 0.3.8 -> 0.3.10
- orchestrator 2.2.4 -> 4.0.0
- add server key rotation vars (V2, CURRENT, OLDEST)
- add realtime limits, DNS_EXTERNAL, ALLOWED_INTERNAL_ADDRESSES, DB_MAX_CONNECTIONS
- add alert config, APNs push and DOMAIN_FUNCTIONS_FALLBACK
- add the optional appwrite-hansi code review service
- raise worker max coroutines from 79 to 83

* fix(appwrite): ship the reviews worker disabled by default

The self-hosted console profile keeps features.reviews off, so the Reviews
screen only shows up behind the internal debug flag. Running appwrite-hansi
without it means a container that cannot be configured from the UI, so keep
the service and its _APP_REVIEWS_* variables commented out and document the
three steps to opt in.

* Update Uptime Kuma image to 'next' version (#1264)

* Update Uptime Kuma image to 'next' version

Uptime Kuma "latest" status is stuck at older version and the official resource recommends to use the "next" tag to get the latest version.

* fix(uptime-kuma): pin 2.5.8 instead of the moving next tag

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Mauricio Siu <siumauricio@icloud.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat: add Puppetflow with Postgres template (#1271)

* feat: add Puppetflow with Postgres template

* chore: bump Puppetflow templates to v2026.10.25

* feat: add second Puppetflow queue worker

* fix: send Puppetflow logs to stderr

* fix: harden Puppetflow Dokploy deployments

* fix: keep Dokploy default certificate handling

* fix: use Dokploy default HTTP domains

* chore: bump Puppetflow templates to v2026.10.26

* fix: configure Puppetflow locale and connection timeout

* chore: bump Puppetflow templates to v2026.10.27

* chore: bump Puppetflow templates to v2026.10.28

* chore: bump Puppetflow templates to v2026.10.29

* chore: bump Puppetflow templates to 2026.10.30

* chore: bump Puppetflow templates to 2026.10.32

* fix: align Pinokio production browser config

* chore: bump Puppetflow templates to v2026.11.1

* chore: bump Puppetflow templates to v2026.11.3

* chore: bump Puppetflow templates to v2026.11.4

* chore: bump Puppetflow templates to v2026.11.5

* chore: bump Puppetflow templates to v2026.11.6

* chore: bump Puppetflow templates to v2026.11.7

* fix(puppetflow): use service names instead of container_name

Templates must not set container_name; Compose service names already
resolve inside the project, so REDIS_HOST, PINOKIO_HOST, DB_HOST and the
internal URLs now point at them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(puppetflow): pinokio has no v2026.11.7 image, use v2026.11.1

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Mauricio Siu <siumauricio@icloud.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Update NaviMusic to version 4.3.0 (#1285)

* fix(navi-music): update to version 4.3.0

* feat(navi-music): update entrypoint for improved startup behavior

* fix(navi-music): pin yt-cipher by digest (it only publishes a moving master tag)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Mauricio Siu <siumauricio@icloud.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* chore: update Windshift to v0.9.3 (#1254)

* chore: update Windshift to v0.9.1

* chore: update Windshift to v0.9.3

Point the blueprint at the current release instead of v0.9.1.

* fix: updates actions runner to 2.338.2 and maintained Node24 (#1255)

* fix: updates actions runner and selects maintained node runtime

* fix: updates actions runner to 2.338.2

* Add ShopNex (#1284)

* Add ShopNex template

* fix(shopnex): pin v0.13.1 instead of latest

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Mauricio Siu <siumauricio@icloud.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* Bump Dagu to 2.25.4 (#1293)

The template pins 2.10.7, which is fifteen minor releases behind the
current Dagu release. The compose file, basic auth variables, volume,
and port are unchanged and still valid on 2.25.4.

* Add kortix deployment to the list of templates (#1294)

* feat: upgrade Seafile template to 14.0 (#1251)

* feat: upgrade Seafile template to 14.0

* fix(seafile): pin seafile-mc 14.0.9 and sdoc-server 2.0.11 instead of moving -latest tags

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Mauricio Siu <siumauricio@icloud.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

* feat(blueprints): add CakePHP 5 template (#1291)

* feat(blueprints): add CakePHP 5 template (themusicdev/php-apache runtime + MariaDB)

* ci: re-trigger build preview (first run hit a transient npm registry failure)

* fix(blueprints/cakephp): env via [config.env] names; pin image to released 1.0.0 (review feedback)

---------

Signed-off-by: William Desportes <williamdes@wdes.fr>
Signed-off-by: dillonstreator <dillonstreator@gmail.com>
Co-authored-by: Khiet Tam Nguyen <86177399+nktnet1@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Madhav Gupta <114633095+M4dhav@users.noreply.github.com>
Co-authored-by: Félicio de SOUZA <feliciodsa.dev@gmail.com>
Co-authored-by: Ivan Ficko <ivan.ficko@outlook.com>
Co-authored-by: William Desportes <williamdes@wdes.fr>
Co-authored-by: Jularbool <markus@radberg.org>
Co-authored-by: Markus Rådberg <3110202+jularboolean@users.noreply.github.com>
Co-authored-by: Théo Meunier <62860058+TheoMeunier@users.noreply.github.com>
Co-authored-by: Kacper <kcprzaton@gmail.com>
Co-authored-by: Web Artisan <ad4ptec@gmail.com>
Co-authored-by: Jose Garcia <47431411+ruxwez@users.noreply.github.com>
Co-authored-by: Ulaş Kalaycı <108589275+ulsklyc@users.noreply.github.com>
Co-authored-by: Ulas Kalayci <ulas.kalayci@icloud.com>
Co-authored-by: Raffaele Pizzari <raffaele.pizzari@gmail.com>
Co-authored-by: Cardona <18017015+SalvadorCardona@users.noreply.github.com>
Co-authored-by: dillonstreator <dillonstreator@gmail.com>
Co-authored-by: Benjamin Touchard <benjamin@kolapsis.com>
Co-authored-by: JRK <jessym.reziga@gmail.com>
Co-authored-by: Perminus Gaita <35493600+Perminus-Gaita@users.noreply.github.com>
Co-authored-by: Lezetho <126505858+lezetho@users.noreply.github.com>
Co-authored-by: Yusuf Gündoğdu <yusufgundogdu555@gmail.com>
Co-authored-by: Waleed <waleedi825@gmail.com>
Co-authored-by: Benjamin Wagner <72468969+benjiwagner@users.noreply.github.com>
Co-authored-by: Carlos Dorneles <duducp2013@gmail.com>
Co-authored-by: Alien <hi@aien.me>
Co-authored-by: Ghazi Ben Dahmane <ghazi.ben.dahmane@gmail.com>
Co-authored-by: Florent Clairambault <florent.clairambault@gmail.com>
Co-authored-by: Thet Hmuu <thethmuueinsoe@gmail.com>
Co-authored-by: Andre Carbajal Vargas <carbajalvargasandre@gmail.com>
Co-authored-by: Stefan Ernst <ernst.stefan@icloud.com>
Co-authored-by: Noah <70114451+zFl4wless@users.noreply.github.com>
Co-authored-by: ArseniyDev <41956571+ArseniyX@users.noreply.github.com>
Co-authored-by: Yota Hamada <yohamta@gmail.com>
Co-authored-by: Kortix SEO <347261315+Kortix-seo@users.noreply.github.com>
Co-authored-by: Angel S. Moreno <angelxmoreno@gmail.com>
2026-11-05 10:20:57 +01:00
Mauricio SiuandGitHub cfce6b69d1 Merge pull request #1253 from Dokploy/canary
New version
2026-10-20 23:26:53 -06:00
Mauricio SiuandGitHub 62199f7d1e Merge pull request #1205 from Dokploy/canary
New Version
2026-10-07 21:12:57 -06:00
123 changed files with 3668 additions and 400 deletions
+130 -13
View File
@@ -6,22 +6,36 @@ x-logging: &x-logging
max-size: "10m"
services:
appwrite:
image: appwrite/appwrite:2.5.0
image: appwrite/appwrite:2.7.0
<<: *x-logging
restart: unless-stopped
labels:
- traefik.enable=true
# Dokploy generates the specific routers (console, API, realtime) from the
# domains declared in template.toml, naming them
# "<appName>-<uniqueConfigKey>-<entrypoint>" and never setting a priority.
# Their priority is therefore Traefik's default: the length of the rule.
# The wildcard routers below are owned by this template, and a HostRegexp
# rule is longer than a Host rule, so without an explicit priority they can
# outrank the console/API router whenever the wildcard also matches the
# host (for example a Sites/Functions wildcard rooted at the same apex as
# the console). Pin every wildcard router to the lowest useful priority so
# the specific router always wins; 1 is below any rule-derived priority.
- 'traefik.http.routers.appwrite-sites-wildcard.rule=HostRegexp(`^.+\.${_APP_DOMAIN_SITES}$$`)'
- traefik.http.routers.appwrite-sites-wildcard.priority=1
- traefik.http.routers.appwrite-sites-wildcard.entrypoints=web
- traefik.http.routers.appwrite-sites-wildcard.service=appwrite-wildcard
- 'traefik.http.routers.appwrite-sites-wildcard-secure.rule=HostRegexp(`^.+\.${_APP_DOMAIN_SITES}$$`)'
- traefik.http.routers.appwrite-sites-wildcard-secure.priority=1
- traefik.http.routers.appwrite-sites-wildcard-secure.entrypoints=websecure
- traefik.http.routers.appwrite-sites-wildcard-secure.tls=true
- traefik.http.routers.appwrite-sites-wildcard-secure.service=appwrite-wildcard
- 'traefik.http.routers.appwrite-functions-wildcard.rule=HostRegexp(`^.+\.${_APP_DOMAIN_FUNCTIONS}$$`)'
- traefik.http.routers.appwrite-functions-wildcard.priority=1
- traefik.http.routers.appwrite-functions-wildcard.entrypoints=web
- traefik.http.routers.appwrite-functions-wildcard.service=appwrite-wildcard
- 'traefik.http.routers.appwrite-functions-wildcard-secure.rule=HostRegexp(`^.+\.${_APP_DOMAIN_FUNCTIONS}$$`)'
- traefik.http.routers.appwrite-functions-wildcard-secure.priority=1
- traefik.http.routers.appwrite-functions-wildcard-secure.entrypoints=websecure
- traefik.http.routers.appwrite-functions-wildcard-secure.tls=true
- traefik.http.routers.appwrite-functions-wildcard-secure.service=appwrite-wildcard
@@ -29,7 +43,7 @@ services:
healthcheck:
test:
- CMD-SHELL
- 'curl -fsS -o /dev/null -H "Host: $${_APP_DOMAIN:-localhost}" http://localhost/v1/health/version'
- 'test -f /tmp/.appwrite-ready && curl -fsS -o /dev/null -H "Host: $${_APP_DOMAIN:-localhost}" http://localhost/v1/health/version'
interval: 5s
timeout: 5s
retries: 12
@@ -52,8 +66,13 @@ services:
condition: service_started
appwrite-autogravity:
condition: service_started
appwrite-exiftool:
condition: service_started
environment:
- _APP_DNS_EXTERNAL
- _APP_ALLOWED_INTERNAL_ADDRESSES
- _APP_ENV
- _APP_MEMORY_LIMIT
- _APP_EDITION
- _APP_WORKER_PER_CORE
- _APP_LOCALE
@@ -86,7 +105,12 @@ services:
- _APP_OPTIONS_ROUTER_FORCE_HTTPS
- _APP_ROUTER_AUTO_CERTIFICATES
- _APP_OPENSSL_KEY_V1
- _APP_OPENSSL_KEY_V2
- _APP_OPENSSL_KEY_CURRENT
- _APP_OPENSSL_KEY_OLDEST
- _APP_NOTIFICATIONS_TRACKING_SECRET
- _APP_NOTIFICATIONS_PUSH_APNS
- _APP_NOTIFICATIONS_PUSH_APNS_KEY
- _APP_DOMAIN
- _APP_CONSOLE_DOMAIN
- _APP_CONSOLE_URL
@@ -97,6 +121,7 @@ services:
- _APP_DOMAIN_TARGET_CAA
- _APP_DNS
- _APP_DOMAIN_FUNCTIONS
- _APP_DOMAIN_FUNCTIONS_FALLBACK
- _APP_DOMAIN_SITES
- _APP_CUSTOM_DOMAIN_DENY_LIST
- _APP_TRUSTED_HEADERS
@@ -134,6 +159,7 @@ services:
- _APP_CONNECTIONS_DATABASE_VECTORSDB
- _APP_EMBEDDING
- _APP_USAGE_STATS
- _APP_ALERTS_USAGE_LAG
- _APP_USAGE_PASS
- _APP_CONNECTIONS_DB_USAGE
- _APP_POOL_SIZE_USAGE
@@ -153,6 +179,7 @@ services:
- _APP_STORAGE_LIMIT
- _APP_STORAGE_PREVIEW_LIMIT
- _APP_AUTOGRAVITY_HOST
- _APP_EXIFTOOL_HOST
- _APP_STORAGE_ANTIVIRUS
- _APP_STORAGE_ANTIVIRUS_HOST
- _APP_STORAGE_ANTIVIRUS_PORT
@@ -162,6 +189,7 @@ services:
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
- _APP_STORAGE_S3_ENDPOINT
- _APP_STORAGE_S3_PATH_STYLE
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
@@ -194,6 +222,7 @@ services:
- _APP_JOBS_HOST
- _APP_JOBS_SECRET
- _APP_JOBS_ENDPOINT
# - _APP_REVIEWS_SECRET # uncomment with the optional reviews setup
- _APP_GEO_SECRET
- _APP_GEO_ENDPOINT
- _APP_LOGGING_CONFIG
@@ -205,6 +234,7 @@ services:
- _APP_MAINTENANCE_RETENTION_AUDIT
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
- _APP_MAINTENANCE_RETENTION_SCHEDULES
- _APP_MAINTENANCE_RETENTION_ALERTS
- _APP_GRAPHQL_INTROSPECTION
- _APP_GRAPHQL_MAX_BATCH_SIZE
- _APP_GRAPHQL_MAX_COMPLEXITY
@@ -229,6 +259,10 @@ services:
- _APP_VCS_BITBUCKET_WEBHOOK_SECRET
- _APP_VCS_ORIGIN_CLIENT_ID
- _APP_VCS_ORIGIN_PRIVATE_KEY
- _APP_VCS_ENTIRE_PLUGIN
- _APP_VCS_ENTIRE_PRIVATE_KEY
- _APP_VCS_ENTIRE_ISSUER
- _APP_VCS_ENTIRE_ENDPOINT
- _APP_VCS_WEBHOOK_URL
- _APP_MIGRATION_HOST
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
@@ -237,16 +271,17 @@ services:
- _APP_PWNED_PASSWORDS_DSN
appwrite-console:
image: appwrite/new:1.2.74-self-hosted
image: appwrite/new:1.2.138-self-hosted
<<: *x-logging
restart: unless-stopped
environment:
- VITE_CONSOLE_PROFILE=self-hosted
- VITE_APPWRITE_VERSION=${_APP_VERSION:-2.7.0}
- APPWRITE_ENDPOINT_SAME_ORIGIN=true
- VITE_GROWTH_ENDPOINT=https://growth.appwrite.io/v1
appwrite-realtime:
image: appwrite/appwrite:2.5.0
image: appwrite/appwrite:2.7.0
entrypoint: realtime
<<: *x-logging
restart: unless-stopped
@@ -257,12 +292,19 @@ services:
condition: service_healthy
environment:
- _APP_ENV
- _APP_MEMORY_LIMIT
- _APP_WORKER_PER_CORE
- _APP_OPTIONS_ABUSE
- _APP_OPTIONS_ROUTER_PROTECTION
- _APP_CONSOLE_HOSTNAMES
- _APP_REALTIME_TAIL_RATE
- _APP_LIMIT_REALTIME_SUBSCRIPTIONS
- _APP_LIMIT_REALTIME_CHANNELS
- _APP_LIMIT_REALTIME_QUERIES
- _APP_OPENSSL_KEY_V1
- _APP_OPENSSL_KEY_V2
- _APP_OPENSSL_KEY_CURRENT
- _APP_OPENSSL_KEY_OLDEST
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
@@ -298,7 +340,7 @@ services:
- _APP_LOGGING_FORMAT
appwrite-mqtt:
image: appwrite/appwrite:2.5.0
image: appwrite/appwrite:2.7.0
entrypoint: mqtt
<<: *x-logging
restart: unless-stopped
@@ -319,11 +361,15 @@ services:
start_period: 20s
environment:
- _APP_ENV
- _APP_MEMORY_LIMIT
- _APP_WORKER_PER_CORE
- _APP_OPTIONS_ABUSE
- _APP_OPTIONS_ROUTER_PROTECTION
- _APP_REALTIME_TAIL_RATE
- _APP_OPENSSL_KEY_V1
- _APP_OPENSSL_KEY_V2
- _APP_OPENSSL_KEY_CURRENT
- _APP_OPENSSL_KEY_OLDEST
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
@@ -348,7 +394,7 @@ services:
- _APP_MQTT_MAX_PACKET_SIZE
appwrite-worker:
image: appwrite/appwrite:2.5.0
image: appwrite/appwrite:2.7.0
entrypoint: worker
<<: *x-logging
restart: unless-stopped
@@ -369,13 +415,21 @@ services:
extra_hosts:
- host.docker.internal:host-gateway
environment:
- _APP_DNS_EXTERNAL
- _APP_ALLOWED_INTERNAL_ADDRESSES
- _APP_ENV
- _APP_MEMORY_LIMIT
- _APP_WORKERS_NUM=1
# Pool sizing only (sum of per-queue caps). Each queue keeps its own maxCoroutines in PHP; databases stays at 1.
- _APP_WORKER_MAX_COROUTINES=78
# Pool sizing only (sum of per-queue caps). Each queue keeps its own maxCoroutines in PHP; databases and maintenance stay at 1.
- _APP_WORKER_MAX_COROUTINES=83
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_OPENSSL_KEY_V2
- _APP_OPENSSL_KEY_CURRENT
- _APP_OPENSSL_KEY_OLDEST
- _APP_NOTIFICATIONS_TRACKING_SECRET
- _APP_NOTIFICATIONS_PUSH_APNS
- _APP_NOTIFICATIONS_PUSH_APNS_KEY
- _APP_EMAIL_SECURITY
- _APP_EMAIL_CERTIFICATES
- _APP_REDIS_HOST
@@ -408,6 +462,7 @@ services:
- _APP_CONNECTIONS_DATABASE_VECTORSDB
- _APP_EMBEDDING
- _APP_USAGE_STATS
- _APP_ALERTS_USAGE_LAG
- _APP_USAGE_PASS
- _APP_CONNECTIONS_DB_USAGE
- _APP_POOL_SIZE_USAGE
@@ -416,6 +471,7 @@ services:
- _APP_MAINTENANCE_RETENTION_USAGE_TTL
- _APP_STATS_USAGE_QUEUE_NAME
- _APP_STATS_RESOURCES_QUEUE_NAME
- _APP_MAINTENANCE_QUEUE_NAME
- _APP_STATS_RESOURCES_INTERVAL
- _APP_LOGGING_CONFIG
- _APP_LOGGING_FORMAT
@@ -440,6 +496,7 @@ services:
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
- _APP_STORAGE_S3_ENDPOINT
- _APP_STORAGE_S3_PATH_STYLE
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
@@ -491,6 +548,10 @@ services:
- _APP_VCS_BITBUCKET_WEBHOOK_SECRET
- _APP_VCS_ORIGIN_CLIENT_ID
- _APP_VCS_ORIGIN_PRIVATE_KEY
- _APP_VCS_ENTIRE_PLUGIN
- _APP_VCS_ENTIRE_PRIVATE_KEY
- _APP_VCS_ENTIRE_ISSUER
- _APP_VCS_ENTIRE_ENDPOINT
- _APP_VCS_WEBHOOK_URL
- _APP_SYSTEM_EMAIL_NAME
- _APP_SYSTEM_EMAIL_ADDRESS
@@ -509,7 +570,7 @@ services:
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
appwrite-task-scheduler:
image: appwrite/appwrite:2.5.0
image: appwrite/appwrite:2.7.0
entrypoint: schedule
<<: *x-logging
restart: unless-stopped
@@ -520,11 +581,15 @@ services:
condition: service_healthy
environment:
- _APP_ENV
- _APP_MEMORY_LIMIT
# Combined mode runs functions/executions/messages timers + enqueue coroutines
# against shared console/cache pools; floor must cover concurrent ticks.
- _APP_WORKER_MAX_COROUTINES=8
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_OPENSSL_KEY_V2
- _APP_OPENSSL_KEY_CURRENT
- _APP_OPENSSL_KEY_OLDEST
- _APP_OPTIONS_FORCE_HTTPS
- _APP_DOMAIN
- _APP_CONSOLE_DOMAIN
@@ -552,12 +617,16 @@ services:
- _APP_MAINTENANCE_RETENTION_USAGE_TTL
- _APP_STATS_USAGE_QUEUE_NAME
- _APP_STATS_RESOURCES_QUEUE_NAME
- _APP_MAINTENANCE_QUEUE_NAME
- _APP_STATS_RESOURCES_INTERVAL
- _APP_FUNCTIONS_SCHEDULE_SPREAD
- _APP_MAINTENANCE_INACTIVE_INTERVAL
- _APP_MAINTENANCE_INTERVAL
- _APP_ALERTS_INTERVAL
- _APP_LOGGING_FORMAT
appwrite-task-maintenance:
image: appwrite/appwrite:2.5.0
image: appwrite/appwrite:2.7.0
entrypoint: maintenance
<<: *x-logging
restart: unless-stopped
@@ -568,6 +637,7 @@ services:
condition: service_healthy
environment:
- _APP_ENV
- _APP_MEMORY_LIMIT
- _APP_EDITION
- _APP_WORKER_PER_CORE
- _APP_DOMAIN
@@ -579,6 +649,9 @@ services:
- _APP_DOMAIN_FUNCTIONS
- _APP_ROUTER_AUTO_CERTIFICATES
- _APP_OPENSSL_KEY_V1
- _APP_OPENSSL_KEY_V2
- _APP_OPENSSL_KEY_CURRENT
- _APP_OPENSSL_KEY_OLDEST
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
@@ -598,10 +671,11 @@ services:
- _APP_MAINTENANCE_RETENTION_AUDIT
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
- _APP_MAINTENANCE_RETENTION_SCHEDULES
- _APP_MAINTENANCE_RETENTION_ALERTS
- _APP_LOGGING_FORMAT
appwrite-task-interval:
image: appwrite/appwrite:2.5.0
image: appwrite/appwrite:2.7.0
entrypoint: interval
<<: *x-logging
restart: unless-stopped
@@ -612,6 +686,7 @@ services:
condition: service_healthy
environment:
- _APP_ENV
- _APP_MEMORY_LIMIT
- _APP_WORKER_PER_CORE
- _APP_DOMAIN
- _APP_DOMAIN_TARGET_CNAME
@@ -622,6 +697,9 @@ services:
- _APP_DOMAIN_FUNCTIONS
- _APP_DOMAIN_SITES
- _APP_OPENSSL_KEY_V1
- _APP_OPENSSL_KEY_V2
- _APP_OPENSSL_KEY_CURRENT
- _APP_OPENSSL_KEY_OLDEST
- _APP_REDIS_HOST
- _APP_REDIS_PORT
- _APP_REDIS_USER
@@ -638,7 +716,7 @@ services:
- _APP_LOGGING_FORMAT
appwrite-browser:
image: appwrite/browser:0.3.6
image: appwrite/browser:0.3.10
<<: *x-logging
restart: unless-stopped
environment:
@@ -649,6 +727,35 @@ services:
- 1.1.1.1
- 8.8.8.8
# AI code review for GitHub pull requests (optional, shipped off by default).
# The Reviews screen is hidden in the self-hosted console profile, so this
# worker would run with nowhere to configure it from. To opt in:
# 1. uncomment the _APP_REVIEWS_* variables in template.toml (this enables
# the /v1/reviews API and generates the shared secret);
# 2. uncomment this service;
# 3. set _APP_REVIEWS_AI_GATEWAY_KEY, otherwise no review ever runs.
# appwrite-hansi:
# image: ghcr.io/appwrite/hansi:0.4.2
# <<: *x-logging
# restart: unless-stopped
# # A stopped review is not redelivered for about a day, so a running one gets time to finish.
# stop_grace_period: 16m
# depends_on:
# redis:
# condition: service_healthy
# appwrite:
# condition: service_started
# environment:
# - HANSI_APPWRITE_ENDPOINT=http://appwrite/v1
# - HANSI_APPWRITE_SECRET=${_APP_REVIEWS_SECRET}
# - HANSI_QUEUE_URL=redis://${_APP_REDIS_HOST:-redis}:${_APP_REDIS_PORT:-6379}
# - HANSI_QUEUE_USER=${_APP_REDIS_USER}
# - HANSI_QUEUE_PASSWORD=${_APP_REDIS_PASS}
# - HANSI_SHUTDOWN_TIMEOUT=900
# - HANSI_REVIEW_MODEL=${_APP_REVIEWS_MODEL}
# - HANSI_VERIFY_MODEL=${_APP_REVIEWS_VERIFY_MODEL:-${_APP_REVIEWS_MODEL}}
# - AI_GATEWAY_API_KEY=${_APP_REVIEWS_AI_GATEWAY_KEY}
appwrite-autogravity:
image: ghcr.io/appwrite/autogravity:0.0.11
<<: *x-logging
@@ -656,6 +763,11 @@ services:
environment:
- MODEL_BACKEND=focalnet
appwrite-exiftool:
image: ghcr.io/appwrite/exiftool:0.1.1
<<: *x-logging
restart: unless-stopped
appwrite-geo:
image: appwrite/geo:0.3.2
<<: *x-logging
@@ -738,7 +850,7 @@ services:
start_period: 5s
orchestrator:
image: ghcr.io/open-runtimes/orchestrator/orchestrator:2.2.2
image: ghcr.io/open-runtimes/orchestrator/orchestrator:4.0.0
hostname: orchestrator
<<: *x-logging
restart: unless-stopped
@@ -761,6 +873,8 @@ services:
image: appwrite/postgres:0.1.0
<<: *x-logging
restart: unless-stopped
init: true
shm_size: 1g
volumes:
- appwrite-postgresql:/var/lib/postgresql:rw
environment:
@@ -769,6 +883,9 @@ services:
- POSTGRES_PASSWORD=${_APP_DB_PASS}
command:
- postgres
# Every HTTP worker and worker coroutine pools its own connections; the default of 100 runs out under load.
- -c
- max_connections=${_APP_DB_MAX_CONNECTIONS:-500}
healthcheck:
test:
- CMD-SHELL
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "appwrite",
"name": "Appwrite",
"version": "2.5.0",
"version": "2.7.0",
"description": "Appwrite is an end-to-end platform for building Web, Mobile, Native, or Backend apps, packaged as a set of Docker microservices. It includes both a backend server and a fully integrated hosting solution for deploying static and server-side rendered frontends. Appwrite abstracts the complexity and repetitiveness required to build modern apps from scratch and allows you to build secure, full-stack applications faster.\nUsing Appwrite, you can easily integrate your app with user authentication and multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, messaging, and more services.",
"links": {
"github": "https://github.com/appwrite/appwrite",
+34 -1
View File
@@ -12,6 +12,9 @@ usage_pw = "${password:32}"
executor_secret = "${password:32}"
jobs_secret = "${password:32}"
geo_secret = "${password:32}"
# Optional AI code review of GitHub pull requests. Uncomment together with the
# _APP_REVIEWS_* variables and the appwrite-hansi service in docker-compose.yml.
# reviews_secret = "${password:32}"
console_domain = "console.${main_domain}"
[config]
@@ -20,6 +23,8 @@ console_domain = "console.${main_domain}"
isolated = false
env = [
"_APP_ENV=production",
"_APP_VERSION=2.7.0",
"_APP_MEMORY_LIMIT=512M",
"_APP_EDITION=self-hosted",
"_APP_LOCALE=en",
"_APP_WORKER_PER_CORE=6",
@@ -31,7 +36,12 @@ env = [
"_APP_ROUTER_AUTO_CERTIFICATES=enabled",
"_APP_LOCKING_ENABLED=enabled",
"_APP_OPENSSL_KEY_V1=${openssl_key}",
"_APP_OPENSSL_KEY_V2=",
"_APP_OPENSSL_KEY_CURRENT=1",
"_APP_OPENSSL_KEY_OLDEST=1",
"_APP_NOTIFICATIONS_TRACKING_SECRET=${notifications_tracking_secret}",
"_APP_NOTIFICATIONS_PUSH_APNS=",
"_APP_NOTIFICATIONS_PUSH_APNS_KEY=",
"_APP_DOMAIN=${main_domain}",
"_APP_CONSOLE_DOMAIN=${console_domain}",
"_APP_CONSOLE_URL=https://${console_domain}",
@@ -39,17 +49,19 @@ env = [
"_APP_CONSOLE_TRUSTED_PROJECTS=",
"_APP_CUSTOM_DOMAIN_DENY_LIST=example.com,test.com,app.example.com",
"_APP_DOMAIN_FUNCTIONS=${functions_domain}",
"_APP_DOMAIN_FUNCTIONS_FALLBACK=",
"_APP_DOMAIN_SITES=${sites_domain}",
"_APP_DOMAIN_TARGET_CNAME=localhost",
"_APP_DOMAIN_TARGET_AAAA=::1",
"_APP_DOMAIN_TARGET_A=127.0.0.1",
"_APP_DOMAIN_TARGET_CAA=",
"_APP_DNS=8.8.8.8",
"_APP_DNS_EXTERNAL=",
"_APP_ALLOWED_INTERNAL_ADDRESSES=",
"_APP_TRUSTED_HEADERS=x-forwarded-for",
"_APP_CONSOLE_WHITELIST_ROOT=enabled",
"_APP_CONSOLE_WHITELIST_EMAILS=",
"_APP_CONSOLE_WHITELIST_IPS=",
"_APP_CONSOLE_HOSTNAMES=",
"_APP_CONSOLE_SCHEMA=appwriteio",
"_APP_CONSOLE_SESSION_ALERTS=disabled",
"_APP_CONSOLE_COUNTRIES_DENYLIST=",
@@ -113,9 +125,15 @@ env = [
"_APP_MAINTENANCE_RETENTION_USAGE_TTL=180",
"_APP_STATS_USAGE_QUEUE_NAME=v1-stats-usage",
"_APP_STATS_RESOURCES_QUEUE_NAME=v1-stats-resources",
"_APP_MAINTENANCE_QUEUE_NAME=v1-maintenance",
"_APP_STATS_RESOURCES_INTERVAL=3600",
"_APP_ALERTS_INTERVAL=60",
"_APP_ALERTS_USAGE_LAG=120",
"_APP_MQTT_REPLAY_DEPTH=5",
"_APP_MQTT_MAX_PACKET_SIZE=64000",
"_APP_LIMIT_REALTIME_SUBSCRIPTIONS=100",
"_APP_LIMIT_REALTIME_CHANNELS=100",
"_APP_LIMIT_REALTIME_QUERIES=100",
"_APP_SMTP_HOST=",
"_APP_SMTP_PORT=",
"_APP_SMTP_SECURE=",
@@ -128,6 +146,7 @@ env = [
"_APP_STORAGE_LIMIT=30000000",
"_APP_STORAGE_PREVIEW_LIMIT=20000000",
"_APP_AUTOGRAVITY_HOST=http://appwrite-autogravity:8080",
"_APP_EXIFTOOL_HOST=http://appwrite-exiftool:8080",
"_APP_STORAGE_ANTIVIRUS=disabled",
"_APP_STORAGE_ANTIVIRUS_HOST=clamav",
"_APP_STORAGE_ANTIVIRUS_PORT=3310",
@@ -137,6 +156,7 @@ env = [
"_APP_STORAGE_S3_REGION=us-east-1",
"_APP_STORAGE_S3_BUCKET=",
"_APP_STORAGE_S3_ENDPOINT=",
"_APP_STORAGE_S3_PATH_STYLE=",
"_APP_STORAGE_DO_SPACES_ACCESS_KEY=",
"_APP_STORAGE_DO_SPACES_SECRET=",
"_APP_STORAGE_DO_SPACES_REGION=us-east-1",
@@ -174,11 +194,18 @@ env = [
"_APP_JOBS_HOST=http://orchestrator:8080",
"_APP_JOBS_SECRET=${jobs_secret}",
"_APP_JOBS_ENDPOINT=http://appwrite",
# Reviews are opt-in: the shared secret turns the /v1/reviews API on, and the
# console hides the screen in the self-hosted profile regardless.
# "_APP_REVIEWS_SECRET=${reviews_secret}",
# "_APP_REVIEWS_MODEL=anthropic/claude-sonnet-4.5",
# "_APP_REVIEWS_VERIFY_MODEL=",
# "_APP_REVIEWS_AI_GATEWAY_KEY=",
"_APP_BROWSER_HOST=http://appwrite-browser:3000/v1",
"_APP_WORKER_SCREENSHOTS_ROUTER=http://appwrite",
"_APP_DOCKER_HUB_USERNAME=",
"_APP_DOCKER_HUB_PASSWORD=",
"_APP_MAINTENANCE_INTERVAL=86400",
"_APP_MAINTENANCE_INACTIVE_INTERVAL=604800",
"_APP_MAINTENANCE_START_TIME=00:00",
"_APP_MAINTENANCE_RETENTION_CACHE=2592000",
"_APP_MAINTENANCE_RETENTION_EXECUTION=1209600",
@@ -186,6 +213,7 @@ env = [
"_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=15778800",
"_APP_MAINTENANCE_RETENTION_ABUSE=86400",
"_APP_MAINTENANCE_RETENTION_SCHEDULES=86400",
"_APP_MAINTENANCE_RETENTION_ALERTS=7776000",
"_APP_INTERVAL_DOMAIN_VERIFICATION=120",
"_APP_INTERVAL_CLEANUP_STALE_EXECUTIONS=300",
"_APP_GRAPHQL_INTROSPECTION=enabled",
@@ -213,12 +241,17 @@ env = [
"_APP_VCS_BITBUCKET_WEBHOOK_SECRET=",
"_APP_VCS_ORIGIN_CLIENT_ID=",
"_APP_VCS_ORIGIN_PRIVATE_KEY=",
"_APP_VCS_ENTIRE_PLUGIN=",
"_APP_VCS_ENTIRE_PRIVATE_KEY=",
"_APP_VCS_ENTIRE_ISSUER=",
"_APP_VCS_ENTIRE_ENDPOINT=",
"_APP_VCS_WEBHOOK_URL=",
"_APP_MIGRATION_HOST=appwrite",
"_APP_MIGRATIONS_FIREBASE_CLIENT_ID=",
"_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET=",
"_APP_DB_ROOT_PASS=${db_root_pw}",
"_APP_DB_USER_PASS=${db_user_pw}",
"_APP_DB_MAX_CONNECTIONS=500",
]
[[config.mounts]]
@@ -1,6 +1,4 @@
# dokploy: allow-host-ports — WoW clients connect directly over raw TCP (3724 authentication, 8085 world); Traefik cannot route the game protocol.
version: "3.8"
services:
azerothcore-database:
image: mysql:8.4.11
+2 -2
View File
@@ -1,7 +1,7 @@
services:
# Web app (public): named after the template, as Dokploy requires.
cachkey:
image: ghcr.io/joyboy-dy/cachkey-web:0.1.0
image: ghcr.io/joyboy-dy/cachkey-web:0.2.0
restart: unless-stopped
expose:
- 3000
@@ -16,7 +16,7 @@ services:
# Applies pending database migrations at startup, then serves /api.
cachkey-api:
image: ghcr.io/joyboy-dy/cachkey-api:0.1.0
image: ghcr.io/joyboy-dy/cachkey-api:0.2.0
restart: unless-stopped
expose:
- 3001
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "cachkey",
"name": "Cachkey",
"version": "0.1.0",
"version": "0.2.0",
"description": "Cachkey is an open-source, self-hosted manager for secrets and environment variables: encrypted values, per-environment access for your team, a CLI and a read-only API for servers and CI.",
"logo": "cachkey.svg",
"links": {
+111
View File
@@ -0,0 +1,111 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="230px" height="24.673px" viewBox="0 0 230 24.673" enable-background="new 0 0 230 24.673" xml:space="preserve">
<g>
<g>
<path fill="#FFFFFF" d="M133.629,15.422c1.175,0,1.926-0.515,1.926-1.304c0-0.619-0.489-0.957-1.343-0.957h-1.849l-0.601,2.261
H133.629z M133.161,18.398c1.183,0,1.924-0.498,1.924-1.313c0-0.667-0.629-1.005-1.511-1.005h-1.99l-0.619,2.318H133.161z
M131.819,12.495h2.458c1.285,0,2.037,0.601,2.037,1.53c0,0.938-0.714,1.539-1.643,1.726c0.647,0.197,1.163,0.619,1.163,1.361
c0,1.135-1.031,1.952-2.759,1.952h-3.021L131.819,12.495z"/>
<path fill="#FFFFFF" d="M137.138,17.666c0-0.226,0.058-0.498,0.123-0.751l0.713-2.702h0.723l-0.741,2.749
c-0.038,0.16-0.064,0.386-0.064,0.545c0,0.637,0.411,1.013,1.078,1.013c0.751,0,1.511-0.647,1.754-1.577l0.732-2.73h0.723
l-1.295,4.851h-0.724l0.217-0.788c-0.441,0.497-0.957,0.892-1.698,0.892C137.749,19.167,137.138,18.585,137.138,17.666"/>
</g>
<path fill="#FFFFFF" d="M144.419,12.355h0.826l-0.217,0.797h-0.824L144.419,12.355z M143.97,14.212h0.722l-1.305,4.852h-0.722
L143.97,14.212z"/>
<polygon fill="#FFFFFF" points="147.075,12.214 147.797,12.214 145.958,19.064 145.235,19.064 "/>
<g>
<path fill="#FFFFFF" d="M152.339,16.249c0-0.845-0.61-1.501-1.502-1.501c-1.154,0-2.026,1.07-2.026,2.309
c0,0.901,0.562,1.482,1.37,1.482C151.26,18.539,152.339,17.441,152.339,16.249 M148.051,17.122c0-1.718,1.304-3.012,2.722-3.012
c0.994,0,1.558,0.562,1.819,1.201l0.826-3.097h0.723l-1.83,6.85h-0.723l0.216-0.826c-0.46,0.525-1.051,0.938-1.83,0.938
C148.876,19.176,148.051,18.351,148.051,17.122"/>
<path fill="#FFFFFF" d="M158.333,14.851h-0.667l0.171-0.638h0.666l0.159-0.582c0.253-0.976,0.825-1.436,1.661-1.436
c0.375,0,0.712,0.075,0.966,0.207l-0.17,0.619c-0.28-0.132-0.516-0.197-0.796-0.197c-0.46,0-0.808,0.282-0.977,0.92l-0.123,0.469
h1.588l-0.18,0.638h-1.577l-1.134,4.213h-0.724L158.333,14.851z"/>
<path fill="#FFFFFF" d="M164.057,17.159l0.093-0.337c-0.421-0.122-0.976-0.216-1.576-0.216c-0.863,0-1.454,0.469-1.454,1.135
c0,0.517,0.403,0.863,1.032,0.863C162.968,18.604,163.821,18.013,164.057,17.159 M160.388,17.825c0-1.088,0.909-1.755,2.157-1.755
c0.648,0,1.258,0.131,1.727,0.263l0.028-0.112c0.038-0.141,0.066-0.319,0.066-0.45c0-0.629-0.432-0.986-1.313-0.986
c-0.518,0-0.939,0.103-1.37,0.253l-0.123-0.601c0.479-0.178,0.976-0.291,1.605-0.291c1.22,0,1.904,0.563,1.904,1.501
c0,0.207-0.037,0.441-0.103,0.666l-0.732,2.75h-0.704l0.207-0.76c-0.45,0.516-1.041,0.863-1.812,0.863
C161.11,19.167,160.388,18.688,160.388,17.825"/>
<path fill="#FFFFFF" d="M165.651,18.323l0.469-0.469c0.525,0.507,1.106,0.713,1.689,0.713c0.553,0,1.069-0.32,1.069-0.807
c0-0.319-0.217-0.554-0.921-0.826c-0.872-0.338-1.37-0.657-1.37-1.333c0-0.825,0.714-1.492,1.84-1.492
c0.714,0,1.389,0.32,1.792,0.667l-0.422,0.497c-0.403-0.328-0.91-0.563-1.436-0.563c-0.685,0-1.052,0.366-1.052,0.77
c0,0.319,0.198,0.525,0.968,0.826c0.873,0.356,1.322,0.704,1.322,1.333c0,0.901-0.825,1.53-1.857,1.53
C166.992,19.167,166.214,18.886,165.651,18.323"/>
<path fill="#FFFFFF" d="M171.074,18.191c0-0.169,0.027-0.356,0.064-0.507l0.761-2.834h-0.666l0.169-0.638h0.675l0.396-1.464h0.713
l-0.395,1.464h1.529l-0.169,0.638h-1.529l-0.751,2.797c-0.019,0.112-0.037,0.253-0.037,0.356c0,0.337,0.253,0.497,0.665,0.497
c0.217,0,0.441-0.046,0.705-0.149l-0.179,0.656c-0.254,0.103-0.488,0.141-0.77,0.141C171.562,19.148,171.074,18.82,171.074,18.191
"/>
<path fill="#FFFFFF" d="M173.794,19.881c0.545-0.141,0.807-0.414,0.882-0.817h-0.348l0.272-0.985h0.855l-0.227,0.845
c-0.226,0.816-0.61,1.135-1.36,1.276L173.794,19.881z"/>
<path fill="#FFFFFF" d="M184.378,16.118c0-0.713-0.562-1.37-1.492-1.37c-1.032,0-1.998,0.854-1.998,2.018
c0,0.863,0.676,1.304,1.416,1.304C183.401,18.069,184.378,17.112,184.378,16.118 M179.489,19.74l0.45-0.507
c0.516,0.441,1.173,0.732,1.914,0.732c0.61,0,1.069-0.197,1.36-0.498c0.301-0.291,0.47-0.666,0.61-1.163l0.131-0.488
c-0.487,0.497-1.061,0.872-1.857,0.872c-1.013,0-1.971-0.666-1.971-1.83c0-1.614,1.36-2.749,2.722-2.749
c1.041,0,1.511,0.582,1.782,1.163l0.282-1.06h0.723l-1.107,4.157c-0.207,0.75-0.441,1.182-0.789,1.53
c-0.45,0.45-1.051,0.685-1.877,0.685C180.972,20.584,180.09,20.265,179.489,19.74"/>
<path fill="#FFFFFF" d="M187.343,14.212h0.723l-0.33,1.267c0.593-0.845,1.343-1.408,2.31-1.352l-0.207,0.779h-0.047
c-1.06,0-2.12,0.779-2.506,2.243l-0.515,1.914h-0.724L187.343,14.212z"/>
<path fill="#FFFFFF" d="M194.491,16.305c0-0.985-0.619-1.558-1.52-1.558c-1.117,0-2.075,1.107-2.075,2.234
c0,0.985,0.62,1.547,1.521,1.547C193.506,18.529,194.491,17.459,194.491,16.305 M190.166,17c0-1.511,1.303-2.891,2.852-2.891
c1.333,0,2.214,0.911,2.214,2.168c0,1.549-1.342,2.9-2.861,2.9C191.038,19.177,190.166,18.257,190.166,17"/>
</g>
<polygon fill="#FFFFFF" points="196.459,14.212 197.19,14.212 197.444,18.079 199.791,14.194 200.391,14.194 200.663,18.079
202.999,14.212 203.75,14.212 200.728,19.102 200.091,19.102 199.809,15.273 197.473,19.102 196.845,19.102 "/>
<g>
<path fill="#FFFFFF" d="M206.461,18.323l0.469-0.469c0.525,0.507,1.106,0.713,1.688,0.713c0.554,0,1.07-0.32,1.07-0.807
c0-0.319-0.216-0.554-0.92-0.826c-0.873-0.338-1.37-0.657-1.37-1.333c0-0.825,0.713-1.492,1.84-1.492
c0.713,0,1.389,0.32,1.791,0.667l-0.422,0.497c-0.403-0.328-0.91-0.563-1.436-0.563c-0.685,0-1.051,0.366-1.051,0.77
c0,0.319,0.197,0.525,0.967,0.826c0.873,0.356,1.323,0.704,1.323,1.333c0,0.901-0.826,1.53-1.857,1.53
C207.802,19.167,207.022,18.886,206.461,18.323"/>
<path fill="#FFFFFF" d="M216.05,16.305c0-0.985-0.619-1.558-1.521-1.558c-1.116,0-2.073,1.107-2.073,2.234
c0,0.985,0.619,1.547,1.521,1.547C215.065,18.529,216.05,17.459,216.05,16.305 M211.723,17c0-1.511,1.306-2.891,2.854-2.891
c1.333,0,2.216,0.911,2.216,2.168c0,1.549-1.343,2.9-2.862,2.9C212.596,19.177,211.723,18.257,211.723,17"/>
</g>
<polygon fill="#FFFFFF" points="219.408,12.214 220.131,12.214 218.291,19.064 217.568,19.064 "/>
<path fill="#FFFFFF" d="M221.895,12.355h0.826l-0.217,0.797h-0.825L221.895,12.355z M221.443,14.212h0.724l-1.305,4.852h-0.724
L221.443,14.212z"/>
<g>
<path fill="#FFFFFF" d="M227.243,16.249c0-0.845-0.61-1.501-1.503-1.501c-1.154,0-2.026,1.07-2.026,2.309
c0,0.901,0.563,1.482,1.37,1.482C226.163,18.539,227.243,17.441,227.243,16.249 M222.954,17.122c0-1.718,1.304-3.012,2.722-3.012
c0.994,0,1.558,0.562,1.821,1.201l0.825-3.097h0.721l-1.829,6.85h-0.723l0.216-0.826c-0.46,0.525-1.051,0.938-1.83,0.938
C223.779,19.176,222.954,18.351,222.954,17.122"/>
</g>
<polygon fill="#FFFFFF" points="229.146,18.079 228.874,19.064 229.738,19.064 230,18.079 "/>
<g>
<path fill="#FFFFFF" d="M15.806,9.873l12.366,3.07c2.152-0.84,3.445-1.911,3.445-3.07V4.935C31.617,2.213,24.537,0,15.806,0
C7.076,0,0,2.213,0,4.935v4.938c0,2.723,7.076,4.933,15.806,4.933V9.873z"/>
<path fill="#FFFFFF" d="M28.171,17.879l-12.366-3.073v4.934l12.366,3.074c2.153-0.844,3.446-1.911,3.446-3.074v-4.934
C31.618,15.969,30.324,17.036,28.171,17.879"/>
<path fill="#FFFFFF" d="M0,14.806v4.935c0,2.724,7.076,4.933,15.806,4.933v-4.933C7.076,19.741,0,17.53,0,14.806"/>
<path fill="#FFFFFF" d="M45.185,19.29c-3.861,0-6.727-2.98-6.727-6.747v-0.036c0-3.728,2.81-6.784,6.838-6.784
c2.473,0,3.955,0.826,5.172,2.024l-1.836,2.117c-1.012-0.918-2.043-1.48-3.354-1.48c-2.212,0-3.803,1.836-3.803,4.084v0.039
c0,2.248,1.554,4.122,3.803,4.122c1.499,0,2.416-0.599,3.446-1.537l1.836,1.854C49.213,18.39,47.714,19.29,45.185,19.29"/>
<path fill="#FFFFFF" d="M58.506,15.017c-0.486-0.227-1.125-0.375-1.817-0.375c-1.218,0-1.969,0.487-1.969,1.387v0.037
c0,0.767,0.638,1.217,1.555,1.217c1.33,0,2.231-0.728,2.231-1.761V15.017z M58.448,19.064v-1.086
c-0.692,0.768-1.647,1.274-3.035,1.274c-1.891,0-3.447-1.087-3.447-3.073v-0.039c0-2.193,1.667-3.205,4.046-3.205
c1.013,0,1.744,0.169,2.457,0.412V13.18c0-1.179-0.731-1.836-2.156-1.836c-1.086,0-1.854,0.207-2.772,0.543l-0.713-2.173
c1.106-0.489,2.193-0.806,3.897-0.806c3.111,0,4.48,1.611,4.48,4.33v5.826H58.448z"/>
</g>
<polygon fill="#FFFFFF" points="70.123,19.064 67.499,14.961 66.505,16.01 66.505,19.064 63.659,19.064 63.659,5.384 66.505,5.384
66.505,12.676 69.842,9.021 73.251,9.021 69.429,12.973 73.382,19.064 "/>
<g>
<path fill="#FFFFFF" d="M78.757,11.12c-1.18,0-1.95,0.843-2.174,2.135h4.292C80.705,11.98,79.956,11.12,78.757,11.12
M83.61,15.037h-6.989c0.28,1.292,1.18,1.966,2.455,1.966c0.956,0,1.648-0.301,2.435-1.031l1.632,1.444
c-0.939,1.162-2.288,1.874-4.105,1.874c-3.017,0-5.249-2.117-5.249-5.19v-0.039c0-2.867,2.044-5.228,4.967-5.228
c3.354,0,4.891,2.605,4.891,5.454v0.037C83.647,14.605,83.629,14.774,83.61,15.037"/>
<path fill="#FFFFFF" d="M93.521,10.538c0-1.292-0.898-1.985-2.342-1.985H88.95v4.012h2.286c1.442,0,2.285-0.865,2.285-1.987
V10.538z M91.141,15.129h-2.19v3.935h-2.886V5.947h5.359c3.128,0,5.021,1.855,5.021,4.537v0.036
C96.444,13.555,94.083,15.129,91.141,15.129"/>
</g>
<polygon fill="#FFFFFF" points="106.787,19.064 106.787,13.796 101.465,13.796 101.465,19.064 98.58,19.064 98.58,5.947
101.465,5.947 101.465,11.138 106.787,11.138 106.787,5.947 109.672,5.947 109.672,19.064 "/>
<g>
<path fill="#FFFFFF" d="M120.277,10.538c0-1.292-0.899-1.985-2.342-1.985h-2.23v4.012h2.285c1.444,0,2.287-0.865,2.287-1.987
V10.538z M117.899,15.129h-2.194v3.935h-2.886V5.947h5.359c3.128,0,5.022,1.855,5.022,4.537v0.036
C123.201,13.555,120.84,15.129,117.899,15.129"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.4 KiB

+30
View File
@@ -0,0 +1,30 @@
services:
cakephp:
image: ghcr.io/themusicdev/cakephp-hello:1.0.0
restart: unless-stopped
depends_on:
- mariadb
environment:
# CakePHP skeleton reads its app config from these env vars
# (config/app_local.php in the starter repo is env-driven)
- DEBUG=${DEBUG}
- SECURITY_SALT=${SECURITY_SALT}
- DATABASE_URL=mysql://${MARIADB_USER}:${MARIADB_PASSWORD}@mariadb:3306/${MARIADB_DATABASE}?encoding=utf8mb4
expose:
- 80
mariadb:
image: mariadb:11
restart: unless-stopped
environment:
- MARIADB_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD}
- MARIADB_DATABASE=${MARIADB_DATABASE}
- MARIADB_USER=${MARIADB_USER}
- MARIADB_PASSWORD=${MARIADB_PASSWORD}
volumes:
- mariadb-data:/var/lib/mysql
expose:
- 3306
volumes:
mariadb-data:
+21
View File
@@ -0,0 +1,21 @@
{
"id": "cakephp",
"name": "CakePHP 5",
"version": "1.0.0",
"description": "CakePHP 5 starter app running on the themusicdev/php-apache 8.5 Apache + PHP runtime image, backed by MariaDB. Fork the starter repo, build your app, and deploy it on Dokploy in a few clicks.",
"logo": "cakephp.svg",
"links": {
"github": "https://github.com/TheMusicDev/cakephp-hello",
"website": "https://cakephp.org/",
"docs": "https://book.cakephp.org/5/en/index.html"
},
"tags": [
"php",
"framework",
"cakephp",
"website"
],
"seoTitle": "CakePHP 5 Docker Compose Setup",
"seoDescription": "Deploy a CakePHP 5 application with MariaDB on Dokploy in minutes — runs on the themusicdev/php-apache Apache + PHP 8.5 runtime image with Traefik proxy awareness built in.",
"newConfig": true
}
+24
View File
@@ -0,0 +1,24 @@
[variables]
main_domain = "${domain}"
root_password = "${password:32}"
database_password = "${password:32}"
database_username = "${username:8}"
database_name = "cakephp"
security_salt = "${base64:32}"
app_debug = "false"
[config]
mounts = []
[[config.domains]]
serviceName = "cakephp"
port = 80
host = "${main_domain}"
[config.env]
DEBUG = "${app_debug}"
SECURITY_SALT = "${security_salt}"
MARIADB_ROOT_PASSWORD = "${root_password}"
MARIADB_DATABASE = "${database_name}"
MARIADB_USER = "${database_username}"
MARIADB_PASSWORD = "${database_password}"
+254 -23
View File
@@ -1,40 +1,271 @@
# If you are on a machine with ARM architecture, please add a "-arm" suffix to the calcom image on line 19.
# If you are on a machine with ARM architecture, please add a "-arm" suffix to the calcom image.
# For example, `calcom/cal.com:v6.2.0` will become `calcom/cal.com:v6.2.0-arm`
# If serving the instance on https, change `NEXT_PUBLIC_WEBAPP_URL` (Line 28) and `NEXTAUTH_URL` (Line 30) to https
#
# If serving the instance over https, change NEXT_PUBLIC_WEBAPP_URL, NEXT_PUBLIC_WEBSITE_URL,
# NEXT_PUBLIC_EMBED_LIB_URL and NEXTAUTH_URL in template.toml to use the https scheme.
services:
postgres:
image: postgres:16-alpine
restart: unless-stopped
volumes:
- calcom-data:/var/lib/postgresql/data
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=password
- POSTGRES_DB=db
- DATABASE_URL=postgres://postgres:password@postgres:5432/db
- POSTGRES_USER
- POSTGRES_PASSWORD
- POSTGRES_DB
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
calcom:
image: calcom/cal.com:v6.2.0
restart: unless-stopped
depends_on:
- postgres
postgres:
condition: service_healthy
expose:
- 3000
environment:
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
- CALENDSO_ENCRYPTION_KEY=${CALENDSO_ENCRYPTION_KEY}
- DATABASE_URL=postgres://postgres:password@postgres:5432/db
- DATABASE_DIRECT_URL=postgres://postgres:password@postgres:5432/db
- DATABASE_HOST=postgres:5432
- NEXT_PUBLIC_WEBAPP_URL=http://${CALCOM_HOST}
- ALLOWED_HOSTNAMES="${CALCOM_HOST}"
- NEXTAUTH_URL=http://${CALCOM_HOST}/api/auth
- NEXT_PUBLIC_DISABLE_SIGNUP=${DISABLE_SIGNUP}
- EMAIL_SERVER_HOST=${SMTP_SERVER}
- EMAIL_SERVER_PORT=${SMTP_PORT}
- EMAIL_SERVER_USER=${EMAIL_SERVER_USER}
- EMAIL_SERVER_PASSWORD=${SMTP_PASSWORD}
- EMAIL_FROM=${EMAIL_FROM}
# --- DATABASE ---------------------------------------------------------------------------
- DATABASE_URL
- DATABASE_DIRECT_URL
- INSIGHTS_DATABASE_URL
# --- SHARED -----------------------------------------------------------------------------
- NEXT_PUBLIC_WEBAPP_URL
- NEXT_PUBLIC_WEBSITE_URL
- NEXT_PUBLIC_EMBED_LIB_URL
- 'ALLOWED_HOSTNAMES="${ALLOWED_HOSTNAMES}"'
- 'RESERVED_SUBDOMAINS="app","auth","docs","design","console","go","status","api","saml","www","matrix","developer","cal","my","team","support","security","blog","learn","admin"'
- SAML_DATABASE_URL
- SAML_ADMINS
- NEXT_PUBLIC_HOSTED_CAL_FEATURES
- PGSSLMODE
# --- NEXTAUTH ---------------------------------------------------------------------------
- NEXTAUTH_URL
- NEXTAUTH_SECRET
- NEXTAUTH_COOKIE_DOMAIN
- CALCOM_TELEMETRY_DISABLED
- CRON_API_KEY
- CRON_ENABLE_APP_SYNC
- CALENDSO_ENCRYPTION_KEY
# --- SUPPORT / ANALYTICS WIDGETS --------------------------------------------------------
- NEXT_PUBLIC_INTERCOM_APP_ID
- INTERCOM_SECRET
- INTERCOM_API_TOKEN
- NEXT_PUBLIC_POSTHOG_KEY
- NEXT_PUBLIC_POSTHOG_HOST
- NEXT_PUBLIC_ZENDESK_KEY
- NEXT_PUBLIC_HELPSCOUT_KEY
- NEXT_PUBLIC_FRESHCHAT_TOKEN
- NEXT_PUBLIC_FRESHCHAT_HOST
# --- URL SHORTENERS ---------------------------------------------------------------------
- DUB_API_KEY
- NEXT_PUBLIC_DUB_PROGRAM_ID
- DUB_SMS_DOMAIN
- DUB_SMS_FOLDER_ID
- SINK_API_URL
- SINK_API_KEY
# --- OAUTH / CALENDAR INTEGRATIONS ------------------------------------------------------
- OUTLOOK_LOGIN_ENABLED
- GOOGLE_CALENDAR_API_KEY
- GOOGLE_LOGIN_ENABLED
- GOOGLE_API_CREDENTIALS
- GOOGLE_WEBHOOK_TOKEN
- GOOGLE_WEBHOOK_URL
- MICROSOFT_WEBHOOK_TOKEN
- MICROSOFT_WEBHOOK_URL
# --- FEEDBACK / TRANSACTIONAL PROVIDERS -------------------------------------------------
- SEND_FEEDBACK_EMAIL
- SENDGRID_API_KEY
- SENDGRID_EMAIL
- NEXT_PUBLIC_SENDGRID_SENDER_NAME
- SENDGRID_SYNC_API_KEY
- RESEND_API_KEY
# --- SENTRY -----------------------------------------------------------------------------
- SENTRY_ORG
- SENTRY_PROJECT
- SENTRY_AUTH_TOKEN
- NEXT_PUBLIC_SENTRY_DSN
- NEXT_PUBLIC_SENTRY_DSN_CLIENT
- SENTRY_DEBUG
- SENTRY_MAX_SPANS
- SENTRY_SAMPLE_RATE
- SENTRY_TRACES_SAMPLE_RATE
- SENTRY_REPLAYS_SESSION_SAMPLE_RATE
- SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE
# --- FORMBRICKS -------------------------------------------------------------------------
- NEXT_PUBLIC_FORMBRICKS_HOST_URL
- NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID
- FORMBRICKS_FEEDBACK_SURVEY_ID
# --- AVATARAPI --------------------------------------------------------------------------
- AVATARAPI_USERNAME
- AVATARAPI_PASSWORD
# --- TWILIO -----------------------------------------------------------------------------
- NEXT_PUBLIC_SENDER_ID
- TWILIO_VERIFY_SID
- TWILIO_OPT_OUT_ENABLED
# --- STRIPE -----------------------------------------------------------------------------
- NEXT_PUBLIC_STRIPE_PRO_PLAN_PRICE
- NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE
- NEXT_PUBLIC_IS_PREMIUM_NEW_PLAN
- NEXT_PUBLIC_STRIPE_PREMIUM_NEW_PLAN_PRICE
- STRIPE_TEAM_MONTHLY_PRICE_ID
- STRIPE_TEAM_ANNUAL_PRICE_ID
- NEXT_PUBLIC_STRIPE_CREDITS_PRICE_ID
- ORG_MONTHLY_CREDITS
- STRIPE_TEAM_PRODUCT_ID
- STRIPE_ORG_MONTHLY_PRICE_ID
- STRIPE_ORG_ANNUAL_PRICE_ID
- STRIPE_ORG_PRODUCT_ID
- STRIPE_ORG_TRIAL_DAYS
- STRIPE_WEBHOOK_SECRET
- STRIPE_WEBHOOK_SECRET_APPS
- STRIPE_WEBHOOK_SECRET_BILLING
- STRIPE_PRIVATE_KEY
- STRIPE_CLIENT_ID
- API_KEY_PREFIX
# --- E-MAIL SETTINGS --------------------------------------------------------------------
- EMAIL_FROM
- EMAIL_FROM_NAME
- EMAIL_SERVER_HOST
- EMAIL_SERVER_PORT
- EMAIL_SERVER_USER
- EMAIL_SERVER_PASSWORD
- AWAITING_PAYMENT_EMAIL_DELAY_MINUTES
# --- BOT PROTECTION ---------------------------------------------------------------------
- NEXT_PUBLIC_CLOUDFLARE_SITEKEY
- NEXT_PUBLIC_CLOUDFLARE_USE_TURNSTILE_IN_BOOKER
- CLOUDFLARE_TURNSTILE_SECRET
- NEXT_PUBLIC_VERCEL_USE_BOTID_IN_BOOKER
# --- CLOSE.COM INTERNAL CRM -------------------------------------------------------------
- CLOSECOM_CLIENT_ID
- CLOSECOM_CLIENT_SECRET
# --- BRANDING ---------------------------------------------------------------------------
- NEXT_PUBLIC_APP_NAME
- NEXT_PUBLIC_SUPPORT_MAIL_ADDRESS
- NEXT_PUBLIC_COMPANY_NAME
- NEXT_PUBLIC_DISABLE_SIGNUP
- NEXT_PUBLIC_WEBSITE_PRIVACY_POLICY_URL
- NEXT_PUBLIC_WEBSITE_TERMS_URL
- NEXT_PUBLIC_HEAD_SCRIPTS
- NEXT_PUBLIC_BODY_SCRIPTS
- CSP_POLICY
- EDGE_CONFIG
# --- BOOKER BEHAVIOUR -------------------------------------------------------------------
- NEXT_PUBLIC_MINUTES_TO_BOOK
- NEXT_PUBLIC_BOOKER_NUMBER_OF_DAYS_TO_LOAD
- NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL
- NEXT_PUBLIC_QUERY_RESERVATION_INTERVAL_SECONDS
- NEXT_PUBLIC_QUERY_RESERVATION_STALE_TIME_SECONDS
- NEXT_PUBLIC_QUERY_AVAILABLE_SLOTS_INTERVAL_SECONDS
- NEXT_PUBLIC_INVALIDATE_AVAILABLE_SLOTS_ON_BOOKING_FORM
- NEXT_PUBLIC_QUICK_AVAILABILITY_ROLLOUT
- BLACKLISTED_GUEST_EMAILS
# --- ORGANIZATIONS ----------------------------------------------------------------------
- ORGANIZATIONS_ENABLED
- NEXT_PUBLIC_ORGANIZATIONS_MIN_SELF_SERVE_SEATS
- NEXT_PUBLIC_ORGANIZATIONS_SELF_SERVE_PRICE_NEW
- ORGANIZATIONS_AUTOLINK
- NEXT_PUBLIC_SINGLE_ORG_SLUG
- PROJECT_ID_VERCEL
- TEAM_ID_VERCEL
- AUTH_BEARER_TOKEN_VERCEL
- LOCAL_TESTING_DOMAIN_VERCEL
- CLOUDFLARE_DNS
- AUTH_BEARER_TOKEN_CLOUDFLARE
- CLOUDFLARE_ZONE_ID
- CLOUDFLARE_VERCEL_CNAME
# --- APP CREDENTIAL SYNC ----------------------------------------------------------------
- CALCOM_CREDENTIAL_SYNC_SECRET
- CALCOM_CREDENTIAL_SYNC_HEADER_NAME
- CALCOM_CREDENTIAL_SYNC_ENDPOINT
- CALCOM_APP_CREDENTIAL_ENCRYPTION_KEY
- CALCOM_SERVICE_ACCOUNT_ENCRYPTION_KEY
# --- API V2 -----------------------------------------------------------------------------
- NEXT_PUBLIC_API_V2_URL
# --- TASKER / BACKGROUND JOBS -----------------------------------------------------------
- TASKER_ENABLE_WEBHOOKS
- TASKER_ENABLE_EMAILS
- ENABLE_ASYNC_TASKER
- TRIGGER_SECRET_KEY
- TRIGGER_API_URL
- TRIGGER_DEV_PROJECT_REF
# --- RATE LIMITING ----------------------------------------------------------------------
- UNKEY_ROOT_KEY
# --- CAL.AI VOICE AGENTS ----------------------------------------------------------------
- RETELL_AI_KEY
- RETELL_AI_TEST_MODE
- RETELL_AI_TEST_EVENT_TYPE_MAP
- RETELL_AI_TEST_CAL_API_KEY
- STRIPE_PHONE_NUMBER_MONTHLY_PRICE_ID
- CAL_AI_CALL_RATE_PER_MINUTE
- NEXT_PUBLIC_CAL_AI_PHONE_NUMBER_MONTHLY_PRICE
# --- VIDEO ------------------------------------------------------------------------------
- HUDDLE01_API_TOKEN
- CAL_VIDEO_BUCKET_NAME
- CAL_VIDEO_BUCKET_REGION
- CAL_VIDEO_ASSUME_ROLE_ARN
- CAL_VIDEO_MEETING_LINK_FOR_TESTING
- CAL_VIDEO_RECORDING_TOKEN_SECRET
# --- WEB PUSH NOTIFICATIONS -------------------------------------------------------------
- NEXT_PUBLIC_VAPID_PUBLIC_KEY
- VAPID_PRIVATE_KEY
# --- MISC -------------------------------------------------------------------------------
- LINGO_DOT_DEV_API_KEY
- IFFY_API_KEY
- DIRECTORY_IDS_TO_LOG
- NEXT_PUBLIC_LOGGER_LEVEL
- DATABASE_CHUNK_SIZE
- SALESFORCE_GRAPHQL_DELAY_MS
- SALESFORCE_GRAPHQL_MAX_DELAY_MS
- SALESFORCE_GRAPHQL_MAX_RETRIES
- TZ
- GOOGLE_ADS_ENABLED
- LINKEDIN_ADS_ENABLED
# --- DEVELOPMENT / E2E ONLY -------------------------------------------------------------
- NEXT_PUBLIC_IS_E2E
- E2E_TEST_MAILHOG_ENABLED
- E2E_TEST_APPLE_CALENDAR_EMAIL
- E2E_TEST_APPLE_CALENDAR_PASSWORD
- E2E_TEST_CALCOM_QA_EMAIL
- E2E_TEST_CALCOM_QA_PASSWORD
- E2E_TEST_CALCOM_QA_GCAL_CREDENTIALS
- E2E_TEST_CALCOM_GCAL_KEYS
- SEED_PLATFORM_OAUTH_CLIENT_ID
- SEED_PLATFORM_OAUTH_CLIENT_SECRET
- SEED_OAUTH2_CLIENT_ID
- SEED_OAUTH2_CLIENT_SECRET_HASHED
volumes:
calcom-data:
+292 -8
View File
@@ -1,19 +1,303 @@
[variables]
main_domain = "${domain}"
calcom_encryption_key = "${base64:32}"
postgres_password = "${password:32}"
database_url = "postgresql://calcom:${postgres_password}@postgres:5432/calendso"
nextauth_secret = "${base64:32}"
calendso_encryption_key = "${base64:24}"
calcom_credential_sync_secret = "${base64:32}"
calcom_app_credential_encryption_key = "${base64:24}"
calcom_service_account_encryption_key = "${base64:24}"
cal_video_recording_token_secret = "${base64:32}"
cron_api_key = "${hash:32}"
[config]
env = [
"CALCOM_HOST=${main_domain}",
# --- POSTGRES (consumed by the `postgres` service) -----------------------------------------
"POSTGRES_USER=calcom",
"POSTGRES_PASSWORD=${postgres_password}",
"POSTGRES_DB=calendso",
# --- DATABASE ------------------------------------------------------------------------------
"DATABASE_URL=${database_url}",
"DATABASE_DIRECT_URL=${database_url}",
# Optional read replica for the Insights dashboard. Falls back to DATABASE_URL when empty.
"INSIGHTS_DATABASE_URL=",
# --- SHARED --------------------------------------------------------------------------------
"NEXT_PUBLIC_WEBAPP_URL=http://${main_domain}",
"NEXT_PUBLIC_WEBSITE_URL=http://${main_domain}",
"NEXT_PUBLIC_EMBED_LIB_URL=http://${main_domain}/embed/embed.js",
"ALLOWED_HOSTNAMES=${main_domain}",
# SAML login needs a separate database and is Enterprise Edition only.
"SAML_DATABASE_URL=",
"SAML_ADMINS=",
"NEXT_PUBLIC_HOSTED_CAL_FEATURES=",
# Set to no-verify only when your Postgres uses a self-signed certificate.
"PGSSLMODE=",
# - NEXTAUTH
"NEXTAUTH_URL=http://${main_domain}",
"NEXTAUTH_SECRET=${nextauth_secret}",
"CALENDSO_ENCRYPTION_KEY=${calcom_encryption_key}",
"DISABLE_SIGNUP=true",
"SMTP_SERVER=",
"SMTP_PORT=",
"SMTP_PASSWORD=",
"NEXTAUTH_COOKIE_DOMAIN=",
# 1 disables anonymous usage collection.
"CALCOM_TELEMETRY_DISABLED=1",
"CRON_API_KEY=${cron_api_key}",
"CRON_ENABLE_APP_SYNC=false",
"CALENDSO_ENCRYPTION_KEY=${calendso_encryption_key}",
# --- SUPPORT / ANALYTICS WIDGETS -----------------------------------------------------------
"NEXT_PUBLIC_INTERCOM_APP_ID=",
"INTERCOM_SECRET=",
"INTERCOM_API_TOKEN=",
"NEXT_PUBLIC_POSTHOG_KEY=",
"NEXT_PUBLIC_POSTHOG_HOST=",
"NEXT_PUBLIC_ZENDESK_KEY=",
"NEXT_PUBLIC_HELPSCOUT_KEY=",
"NEXT_PUBLIC_FRESHCHAT_TOKEN=",
"NEXT_PUBLIC_FRESHCHAT_HOST=",
# --- URL SHORTENERS (SMS workflow links) ---------------------------------------------------
"DUB_API_KEY=",
"NEXT_PUBLIC_DUB_PROGRAM_ID=",
"DUB_SMS_DOMAIN=",
"DUB_SMS_FOLDER_ID=",
"SINK_API_URL=",
"SINK_API_KEY=",
# --- OAUTH / CALENDAR INTEGRATIONS ---------------------------------------------------------
"OUTLOOK_LOGIN_ENABLED=false",
"GOOGLE_CALENDAR_API_KEY=",
"GOOGLE_LOGIN_ENABLED=false",
"GOOGLE_API_CREDENTIALS=",
"GOOGLE_WEBHOOK_TOKEN=",
# Defaults to NEXT_PUBLIC_WEBAPP_URL when empty.
"GOOGLE_WEBHOOK_URL=",
"MICROSOFT_WEBHOOK_TOKEN=",
"MICROSOFT_WEBHOOK_URL=",
# --- FEEDBACK / TRANSACTIONAL PROVIDERS ----------------------------------------------------
"SEND_FEEDBACK_EMAIL=",
"SENDGRID_API_KEY=",
"SENDGRID_EMAIL=",
"NEXT_PUBLIC_SENDGRID_SENDER_NAME=",
"SENDGRID_SYNC_API_KEY=",
"RESEND_API_KEY=",
# --- SENTRY --------------------------------------------------------------------------------
"SENTRY_ORG=",
"SENTRY_PROJECT=",
"SENTRY_AUTH_TOKEN=",
"NEXT_PUBLIC_SENTRY_DSN=",
"NEXT_PUBLIC_SENTRY_DSN_CLIENT=",
"SENTRY_DEBUG=",
"SENTRY_MAX_SPANS=",
"SENTRY_SAMPLE_RATE=",
"SENTRY_TRACES_SAMPLE_RATE=",
"SENTRY_REPLAYS_SESSION_SAMPLE_RATE=",
"SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE=",
# --- FORMBRICKS ----------------------------------------------------------------------------
"NEXT_PUBLIC_FORMBRICKS_HOST_URL=https://app.formbricks.com",
"NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID=",
"FORMBRICKS_FEEDBACK_SURVEY_ID=",
# --- AVATARAPI (pre-fills avatars during signup) -------------------------------------------
"AVATARAPI_USERNAME=",
"AVATARAPI_PASSWORD=",
# --- TWILIO (SMS workflows) ----------------------------------------------------------------
# NEXT_PUBLIC_SENDER_ID: letters, numbers and spaces only, max 11 characters.
"NEXT_PUBLIC_SENDER_ID=",
"TWILIO_VERIFY_SID=",
"TWILIO_OPT_OUT_ENABLED=",
# --- STRIPE (internal billing, teams and organizations) ------------------------------------
"NEXT_PUBLIC_STRIPE_PRO_PLAN_PRICE=",
"NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE=",
"NEXT_PUBLIC_IS_PREMIUM_NEW_PLAN=0",
"NEXT_PUBLIC_STRIPE_PREMIUM_NEW_PLAN_PRICE=",
"STRIPE_TEAM_MONTHLY_PRICE_ID=",
"STRIPE_TEAM_ANNUAL_PRICE_ID=",
"NEXT_PUBLIC_STRIPE_CREDITS_PRICE_ID=",
"ORG_MONTHLY_CREDITS=",
"STRIPE_TEAM_PRODUCT_ID=",
# A price ID belonging to the product in STRIPE_ORG_PRODUCT_ID.
"STRIPE_ORG_MONTHLY_PRICE_ID=",
"STRIPE_ORG_ANNUAL_PRICE_ID=",
"STRIPE_ORG_PRODUCT_ID=",
# Trial days passed to the Stripe checkout session for organizations.
"STRIPE_ORG_TRIAL_DAYS=",
"STRIPE_WEBHOOK_SECRET=",
"STRIPE_WEBHOOK_SECRET_APPS=",
"STRIPE_WEBHOOK_SECRET_BILLING=",
"STRIPE_PRIVATE_KEY=",
"STRIPE_CLIENT_ID=",
# Prefix for public API keys.
"API_KEY_PREFIX=cal_",
# --- E-MAIL SETTINGS -----------------------------------------------------------------------
"EMAIL_FROM=notifications@${main_domain}",
"EMAIL_FROM_NAME=Cal.com",
"EMAIL_SERVER_HOST=",
"EMAIL_SERVER_PORT=587",
"EMAIL_SERVER_USER=",
"EMAIL_FROM=",
"EMAIL_SERVER_PASSWORD=",
"AWAITING_PAYMENT_EMAIL_DELAY_MINUTES=",
# --- BOT PROTECTION ------------------------------------------------------------------------
"NEXT_PUBLIC_CLOUDFLARE_SITEKEY=",
"NEXT_PUBLIC_CLOUDFLARE_USE_TURNSTILE_IN_BOOKER=",
"CLOUDFLARE_TURNSTILE_SECRET=",
"NEXT_PUBLIC_VERCEL_USE_BOTID_IN_BOOKER=0",
# --- CLOSE.COM INTERNAL CRM ----------------------------------------------------------------
"CLOSECOM_CLIENT_ID=",
"CLOSECOM_CLIENT_SECRET=",
# --- BRANDING ------------------------------------------------------------------------------
"NEXT_PUBLIC_APP_NAME=Cal.com",
"NEXT_PUBLIC_SUPPORT_MAIL_ADDRESS=help@cal.com",
"NEXT_PUBLIC_COMPANY_NAME=Cal.com, Inc.",
"NEXT_PUBLIC_DISABLE_SIGNUP=false",
"NEXT_PUBLIC_WEBSITE_PRIVACY_POLICY_URL=",
"NEXT_PUBLIC_WEBSITE_TERMS_URL=",
# Deprecated: NEXT_PUBLIC_HEAD_SCRIPTS is injected into the body only, use BODY_SCRIPTS.
"NEXT_PUBLIC_HEAD_SCRIPTS=",
"NEXT_PUBLIC_BODY_SCRIPTS=",
# Set to non-strict to enable a Content Security Policy for support pages.
"CSP_POLICY=",
# Vercel Edge Config, unused outside Vercel.
"EDGE_CONFIG=",
# --- BOOKER BEHAVIOUR ----------------------------------------------------------------------
"NEXT_PUBLIC_MINUTES_TO_BOOK=5",
# Override the booker to only load X days worth of data. 0 = no override.
"NEXT_PUBLIC_BOOKER_NUMBER_OF_DAYS_TO_LOAD=0",
"NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL=",
# Retry interval for stale slot-reservation checks.
"NEXT_PUBLIC_QUERY_RESERVATION_INTERVAL_SECONDS=",
# Must be lower than NEXT_PUBLIC_QUERY_RESERVATION_INTERVAL_SECONDS.
"NEXT_PUBLIC_QUERY_RESERVATION_STALE_TIME_SECONDS=",
# Keep high (minutes) — low values put significant load on the instance.
"NEXT_PUBLIC_QUERY_AVAILABLE_SLOTS_INTERVAL_SECONDS=",
"NEXT_PUBLIC_INVALIDATE_AVAILABLE_SLOTS_ON_BOOKING_FORM=0",
# Percentage of visitors that get quick availability checks.
"NEXT_PUBLIC_QUICK_AVAILABILITY_ROLLOUT=10",
# Emails that may never be added as booking guests.
"BLACKLISTED_GUEST_EMAILS=",
# --- ORGANIZATIONS -------------------------------------------------------------------------
# Organizations need a full domain pointing at the app and must also be enabled at build
# time, so setting this on a prebuilt image is not enough on its own.
"ORGANIZATIONS_ENABLED=",
"NEXT_PUBLIC_ORGANIZATIONS_MIN_SELF_SERVE_SEATS=30",
# $37.00 per seat
"NEXT_PUBLIC_ORGANIZATIONS_SELF_SERVE_PRICE_NEW=37",
# Autolink external provider sign-ups to existing orgs by email domain.
"ORGANIZATIONS_AUTOLINK=",
# Serve only one organization's booking pages. Baked in at build time.
"NEXT_PUBLIC_SINGLE_ORG_SLUG=",
# Vercel/Cloudflare subdomain management for organizations. Only relevant on Vercel.
"PROJECT_ID_VERCEL=",
"TEAM_ID_VERCEL=",
"AUTH_BEARER_TOKEN_VERCEL=",
"LOCAL_TESTING_DOMAIN_VERCEL=",
"CLOUDFLARE_DNS=",
"AUTH_BEARER_TOKEN_CLOUDFLARE=",
"CLOUDFLARE_ZONE_ID=",
"CLOUDFLARE_VERCEL_CNAME=",
# --- APP CREDENTIAL SYNC -------------------------------------------------------------------
# For self-hosters embedding Cal into an app that already holds the integration secrets.
"CALCOM_CREDENTIAL_SYNC_SECRET=${calcom_credential_sync_secret}",
# Header used to verify the webhook secret. Must be lowercase.
"CALCOM_CREDENTIAL_SYNC_HEADER_NAME=calcom-credential-sync-secret",
"CALCOM_CREDENTIAL_SYNC_ENDPOINT=",
# Must match the key configured in your application.
"CALCOM_APP_CREDENTIAL_ENCRYPTION_KEY=${calcom_app_credential_encryption_key}",
"CALCOM_SERVICE_ACCOUNT_ENCRYPTION_KEY=${calcom_service_account_encryption_key}",
# --- API V2 --------------------------------------------------------------------------------
# This blueprint does not ship the API v2 service (upstream builds it from source and has no
# published image). Point this at your own deployment to enable the v2 API.
"NEXT_PUBLIC_API_V2_URL=",
# --- TASKER / BACKGROUND JOBS --------------------------------------------------------------
"TASKER_ENABLE_WEBHOOKS=0",
"TASKER_ENABLE_EMAILS=0",
"ENABLE_ASYNC_TASKER=false",
"TRIGGER_SECRET_KEY=",
"TRIGGER_API_URL=https://api.trigger.dev",
"TRIGGER_DEV_PROJECT_REF=",
# --- RATE LIMITING (Unkey) -----------------------------------------------------------------
# Optional. Not needed for self-hosting unless you want rate limiting.
"UNKEY_ROOT_KEY=",
# --- CAL.AI VOICE AGENTS (Retell AI) -------------------------------------------------------
"RETELL_AI_KEY=",
"RETELL_AI_TEST_MODE=false",
# JSON map of local to production event type IDs.
"RETELL_AI_TEST_EVENT_TYPE_MAP=",
"RETELL_AI_TEST_CAL_API_KEY=",
"STRIPE_PHONE_NUMBER_MONTHLY_PRICE_ID=",
"CAL_AI_CALL_RATE_PER_MINUTE=0.29",
# Price for buying a phone number for the Cal.ai voice agent (default 5).
"NEXT_PUBLIC_CAL_AI_PHONE_NUMBER_MONTHLY_PRICE=",
# --- VIDEO ---------------------------------------------------------------------------------
"HUDDLE01_API_TOKEN=",
# S3 storage for Daily Video recordings.
"CAL_VIDEO_BUCKET_NAME=",
"CAL_VIDEO_BUCKET_REGION=",
"CAL_VIDEO_ASSUME_ROLE_ARN=",
"CAL_VIDEO_MEETING_LINK_FOR_TESTING=",
"CAL_VIDEO_RECORDING_TOKEN_SECRET=${cal_video_recording_token_secret}",
# --- WEB PUSH NOTIFICATIONS ----------------------------------------------------------------
# Generate a pair with: npx web-push generate-vapid-keys
"NEXT_PUBLIC_VAPID_PUBLIC_KEY=",
"VAPID_PRIVATE_KEY=",
# --- MISC ----------------------------------------------------------------------------------
# Real-time AI localization via lingo.dev.
"LINGO_DOT_DEV_API_KEY=",
# Content moderation.
"IFFY_API_KEY=",
# Comma-separated DSyncData.directoryId values to log SCIM requests for (debugging only).
"DIRECTORY_IDS_TO_LOG=",
# 0: silly, 1: trace, 2: debug, 3: info, 4: warn, 5: error/fatal, 6: fatal
"NEXT_PUBLIC_LOGGER_LEVEL=",
"DATABASE_CHUNK_SIZE=",
"SALESFORCE_GRAPHQL_DELAY_MS=500",
"SALESFORCE_GRAPHQL_MAX_DELAY_MS=2000",
"SALESFORCE_GRAPHQL_MAX_RETRIES=3",
# Force Node.js to use UTC as the process timezone.
"TZ=UTC",
# Ad click tracking (gclid / li_fat_id). Off by default for self-hosted instances.
"GOOGLE_ADS_ENABLED=0",
"LINKEDIN_ADS_ENABLED=0",
# --- DEVELOPMENT / E2E ONLY ----------------------------------------------------------------
# Leave empty on a real deployment.
"NEXT_PUBLIC_IS_E2E=",
"E2E_TEST_MAILHOG_ENABLED=",
"E2E_TEST_APPLE_CALENDAR_EMAIL=",
"E2E_TEST_APPLE_CALENDAR_PASSWORD=",
"E2E_TEST_CALCOM_QA_EMAIL=",
"E2E_TEST_CALCOM_QA_PASSWORD=",
"E2E_TEST_CALCOM_QA_GCAL_CREDENTIALS=",
"E2E_TEST_CALCOM_GCAL_KEYS=",
"SEED_PLATFORM_OAUTH_CLIENT_ID=",
"SEED_PLATFORM_OAUTH_CLIENT_SECRET=",
"SEED_OAUTH2_CLIENT_ID=",
"SEED_OAUTH2_CLIENT_SECRET_HASHED=",
]
mounts = []
+4
View File
@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 27 31">
<path fill="#60a5fa" d="m 3.043653,30.614292 c -1.04707,-0.32444 -1.94939,-1.09611 -2.51053002,-2.14706 l -0.28493,-0.53364 -0.0338,-10.26902 c -0.0333,-10.1001 -0.0296,-10.28026 0.22157,-10.95165 C 0.93698298,5.3738426 2.254043,4.3160626 3.592343,4.1779326 l 0.66734,-0.069 0.0442,1.54722 c 0.0411,1.4322294 0.069,1.5846294 0.37758,2.0507194 0.43775,0.66128 1.06374,1.03377 1.8697695,1.11256 0.83411,0.0815 1.60889,-0.30288 2.1454309,-1.06449 0.35775,-0.50781 0.37448,-0.59108 0.41656,-2.0715194 l 0.0439,-1.54245 h 4.3226446 4.32263 l 0.0491,1.45985 c 0.0578,1.7152194 0.26715,2.2526994 1.10313,2.8320394 0.44147,0.30594 0.6462,0.36331 1.30282,0.36509 0.6673,0.002 0.85479,-0.0513 1.30717,-0.3706 0.83953,-0.59252 1.03808,-1.10942 1.09117,-2.8410394 l 0.0452,-1.47436 0.61114,0.0588 c 0.88513,0.085 1.92322,0.66148 2.52855,1.40407 0.98071,1.2030494 0.9433,0.7026404 0.90509,12.1120594 l -0.0339,10.12241 -0.34547,0.70339 c -0.37943,0.77247 -1.03179,1.43013 -1.85424,1.86928 l -0.53363,0.28492 -10.31215,0.0218 c -5.6716955,0.0121 -10.451945,-0.0215 -10.622765,-0.0745 z M 5.994413,7.609932 C 5.466163,7.302262 5.404273,6.907952 5.404273,3.8497926 v -2.91273 l 0.36045,-0.38587 c 0.39686,-0.42484 0.9678395,-0.51125 1.5687795,-0.23743 0.6263,0.28536 0.67987,0.58051 0.67987,3.7459 V 6.972402 l -0.36047,0.38586 c -0.29807,0.31911 -0.45393,0.38521 -0.90075,0.3821 -0.29716,-0.002 -0.6381595,-0.0608 -0.7577395,-0.13043 z m 13.312785,-0.25167 -0.36045,-0.38586 V 4.0596626 c 0,-3.08584 0.0628,-3.47128 0.61433,-3.76641 0.31968,-0.17109 0.91477,-0.16181 1.3149,0.0204 0.62629,0.28536 0.67987,0.58051 0.67987,3.74591 V 6.972292 l -0.36046,0.38587 c -0.30429,0.32575 -0.45138,0.38587 -0.9441,0.38587 -0.4927,0 -0.6398,-0.0601 -0.94409,-0.38587 z"/>
<path fill="#ffffff" d="M 13.529898,23.489202 c 0.41676,-0.42858 2.30921,-2.34577 4.20548,-4.26044 3.89443,-3.93222 3.79896,-3.77881 2.93494,-4.71617 -0.86333,-0.9366 -0.70987,-1.03489 -4.7574,3.04728 -2.01816,2.03542 -3.63135,3.56753 -3.70704,3.52074 -0.0737,-0.0455 -0.86549,-0.83379 -1.759495,-1.7516 -1.7365396,-1.78282 -2.1646795,-2.10404 -2.5380305,-1.90423 -0.40259,0.21546 -1.13741,1.12099 -1.13741,1.40162 0,0.18848 0.79327,1.06899 2.5741409,2.85723 3.0861346,3.09893 2.9741146,3.05059 4.1848146,1.80557 z"/>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

+47
View File
@@ -0,0 +1,47 @@
services:
calnode:
image: ghcr.io/calnode/calnode:0.12.0
restart: unless-stopped
volumes:
- calnode_data:/data
expose:
- "3000"
environment:
PORT: ${PORT}
BASE_URL: ${BASE_URL}
PUBLIC_BASE_URL: ${PUBLIC_BASE_URL}
DATABASE_URL: ${DATABASE_URL}
CALNODE_ENCRYPTION_KEY: ${CALNODE_ENCRYPTION_KEY}
CALNODE_RECOVERY_SECRET: ${CALNODE_RECOVERY_SECRET}
GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET}
MICROSOFT_CLIENT_ID: ${MICROSOFT_CLIENT_ID}
MICROSOFT_CLIENT_SECRET: ${MICROSOFT_CLIENT_SECRET}
MICROSOFT_TENANT: ${MICROSOFT_TENANT}
EMAIL_SMTP_HOST: ${EMAIL_SMTP_HOST}
EMAIL_SMTP_PORT : ${EMAIL_SMTP_PORT}
EMAIL_SMTP_CONNECT_HOST: ${EMAIL_SMTP_CONNECT_HOST}
EMAIL_SMTP_CONNECT_PORT: ${EMAIL_SMTP_CONNECT_PORT}
EMAIL_SMTP_USER: ${EMAIL_SMTP_USER}
EMAIL_SMTP_PASS : ${EMAIL_SMTP_PASS}
EMAIL_FROM_ADDRESS: ${EMAIL_FROM_ADDRESS}
EMAIL_FROM_NAME: ${EMAIL_FROM_NAME}
EMAIL_SMTP_TLS: ${EMAIL_SMTP_TLS}
EMAIL_SMTP_STARTTLS: ${EMAIL_SMTP_STARTTLS}
LITESTREAM_REPLICA_URL: ${LITESTREAM_REPLICA_URL}
LITESTREAM_ACCESS_KEY_ID: ${LITESTREAM_ACCESS_KEY_ID}
LITESTREAM_SECRET_ACCESS_KEY: ${LITESTREAM_SECRET_ACCESS_KEY}
LITESTREAM_ENDPOINT: ${LITESTREAM_ENDPOINT}
LITESTREAM_REGION: ${LITESTREAM_REGION}
COOKIE_SECURE: ${COOKIE_SECURE}
TRUSTED_PROXY_CIDRS: ${TRUSTED_PROXY_CIDRS}
FRAME_ANCESTORS: ${FRAME_ANCESTORS}
LOG_LEVEL: ${LOG_LEVEL}
volumes:
calnode_data:
+20
View File
@@ -0,0 +1,20 @@
{
"id": "calnode",
"name": "Calnode",
"version": "v0.12.0",
"description": "Calnode is a Calendly-style booking app — with first-party video meetings, recording, and AI notetaking built in. It's API-first, webhook-native, and built for a world where agents do the booking. Nothing is paywalled.",
"links": {
"github": "https://github.com/Calnode/calnode",
"website": "https://calnode.com/",
"docs": "https://github.com/Calnode/calnode/tree/main/docs"
},
"logo": "calnode.svg",
"tags": [
"scheduling",
"booking",
"calendar",
"meetings"
],
"seoTitle": "Self-Host Calnode in minutes",
"seoDescription": "Scheduling and booking tool, an alternative to Calendly. Self-host Calnode on Dokploy in minutes – no manual setup needed."
}
+64
View File
@@ -0,0 +1,64 @@
[variables]
main_domain = "${domain}"
calnode_encryption_key = "${base64:32}"
[config]
env = [
"PORT=3000",
"BASE_URL=http:${main_domain}",
"PUBLIC_BASE_URL=",
"DATABASE_URL=sqlite://./data/calnode.db",
"COOKIE_SECURE=",
"CALNODE_ENCRYPTION_KEY=${calnode_encryption_key}",
"CALNODE_RECOVERY_SECRET=",
# Redirect URIs to add:
# http://<domain>/v1/auth/callback
# http://<domain>/v1/calendar/callback
"GOOGLE_CLIENT_ID=",
"GOOGLE_CLIENT_SECRET=",
# Add a Web platform with these redirect URIs:
# http://<domain>/v1/auth/microsoft/callback
# http://<domain>/v1/calendar/callback
"MICROSOFT_CLIENT_ID=",
"MICROSOFT_CLIENT_SECRET=",
"MICROSOFT_TENANT=common",
"EMAIL_SMTP_HOST=",
"EMAIL_SMTP_PORT=587",
"EMAIL_SMTP_CONNECT_HOST=",
"EMAIL_SMTP_CONNECT_PORT=",
"EMAIL_SMTP_USER=",
"EMAIL_SMTP_PASS=",
"EMAIL_FROM_ADDRESS=",
"EMAIL_FROM_NAME=Calnode",
"EMAIL_SMTP_TLS=",
"EMAIL_SMTP_STARTTLS=",
# Object storage (Litestream) — optional, but required for two things: continuous
# SQLite backups, and meeting recordings (Settings → Storage; the "Record" button
# only appears once this is configured AND recordings are turned on there). Both
# share one S3-compatible bucket. No in-app form for this — set as environment
# variables/secrets with your hosting provider and redeploy.
"LITESTREAM_REPLICA_URL=",
"LITESTREAM_ACCESS_KEY_ID=",
"LITESTREAM_SECRET_ACCESS_KEY=",
# LITESTREAM_ENDPOINT is required for any provider other than AWS S3 (Cloudflare
# R2, Backblaze B2, MinIO, etc.) — set it to that provider's S3-compatible endpoint.
"LITESTREAM_ENDPOINT=",
# LITESTREAM_REGION is optional — only some providers need it.
"LITESTREAM_REGION=",
"TRUSTED_PROXY_CIDRS=",
"FRAME_ANCESTORS=",
"LOG_LEVEL=",
]
mounts = []
[[config.domains]]
serviceName = "calnode"
port = 3_000
host = "${main_domain}"
@@ -0,0 +1,21 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
<rect width="512" height="512" rx="96" fill="#0b1220"/>
<g stroke="#1e2a44" stroke-width="2" opacity="0.7">
<path d="M96 128h320M96 192h320M96 256h320M96 320h320M96 384h320"/>
<path d="M128 96v320M192 96v320M256 96v320M320 96v320M384 96v320"/>
</g>
<g fill="#1f6feb" opacity="0.9">
<rect x="136" y="288" width="40" height="96" rx="6"/>
<rect x="200" y="240" width="40" height="144" rx="6"/>
<rect x="264" y="176" width="40" height="208" rx="6"/>
<rect x="328" y="216" width="40" height="168" rx="6"/>
</g>
<path d="M120 352l64-80 56 24 72-96 80 48" fill="none" stroke="#3fb950" stroke-width="12" stroke-linecap="round" stroke-linejoin="round"/>
<g fill="#3fb950">
<circle cx="120" cy="352" r="12"/>
<circle cx="184" cy="272" r="12"/>
<circle cx="240" cy="296" r="12"/>
<circle cx="312" cy="200" r="12"/>
<circle cx="392" cy="248" r="12"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 999 B

@@ -0,0 +1,57 @@
services:
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.55.1
restart: unless-stopped
privileged: true
devices:
- /dev/kmsg
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
command:
- --housekeeping_interval=15s
- --docker_only=true
node-exporter:
image: prom/node-exporter:v1.12.1
restart: unless-stopped
pid: host
volumes:
- /:/host:ro,rslave
command:
- --path.rootfs=/host
prometheus:
image: prom/prometheus:v3.15.1
restart: unless-stopped
volumes:
- ../files/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus-data:/prometheus
command:
- --config.file=/etc/prometheus/prometheus.yml
- --storage.tsdb.path=/prometheus
- --storage.tsdb.retention.time=30d
grafana:
image: grafana/grafana:13.2.4
restart: unless-stopped
environment:
GF_SECURITY_ADMIN_USER: admin
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD}
GF_USERS_ALLOW_SIGN_UP: "false"
GF_AUTH_ANONYMOUS_ENABLED: "false"
volumes:
- grafana-data:/var/lib/grafana
- ../files/grafana/datasources.yml:/etc/grafana/provisioning/datasources/prometheus.yml:ro
- ../files/grafana/dashboards.yml:/etc/grafana/provisioning/dashboards/provider.yml:ro
- ../files/grafana/cluster-overview.json:/etc/grafana/provisioning/dashboards/cluster-overview.json:ro
- ../files/grafana/container-detail.json:/etc/grafana/provisioning/dashboards/container-detail.json:ro
depends_on:
- prometheus
volumes:
prometheus-data: {}
grafana-data: {}
+23
View File
@@ -0,0 +1,23 @@
{
"id": "container-monitoring",
"name": "Container Monitoring",
"version": "13.2.4",
"description": "Per-container and host monitoring with cAdvisor, node-exporter, Prometheus and Grafana. Ships two ready dashboards: a cluster overview and a container detail view with project/container filters.",
"logo": "container-monitoring.svg",
"links": {
"github": "https://github.com/google/cadvisor",
"website": "https://prometheus.io/",
"docs": "https://prometheus.io/docs/introduction/overview/"
},
"tags": [
"monitoring",
"observability",
"metrics",
"prometheus",
"grafana",
"docker"
],
"seoTitle": "Container Monitoring with Prometheus and Grafana",
"seoDescription": "Self-host cAdvisor, node-exporter, Prometheus and Grafana with Docker Compose on Dokploy. Includes per-container CPU, memory and network dashboards.",
"newConfig": true
}
@@ -0,0 +1,543 @@
[variables]
main_domain = "${domain}"
grafana_admin_password = "${password:24}"
[config.env]
GRAFANA_ADMIN_PASSWORD = "${grafana_admin_password}"
[[config.domains]]
serviceName = "grafana"
port = 3000
host = "${main_domain}"
[[config.mounts]]
filePath = "/prometheus.yml"
content = '''
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: cadvisor
static_configs:
- targets: ["cadvisor:8080"]
- job_name: node
static_configs:
- targets: ["node-exporter:9100"]
'''
[[config.mounts]]
filePath = "/grafana/datasources.yml"
content = '''
apiVersion: 1
datasources:
- name: Prometheus
uid: prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
editable: true
'''
[[config.mounts]]
filePath = "/grafana/dashboards.yml"
content = '''
apiVersion: 1
providers:
- name: containers
orgId: 1
folder: ""
type: file
disableDeletion: false
updateIntervalSeconds: 30
allowUiUpdates: true
options:
path: /etc/grafana/provisioning/dashboards
'''
[[config.mounts]]
filePath = "/grafana/cluster-overview.json"
content = '''
{
"annotations": { "list": [] },
"editable": true,
"graphTooltip": 1,
"links": [],
"panels": [
{
"id": 1,
"type": "stat",
"title": "CPU used",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 5, "w": 4, "x": 0, "y": 0 },
"options": {
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"textMode": "auto",
"orientation": "auto"
},
"fieldConfig": {
"defaults": {
"unit": "percent",
"decimals": 1,
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }, { "color": "yellow", "value": 70 }, { "color": "red", "value": 90 }] }
},
"overrides": []
},
"targets": [
{ "refId": "A", "expr": "100 - (avg(rate(node_cpu_seconds_total{mode=\"idle\"}[$__rate_interval])) * 100)" }
]
},
{
"id": 2,
"type": "stat",
"title": "RAM used",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 5, "w": 4, "x": 4, "y": 0 },
"options": {
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"textMode": "auto",
"orientation": "auto"
},
"fieldConfig": {
"defaults": {
"unit": "bytes",
"decimals": 1,
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }, { "color": "yellow", "value": 70 }, { "color": "red", "value": 90 }] }
},
"overrides": []
},
"targets": [
{ "refId": "A", "expr": "node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes" }
]
},
{
"id": 3,
"type": "stat",
"title": "RAM used %",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 5, "w": 4, "x": 8, "y": 0 },
"options": {
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"textMode": "auto",
"orientation": "auto"
},
"fieldConfig": {
"defaults": {
"unit": "percent",
"decimals": 1,
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }, { "color": "yellow", "value": 70 }, { "color": "red", "value": 90 }] }
},
"overrides": []
},
"targets": [
{ "refId": "A", "expr": "100 * (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)" }
]
},
{
"id": 4,
"type": "stat",
"title": "RAM available",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 5, "w": 4, "x": 12, "y": 0 },
"options": {
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"textMode": "auto",
"orientation": "auto"
},
"fieldConfig": { "defaults": { "unit": "bytes", "decimals": 1 }, "overrides": [] },
"targets": [
{ "refId": "A", "expr": "node_memory_MemAvailable_bytes" }
]
},
{
"id": 5,
"type": "stat",
"title": "Containers",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 5, "w": 4, "x": 16, "y": 0 },
"options": {
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"textMode": "auto",
"orientation": "auto"
},
"fieldConfig": { "defaults": { "unit": "none", "decimals": 0 }, "overrides": [] },
"targets": [
{ "refId": "A", "expr": "count(count by (name) (container_last_seen{name!=\"\"}))" }
]
},
{
"id": 6,
"type": "stat",
"title": "Disk / used",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 5, "w": 4, "x": 20, "y": 0 },
"options": {
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"textMode": "auto",
"orientation": "auto"
},
"fieldConfig": {
"defaults": {
"unit": "percent",
"decimals": 1,
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }, { "color": "yellow", "value": 75 }, { "color": "red", "value": 90 }] }
},
"overrides": []
},
"targets": [
{ "refId": "A", "expr": "100 - (node_filesystem_avail_bytes{mountpoint=\"/\",fstype!~\"tmpfs|overlay\"} / node_filesystem_size_bytes{mountpoint=\"/\",fstype!~\"tmpfs|overlay\"} * 100)" }
]
},
{
"id": 7,
"type": "timeseries",
"title": "Host CPU by mode",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 5 },
"fieldConfig": { "defaults": { "unit": "percent", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
"targets": [
{ "refId": "A", "expr": "avg by (mode) (rate(node_cpu_seconds_total{mode!=\"idle\"}[$__rate_interval])) * 100", "legendFormat": "{{mode}}" }
]
},
{
"id": 8,
"type": "timeseries",
"title": "Host memory",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 5 },
"fieldConfig": { "defaults": { "unit": "bytes", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
"targets": [
{ "refId": "A", "expr": "node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes", "legendFormat": "used" },
{ "refId": "B", "expr": "node_memory_MemAvailable_bytes", "legendFormat": "available" },
{ "refId": "C", "expr": "node_memory_MemTotal_bytes", "legendFormat": "total" }
]
},
{
"id": 9,
"type": "timeseries",
"title": "Container CPU (all)",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 13 },
"fieldConfig": { "defaults": { "unit": "percent", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
"targets": [
{ "refId": "A", "expr": "sum(rate(container_cpu_usage_seconds_total{name!=\"\", cpu=\"total\"}[$__rate_interval])) * 100", "legendFormat": "all containers" }
]
},
{
"id": 10,
"type": "timeseries",
"title": "Container memory (all)",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 13 },
"fieldConfig": { "defaults": { "unit": "bytes", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
"targets": [
{ "refId": "A", "expr": "sum(container_memory_working_set_bytes{name!=\"\"})", "legendFormat": "all containers" }
]
},
{
"id": 11,
"type": "timeseries",
"title": "Container network (all)",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 7, "w": 24, "x": 0, "y": 21 },
"fieldConfig": { "defaults": { "unit": "Bps", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
"targets": [
{ "refId": "A", "expr": "sum(rate(container_network_receive_bytes_total{name!=\"\"}[$__rate_interval]))", "legendFormat": "RX" },
{ "refId": "B", "expr": "sum(rate(container_network_transmit_bytes_total{name!=\"\"}[$__rate_interval]))", "legendFormat": "TX" }
]
},
{
"id": 12,
"type": "table",
"title": "Top containers by memory",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 9, "w": 24, "x": 0, "y": 28 },
"fieldConfig": { "defaults": { "unit": "bytes", "custom": { "align": "auto" } }, "overrides": [] },
"options": { "showHeader": true, "sortBy": [{ "displayName": "Value", "desc": true }] },
"targets": [
{
"refId": "A",
"expr": "topk(10, sum by (name, container_label_com_docker_compose_project) (container_memory_working_set_bytes{name!=\"\"}))",
"instant": true,
"format": "table"
}
]
}
],
"refresh": "30s",
"schemaVersion": 39,
"tags": ["cluster"],
"templating": { "list": [] },
"time": { "from": "now-6h", "to": "now" },
"timezone": "browser",
"title": "Cluster Overview",
"uid": "cluster-overview",
"version": 1
}
'''
[[config.mounts]]
filePath = "/grafana/container-detail.json"
content = '''
{
"annotations": { "list": [] },
"editable": true,
"graphTooltip": 1,
"links": [],
"panels": [
{
"id": 1,
"type": "stat",
"title": "CPU",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 5, "w": 4, "x": 0, "y": 0 },
"options": {
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"textMode": "auto",
"orientation": "auto"
},
"fieldConfig": { "defaults": { "unit": "percent", "decimals": 1, "min": 0 }, "overrides": [] },
"targets": [
{ "refId": "A", "expr": "sum(rate(container_cpu_usage_seconds_total{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\", cpu=\"total\"}[$__rate_interval])) by (name) * 100", "legendFormat": "{{name}}" }
]
},
{
"id": 2,
"type": "stat",
"title": "Memory",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 5, "w": 4, "x": 4, "y": 0 },
"options": {
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"textMode": "auto",
"orientation": "auto"
},
"fieldConfig": { "defaults": { "unit": "bytes", "decimals": 1, "min": 0 }, "overrides": [] },
"targets": [
{ "refId": "A", "expr": "sum(container_memory_working_set_bytes{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}) by (name)", "legendFormat": "{{name}}" }
]
},
{
"id": 3,
"type": "stat",
"title": "RAM % of host",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 5, "w": 4, "x": 8, "y": 0 },
"options": {
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"textMode": "auto",
"orientation": "auto"
},
"fieldConfig": { "defaults": { "unit": "percent", "decimals": 2, "min": 0 }, "overrides": [] },
"targets": [
{ "refId": "A", "expr": "100 * sum(container_memory_working_set_bytes{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}) by (name) / scalar(node_memory_MemTotal_bytes)", "legendFormat": "{{name}}" }
]
},
{
"id": 4,
"type": "stat",
"title": "Network RX",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 5, "w": 4, "x": 12, "y": 0 },
"options": {
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"textMode": "auto",
"orientation": "auto"
},
"fieldConfig": { "defaults": { "unit": "Bps", "decimals": 1, "min": 0 }, "overrides": [] },
"targets": [
{ "refId": "A", "expr": "sum(rate(container_network_receive_bytes_total{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}[$__rate_interval])) by (name)", "legendFormat": "{{name}}" }
]
},
{
"id": 5,
"type": "stat",
"title": "Network TX",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 5, "w": 4, "x": 16, "y": 0 },
"options": {
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
"colorMode": "value",
"graphMode": "area",
"justifyMode": "auto",
"textMode": "auto",
"orientation": "auto"
},
"fieldConfig": { "defaults": { "unit": "Bps", "decimals": 1, "min": 0 }, "overrides": [] },
"targets": [
{ "refId": "A", "expr": "sum(rate(container_network_transmit_bytes_total{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}[$__rate_interval])) by (name)", "legendFormat": "{{name}}" }
]
},
{
"id": 6,
"type": "stat",
"title": "Uptime",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 5, "w": 4, "x": 20, "y": 0 },
"options": {
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
"colorMode": "value",
"graphMode": "none",
"justifyMode": "auto",
"textMode": "auto",
"orientation": "auto"
},
"fieldConfig": { "defaults": { "unit": "s", "decimals": 0, "min": 0 }, "overrides": [] },
"targets": [
{ "refId": "A", "expr": "time() - container_start_time_seconds{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}", "legendFormat": "{{name}}" }
]
},
{
"id": 7,
"type": "timeseries",
"title": "CPU",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 5 },
"fieldConfig": { "defaults": { "unit": "percent", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
"targets": [
{ "refId": "A", "expr": "sum(rate(container_cpu_usage_seconds_total{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\", cpu=\"total\"}[$__rate_interval])) by (name) * 100", "legendFormat": "{{name}}" }
]
},
{
"id": 8,
"type": "timeseries",
"title": "Memory working set",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 5 },
"fieldConfig": { "defaults": { "unit": "bytes", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
"targets": [
{ "refId": "A", "expr": "sum(container_memory_working_set_bytes{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}) by (name)", "legendFormat": "{{name}}" }
]
},
{
"id": 9,
"type": "timeseries",
"title": "Network RX / TX",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 8, "w": 24, "x": 0, "y": 13 },
"fieldConfig": { "defaults": { "unit": "Bps", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
"targets": [
{ "refId": "A", "expr": "sum(rate(container_network_receive_bytes_total{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}[$__rate_interval])) by (name)", "legendFormat": "RX {{name}}" },
{ "refId": "B", "expr": "sum(rate(container_network_transmit_bytes_total{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}[$__rate_interval])) by (name)", "legendFormat": "TX {{name}}" }
]
},
{
"id": 10,
"type": "timeseries",
"title": "Block I/O",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 21 },
"fieldConfig": { "defaults": { "unit": "Bps", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
"targets": [
{ "refId": "A", "expr": "sum(rate(container_fs_reads_bytes_total{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}[$__rate_interval])) by (name)", "legendFormat": "read {{name}}" },
{ "refId": "B", "expr": "sum(rate(container_fs_writes_bytes_total{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}[$__rate_interval])) by (name)", "legendFormat": "write {{name}}" }
]
},
{
"id": 11,
"type": "table",
"title": "Containers",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 21 },
"fieldConfig": { "defaults": { "unit": "bytes", "custom": { "align": "auto" } }, "overrides": [] },
"options": { "showHeader": true },
"targets": [
{
"refId": "A",
"expr": "sum by (name, image, container_label_com_docker_compose_project) (container_memory_working_set_bytes{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"})",
"instant": true,
"format": "table"
}
]
}
],
"refresh": "30s",
"schemaVersion": 39,
"tags": ["containers"],
"templating": {
"list": [
{
"name": "project",
"label": "Project",
"type": "query",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"definition": "label_values(container_last_seen{container_label_com_docker_compose_project!=\"\"}, container_label_com_docker_compose_project)",
"query": {
"query": "label_values(container_last_seen{container_label_com_docker_compose_project!=\"\"}, container_label_com_docker_compose_project)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"multi": true,
"includeAll": true,
"allValue": ".*",
"current": { "selected": true, "text": ["All"], "value": ["$__all"] },
"options": []
},
{
"name": "container",
"label": "Container",
"type": "query",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"definition": "label_values(container_last_seen{container_label_com_docker_compose_project=~\"$project\", name!=\"\"}, name)",
"query": {
"query": "label_values(container_last_seen{container_label_com_docker_compose_project=~\"$project\", name!=\"\"}, name)",
"refId": "StandardVariableQuery"
},
"refresh": 2,
"multi": false,
"includeAll": false,
"current": {},
"options": [],
"sort": 1
}
]
},
"time": { "from": "now-6h", "to": "now" },
"timezone": "browser",
"title": "Container Detail",
"uid": "container-detail",
"version": 1
}
'''
@@ -0,0 +1,13 @@
<svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_10269_2435)">
<path d="M206.222 0H49.7778C22.2863 0 0 22.2863 0 49.7778V206.222C0 233.714 22.2863 256 49.7778 256H206.222C233.714 256 256 233.714 256 206.222V49.7778C256 22.2863 233.714 0 206.222 0Z" fill="white"/>
<path d="M201.697 178.505L175.67 168.424C169.43 166.007 162.039 168.153 156.544 171.971C149.591 176.802 137.646 182.809 118.247 186.566C81.5296 193.677 60.3846 153.139 60.3846 153.139C60.3846 153.139 64.84 196.282 114.909 210.505C164.978 224.727 201.697 178.505 201.697 178.505Z" fill="black"/>
<path d="M161.754 53.5827C161.754 53.5827 98.2194 61.1686 91.5434 110.946C84.8675 160.724 134.937 178.502 134.937 178.502C134.937 178.502 115.366 188.683 95.3394 181.576C75.3116 174.468 64.8398 153.61 64.8398 153.61C64.8398 153.61 41.4738 114.502 74.8537 75.3907C108.233 36.2797 161.754 53.5827 161.754 53.5827Z" fill="black"/>
<path d="M201.672 86.0414L181.054 96.11C172.525 100.275 159.267 88.6796 150.153 86.0293C147.272 85.1916 143.526 84.9392 138.683 85.555C110.719 89.1106 96.0384 103.819 96.0384 103.819C96.0384 103.819 100.233 77.3772 142.179 61.3915C184.124 45.4054 201.672 86.0414 201.672 86.0414Z" fill="black"/>
</g>
<defs>
<clipPath id="clip0_10269_2435">
<rect width="256" height="256" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@@ -0,0 +1,38 @@
services:
customermates:
image: ghcr.io/customermates/customermates:sha-4f4d61c
restart: unless-stopped
depends_on:
customermates-postgres:
condition: service_healthy
environment:
APP_MODE: self-hosted
NODE_ENV: production
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@customermates-postgres:5432/${POSTGRES_DB}
WORKFLOW_TARGET_WORLD: "@workflow/world-postgres"
WORKFLOW_POSTGRES_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@customermates-postgres:5432/${POSTGRES_DB}
BASE_URL: ${BASE_URL}
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
CRON_SECRET: ${CRON_SECRET}
RESEND_API_KEY: ${RESEND_API_KEY}
RESEND_OPERATOR_EMAIL: ${RESEND_OPERATOR_EMAIL}
expose:
- 4000
customermates-postgres:
image: postgres:16.15-alpine
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- customermates-postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 5s
timeout: 5s
retries: 10
volumes:
customermates-postgres-data: {}
+17
View File
@@ -0,0 +1,17 @@
{
"id": "customermates",
"name": "Customermates",
"version": "sha-4f4d61c",
"description": "Customermates is an open-source CRM for contacts, organizations, deals, services and tasks, with a REST API, webhooks and an MCP endpoint for external AI clients. Self-hosted, it runs on PostgreSQL 16 and uses the Starter feature set.",
"logo": "customermates.svg",
"links": {
"github": "https://github.com/customermates/customermates",
"website": "https://customermates.com",
"docs": "https://customermates.com/docs/self-hosting"
},
"tags": [
"crm",
"sales",
"business"
]
}
+23
View File
@@ -0,0 +1,23 @@
[variables]
main_domain = "${domain}"
postgres_password = "${hash:16}"
auth_secret = "${hash:32}"
cron_secret = "${hash:32}"
[config]
mounts = []
[[config.domains]]
serviceName = "customermates"
port = 4000
host = "${main_domain}"
[config.env]
BASE_URL = "http://${main_domain}"
BETTER_AUTH_SECRET = "${auth_secret}"
CRON_SECRET = "${cron_secret}"
POSTGRES_USER = "customermates"
POSTGRES_PASSWORD = "${postgres_password}"
POSTGRES_DB = "customermates"
RESEND_API_KEY = ""
RESEND_OPERATOR_EMAIL = "mail@your-company.com"
+1 -1
View File
@@ -4,7 +4,7 @@
services:
dagu:
image: ghcr.io/dagucloud/dagu:2.10.7
image: ghcr.io/dagucloud/dagu:2.25.4
command: dagu start-all
restart: unless-stopped
expose:
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "dagu",
"name": "Dagu",
"version": "2.10.7",
"version": "2.25.4",
"description": "Dagu is a self-contained workflow engine with a Web UI. Schedule and orchestrate jobs as DAGs defined in declarative YAML, with no DBMS required.",
"logo": "logo.png",
"links": {
-1
View File
@@ -1,4 +1,3 @@
version: "3.8"
services:
docktail:
image: ghcr.io/marvinvr/docktail:1.6.0
+3 -2
View File
@@ -11,9 +11,9 @@ services:
- DATABASE_URL=postgresql://${POSTGRES_USER:-docuseal}:${POSTGRES_PASSWORD}@docu-postgres:5432/${POSTGRES_DB:-docuseal}
docu-postgres:
image: postgres:latest
image: postgres:18
volumes:
- docuseal-db:/var/lib/postgresql/data
- docuseal-db:/var/lib/postgresql
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
@@ -24,6 +24,7 @@ services:
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
docu-redis:
image: redis:alpine
@@ -1,7 +1,7 @@
services:
dokploy-actions-runner:
# Maintained upstream runner, Ubuntu 24.04; multi-architecture index digest.
image: ghcr.io/myoung34/docker-github-actions-runner:2.338.0-ubuntu-noble@sha256:2112bde2ee92b7480babfbe3043d0461e322b97ca01e6ac94698895f3dc1f528
image: ghcr.io/myoung34/docker-github-actions-runner:2.338.2-ubuntu-noble@sha256:23e3a4a1da30de5b462ad0ae13d901288e803a688075c3b9b5bb79b7148c07fa
restart: unless-stopped
user: runner
cap_drop:
@@ -19,6 +19,9 @@ services:
RUNNER_NAME: ${RUNNER_NAME:?Set a unique RUNNER_NAME for each deployment}
LABELS: ${LABELS:?Set comma-separated runner LABELS}
RUNNER_GROUP: ${RUNNER_GROUP:-Default}
# Use the maintained embedded Node24 for shell steps as well as JS actions.
# Keep upstream runtime slots intact; this is not a Node20 binary replacement.
PATH: /actions-runner/externals/node24/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
RUN_AS_ROOT: "false"
START_DOCKER_SERVICE: "false"
DISABLE_AUTOMATIC_DEREGISTRATION: "false"
@@ -26,7 +29,7 @@ services:
# Keep the PAT in the entrypoint shell for shutdown deregistration.
# Upstream un-exports it before starting the listener. See the linked project security guide.
UNSET_CONFIG_VARS: "false"
# Only validates configuration, then execs the upstream lifecycle handler.
# Validates configuration and the runtime floor, then execs upstream lifecycle.
# Inline so Dokploy imports need no custom image or repository file mounts.
# Double dollars defer expansion to the container, not Compose/Dokploy.
entrypoint:
@@ -55,6 +58,14 @@ services:
;;
*) fail 'RUNNER_SCOPE must be exactly repo or org' ;;
esac
# Runtime gate: refuse fallback to distro Node after a runner self-update.
node_binary=/actions-runner/externals/node24/bin/node
[[ -x "$${node_binary}" ]] || fail 'The maintained Node24 runtime is missing; update the image'
[[ "$$(command -v node)" == "$${node_binary}" ]] || fail 'Default node must use the maintained Node24 runtime'
node_version="$$("$${node_binary}" --version)"
[[ "$${node_version}" =~ ^v24\.([0-9]+)\.([0-9]+)$$ ]] || fail 'The maintained Node24 runtime is required'
(( 10#$${BASH_REMATCH[1]} > 22 || (10#$${BASH_REMATCH[1]} == 22 && 10#$${BASH_REMATCH[2]} >= 1) )) || fail 'Node24 is below the security baseline; update the image'
# End runtime gate.
exec /entrypoint.sh ./bin/Runner.Listener run --startuptype service
# Local listener liveness only; does not prove GitHub connectivity/readiness.
healthcheck:
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "dokploy-actions-runner",
"name": "GitHub Actions Runner",
"version": "2.338.0-ubuntu-noble",
"version": "2.338.2-ubuntu-noble",
"description": "Self-hosted GitHub Actions runner for repositories or organizations, with independent names, labels and runner groups. Runs without privileged mode or Docker socket access.",
"logo": "logo.svg",
"links": {
+2 -1
View File
@@ -1,6 +1,6 @@
services:
dossier:
image: ghcr.io/aientech/dossier:v1.5.0
image: ghcr.io/aientech/dossier:v1.9.0
restart: unless-stopped
env_file:
- path: .env
@@ -14,6 +14,7 @@ services:
DOSSIER_SECRET: "${DOSSIER_SECRET:?Keep the generated DOSSIER_SECRET}"
DOSSIER_DATA_DIR: /data
DOSSIER_TELEMETRY: "${DOSSIER_TELEMETRY:-off}"
DOSSIER_JOBS_ARBEITSAGENTUR: "${DOSSIER_JOBS_ARBEITSAGENTUR:-off}"
DOSSIER_BACKUP_RETENTION_DAYS: "${DOSSIER_BACKUP_RETENTION_DAYS:-14}"
TZ: "${TZ:-UTC}"
command:
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "dossier",
"name": "Dossier",
"version": "v1.5.0",
"version": "v1.9.0",
"description": "Dossier is a personal job search app with a career profile, resume and cover letter drafting, PDF export, and an application tracking board. It supports local and hosted AI providers.",
"logo": "dossier.svg",
"links": {
@@ -1,4 +1,3 @@
version: "3.8"
services:
emaki-video-starter:
image: san8888/emaki-video-starter:1.0.0
-2
View File
@@ -1,5 +1,3 @@
version: "3.8"
services:
heyo-docs:
build:
+182
View File
@@ -0,0 +1,182 @@
# Dokploy template for the Community edition of It's a Plan.
# Dokploy routes the api and web services through its proxy, so this file uses
# expose instead of publishing host ports.
services:
postgres:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER:-itsaplan}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in Dokploy}
POSTGRES_DB: ${POSTGRES_DB:-itsaplan}
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test:
[
"CMD-SHELL",
"pg_isready -U ${POSTGRES_USER:-itsaplan} -d ${POSTGRES_DB:-itsaplan}",
]
interval: 5s
timeout: 5s
retries: 10
minio:
image: rustfs/rustfs:1.0.0
restart: unless-stopped
environment:
RUSTFS_ACCESS_KEY: ${S3_ACCESS_KEY_ID:?set S3_ACCESS_KEY_ID in Dokploy}
RUSTFS_SECRET_KEY: ${S3_SECRET_ACCESS_KEY:?set S3_SECRET_ACCESS_KEY in Dokploy}
volumes:
- minio-data:/data
healthcheck:
test:
[
"CMD",
"curl",
"-fsS",
"-o",
"/dev/null",
"http://127.0.0.1:9000/health",
]
interval: 15s
timeout: 5s
retries: 5
start_period: 20s
minio-init:
image: rustfs/rustfs:1.0.0
restart: "no"
depends_on:
minio:
condition: service_healthy
environment:
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID}
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY}
S3_BUCKET: ${S3_BUCKET:-planner-attachments}
entrypoint:
- /bin/sh
- -c
- >-
curl -fsS -X PUT --aws-sigv4 aws:amz:us-east-1:s3
--user "$$S3_ACCESS_KEY_ID:$$S3_SECRET_ACCESS_KEY"
"http://minio:9000/$$S3_BUCKET" &&
echo "bucket ready: $$S3_BUCKET"
migrate:
image: ghcr.io/croffasia/itsaplan-api:1.9.0
restart: "no"
command: ["bun", "run", "packages/db/src/migrate.ts"]
depends_on:
postgres:
condition: service_healthy
environment:
DATABASE_URL: postgres://${POSTGRES_USER:-itsaplan}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-itsaplan}
BACKUP_RETENTION_DAYS: ${BACKUP_RETENTION_DAYS:-30}
SKIP_PRE_MIGRATION_BACKUP: ${SKIP_PRE_MIGRATION_BACKUP:-}
volumes:
- db-backups:/backups
api:
image: ghcr.io/croffasia/itsaplan-api:1.9.0
restart: unless-stopped
command: ["bun", "run", "apps/api/src/index.ts"]
depends_on:
postgres:
condition: service_healthy
migrate:
condition: service_completed_successfully
minio-init:
condition: service_completed_successfully
environment:
NODE_ENV: production
API_PORT: 3000
DATABASE_URL: postgres://${POSTGRES_USER:-itsaplan}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-itsaplan}
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET:?set BETTER_AUTH_SECRET in Dokploy}
APP_ENCRYPTION_KEY: ${APP_ENCRYPTION_KEY:?set APP_ENCRYPTION_KEY in Dokploy}
API_URL: ${API_URL:?set API_URL in Dokploy}
APP_URL: ${APP_URL:?set APP_URL in Dokploy}
COOKIE_DOMAIN: ${COOKIE_DOMAIN:-}
CLIENT_IP_HEADER: ${CLIENT_IP_HEADER:-}
TRUSTED_PROXIES: ${TRUSTED_PROXIES:-}
GIT_WEBHOOK_BASE_URL: ${GIT_WEBHOOK_BASE_URL:-}
S3_ENDPOINT: http://minio:9000
S3_BUCKET: ${S3_BUCKET:-planner-attachments}
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:?set S3_ACCESS_KEY_ID in Dokploy}
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:?set S3_SECRET_ACCESS_KEY in Dokploy}
S3_REGION: ${S3_REGION:-us-east-1}
S3_FORCE_PATH_STYLE: ${S3_FORCE_PATH_STYLE:-true}
SSRF_ALLOWED_HOSTS: ${SSRF_ALLOWED_HOSTS:-}
healthcheck:
test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:3000/"]
interval: 15s
timeout: 5s
retries: 5
start_period: 30s
expose:
- "3000"
worker:
image: ghcr.io/croffasia/itsaplan-worker:1.9.0
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
migrate:
condition: service_completed_successfully
environment:
NODE_ENV: production
DATABASE_URL: postgres://${POSTGRES_USER:-itsaplan}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-itsaplan}
APP_ENCRYPTION_KEY: ${APP_ENCRYPTION_KEY:?set APP_ENCRYPTION_KEY in Dokploy}
TELEMETRY_DISABLED: ${TELEMETRY_DISABLED:-}
DO_NOT_TRACK: ${DO_NOT_TRACK:-}
TELEMETRY_DEBUG: ${TELEMETRY_DEBUG:-}
SSRF_ALLOWED_HOSTS: ${SSRF_ALLOWED_HOSTS:-}
S3_ENDPOINT: http://minio:9000
S3_BUCKET: ${S3_BUCKET:-planner-attachments}
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:?set S3_ACCESS_KEY_ID in Dokploy}
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:?set S3_SECRET_ACCESS_KEY in Dokploy}
S3_REGION: ${S3_REGION:-us-east-1}
S3_FORCE_PATH_STYLE: ${S3_FORCE_PATH_STYLE:-true}
bot:
image: ghcr.io/croffasia/itsaplan-bot:1.9.0
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
migrate:
condition: service_completed_successfully
environment:
NODE_ENV: production
DATABASE_URL: postgres://${POSTGRES_USER:-itsaplan}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-itsaplan}
APP_ENCRYPTION_KEY: ${APP_ENCRYPTION_KEY:?set APP_ENCRYPTION_KEY in Dokploy}
web:
image: ghcr.io/croffasia/itsaplan-web:1.9.0
restart: unless-stopped
depends_on:
- api
environment:
NODE_ENV: production
PORT: 3001
HOSTNAME: 0.0.0.0
API_URL: ${API_URL:?set API_URL in Dokploy}
SERVICE_URL_API: http://api:3000
PRIVACY_URL: ${PRIVACY_URL:-}
TERMS_URL: ${TERMS_URL:-}
healthcheck:
test:
["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:3001/login"]
interval: 15s
timeout: 5s
retries: 5
start_period: 20s
expose:
- "3001"
volumes:
postgres-data: {}
minio-data: {}
db-backups: {}
+8
View File
@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 32 32">
<rect width="32" height="32" rx="7" fill="#08090a"/>
<g transform="translate(4 4) scale(0.75)" fill="none">
<rect x="13" y="14.3" width="6" height="3.4" rx="1.7" fill="#fbfbfa" opacity="0.4"/>
<circle cx="9.5" cy="16" r="6" fill="#fbfbfa"/>
<rect x="17" y="10.5" width="11" height="11" rx="3.4" stroke="#fbfbfa" stroke-width="3"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 447 B

+15
View File
@@ -0,0 +1,15 @@
{
"id": "itsaplan",
"name": "It's a Plan",
"version": "1.9.0",
"description": "It's a Plan is an open-source project management and issue tracking platform where people and AI agents work together.",
"logo": "itsaplan.svg",
"links": {
"github": "https://github.com/croffasia/itsaplan",
"website": "https://itsaplan.dev",
"docs": "https://github.com/croffasia/itsaplan/blob/main/docs/self-hosting.md"
},
"tags": ["project-management", "issue-tracking", "ai"],
"seoTitle": "Self-host It's a Plan with Dokploy",
"seoDescription": "Deploy the open-source project management and issue tracking platform It's a Plan with Dokploy."
}
+36
View File
@@ -0,0 +1,36 @@
[variables]
main_domain = "${domain}"
api_domain = "api.${main_domain}"
postgres_password = "${password:32}"
auth_secret = "${base64:32}"
encryption_key = "${base64:32}"
s3_access_key = "${username}"
s3_secret_key = "${password:32}"
[config]
env = [
"POSTGRES_USER=itsaplan",
"POSTGRES_PASSWORD=${postgres_password}",
"POSTGRES_DB=itsaplan",
"BETTER_AUTH_SECRET=${auth_secret}",
"APP_ENCRYPTION_KEY=${encryption_key}",
"API_URL=https://${api_domain}",
"APP_URL=https://${main_domain}",
"S3_BUCKET=planner-attachments",
"S3_ACCESS_KEY_ID=${s3_access_key}",
"S3_SECRET_ACCESS_KEY=${s3_secret_key}",
"S3_REGION=us-east-1",
"S3_FORCE_PATH_STYLE=true",
"BACKUP_RETENTION_DAYS=30",
]
mounts = []
[[config.domains]]
serviceName = "api"
port = 3000
host = "${api_domain}"
[[config.domains]]
serviceName = "web"
port = 3001
host = "${main_domain}"
+1 -1
View File
@@ -1,6 +1,6 @@
services:
junctio:
image: ghcr.io/k2so-dev/junctio:0.2.1
image: ghcr.io/k2so-dev/junctio:0.2.6
restart: unless-stopped
expose:
- 3000
+3 -3
View File
@@ -1,13 +1,13 @@
{
"id": "junctio",
"name": "Junctio",
"version": "0.2.1",
"version": "0.2.6",
"description": "Self-hosted MCP gateway that puts stdio, Docker and remote MCP servers behind one endpoint per client, with API key or OAuth downstream auth and upstream tokens refreshed before they expire.",
"logo": "logo.png",
"links": {
"github": "https://github.com/k2so-dev/junctio",
"website": "https://junctio.pages.dev",
"docs": "https://junctio.pages.dev/docs/"
"website": "https://junctio.org",
"docs": "https://junctio.org/docs/"
},
"tags": [
"ai",
File diff suppressed because one or more lines are too long
+18
View File
@@ -0,0 +1,18 @@
# Kortix Setup Instructions
## Deploy
1. Create the service from the **Kortix** template. Dokploy generates the database password, JWT secret and secret seed, and three domains (app, API, Supabase gateway).
2. In the service's **Environment** tab, replace each `REPLACE_ME`:
- `PLATINUM_API_KEY`: Platinum API key. Kortix agents run in Platinum cloud sandboxes; get a key at https://platinum.dev.
- `KORTIX_ADMIN_EMAIL`: Email of the first admin. Sign up with this address right after the deploy finishes.
3. In the **Domains** tab, edit each of the three domains (frontend, api, kong), turn on **HTTPS** and choose **Let's Encrypt**. The template's addresses use `https://`; if you swap in your own domains, update `PUBLIC_URL`, `API_PUBLIC_URL` and `SUPABASE_PUBLIC_URL` to match.
4. Deploy and wait until every container is healthy. The first deploy takes a few minutes while the images download and Postgres initializes.
## After the first deploy
1. Open the Kortix app's address and **sign up with the admin email** right away.
2. Signed in as the admin, open **`/admin/git`** and connect GitHub. Install the GitHub App on an organization so Kortix can create project repos. On a personal account, create each repo on GitHub first, then import it.
3. Add your model key in **Settings → Model**.
4. Create a project and give an agent its first task.
5. To stop others from signing up, set `DISABLE_SIGNUP=true` and redeploy.
+3
View File
@@ -0,0 +1,3 @@
<svg width="30" height="25" viewBox="0 0 30 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M25.5614 24.916H29.8268C29.8268 19.6306 26.9378 15.0039 22.6171 12.4587C26.9377 9.91355 29.8267 5.28685 29.8267 0.00146484H25.5613C25.5613 5.00287 21.8906 9.18692 17.0654 10.1679V0.00146484H12.8005V10.1679C7.9526 9.20401 4.3046 5.0186 4.3046 0.00146484H0.0391572C0.0391572 5.28685 2.92822 9.91355 7.24884 12.4587C2.92818 15.0039 0.0390625 19.6306 0.0390625 24.916H4.30451C4.30451 19.8989 7.95259 15.7135 12.8005 14.7496V24.9206H17.0654V14.7496C21.9133 15.7134 25.5614 19.8989 25.5614 24.916Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 620 B

+20
View File
@@ -0,0 +1,20 @@
{
"id": "kortix",
"name": "Kortix",
"version": "0.14.19",
"description": "Kortix is an open source AI Operating System: AI agents that do real work for your team, with your own models and tools. Self-host it on your own server with Dokploy in a few clicks.",
"logo": "kortix.svg",
"links": {
"github": "https://github.com/kortix-ai/suna",
"website": "https://kortix.com",
"docs": "https://kortix.com/docs/developers#self-hosting"
},
"tags": [
"ai",
"agents",
"automation",
"self-hosted"
],
"seoTitle": "Kortix: Self-Hosted AI Agents & Docker Compose",
"seoDescription": "Open source AI agents for your team. Self-host Kortix via Docker Compose on Dokploy: your data, your model keys."
}
+38
View File
@@ -0,0 +1,38 @@
[variables]
main_domain = "${domain}"
api_domain = "${domain}"
supabase_domain = "${domain}"
postgres_password = "${password:64}"
jwt_secret = "${password:128}"
kortix_secret_seed = "${password:64}"
[config]
env = [
"POSTGRES_PASSWORD=${postgres_password}",
"JWT_SECRET=${jwt_secret}",
"KORTIX_SECRET_SEED=${kortix_secret_seed}",
"PUBLIC_URL=https://${main_domain}",
"API_PUBLIC_URL=https://${api_domain}",
"SUPABASE_PUBLIC_URL=https://${supabase_domain}",
"PLATINUM_API_KEY=REPLACE_ME",
"KORTIX_ADMIN_EMAIL=REPLACE_ME",
"DISABLE_SIGNUP=false",
"EMAIL_URL=",
"EMAIL_FROM=",
"COMPOSIO_API_KEY=",
]
[[config.domains]]
serviceName = "frontend"
port = 3000
host = "${main_domain}"
[[config.domains]]
serviceName = "api"
port = 8008
host = "${api_domain}"
[[config.domains]]
serviceName = "kong"
port = 8000
host = "${supabase_domain}"
+1 -1
View File
@@ -1,6 +1,6 @@
services:
legejo:
image: slurvdjur/legejo:1.23.1
image: slurvdjur/legejo:1.33.0
restart: unless-stopped
expose:
- "3000"
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "legejo",
"name": "Legejo",
"version": "1.23.1",
"version": "1.33.0",
"description": "Legejo is a self-hosted library for your EPUB books, with a web reader, Kobo sync, OPDS for reading apps, KOReader progress sync, shared shelves and audiobooks. Runs on SQLite with no other services needed.",
"logo": "legejo.svg",
"links": {
+6 -2
View File
@@ -13,19 +13,23 @@ host = "${main_domain}"
# An empty value counts as unset.
[config.env]
# The first admin account, created on the first start; sign in with these.
# (Left empty, the first visitor would create it in the browser instead.)
LEGEJO_ADMIN_USER = "admin"
LEGEJO_ADMIN_PASSWORD = "${admin_password}"
# Change to https:// once the domain has a certificate: session cookies are
# then marked Secure, and federation and mailed links use it.
LEGEJO_PUBLIC_URL = "http://${main_domain}"
# Mail, for self-registration, invitations and password reset.
# Mail, for self-registration, invitations and password reset. Empty: it can
# be set up on Legejo's Admin page instead, with a test mail.
LEGEJO_SMTP_HOST = ""
LEGEJO_SMTP_PORT = "587"
LEGEJO_SMTP_USER = ""
LEGEJO_SMTP_PASSWORD = ""
LEGEJO_MAIL_FROM = ""
# Searching inside the books; keeps the text of the EPUBs in the database.
LEGEJO_FULLTEXT = "false"
# Empty: switched on and off on Legejo's Admin page. "true" or "false" here
# fixes it, and the Admin page shows it as set by the environment.
LEGEJO_FULLTEXT = ""
# Read-only MCP server for AI assistants at /api/mcp.
LEGEJO_MCP = "false"
# The librarian: book suggestions from an OpenAI-compatible language model.
+1 -1
View File
@@ -1,6 +1,6 @@
services:
libredb-studio:
image: ghcr.io/libredb/libredb-studio:1.0.0
image: ghcr.io/libredb/libredb-studio:1.2.0
restart: unless-stopped
environment:
# Since 0.18.0 ADMIN_PASSWORD and USER_PASSWORD seed the account table only
+2 -2
View File
@@ -1,8 +1,8 @@
{
"id": "libredb-studio",
"name": "LibreDB Studio",
"version": "1.0.0",
"description": "The open-source SQL IDE you host yourself. Query PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Redis, ClickHouse, Cassandra and more from your browser, twenty-seven drivers reaching fifty-four named engines.",
"version": "1.2.0",
"description": "The open-source SQL IDE you host yourself. Query PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Redis, ClickHouse, Cassandra and more from your browser, forty-two drivers reaching sixty-nine named engines.",
"logo": "libredb-studio.svg",
"links": {
"github": "https://github.com/libredb/libredb-studio",
+44
View File
@@ -0,0 +1,44 @@
services:
maintenant:
image: nginxinc/nginx-unprivileged:1.29-alpine
restart: unless-stopped
read_only: true
security_opt:
- no-new-privileges:true
tmpfs:
- /tmp:noexec,nosuid,size=16m
entrypoint:
- /bin/sh
- -c
- printf '%s:{PLAIN}%s\n' "$$AUTH_USER" "$$AUTH_PASSWORD" > /tmp/htpasswd && exec nginx -g 'daemon off;'
environment:
AUTH_USER: ${AUTH_USER}
AUTH_PASSWORD: ${AUTH_PASSWORD}
volumes:
- ../files/default.conf:/etc/nginx/conf.d/default.conf:ro
expose:
- 8080
depends_on:
- maintenant-app
maintenant-app:
image: ghcr.io/kolapsis/maintenant:1.10.1
restart: unless-stopped
read_only: true
security_opt:
- no-new-privileges:true
tmpfs:
- /tmp:noexec,nosuid,size=64m
volumes:
- maintenant-data:/data
- /var/run/docker.sock:/var/run/docker.sock:ro
- /proc:/host/proc:ro
- /etc/os-release:/host/etc/os-release:ro
environment:
MAINTENANT_ADDR: 0.0.0.0:8080
MAINTENANT_DB: /data/maintenant.db
MAINTENANT_BASE_URL: ${MAINTENANT_BASE_URL}
MAINTENANT_TRUSTED_PROXIES: 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
volumes:
maintenant-data: {}
+17
View File
@@ -0,0 +1,17 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32">
<defs>
<linearGradient id="sig" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#3ECF8E;stop-opacity:0.5"/>
<stop offset="60%" style="stop-color:#3ECF8E"/>
<stop offset="100%" style="stop-color:#22D3EE;stop-opacity:0.7"/>
</linearGradient>
<filter id="gl">
<feGaussianBlur stdDeviation="1.2" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<rect width="32" height="32" rx="7" fill="#12151C"/>
<polyline points="6,25 6,7 16,20 26,7 26,25" fill="none" stroke="url(#sig)" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" filter="url(#gl)"/>
<line x1="26" y1="25" x2="28.5" y2="25" stroke="#3ECF8E" stroke-width="2" stroke-linecap="round" opacity="0.3"/>
<circle cx="30" cy="25" r="1.5" fill="#3ECF8E"/>
</svg>

After

Width:  |  Height:  |  Size: 944 B

+17
View File
@@ -0,0 +1,17 @@
{
"id": "maintenant",
"name": "maintenant",
"version": "1.10.1",
"description": "Self-hosted monitoring for Docker, Swarm and Kubernetes in a single Go binary that uses about 100 MB of RAM. maintenant has no login of its own, so this template puts an nginx basic-auth proxy in front of it: the user is admin and the password is the AUTH_PASSWORD variable in the Environment tab. Heartbeat pings and the public status page stay reachable without auth.",
"logo": "logo.svg",
"links": {
"github": "https://github.com/kolapsis/maintenant",
"website": "https://maintenant.dev",
"docs": "https://docs.maintenant.dev/"
},
"tags": [
"monitoring",
"docker",
"alerts"
]
}
+40
View File
@@ -0,0 +1,40 @@
[variables]
main_domain = "${domain}"
auth_password = "${password:32}"
[config]
[[config.domains]]
serviceName = "maintenant"
port = 8080
host = "${main_domain}"
[config.env]
AUTH_USER = "admin"
AUTH_PASSWORD = "${auth_password}"
MAINTENANT_BASE_URL = "https://${main_domain}"
[[config.mounts]]
filePath = "/default.conf"
content = """
server {
listen 8080;
server_name _;
auth_basic "maintenant";
auth_basic_user_file /tmp/htpasswd;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
location ~ ^/((ping|status|assets|screenshots)(/|$)|workbox-|favicon|icon|(sw|registerSW)[.]js$|manifest[.]webmanifest$|apple-touch-icon[.]png$|logo[.]svg$) {
auth_basic off;
proxy_pass http://maintenant-app:8080;
}
location / {
proxy_pass http://maintenant-app:8080;
}
}
"""
+60
View File
@@ -0,0 +1,60 @@
services:
db:
image: timescale/timescaledb:2.30.1-pg17
restart: unless-stopped
environment:
POSTGRES_USER: mcpspan
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: mcpspan
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -h 127.0.0.1 -U mcpspan -d mcpspan"]
interval: 5s
timeout: 5s
retries: 10
migrate:
image: ghcr.io/mcpspan/core-api:0.13.0
restart: "no"
depends_on:
db:
condition: service_healthy
environment:
DATABASE_URL: postgres://mcpspan:${POSTGRES_PASSWORD}@db:5432/mcpspan
command: ["./node_modules/.bin/node-pg-migrate", "up"]
api:
image: ghcr.io/mcpspan/core-api:0.13.0
restart: unless-stopped
depends_on:
migrate:
condition: service_completed_successfully
environment:
DATABASE_URL: postgres://mcpspan:${POSTGRES_PASSWORD}@db:5432/mcpspan
PORT: 6271
API_KEY_SECRET: ${API_KEY_SECRET}
MCPSPAN_DASHBOARD_URL: ${MCPSPAN_DASHBOARD_URL}
expose:
- 6271
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:6271/health').then(r=>process.exit(r.ok?0:1),()=>process.exit(1))"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
dashboard:
image: ghcr.io/mcpspan/core-dashboard:0.13.0
restart: unless-stopped
depends_on:
api:
condition: service_healthy
environment:
CORE_API_URL: http://api:6271
MCPSPAN_INGEST_URL: ${MCPSPAN_INGEST_URL}
expose:
- 6270
volumes:
db-data: {}
+7
View File
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
<rect width="64" height="64" rx="14" fill="#23262b"/>
<path d="M17 23.5Q19.5 29.5 25.5 32Q19.5 34.5 17 40.5Q14.5 34.5 8.5 32Q14.5 29.5 17 23.5Z" fill="#fff" stroke="#fff" stroke-width="2.5" stroke-linejoin="round"/>
<rect x="30" y="16" width="22" height="7" rx="3.5" fill="#8a9099"/>
<rect x="30" y="28.5" width="16" height="7" rx="3.5" fill="#2a78d6"/>
<rect x="30" y="41" width="26" height="7" rx="3.5" fill="#8a9099"/>
</svg>

After

Width:  |  Height:  |  Size: 500 B

+17
View File
@@ -0,0 +1,17 @@
{
"id": "mcpspan",
"name": "mcpspan",
"version": "0.13.0",
"description": "mcpspan is open-source analytics for MCP servers: which tools agents call, how often they fail and why, which clients call them, and how fast they answer. Add one line with an SDK in any of eight languages, or none at all behind its proxy, and see it in the dashboard. Parameter values never leave your server.",
"logo": "mcpspan.svg",
"links": {
"github": "https://github.com/mcpspan/mcpspan",
"website": "https://mcpspan.com",
"docs": "https://mcpspan.com/docs/self-hosting/"
},
"tags": [
"analytics",
"monitoring",
"mcp"
]
}
+27
View File
@@ -0,0 +1,27 @@
[variables]
main_domain = "${domain}"
api_domain = "${domain}"
[config]
mounts = []
# The dashboard, where you sign in.
[[config.domains]]
serviceName = "dashboard"
port = 6270
host = "${main_domain}"
# Where your MCP servers send their calls, with the API key from the dashboard.
[[config.domains]]
serviceName = "api"
port = 6271
host = "${api_domain}"
[config.env]
POSTGRES_PASSWORD = "${password:32}"
# Signs API keys; changing it later invalidates every key issued.
API_KEY_SECRET = "${base64:48}"
# The address the dashboard's setup snippet tells MCP servers to send to.
MCPSPAN_INGEST_URL = "http://${api_domain}"
# Where MCP clients that sign in to the API's /mcp (claude.ai, Claude Code...) send people to allow them.
MCPSPAN_DASHBOARD_URL = "http://${main_domain}"
+13 -11
View File
@@ -1,16 +1,9 @@
services:
navi-music:
# 4.1.0 is the newest release that can boot without a YouTube OAuth2 refresh
# token; 4.1.1+ throws at startup ("YouTube OAuth token is mandatory") unless
# a valid token obtained via an interactive device-code flow is provided, so
# newer tags can never boot with template defaults.
image: anvian/navi-music:4.1.0
image: ghcr.io/andre-carbajal/navimusic:4.3.0
restart: unless-stopped
# NaviMusic logs (rather than throws) when DISCORD_TOKEN is empty or invalid,
# then exits 0 because no JDA threads keep the JVM alive. Keep the container
# running in that case so first-time users see the instructions in the logs
# instead of a restart loop; real crashes (non-zero exits) still propagate to
# the restart policy.
depends_on:
- yt-cipher
entrypoint:
- sh
- -c
@@ -18,7 +11,7 @@ services:
java $$JAVA_OPTS -jar /app/NaviMusic.jar nogui --spring.profiles.active=prod;
code=$$?;
if [ "$$code" -eq 0 ]; then
echo "NaviMusic is idle. Set DISCORD_TOKEN (and optionally Spotify/YouTube credentials) in the Environment tab, then redeploy.";
echo "NaviMusic is idle. Set DISCORD_TOKEN and required YouTube credentials in the Environment tab, then redeploy.";
tail -f /dev/null;
fi;
exit $$code
@@ -29,3 +22,12 @@ services:
YOUTUBE_POTOKEN: ${YOUTUBE_POTOKEN}
YOUTUBE_VISITOR: ${YOUTUBE_VISITOR}
YOUTUBE_OAUTH2: ${YOUTUBE_OAUTH2}
YOUTUBE_CIPHER_URL: http://yt-cipher:8001
YOUTUBE_CIPHER_PASSWORD: ${YOUTUBE_CIPHER_PASSWORD}
yt-cipher:
image: ghcr.io/kikkia/yt-cipher:master@sha256:4c5ec381ff57336cfc24822d2b526a5ad7cd0171f61065a1bbc87bb736842449
restart: unless-stopped
environment:
OVERRIDE_PLAYER_VARIANT: IAS
API_TOKEN: ${YOUTUBE_CIPHER_PASSWORD}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "navi-music",
"name": "NaviMusic",
"version": "4.1.0",
"version": "4.3.0",
"description": "A Discord music bot that plays YouTube and Spotify tracks and playlists in voice channels.",
"logo": "navi-music.png",
"links": {
+5 -2
View File
@@ -5,8 +5,11 @@ env = [
# Optional but recommended for Spotify links: https://developer.spotify.com/dashboard
"SPOTIFY_CLIENT_ID=",
"SPOTIFY_CLIENT_SECRET=",
# Optional YouTube tweaks (leave empty to use the default anonymous clients).
# YouTube OAuth2 refresh token is required by current NaviMusic versions.
"YOUTUBE_OAUTH2=",
# Optional YouTube tweaks.
"YOUTUBE_POTOKEN=",
"YOUTUBE_VISITOR=",
"YOUTUBE_OAUTH2=",
# Shared secret for the internal yt-cipher service.
"YOUTUBE_CIPHER_PASSWORD=${password:32}",
]
-1
View File
@@ -1,7 +1,6 @@
# dokploy: allow-host-ports
# LiveKit requires public TCP/UDP media ports 7881 and 7882 for WebRTC.
# Dokploy owns routing and the isolated network.
version: "3.8"
services:
frontend:
build:
-2
View File
@@ -1,5 +1,3 @@
version: "3.8"
services:
opendots:
build:
+22
View File
@@ -0,0 +1,22 @@
services:
opentodo:
image: ghcr.io/opentodoapp/opentodo:0.19.0
restart: unless-stopped
expose:
- 8080
environment:
- OPENTODO_BASE_URL=${OPENTODO_BASE_URL:-}
- OPENTODO_SETUP_TOKEN=${OPENTODO_SETUP_TOKEN:-}
- OPENTODO_ALLOW_SIGNUP=${OPENTODO_ALLOW_SIGNUP:-false}
- OPENTODO_TRUSTED_PROXIES=${OPENTODO_TRUSTED_PROXIES:-}
volumes:
- opentodo-data:/data
healthcheck:
test: ["CMD", "/opentodo", "healthcheck"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
volumes:
opentodo-data:
+18
View File
@@ -0,0 +1,18 @@
{
"id": "opentodo",
"name": "OpenTodo",
"version": "0.19.0",
"description": "Open-source, local-first task manager. Works offline and syncs every device from one small container.",
"logo": "opentodo.svg",
"links": {
"github": "https://github.com/OpenTodoApp/OpenTodo",
"website": "https://open-todo.app",
"docs": "https://open-todo.app/docs/self-hosting/dokploy/"
},
"tags": [
"productivity",
"tasks",
"todo",
"self-hosted"
]
}
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img"><title>OpenTodo</title><!-- OpenTodo brand mark. Part of OpenTodo, AGPL-3.0 (see LICENSE). --><rect width="64" height="64" rx="14" fill="#0f172a"/><g transform="translate(8 6) scale(2)" fill="none" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"><path d="M19.73 10.93A8 8 0 1 1 12.7 5.03" stroke="#34d399"/><path d="M8 13l3 3" stroke="#ffffff"/><path d="M11 16l9-9" stroke="#34d399"/></g></svg>

After

Width:  |  Height:  |  Size: 484 B

+20
View File
@@ -0,0 +1,20 @@
[variables]
main_domain = "${domain}"
setup_token = "${password:32}"
[config]
mounts = []
[[config.domains]]
serviceName = "opentodo"
port = 8080
host = "${main_domain}"
[config.env]
# Empty while the domain is plain http (an https value there breaks sign-in).
# Once the domain has HTTPS, set https://<your domain> and redeploy.
OPENTODO_BASE_URL = ""
# Asked for when you create the owner account on the first visit.
OPENTODO_SETUP_TOKEN = "${setup_token}"
OPENTODO_ALLOW_SIGNUP = "false"
OPENTODO_TRUSTED_PROXIES = ""
+9 -1
View File
@@ -1,7 +1,10 @@
services:
openwa:
image: ghcr.io/rmyndharis/openwa:0.24.0
image: ghcr.io/rmyndharis/openwa:0.25.0
restart: unless-stopped
# Bounded teardown: drain + engines + webhook flush + queue closes can take up to
# 63s in the worst case; the process force-exits after 67s.
stop_grace_period: 75s
# Hardened runtime matching the upstream production defaults: Chromium (used by the
# whatsapp-web.js engine) launches with --no-sandbox, so the container is the confinement
# boundary. The caps that remain are only what the entrypoint needs to fix named-volume
@@ -37,6 +40,11 @@ services:
# Off by default so the template works over HTTP or HTTPS; set "true" when you only ever reach
# it through a TLS-terminating proxy.
- CSP_UPGRADE_INSECURE_REQUESTS=${CSP_UPGRADE_INSECURE_REQUESTS}
# MCP server at POST /mcp. Read-only unless MCP_READONLY is explicitly "false".
- MCP_ENABLED=${MCP_ENABLED}
- MCP_READONLY=${MCP_READONLY}
# Swagger UI at /api/docs; enabled here despite the production default.
- ENABLE_SWAGGER=${ENABLE_SWAGGER}
expose:
- "2785"
volumes:
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "openwa",
"name": "OpenWA",
"version": "0.24.0",
"version": "0.25.0",
"description": "OpenWA is a free, self-hosted WhatsApp API gateway with a REST API, webhooks, multi-session support, and a bundled web dashboard.",
"logo": "openwa.svg",
"links": {
+10
View File
@@ -6,6 +6,13 @@ timezone = "UTC"
# Set to "true" only when the dashboard is reached exclusively through a TLS-terminating proxy.
# Left "false" so the bundled SPA loads over plain HTTP (see comments in docker-compose.yml).
csp_upgrade_insecure_requests = "false"
# The MCP server is opt-in upstream. Enabled here so the template exposes POST /mcp by default.
# Read-only is the upstream-recommended default; set to "false" to mount the write tools too.
mcp_enabled = "true"
mcp_readonly = "true"
# Swagger UI at /api/docs. Upstream disables it under NODE_ENV=production by default.
# Note: the docs mount is not behind the API-key guard, so it exposes the schema publicly.
enable_swagger = "true"
[config]
env = [
@@ -15,6 +22,9 @@ env = [
"AUTO_START_SESSIONS=${auto_start_sessions}",
"TZ=${timezone}",
"CSP_UPGRADE_INSECURE_REQUESTS=${csp_upgrade_insecure_requests}",
"MCP_ENABLED=${mcp_enabled}",
"MCP_READONLY=${mcp_readonly}",
"ENABLE_SWAGGER=${enable_swagger}",
]
mounts = []
-1
View File
@@ -227,4 +227,3 @@ volumes:
postgres: null
redis: null
storage: null
version: '3.8'
+1 -1
View File
@@ -11,7 +11,7 @@ services:
phpmyadmin:
image: phpmyadmin/phpmyadmin:5.2.1
image: phpmyadmin:5.2.3
environment:
PMA_HOST: db
PMA_USER: ${MYSQL_USER}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "phpmyadmin",
"name": "Phpmyadmin",
"version": "5.2.1",
"version": "5.2.3",
"description": "phpMyAdmin is an open-source web interface for managing MySQL and MariaDB databases. Self-host it on your own server with Dokploy, which deploys phpMyAdmin as a Docker Compose service in a few clicks.",
"logo": "phpmyadmin.png",
"links": {
+16 -1
View File
@@ -1,7 +1,10 @@
services:
ponos:
image: ghcr.io/salvadorcardona/ponos:0.1.0
image: ghcr.io/hermez-agency/ponos:0.2.0
restart: unless-stopped
# The image's own user, said again so that nothing runs it as root: Claude
# Code refuses bypassPermissions to root.
user: ponos
expose:
- "8787"
environment:
@@ -9,10 +12,14 @@ services:
PONOS_WEB_PASSWORD: ${PONOS_WEB_PASSWORD}
PONOS_WEB_TOKEN: ${PONOS_WEB_TOKEN}
PONOS_LANGUAGE: ${PONOS_LANGUAGE}
TZ: ${TZ}
CLAUDE_CODE_OAUTH_TOKEN: ${CLAUDE_CODE_OAUTH_TOKEN}
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
OPENROUTER_API_KEY: ${OPENROUTER_API_KEY}
GH_TOKEN: ${GH_TOKEN}
PONOS_NOTION_TOKEN: ${PONOS_NOTION_TOKEN}
PONOS_TELEGRAM_TOKEN: ${PONOS_TELEGRAM_TOKEN}
PONOS_SLACK_TOKEN: ${PONOS_SLACK_TOKEN}
volumes:
- ponos-data:/data
- ponos-workspace:/workspace
@@ -24,6 +31,14 @@ services:
timeout: 5s
retries: 3
start_period: 60s
# A ceiling, not a reservation: a Claude Code session is a Node process of
# a few hundred megabytes, and a build or a test suite it runs adds its own.
# Four gigabytes hold the two runner.max_concurrent allows by default; raise
# it with that number.
deploy:
resources:
limits:
memory: 4g
volumes:
ponos-data:
+9 -5
View File
@@ -1,17 +1,21 @@
{
"id": "ponos",
"name": "Ponos",
"version": "0.1.0",
"description": "Ponos runs your tickets with Claude Code: a ticket set to Ready becomes a session on a throwaway git worktree, and comes back as a pull request. Board in Notion or in Markdown files, with a web console.",
"version": "0.2.0",
"description": "A harness around Claude Code that runs your tasks — code or not — from Notion or its own board: a ticket comes back as a pull request on GitHub, a text, an action carried out or a post, and nothing ships until you say yes. Web console, Telegram and Slack.",
"logo": "ponos.svg",
"links": {
"github": "https://github.com/SalvadorCardona/ponos",
"github": "https://github.com/hermez-agency/ponos",
"website": "https://the-ponos.app/",
"docs": "https://github.com/SalvadorCardona/ponos#install-with-dokploy"
"docs": "https://github.com/hermez-agency/ponos/blob/main/guide/server.md#install-with-dokploy"
},
"tags": [
"ai",
"ai-agent",
"automation",
"developer-tools"
"claude",
"developer-tools",
"notion",
"github"
]
}
+7 -242
View File
@@ -1,244 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" data-state="idle" data-theme="auto" role="img">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120" role="img">
<title>Ponos</title>
<style>
svg { --robot-body: #78a0ff; --robot-body-shade: #5079e6; --robot-screen: #1c2547; --robot-eye: #b4f1ff; --robot-accent: #ffcf5c; --robot-flame: #f59a3c; --robot-flame-core: #fbd35a; --robot-gold: #f2c65a; --robot-gold-deep: #b8861f; --robot-tunic: #f3ecdc; --robot-sash: #c4553a; --robot-pink: #ff8fb0; --robot-glint: #ffffff; --robot-alert: #ff6b86; --robot-ink: #46599a; --robot-shadow: rgba(36, 52, 110, .16); }
svg[data-theme="dark"] { --robot-body: #82a8ff; --robot-body-shade: #5c84ee; --robot-screen: #141b36; --robot-eye: #b4f1ff; --robot-accent: #ffd36b; --robot-flame: #f59a3c; --robot-flame-core: #fbd35a; --robot-gold: #f2c65a; --robot-gold-deep: #b8861f; --robot-tunic: #f3ecdc; --robot-sash: #c4553a; --robot-pink: #ff8fb0; --robot-glint: #ffffff; --robot-alert: #ff7d93; --robot-ink: #a9bdf2; --robot-shadow: rgba(130, 168, 255, .16); }
@media (prefers-color-scheme: dark) { svg:not([data-theme="light"]) { --robot-body: #82a8ff; --robot-body-shade: #5c84ee; --robot-screen: #141b36; --robot-eye: #b4f1ff; --robot-accent: #ffd36b; --robot-flame: #f59a3c; --robot-flame-core: #fbd35a; --robot-gold: #f2c65a; --robot-gold-deep: #b8861f; --robot-tunic: #f3ecdc; --robot-sash: #c4553a; --robot-pink: #ff8fb0; --robot-glint: #ffffff; --robot-alert: #ff7d93; --robot-ink: #a9bdf2; --robot-shadow: rgba(130, 168, 255, .16); } }
svg { display: block; width: 100%; height: auto; overflow: visible; }
[data-layer] { transform-box: view-box; }
[data-layer="frame"] { transform-origin: 64px 44px; }
[data-layer="base"] { transform-origin: 64px 119px; }
[data-layer="rig"] { transform-origin: 64px 119px; }
[data-layer="head"] { transform-origin: 64px 86px; }
[data-layer="flame"] { transform-origin: 64px 22px; }
[data-layer="fire"] { transform-origin: 64px 21px; }
[data-layer="arm-left"] { transform-origin: 45px 89px; }
[data-layer="arm-right"] { transform-origin: 83px 89px; }
[data-layer="forearm-left"] { transform-origin: 38.5px 96px; }
[data-layer="forearm-right"] { transform-origin: 89.5px 96px; }
[data-layer="leg-left"] { transform-origin: 54px 104px; }
[data-layer="leg-right"] { transform-origin: 74px 104px; }
[data-layer="lid-left"] { transform-origin: 50px 42px; }
[data-layer="lid-right"] { transform-origin: 78px 42px; }
[data-layer="mouth"] { transform-origin: 64px 68px; }
[data-layer="tear"] { transform-origin: 88px 60px; }
[data-layer="z1"] { transform-origin: 97px 23px; }
[data-layer="z2"] { transform-origin: 106px 13px; }
[data-layer="z3"] { transform-origin: 115px 4px; }
.shadow { fill: var(--robot-shadow); }
.shell { fill: var(--robot-body); }
.ear, .hand, .foot, .limb-fill { fill: var(--robot-body-shade); }
.limb { fill: none; stroke: var(--robot-body-shade); stroke-width: 8; stroke-linecap: round; }
.sheen { fill: none; stroke: var(--robot-glint); stroke-width: 3.6; stroke-linecap: round; opacity: .55; }
.tunic { fill: var(--robot-tunic); }
.sash { fill: var(--robot-sash); }
.brooch, .socket { fill: var(--robot-gold); }
.brooch-pin { fill: var(--robot-gold-deep); }
.fire { fill: var(--robot-flame); stroke: var(--robot-flame); stroke-width: 0; stroke-linejoin: round; }
.fire-core { fill: var(--robot-flame-core); }
.screen, .lid { fill: var(--robot-screen); }
.eye, .mouth-fill { fill: var(--robot-eye); }
.glint { fill: var(--robot-glint); }
.eye .glint, .eye-open .glint { opacity: .95; }
.eye-line, .mouth-line { fill: none; stroke: var(--robot-eye); stroke-width: 4.2; stroke-linecap: round; stroke-linejoin: round; }
.mouth-line { stroke-width: 2.6; }
.eye-joy, .eye-closed, .mouth-alt { opacity: 0; }
.tongue { fill: var(--robot-pink); }
.tear { fill: var(--robot-eye); opacity: 0; }
.lid { transform: scaleY(0); transition: transform .07s ease-in; }
.z { fill: none; stroke: var(--robot-body-shade); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.star { fill: var(--robot-accent); }
.heart { fill: var(--robot-pink); }
.dot { fill: var(--robot-body-shade); }
.fx-zzz, .fx-stars, .fx-dots { opacity: 0; }
svg.blinking[data-state] [data-layer^="lid-"] { transform: scaleY(1); }
svg[data-state="thinking"] [data-layer="head"] { transform: rotate(4deg); }
svg[data-state="thinking"] [data-layer="eyes"] { transform: translate(4px, -4px); }
svg[data-state="thinking"] [data-layer="mouth-smile"] { opacity: 0; }
svg[data-state="thinking"] [data-layer="mouth-flat"] { opacity: 1; }
svg[data-state="thinking"] [data-layer="arm-right"] { transform: rotate(-128deg); }
svg[data-state="thinking"] [data-layer="forearm-right"] { transform: rotate(-40deg); }
svg[data-state="working"] [data-layer="lid-left"] { transform: scaleY(.3); }
svg[data-state="working"] [data-layer="lid-right"] { transform: scaleY(.3); }
svg[data-state="working"] [data-layer="mouth-smile"] { opacity: 0; }
svg[data-state="working"] [data-layer="mouth-flat"] { opacity: 1; }
svg[data-state="working"] [data-layer="arm-left"] { transform: rotate(40deg); }
svg[data-state="working"] [data-layer="arm-right"] { transform: rotate(-40deg); }
svg[data-state="working"] [data-layer="forearm-left"] { transform: rotate(-50deg); }
svg[data-state="working"] [data-layer="forearm-right"] { transform: rotate(50deg); }
svg[data-state="working"] [data-layer="fire"] { transform: scale(1.15, 1.3); }
svg[data-state="success"] [data-layer="eye-open-left"] { opacity: 0; }
svg[data-state="success"] [data-layer="eye-open-right"] { opacity: 0; }
svg[data-state="success"] [data-layer="eye-joy-left"] { opacity: 1; }
svg[data-state="success"] [data-layer="eye-joy-right"] { opacity: 1; }
svg[data-state="success"] [data-layer="mouth-smile"] { opacity: 0; }
svg[data-state="success"] [data-layer="mouth-open"] { opacity: 1; }
svg[data-state="success"] [data-layer="arm-left"] { transform: rotate(100deg); }
svg[data-state="success"] [data-layer="arm-right"] { transform: rotate(-100deg); }
svg[data-state="success"] [data-layer="forearm-left"] { transform: rotate(30deg); }
svg[data-state="success"] [data-layer="forearm-right"] { transform: rotate(-30deg); }
svg[data-state="success"] [data-layer="fx-stars"] { opacity: 1; }
svg[data-state="success"] .star { transform-box: fill-box; transform-origin: center; }
svg[data-state="success"] .heart { transform-box: fill-box; transform-origin: center; }
svg[data-state="error"] [data-layer="rig"] { transform: translateY(2px); }
svg[data-state="error"] [data-layer="head"] { transform: rotate(-5deg); }
svg[data-state="error"] [data-layer="lid-left"] { transform: rotate(-14deg) scaleY(.32); }
svg[data-state="error"] [data-layer="lid-right"] { transform: rotate(14deg) scaleY(.32); }
svg[data-state="error"] [data-layer="eyes"] { transform: translateY(2px); }
svg[data-state="error"] [data-layer="mouth-smile"] { opacity: 0; }
svg[data-state="error"] [data-layer="mouth-frown"] { opacity: 1; }
svg[data-state="error"] [data-layer="arm-left"] { transform: rotate(-14deg); }
svg[data-state="error"] [data-layer="arm-right"] { transform: rotate(14deg); }
svg[data-state="error"] [data-layer="flame"] { transform: rotate(-22deg); }
svg[data-state="error"] .fire { fill: var(--robot-alert); stroke: var(--robot-alert); }
svg[data-state="error"] [data-layer="tear"] { opacity: 1; }
svg[data-state="sleep"] [data-layer="rig"] { transform: translateY(1px); }
svg[data-state="sleep"] [data-layer="head"] { transform: rotate(-7deg); }
svg[data-state="sleep"] [data-layer="flame"] { transform: rotate(-12deg); }
svg[data-state="sleep"] [data-layer="eye-open-left"] { opacity: 0; }
svg[data-state="sleep"] [data-layer="eye-open-right"] { opacity: 0; }
svg[data-state="sleep"] [data-layer="eye-closed-left"] { opacity: 1; }
svg[data-state="sleep"] [data-layer="eye-closed-right"] { opacity: 1; }
svg[data-state="sleep"] [data-layer="mouth-smile"] { opacity: 0; }
svg[data-state="sleep"] [data-layer="mouth-o"] { opacity: 1; }
svg[data-state="sleep"] [data-layer="fire"] { transform: scale(.45); opacity: .5; }
svg[data-state="sleep"] .fire-core { opacity: 0; }
svg[data-state="sleep"] [data-layer="fx-zzz"] { opacity: 1; }
svg[data-state="waiting"] [data-layer="head"] { transform: rotate(-6deg); }
svg[data-state="waiting"] [data-layer="eyes"] { transform: translate(5px, -4px); }
svg[data-state="waiting"] [data-layer="mouth-smile"] { opacity: 0; }
svg[data-state="waiting"] [data-layer="mouth-o"] { opacity: 1; }
svg[data-state="waiting"] [data-layer="fx-dots"] { opacity: 1; }svg.small [data-layer="frame"] { transform: translateY(20px) scale(1.4); }svg.small [data-layer="base"], svg.small [data-layer="body"], svg.small [data-layer="arm-left"], svg.small [data-layer="arm-right"], svg.small [data-layer="accessories"], svg.small [data-layer="fx"], svg.small .ear, svg.small .sheen, svg.small .glint-small, svg.small .tear, svg.small .fire-core, svg.small .socket { display: none; }svg.small .fire { stroke-width: 4.5; }svg.small .eye-line { stroke-width: 6; }svg.small .mouth-line { stroke-width: 4; }
@media (max-width: 40px) { svg [data-layer="frame"] { transform: translateY(20px) scale(1.4); }svg [data-layer="base"], svg [data-layer="body"], svg [data-layer="arm-left"], svg [data-layer="arm-right"], svg [data-layer="accessories"], svg [data-layer="fx"], svg .ear, svg .sheen, svg .glint-small, svg .tear, svg .fire-core, svg .socket { display: none; }svg .fire { stroke-width: 4.5; }svg .eye-line { stroke-width: 6; }svg .mouth-line { stroke-width: 4; }
}
@container (max-width: 40px) { svg [data-layer="frame"] { transform: translateY(20px) scale(1.4); }svg [data-layer="base"], svg [data-layer="body"], svg [data-layer="arm-left"], svg [data-layer="arm-right"], svg [data-layer="accessories"], svg [data-layer="fx"], svg .ear, svg .sheen, svg .glint-small, svg .tear, svg .fire-core, svg .socket { display: none; }svg .fire { stroke-width: 4.5; }svg .eye-line { stroke-width: 6; }svg .mouth-line { stroke-width: 4; }
}</style>
<defs>
<linearGradient id="trr-shade" x1="0" y1="0" x2="0" y2="1">
<stop offset=".4" stop-color="#0b1330" stop-opacity="0"/>
<stop offset="1" stop-color="#0b1330" stop-opacity=".2"/>
</linearGradient>
<radialGradient id="trr-sheen" cx=".32" cy=".18" r=".75">
<stop offset="0" stop-color="#fff" stop-opacity=".38"/>
<stop offset=".6" stop-color="#fff" stop-opacity="0"/>
</radialGradient>
<radialGradient id="trr-glow" cx=".5" cy=".35" r=".7">
<stop offset="0" stop-color="#fff" stop-opacity=".1"/>
<stop offset="1" stop-color="#fff" stop-opacity="0"/>
</radialGradient>
<clipPath id="trr-torso"><rect x="42" y="78" width="44" height="30" rx="15"/></clipPath>
</defs>
<g data-layer="frame">
<g data-layer="base">
<ellipse class="shadow" cx="64" cy="119" rx="27" ry="4.6"/>
<ellipse class="shadow" cx="64" cy="119" rx="17" ry="3"/>
</g>
<g data-layer="rig">
<g data-layer="body">
<g data-layer="leg-left">
<rect class="limb-fill" x="48" y="99" width="12" height="14" rx="6"/>
<ellipse class="foot" cx="53" cy="114.5" rx="8" ry="4.5"/>
</g>
<g data-layer="leg-right">
<rect class="limb-fill" x="68" y="99" width="12" height="14" rx="6"/>
<ellipse class="foot" cx="75" cy="114.5" rx="8" ry="4.5"/>
</g>
<rect class="shell" x="42" y="78" width="44" height="30" rx="15"/>
<g data-layer="dress" clip-path="url(#trr-torso)">
<path class="tunic" d="M42 92 Q64 89 86 92 V108 H42 Z"/>
<path class="sash" d="M42 86 L54 81.5 L86 100 L86 108 Z"/>
</g>
<rect x="42" y="78" width="44" height="30" rx="15" fill="url(#trr-shade)"/>
<g data-layer="brooch">
<circle class="brooch" cx="51" cy="89" r="3.4"/>
<circle class="brooch-pin" cx="51" cy="89" r="1.5"/>
<circle class="glint" cx="50" cy="88" r=".8"/>
</g>
</g>
<g data-layer="head">
<g data-layer="flame">
<g data-layer="fire">
<path class="fire" d="M64 4.6 C68.8 10.6 70.6 15.4 67.6 20.2 C66.4 22 61.6 22 60.4 20.2 C57.4 15.4 59.2 10.6 64 4.6 Z"/>
<path class="fire-core" d="M64 10.6 C66.4 14.2 67 17.2 65.2 19.6 C64.6 20.2 63.4 20.2 62.8 19.6 C61 17.2 61.6 14.2 64 10.6 Z"/>
</g>
<rect class="socket" x="59.2" y="19.6" width="9.6" height="3.6" rx="1.2"/>
</g>
<circle class="ear" cx="19.5" cy="56" r="7.5"/>
<circle class="ear" cx="108.5" cy="56" r="7.5"/>
<rect class="shell" x="20" y="22" width="88" height="64" rx="30"/>
<rect x="20" y="22" width="88" height="64" rx="30" fill="url(#trr-shade)"/>
<rect x="20" y="22" width="88" height="64" rx="30" fill="url(#trr-sheen)"/>
<path class="sheen" d="M33 38 Q38 29 50 26.5"/>
<rect class="screen" x="30" y="33" width="68" height="44" rx="20"/>
<g data-layer="eyes">
<g data-layer="eye-left">
<g data-layer="eye-open-left" class="eye-open">
<rect class="eye" x="42.5" y="44" width="15" height="18" rx="7.5"/>
<circle class="glint" cx="47" cy="49" r="3"/>
<circle class="glint glint-small" cx="53" cy="57.5" r="1.4"/>
</g>
<path data-layer="eye-joy-left" class="eye-line eye-joy" d="M43.5 55 Q50 45.5 56.5 55"/>
<path data-layer="eye-closed-left" class="eye-line eye-closed" d="M43.5 53 Q50 58.5 56.5 53"/>
</g>
<g data-layer="eye-right">
<g data-layer="eye-open-right" class="eye-open">
<rect class="eye" x="70.5" y="44" width="15" height="18" rx="7.5"/>
<circle class="glint" cx="75" cy="49" r="3"/>
<circle class="glint glint-small" cx="81" cy="57.5" r="1.4"/>
</g>
<path data-layer="eye-joy-right" class="eye-line eye-joy" d="M71.5 55 Q78 45.5 84.5 55"/>
<path data-layer="eye-closed-right" class="eye-line eye-closed" d="M71.5 53 Q78 58.5 84.5 53"/>
</g>
</g>
<g data-layer="eyelids">
<rect data-layer="lid-left" class="lid" x="40" y="42" width="20" height="22"/>
<rect data-layer="lid-right" class="lid" x="68" y="42" width="20" height="22"/>
</g>
<rect x="30" y="33" width="68" height="44" rx="20" fill="url(#trr-glow)"/>
<g data-layer="mouth">
<path data-layer="mouth-smile" class="mouth-line" d="M59.5 66 Q64 70.5 68.5 66"/>
<g data-layer="mouth-open" class="mouth-alt">
<path class="mouth-fill" d="M58.5 65 Q64 66 69.5 65 Q69 73 64 73 Q59 73 58.5 65 Z"/>
<path class="tongue" d="M60.8 70.6 Q64 68.4 67.2 70.6 Q64 73 60.8 70.6 Z"/>
</g>
<path data-layer="mouth-frown" class="mouth-line mouth-alt" d="M59.5 70 Q64 65.5 68.5 70"/>
<ellipse data-layer="mouth-o" class="mouth-line mouth-alt" cx="64" cy="68" rx="2.4" ry="2.8"/>
<path data-layer="mouth-flat" class="mouth-line mouth-alt" d="M60.5 67.5 Q62.5 66.2 64.5 67.5 Q66.5 68.8 68 67.2"/>
</g>
<path data-layer="tear" class="tear" d="M88 60 C85.6 64 85.6 66.6 88 66.6 C90.4 66.6 90.4 64 88 60 Z"/>
</g>
<g data-layer="arm-left">
<path class="limb" d="M45 89 L38.5 96"/>
<g data-layer="forearm-left">
<path class="limb" d="M38.5 96 L37 99.5"/>
<circle class="hand" cx="37" cy="100.5" r="5.5"/>
</g>
</g>
<g data-layer="arm-right">
<path class="limb" d="M83 89 L89.5 96"/>
<g data-layer="forearm-right">
<path class="limb" d="M89.5 96 L91 99.5"/>
<circle class="hand" cx="91" cy="100.5" r="5.5"/>
</g>
</g>
<g data-layer="accessories"></g>
</g>
<g data-layer="fx">
<g data-layer="fx-zzz" class="fx-zzz">
<path data-layer="z1" class="z" d="M94 20 h6 l-6 7 h6"/>
<path data-layer="z2" class="z" d="M104 10 h5 l-5 6 h5"/>
<path data-layer="z3" class="z" d="M113 2 h4 l-4 5 h4"/>
</g>
<g data-layer="fx-dots" class="fx-dots">
<circle data-layer="dot1" class="dot" cx="98" cy="15" r="2.8"/>
<circle data-layer="dot2" class="dot" cx="106.5" cy="15" r="2.8"/>
<circle data-layer="dot3" class="dot" cx="115" cy="15" r="2.8"/>
</g>
<g data-layer="fx-stars" class="fx-stars">
<path class="star" d="M14 24 l2 4.4 l4.4 2 l-4.4 2 l-2 4.4 l-2 -4.4 l-4.4 -2 l4.4 -2 z"/>
<path class="star" d="M114 30 l1.5 3.3 l3.3 1.5 l-3.3 1.5 l-1.5 3.3 l-1.5 -3.3 l-3.3 -1.5 l3.3 -1.5 z"/>
<path class="heart" d="M104 8.5 c-1.6 -3 -6 -2 -5 1.6 c.6 2.2 5 5 5 5 s4.4 -2.8 5 -5 c1 -3.6 -3.4 -4.6 -5 -1.6 z"/>
</g>
</g>
</g>
<style>.ground { fill: #FFFFFF; } .screen { fill: #1c1917; }</style>
<rect x="4" y="4" width="112" height="112" rx="26" class="ground" stroke="#E8611A" stroke-width="8"/>
<path d="M60 20C67 27 69 32 66 36C64 39 56 39 54 36C51 32 53 27 60 20Z" fill="#E8611A"/>
<rect x="28" y="44" width="64" height="50" rx="16" class="screen"/>
<circle cx="48" cy="69" r="7" fill="#FFE1CC"/>
<circle cx="72" cy="69" r="7" fill="#FFE1CC"/>
</svg>

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 524 B

+42 -13
View File
@@ -6,24 +6,53 @@ api_token = "${password:48}"
[config]
mounts = []
env = [
# Generated: the console's sign-in, and the token scripts carry. Change the email
# to yours if you like; the password is in this tab whenever you need it.
# -- Generated -------------------------------------------------------------
# The console's sign-in: both set, it is claimed before anybody opens it. The
# email is only a login, never written to — change it to yours if you like;
# the password is in this tab whenever you need it.
"PONOS_WEB_EMAIL=admin@${main_domain}",
"PONOS_WEB_PASSWORD=${admin_password}",
# What a script carries in `Authorization: Bearer`.
"PONOS_WEB_TOKEN=${api_token}",
# -- Who answers the sessions: one of these is required --------------------
# Your Claude subscription: run `claude setup-token` on a machine with a
# browser and paste what it prints...
"CLAUDE_CODE_OAUTH_TOKEN=",
# ...or an Anthropic API key, billed by the token (console.anthropic.com).
# Given without the token above, the sessions are billed to it from the start.
"ANTHROPIC_API_KEY=",
# Optional: an OpenRouter key (openrouter.ai/keys), in every session's
# environment for the other models a ticket may call. The sessions only run
# there once Settings › OpenRouter says so.
"OPENROUTER_API_KEY=",
# -- GitHub, optional ------------------------------------------------------
# A token (repo scope, or a fine-grained one with Contents and Pull requests
# on read and write), so Ponos clones, pushes and opens pull requests as that
# account. Leave it empty to create a GitHub App from the console instead:
# Settings › GitHub › Connect GitHub. Writing tickets need neither.
"GH_TOKEN=",
# -- The board, optional ---------------------------------------------------
# A Notion integration token. Without one the board is kept in Markdown files
# on the ponos-data volume, and the console is all you need.
"PONOS_NOTION_TOKEN=",
# -- Your phone, optional --------------------------------------------------
# A Telegram bot token, from @BotFather (/newbot). Say anything to the bot,
# then `ponos notify --pair` in Dokploy's Terminal finds your chat.
"PONOS_TELEGRAM_TOKEN=",
# A Slack bot token (xoxb-…, chat:write and channels:history); the channel's
# ID goes in the console's Settings › Slack.
"PONOS_SLACK_TOKEN=",
# -- Where and in what words -----------------------------------------------
# en or fr: the reports Ponos writes, and the console until you pick another.
"PONOS_LANGUAGE=en",
# Required, one of the two. Your Claude subscription: run `claude setup-token`
# on a machine with a browser and paste what it prints...
"CLAUDE_CODE_OAUTH_TOKEN=",
# ...or an Anthropic API key, billed by the token (https://console.anthropic.com).
"ANTHROPIC_API_KEY=",
# Optional: a GitHub token (repo scope), so Ponos clones, pushes and opens pull
# requests. The console's GitHub step says what is missing without it.
"GH_TOKEN=",
# Optional: a Notion integration token. Without one the board is kept in Markdown
# files on the ponos-data volume, and the console is all you need.
"PONOS_NOTION_TOKEN=",
# The zone a schedule's hours are read in: 09:00 is nine there. An IANA name,
# Europe/Paris for instance.
"TZ=UTC",
]
# The console: sign in with PONOS_WEB_EMAIL and PONOS_WEB_PASSWORD above.
@@ -0,0 +1,32 @@
services:
postgres-extensor:
image: ruxwez/postgres:18-v1.1.0
restart: unless-stopped
# Libraries loaded at startup. pg_cron and the other "preload" extensions
# need to be listed here before CREATE EXTENSION works.
command:
- postgres
- -c
- shared_preload_libraries=${SHARED_PRELOAD_LIBRARIES}
- -c
- cron.database_name=${POSTGRES_DB}
- -c
- max_worker_processes=32
# Uncomment 'ports' settings below to enable external access
# ports:
# - "5432:5432"
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB}
volumes:
- postgres-data:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
start_period: 20s
volumes:
postgres-data:
+13
View File
@@ -0,0 +1,13 @@
{
"id": "postgres-extensor",
"name": "PostgreSQL with 80+ Extensions",
"version": "18-v1.1.0",
"description": "The official PostgreSQL 18 image with 80+ tested extensions preinstalled: pgvector, PostGIS, TimescaleDB, pgmq, pg_cron, pg_duckdb, Apache AGE, pg_graphql and more. Multi-arch (amd64, arm64).",
"logo": "postgres-extensor.svg",
"links": {
"github": "https://github.com/ruxwez/postgres",
"website": "https://hub.docker.com/r/ruxwez/postgres",
"docs": "https://github.com/ruxwez/postgres/blob/main/.docs/included-extensions.md"
},
"tags": ["database", "postgres", "postgresql", "vector", "pgvector", "postgis", "timescaledb", "ai"]
}
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="576.095" height="593.844" viewBox="0 0 432.071 445.383"><g style="fill-rule:nonzero;clip-rule:nonzero;fill:none;stroke:#fff;stroke-width:12.4651;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4"><path d="M323.205 324.227c2.833-23.601 1.984-27.062 19.563-23.239l4.463.392c13.517.615 31.199-2.174 41.587-7 22.362-10.376 35.622-27.7 13.572-23.148-50.297 10.376-53.755-6.655-53.755-6.655 53.111-78.803 75.313-178.836 56.149-203.322-52.27-66.789-142.748-35.206-144.262-34.386l-.482.089c-9.938-2.062-21.06-3.294-33.554-3.496-22.761-.374-40.032 5.967-53.133 15.904 0 0-161.408-66.498-153.899 83.628 1.597 31.936 45.777 241.655 98.47 178.31 19.259-23.163 37.871-42.748 37.871-42.748 9.242 6.14 20.307 9.272 31.912 8.147l.897-.765c-.281 2.876-.157 5.689.359 9.019-13.572 15.167-9.584 17.83-36.723 23.416-27.457 5.659-11.326 15.734-.797 18.367 12.768 3.193 42.305 7.716 62.268-20.224l-.795 3.188c5.325 4.26 4.965 30.619 5.72 49.452.756 18.834 2.017 36.409 5.856 46.771 3.839 10.36 8.369 37.05 44.036 29.406 29.809-6.388 52.6-15.582 54.677-101.107" style="fill:#000;stroke:#000;stroke-width:37.3953;stroke-linecap:butt;stroke-linejoin:miter"/><path stroke="none" d="M402.395 271.23c-50.302 10.376-53.76-6.655-53.76-6.655 53.111-78.808 75.313-178.843 56.153-203.326-52.27-66.785-142.752-35.2-144.262-34.38l-.486.087c-9.938-2.063-21.06-3.292-33.56-3.496-22.761-.373-40.026 5.967-53.127 15.902 0 0-161.411-66.495-153.904 83.63 1.597 31.938 45.776 241.657 98.471 178.312 19.26-23.163 37.869-42.748 37.869-42.748 9.243 6.14 20.308 9.272 31.908 8.147l.901-.765c-.28 2.876-.152 5.689.361 9.019-13.575 15.167-9.586 17.83-36.723 23.416-27.459 5.659-11.328 15.734-.796 18.367 12.768 3.193 42.307 7.716 62.266-20.224l-.796 3.188c5.319 4.26 9.054 27.711 8.428 48.969s-1.044 35.854 3.147 47.254 8.368 37.05 44.042 29.406c29.809-6.388 45.256-22.942 47.405-50.555 1.525-19.631 4.976-16.729 5.194-34.28l2.768-8.309c3.192-26.611.507-35.196 18.872-31.203l4.463.392c13.517.615 31.208-2.174 41.591-7 22.358-10.376 35.618-27.7 13.573-23.148z" style="fill:#336791;stroke:none"/><path d="M215.866 286.484c-1.385 49.516.348 99.377 5.193 111.495 4.848 12.118 15.223 35.688 50.9 28.045 29.806-6.39 40.651-18.756 45.357-46.051 3.466-20.082 10.148-75.854 11.005-87.281M173.104 38.256S11.583-27.76 19.092 122.365c1.597 31.938 45.779 241.664 98.473 178.316 19.256-23.166 36.671-41.335 36.671-41.335M260.349 26.207c-5.591 1.753 89.848-34.889 144.087 34.417 19.159 24.484-3.043 124.519-56.153 203.329"/><path d="M348.282 263.953s3.461 17.036 53.764 6.653c22.04-4.552 8.776 12.774-13.577 23.155-18.345 8.514-59.474 10.696-60.146-1.069-1.729-30.355 21.647-21.133 19.96-28.739-1.525-6.85-11.979-13.573-18.894-30.338-6.037-14.633-82.796-126.849 21.287-110.183 3.813-.789-27.146-99.002-124.553-100.599-97.385-1.597-94.19 119.762-94.19 119.762" style="stroke-linejoin:bevel"/><path d="M188.604 274.334c-13.577 15.166-9.584 17.829-36.723 23.417-27.459 5.66-11.326 15.733-.797 18.365 12.768 3.195 42.307 7.718 62.266-20.229 6.078-8.509-.036-22.086-8.385-25.547-4.034-1.671-9.428-3.765-16.361 3.994"/><path d="M187.715 274.069c-1.368-8.917 2.93-19.528 7.536-31.942 6.922-18.626 22.893-37.255 10.117-96.339-9.523-44.029-73.396-9.163-73.436-3.193-.039 5.968 2.889 30.26-1.067 58.548-5.162 36.913 23.488 68.132 56.479 64.938"/><path d="M172.517 141.7c-.288 2.039 3.733 7.48 8.976 8.207 5.234.73 9.714-3.522 9.998-5.559.284-2.039-3.732-4.285-8.977-5.015-5.237-.731-9.719.333-9.996 2.367z" style="fill:#fff;stroke-width:4.155;stroke-linecap:butt;stroke-linejoin:miter"/><path d="M331.941 137.543c.284 2.039-3.732 7.48-8.976 8.207-5.238.73-9.718-3.522-10.005-5.559-.277-2.039 3.74-4.285 8.979-5.015s9.718.333 10.002 2.368z" style="fill:#fff;stroke-width:2.0775;stroke-linecap:butt;stroke-linejoin:miter"/><path d="M350.676 123.432c.863 15.994-3.445 26.888-3.988 43.914-.804 24.748 11.799 53.074-7.191 81.435"/></g></svg>

After

Width:  |  Height:  |  Size: 3.9 KiB

@@ -0,0 +1,11 @@
[variables]
postgres_user = "${username}"
postgres_password = "${password:32}"
postgres_db = "postgres"
[config.env]
POSTGRES_USER = "${postgres_user}"
POSTGRES_PASSWORD = "${postgres_password}"
POSTGRES_DB = "${postgres_db}"
# Add more preload extensions here, comma-separated (e.g. timescaledb, pg_duckdb).
SHARED_PRELOAD_LIBRARIES = "pg_stat_statements,pg_cron"
@@ -0,0 +1,19 @@
services:
privatepaste:
image: ghcr.io/dynamicsninja/privatepaste:0.5.0
restart: unless-stopped
stop_grace_period: 15s
environment:
PP_DB_KEY: ${PP_DB_KEY}
PP_PASSWORD: ${PP_PASSWORD}
PP_MAX_IMAGE_MB: ${PP_MAX_IMAGE_MB}
PP_MAX_FILE_MB: ${PP_MAX_FILE_MB}
PP_MAX_TEXT_KB: ${PP_MAX_TEXT_KB}
PP_TRUST_CLOUDFLARE: ${PP_TRUST_CLOUDFLARE}
volumes:
- privatepaste-data:/data
expose:
- 8080
volumes:
privatepaste-data:
+17
View File
@@ -0,0 +1,17 @@
{
"id": "privatepaste",
"name": "PrivatePaste",
"version": "0.5.0",
"description": "Self-hosted clipboard sync: copy on one device, paste on your others, with an encrypted, searchable history and apps for Windows, macOS, Linux and Android.",
"logo": "privatepaste.svg",
"links": {
"github": "https://github.com/DynamicsNinja/privatepaste",
"website": "https://github.com/DynamicsNinja/privatepaste",
"docs": "https://github.com/DynamicsNinja/privatepaste/blob/main/docs/self-hosting.md"
},
"tags": [
"productivity",
"clipboard",
"sync"
]
}
+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="PrivatePaste">
<rect x="2" y="2" width="60" height="60" rx="18" fill="#221D40"/>
<rect x="2.75" y="2.75" width="58.5" height="58.5" rx="17.25" fill="none" stroke="#B7A5FF" stroke-opacity=".35" stroke-width="1.5"/>
<circle cx="32" cy="26" r="9" fill="#B7A5FF"/>
<path d="M27.5 31.5h9l3 17.5h-15z" fill="#B7A5FF"/>
</svg>

After

Width:  |  Height:  |  Size: 411 B

+22
View File
@@ -0,0 +1,22 @@
[variables]
main_domain = "${domain}"
# 32 random bytes, base64: the encryption key for the database and images. Back it up: without it the data is lost.
db_key = "${base64:32}"
login_password = "${password:24}"
[config]
mounts = []
[[config.domains]]
serviceName = "privatepaste"
port = 8080
host = "${main_domain}"
[config.env]
PP_DB_KEY = "${db_key}"
PP_PASSWORD = "${login_password}"
PP_MAX_IMAGE_MB = "20"
PP_MAX_FILE_MB = "25"
PP_MAX_TEXT_KB = "1024"
# Set to "true" only if the server is reachable exclusively through a Cloudflare tunnel.
PP_TRUST_CLOUDFLARE = "false"
@@ -0,0 +1,179 @@
# dokploy: allow-container-names
x-puppetflow-environment: &puppetflow-environment
APP_ENV: production
LOG_STACK: single,stderr
LANG: ${LANG}
LANGUAGE: ${LANGUAGE}
CONNECTION_TIMEOUT_MS: ${CONNECTION_TIMEOUT_MS}
APP_URL: ${APP_URL}
APP_KEY: ${APP_KEY}
APP_QUEUES_COUNTER: "2"
DB_CONNECTION: pgsql
DB_HOST: postgres
DB_PORT: "5432"
DB_DATABASE: ${POSTGRES_DB}
DB_USERNAME: ${POSTGRES_USER}
DB_PASSWORD: ${POSTGRES_PASSWORD}
REDIS_HOST: redis
REDIS_PORT: "6379"
PINOKIO_HOST: pinokio
PINOKIO_PORT: "3000"
PINOKIO_TOKEN: ${PINOKIO_TOKEN}
RUNNER_API_INTERNAL_URL: http://puppetflow:8000/api/internal/runner
BROWSER_STREAM_INTERNAL_URL: http://stream-server:6080
BROWSER_STREAM_PUBLIC_URL: ${BROWSER_STREAM_PUBLIC_URL}
BROWSER_STREAM_ALLOWED_ORIGINS: ${APP_URL}
BROWSER_STREAM_SECRET: ${BROWSER_STREAM_SECRET}
services:
puppetflow:
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
restart: unless-stopped
expose:
- 8000
volumes:
- puppetflow-framework:/app/storage
- puppetflow-execution:/app/data/execution
- puppetflow-uploads:/app/data/storage
environment: *puppetflow-environment
healthcheck:
test: ["CMD", "curl", "-fsS", "http://localhost:8000/up"]
interval: 30s
timeout: 5s
retries: 3
start_period: 15s
depends_on:
migrate:
condition: service_completed_successfully
pinokio:
condition: service_started
stream-server:
condition: service_started
migrate:
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
command: ["php", "artisan", "migrate", "--force"]
restart: "no"
volumes:
- puppetflow-framework:/app/storage
environment: *puppetflow-environment
depends_on:
init-volumes:
condition: service_completed_successfully
postgres:
condition: service_healthy
queue-1:
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
command: ["php", "artisan", "queue:work", "--queue=1", "--tries=1", "--timeout=630", "--sleep=3", "--max-jobs=500", "--max-time=3600"]
restart: unless-stopped
volumes:
- puppetflow-framework:/app/storage
- puppetflow-execution:/app/data/execution
- puppetflow-uploads:/app/data/storage
environment: *puppetflow-environment
depends_on:
migrate:
condition: service_completed_successfully
stream-server:
condition: service_started
queue-2:
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
command: ["php", "artisan", "queue:work", "--queue=2", "--tries=1", "--timeout=630", "--sleep=3", "--max-jobs=500", "--max-time=3600"]
restart: unless-stopped
volumes:
- puppetflow-framework:/app/storage
- puppetflow-execution:/app/data/execution
- puppetflow-uploads:/app/data/storage
environment: *puppetflow-environment
depends_on:
migrate:
condition: service_completed_successfully
stream-server:
condition: service_started
scheduler:
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
command: ["php", "artisan", "schedule:work"]
restart: unless-stopped
volumes:
- puppetflow-framework:/app/storage
- puppetflow-execution:/app/data/execution
- puppetflow-uploads:/app/data/storage
environment: *puppetflow-environment
depends_on:
migrate:
condition: service_completed_successfully
stream-server:
image: ghcr.io/puppetflow/puppetflow-stream-server:v2026.11.7
restart: unless-stopped
stop_grace_period: 30s
expose:
- 6080
environment: *puppetflow-environment
depends_on:
redis:
condition: service_healthy
init-volumes:
image: busybox:1.37.0
command: ["sh", "-c", "chown -R 33:33 /framework /execution /uploads /browsers"]
restart: "no"
volumes:
- puppetflow-framework:/framework
- puppetflow-execution:/execution
- puppetflow-uploads:/uploads
- pinokio-downloads:/browsers
pinokio:
image: ghcr.io/puppetflow/pinokio:v2026.11.1
restart: unless-stopped
user: "33:33"
shm_size: "1gb"
volumes:
- puppetflow-execution:/app/data/execution
- pinokio-downloads:/opt/browsers
environment:
TOKEN: ${PINOKIO_TOKEN}
HOME: /tmp
XDG_CONFIG_HOME: /tmp/.config
XDG_CACHE_HOME: /tmp/.cache
LANG: ${LANG}
LANGUAGE: ${LANGUAGE}
depends_on:
init-volumes:
condition: service_completed_successfully
postgres:
image: postgres:17-alpine
restart: unless-stopped
volumes:
- puppetflow-db:/var/lib/postgresql/data
environment:
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U \"$${POSTGRES_USER}\" -d \"$${POSTGRES_DB}\""]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:8.2.1-alpine
command: ["redis-server", "--save", "", "--appendonly", "no"]
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
volumes:
puppetflow-framework:
puppetflow-uploads:
puppetflow-execution:
puppetflow-db:
pinokio-downloads:
+18
View File
@@ -0,0 +1,18 @@
{
"id": "puppetflow-postgres",
"name": "Puppetflow with Postgres",
"version": "v2026.11.7",
"description": "A self-hosted browser automation platform for building, running, and monitoring JavaScript workflows powered by Puppeteer and PostgreSQL.",
"logo": "puppetflow.png",
"links": {
"github": "https://github.com/puppetflow/puppetflow",
"website": "https://puppetflow.com/",
"docs": "https://docs.puppetflow.com/"
},
"tags": [
"automation",
"browser",
"workflow",
"postgres"
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

@@ -0,0 +1,36 @@
[variables]
main_domain = "${domain}"
stream_domain = "${domain}"
app_key = "${base64:32}"
browser_stream_secret = "${hash:32}"
pinokio_token = "${hash:32}"
postgres_user = "${username}"
postgres_password = "${password:32}"
postgres_database = "puppetflow"
instance_id = "${hash:8}"
[config]
[[config.domains]]
serviceName = "puppetflow"
port = 8000
host = "${main_domain}"
[[config.domains]]
serviceName = "stream-server"
port = 6080
host = "${stream_domain}"
[config.env]
LANG = "C.UTF-8"
LANGUAGE = "en-US"
CONNECTION_TIMEOUT_MS = "60000000"
APP_URL = "http://${main_domain}"
APP_KEY = "base64:${app_key}"
BROWSER_STREAM_PUBLIC_URL = "http://${stream_domain}"
BROWSER_STREAM_SECRET = "${browser_stream_secret}"
PINOKIO_TOKEN = "${pinokio_token}"
POSTGRES_USER = "${postgres_user}"
POSTGRES_PASSWORD = "${postgres_password}"
POSTGRES_DB = "${postgres_database}"
PUPPETFLOW_INSTANCE_ID = "${instance_id}"
+36 -11
View File
@@ -1,10 +1,13 @@
version: "3.8"
# dokploy: allow-container-names
x-puppetflow-environment: &puppetflow-environment
APP_ENV: production
LOG_STACK: single,stderr
LANG: ${LANG}
LANGUAGE: ${LANGUAGE}
CONNECTION_TIMEOUT_MS: ${CONNECTION_TIMEOUT_MS}
APP_URL: ${APP_URL}
APP_KEY: ${APP_KEY}
APP_QUEUES_COUNTER: "1"
APP_QUEUES_COUNTER: "2"
DB_CONNECTION: sqlite
DB_DATABASE: /app/storage/database.sqlite
REDIS_HOST: redis
@@ -20,7 +23,7 @@ x-puppetflow-environment: &puppetflow-environment
services:
puppetflow:
image: ghcr.io/puppetflow/puppetflow:v2026.10.20
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
restart: unless-stopped
expose:
- 8000
@@ -44,7 +47,7 @@ services:
condition: service_started
migrate:
image: ghcr.io/puppetflow/puppetflow:v2026.10.20
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
command: ["php", "artisan", "migrate", "--force"]
restart: "no"
volumes:
@@ -54,8 +57,8 @@ services:
init-volumes:
condition: service_completed_successfully
queue:
image: ghcr.io/puppetflow/puppetflow:v2026.10.20
queue-1:
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
command: ["php", "artisan", "queue:work", "--queue=1", "--tries=1", "--timeout=630", "--sleep=3", "--max-jobs=500", "--max-time=3600"]
restart: unless-stopped
volumes:
@@ -69,8 +72,23 @@ services:
stream-server:
condition: service_started
queue-2:
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
command: ["php", "artisan", "queue:work", "--queue=2", "--tries=1", "--timeout=630", "--sleep=3", "--max-jobs=500", "--max-time=3600"]
restart: unless-stopped
volumes:
- puppetflow-framework:/app/storage
- puppetflow-execution:/app/data/execution
- puppetflow-uploads:/app/data/storage
environment: *puppetflow-environment
depends_on:
migrate:
condition: service_completed_successfully
stream-server:
condition: service_started
scheduler:
image: ghcr.io/puppetflow/puppetflow:v2026.10.20
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
command: ["php", "artisan", "schedule:work"]
restart: unless-stopped
volumes:
@@ -83,7 +101,7 @@ services:
condition: service_completed_successfully
stream-server:
image: ghcr.io/puppetflow/puppetflow-stream-server:v2026.10.20
image: ghcr.io/puppetflow/puppetflow-stream-server:v2026.11.7
restart: unless-stopped
stop_grace_period: 30s
expose:
@@ -95,22 +113,29 @@ services:
init-volumes:
image: busybox:1.37.0
command: ["sh", "-c", "touch /framework/database.sqlite && chown -R 33:33 /framework /execution /uploads"]
command: ["sh", "-c", "touch /framework/database.sqlite && chown -R 33:33 /framework /execution /uploads /browsers"]
restart: "no"
volumes:
- puppetflow-framework:/framework
- puppetflow-execution:/execution
- puppetflow-uploads:/uploads
- pinokio-downloads:/browsers
pinokio:
image: ghcr.io/puppetflow/pinokio:v2026.9.6
image: ghcr.io/puppetflow/pinokio:v2026.11.1
restart: unless-stopped
user: "33:33"
shm_size: "1gb"
volumes:
- puppetflow-execution:/app/data/execution
- pinokio-downloads:/opt/browsers
environment:
TOKEN: ${PINOKIO_TOKEN}
HOME: /tmp
XDG_CONFIG_HOME: /tmp/.config
XDG_CACHE_HOME: /tmp/.cache
LANG: ${LANG}
LANGUAGE: ${LANGUAGE}
depends_on:
init-volumes:
condition: service_completed_successfully
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "puppetflow",
"name": "Puppetflow",
"version": "v2026.10.20",
"version": "v2026.11.7",
"description": "A self-hosted browser automation platform for building, running, and monitoring JavaScript workflows powered by Puppeteer.",
"logo": "puppetflow.png",
"links": {
+7 -4
View File
@@ -4,6 +4,7 @@ stream_domain = "${domain}"
app_key = "${base64:32}"
browser_stream_secret = "${hash:32}"
pinokio_token = "${hash:32}"
instance_id = "${hash:8}"
[config]
@@ -11,17 +12,19 @@ pinokio_token = "${hash:32}"
serviceName = "puppetflow"
port = 8000
host = "${main_domain}"
https = true
[[config.domains]]
serviceName = "stream-server"
port = 6080
host = "${stream_domain}"
https = true
[config.env]
APP_URL = "https://${main_domain}"
LANG = "C.UTF-8"
LANGUAGE = "en-US"
CONNECTION_TIMEOUT_MS = "60000000"
APP_URL = "http://${main_domain}"
APP_KEY = "base64:${app_key}"
BROWSER_STREAM_PUBLIC_URL = "https://${stream_domain}"
BROWSER_STREAM_PUBLIC_URL = "http://${stream_domain}"
BROWSER_STREAM_SECRET = "${browser_stream_secret}"
PINOKIO_TOKEN = "${pinokio_token}"
PUPPETFLOW_INSTANCE_ID = "${instance_id}"
+55
View File
@@ -0,0 +1,55 @@
services:
reelsaw:
image: ghcr.io/osbytes/reelsaw:0.18.2
restart: always
# a deploy waits for running renders instead of killing them (SHUTDOWN_GRACE_SECONDS=300)
stop_grace_period: 330s
expose:
- 3000
healthcheck:
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:3000/api/health"]
interval: 10s
timeout: 5s
retries: 12
depends_on:
db:
condition: service_healthy
environment:
PORT: "3000"
DATA_DIR: /data
LOG_FILE: /data/logs/reelsaw.log
RUN_HTTP: "true"
RUN_WORKERS: "true"
TRUST_PROXY: "true"
DATABASE_URL: postgres://reelsaw:${DB_PASSWORD}@db:5432/reelsaw
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
APP_URL: ${APP_URL}
SIGNUP_MODE: ${SIGNUP_MODE}
AI_MODEL: ${AI_MODEL}
TRANSCRIPTION_MODEL: ${TRANSCRIPTION_MODEL}
OPENAI_API_KEY: ${OPENAI_API_KEY}
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
GOOGLE_GENERATIVE_AI_API_KEY: ${GOOGLE_GENERATIVE_AI_API_KEY}
GROQ_API_KEY: ${GROQ_API_KEY}
DEEPGRAM_API_KEY: ${DEEPGRAM_API_KEY}
volumes:
- data:/data
db:
image: postgres:17-alpine
restart: always
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 5s
timeout: 5s
retries: 20
environment:
POSTGRES_USER: reelsaw
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: reelsaw
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
data:
pgdata:
+20
View File
@@ -0,0 +1,20 @@
{
"id": "reelsaw",
"name": "Reelsaw",
"version": "v0.18.2",
"description": "Reelsaw is a self-hosted, AI-powered video clipper: paste a YouTube link or upload a video and it transcribes it, asks a language model for the most clippable moments, reframes the speaker into vertical 9:16 with face tracking, cuts fillers and burns in word-highlight captions. Open source (AGPL-3.0), any model provider (OpenAI, Anthropic, Google, Groq, Deepgram, or a local Ollama and Whisper), and an MCP server so agents can drive it. Deploy it on Dokploy with Docker Compose and a Postgres database in a few clicks.",
"logo": "reelsaw.png",
"links": {
"github": "https://github.com/osbytes/reelsaw",
"website": "https://reelsaw.com",
"docs": "https://github.com/osbytes/reelsaw#readme"
},
"tags": [
"video",
"ai",
"self-hosted"
],
"seoTitle": "Reelsaw Docker Compose Setup",
"seoDescription": "Self-hosted AI video clipper: long videos to vertical shorts with face-tracked reframing and word-highlight captions. Deploy Reelsaw with Docker Compose on Dokploy in minutes – free, open source, any AI provider.",
"newConfig": true
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

+26
View File
@@ -0,0 +1,26 @@
[variables]
main_domain = "${domain}"
[config]
mounts = []
[[config.domains]]
serviceName = "reelsaw"
port = 3_000
host = "${main_domain}"
[config.env]
APP_URL = "https://${main_domain}"
BETTER_AUTH_SECRET = "${base64:48}"
DB_PASSWORD = "${password:32}"
# open: anyone may sign up; the first account becomes the admin. Switch to approval or closed afterwards.
SIGNUP_MODE = "open"
# One model provider key is required before first boot (Reelsaw exits with a readable reason otherwise).
# Defaults use OpenAI for both models; any provider works, see https://github.com/osbytes/reelsaw#model-configuration
AI_MODEL = "openai:gpt-4o-mini"
TRANSCRIPTION_MODEL = "openai:whisper-1"
OPENAI_API_KEY = ""
ANTHROPIC_API_KEY = ""
GOOGLE_GENERATIVE_AI_API_KEY = ""
GROQ_API_KEY = ""
DEEPGRAM_API_KEY = ""
+10 -4
View File
@@ -1,4 +1,4 @@
# https://manual.seafile.com/latest/setup/setup_ce_by_docker/
# https://manual.seafile.com/14.0/setup/setup_ce_by_docker/
#
# This Dokploy template for seafile sets the default credentials to:
# USERNAME: admin@example.com
@@ -10,6 +10,10 @@
#
# If you have already deployed once, changes to some environment
# variables may not take effect. For example, initial passwords.
#
# Upgrading an existing Seafile 13 instance requires a backup and migration
# of any customised settings stored in its persistent volume. See:
# https://manual.seafile.com/14.0/upgrade/upgrade_docker_14.0/
services:
seafile-db:
@@ -46,7 +50,7 @@ services:
- REDIS_PASSWORD=${REDIS_PASSWORD:?Variable is not set or empty}
seafile:
image: seafileltd/seafile-mc:13.0-latest
image: seafileltd/seafile-mc:14.0.9
restart: unless-stopped
volumes:
- seafile-data:/shared
@@ -69,6 +73,8 @@ services:
- JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
- SEAFILE_LOG_TO_STDOUT=${SEAFILE_LOG_TO_STDOUT:-false}
- ENABLE_GO_FILESERVER=${ENABLE_GO_FILESERVER:-true}
- ENABLE_SEAFDAV=${ENABLE_SEAFDAV:-false}
- SEAFDAV_WORKERS=${SEAFDAV_WORKERS:-5}
- ENABLE_SEADOC=${ENABLE_SEADOC:-true}
- SEADOC_SERVER_URL=${SEADOC_SERVER_URL:?Variable is not set or empty}
- CACHE_PROVIDER=${CACHE_PROVIDER:-redis}
@@ -101,7 +107,7 @@ services:
condition: service_started
seadoc:
image: seafileltd/sdoc-server:2.0-latest
image: seafileltd/sdoc-server:2.0.11
restart: unless-stopped
volumes:
- seadoc-data:/shared
@@ -110,7 +116,7 @@ services:
- DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
- DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
- DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
- DB_NAME=${SEADOC_MYSQL_DB_NAME:-seahub_db}
- DB_NAME=${SEADOC_MYSQL_DB_NAME:-${SEAFILE_MYSQL_DB_SEAHUB_DB_NAME:-seahub_db}}
- TIME_ZONE=${TIME_ZONE:-Etc/UTC}
- JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
- NON_ROOT=${NON_ROOT:-false}
+3 -7
View File
@@ -1,19 +1,15 @@
{
"id": "seafile",
"name": "Seafile",
"version": "13.0-latest",
"version": "14.0.9",
"description": "Seafile is an open-source file sync and sharing platform. Self-host it on your own server with Dokploy, which deploys Seafile as a Docker Compose service in a few clicks.",
"logo": "seafile.svg",
"links": {
"github": "https://github.com/haiwen/seafile",
"website": "https://seafile.com",
"docs": "https://manual.seafile.com/13.0"
"docs": "https://manual.seafile.com/14.0"
},
"tags": [
"file-manager",
"file-sharing",
"storage"
],
"tags": ["file-manager", "file-sharing", "storage"],
"seoTitle": "Self-Host Seafile in minutes",
"seoDescription": "Cloud storage for file sync and sharing. Self-host Seafile on Dokploy in minutes – no manual setup needed."
}
+3 -1
View File
@@ -30,5 +30,7 @@ INIT_SEAFILE_ADMIN_EMAIL = "admin@example.com"
INIT_SEAFILE_ADMIN_PASSWORD = "${admin_password}"
ENABLE_GO_FILESERVER = "true"
ENABLE_SEAFDAV = "false"
SEAFDAV_WORKERS = "5"
ENABLE_SEADOC = "true"
SEADOC_SERVER_URL = "https://${main_domain}/sdoc-server"
SEADOC_SERVER_URL = "https://${main_domain}/sdoc-server"
+52
View File
@@ -0,0 +1,52 @@
# Dokploy template: the Dokploy Compose file minus the optional CJ Dropshipping app.
# Variables come from template.toml. Keep the rest in sync with ../docker-compose.dokploy.yml.
services:
db:
image: postgres:17
restart: unless-stopped
environment:
POSTGRES_USER: shopnex
POSTGRES_PASSWORD: shopnex
POSTGRES_DB: shopnex
volumes:
- db:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U shopnex']
interval: 5s
timeout: 5s
retries: 10
shopnex:
image: ghcr.io/shopnex-ai/shopnex:${SHOPNEX_VERSION:-v0.13.1}
pull_policy: always
restart: unless-stopped
depends_on:
db: { condition: service_healthy }
volumes:
- shopnex_data:/data
environment:
DATABASE_URL: postgres://shopnex:shopnex@db:5432/shopnex
APP_URL: ${APP_URL:-http://localhost:3000}
BETTER_AUTH_URL: ${APP_URL:-http://localhost:3000}
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET:-}
SHOPNEX_SECRET: ${SHOPNEX_SECRET:-}
TENANCY_MODE: single
DEFAULT_SHOP_NAME: ${DEFAULT_SHOP_NAME:-My Shop}
# Look for the bundled apps (stripe, cj-dropshipping) at their service names on this network
SHOPNEX_BUNDLED_APPS: docker
stripe:
image: ghcr.io/shopnex-ai/shopnex-stripe:${SHOPNEX_VERSION:-v0.13.1}
pull_policy: always
restart: unless-stopped
volumes:
- stripe_data:/data
environment:
STRIPE_APP_URL: ${STRIPE_APP_URL:-http://localhost:4600}
SHOPNEX_INTERNAL_URL: http://shopnex:3000
DATA_DIR: /data
volumes:
db:
shopnex_data:
stripe_data:

Some files were not shown because too many files have changed in this diff Show More