Compare commits

...
Author SHA1 Message Date
Mauricio SiuandClaude Opus 5.5 ad464c371b fix(feedbacks): bundle private S3 storage so the template deploys out of the box
The template shipped every S3_* variable empty while the compose requires
them, so it could never deploy. Feedbacks needs an HTTPS S3 endpoint in
production: the template now ships SeaweedFS (minio images are no longer
pullable) with a self-signed cert generated on first start and trusted via
NODE_EXTRA_CA_CERTS, plus a one-shot bucket job. External S3 can still be
used by overriding S3_*. The image digest is pinned in the compose file.

Verified on Dokploy: feedbacks returns 200, all services healthy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 20:24:23 -06:00
Mauricio SiuandGitHub 4cc1cbbe77 Merge pull request #1194 from officialsuyogdixit/codex/add-feedbacks-template
Add Feedbacks template
2026-10-07 18:18:02 -06:00
Mauricio SiuandGitHub e38ef3abd5 Merge pull request #1171 from Furox-Art/add/versitygw
feat: add VersityGW template
2026-10-07 17:48:16 -06:00
Mauricio SiuandGitHub fffa46deac Merge pull request #1182 from skender18/add-opencode
feat: add OpenCode template
2026-10-07 17:42:40 -06:00
Mauricio SiuandGitHub 1278af50b5 Merge pull request #1145 from guidoesser/add-prozesswerk-template
feat: add Prozesswerk template (text-to-BPMN, self-hosted)
2026-10-07 17:41:05 -06:00
Mauricio SiuandGitHub 816134d4d0 Merge pull request #1141 from yusuf-gundogdu/fix/libredb-studio-0.14.1
libredb-studio: bump version to 0.18.0, add a healthcheck and pass the generated secrets
2026-10-07 17:40:33 -06:00
Mauricio SiuandGitHub 34d9dca9ee Merge pull request #1149 from whollacsek/feat/supabase-sb-key-only-and-s3-backend
fix(supabase): make sb_-key-only mode work, and document the S3/R2 backend
2026-10-07 17:36:11 -06:00
Mauricio SiuandGitHub 5b41b6bbda Merge pull request #1170 from aindot/canary
New template: OpenProject 17
2026-10-07 17:34:14 -06:00
Mauricio SiuandGitHub a9061f61cf Merge pull request #1132 from ChiragAgg5k/appwrite-2.0.0
feat(appwrite): update template to 2.3.0
2026-10-07 17:32:58 -06:00
Mauricio SiuandGitHub 7a594e8eb1 Merge pull request #1185 from fclairamb/add-solidping-template
Add SolidPing template
2026-10-07 17:26:53 -06:00
Mauricio SiuandGitHub 5e4eb93f6b Merge pull request #1155 from vitabaks/autobase-2-11
Update Autobase to version 2.11
2026-10-07 17:26:41 -06:00
Mauricio SiuandGitHub cae917a8fd feat: add OpenLivery multi-client WhatsApp agent template (#1140)
* feat: add OpenLivery template

* Use canonical self-hosting documentation link
2026-10-07 17:26:25 -06:00
Mauricio SiuandGitHub 3d7dbc0f70 Merge pull request #1136 from xob0t/feat/hyperdx-template
feat: add HyperDX template
2026-10-07 17:25:48 -06:00
Mauricio SiuandGitHub ab35b586e1 Merge pull request #1133 from jdjimenez2312/update-gitea-1.27.3
fix: update Gitea with PostgreSQL blueprint template whit 1.27.3 version
2026-10-07 17:25:39 -06:00
Mauricio SiuandGitHub dae4af28be Merge pull request #1148 from kacperwyczawski/canary
feat: update seafile to 13.0
2026-10-07 17:22:49 -06:00
Mauricio SiuandGitHub c77bd2ca70 Merge pull request #1175 from reynaldichernando/feat/corsfix-template
Add Corsfix template
2026-10-07 17:21:55 -06:00
Mauricio SiuandGitHub e3ead8bfa8 Merge pull request #1174 from grovs-io/add-grovs-template
feat: add Grovs template
2026-10-07 17:17:09 -06:00
Mauricio SiuandGitHub 60fb82046e Merge pull request #1165 from duducp/fix/metabase-v0.63.18
fix: update Metabase template to v0.63.18
2026-10-07 17:16:22 -06:00
Mauricio SiuandGitHub d93f17ed53 Merge pull request #1169 from DouglasAR01/patch-1
chore: Update BentoPDF template
2026-10-07 17:11:46 -06:00
Mauricio SiuandGitHub fad0db2689 Merge pull request #1153 from kacperwyczawski/feat/opencloud
feat: add OpenCloud template
2026-10-07 17:09:31 -06:00
Mauricio SiuandGitHub a33ce26ace Merge pull request #1162 from lilsnibbi/feat/add-keyzori-template
feat: add Keyzori template
2026-10-07 17:09:01 -06:00
Mauricio SiuandGitHub 41841e1441 Merge pull request #1160 from manganate006/add-openlmnp
Add OpenLMNP template
2026-10-07 17:08:46 -06:00
Mauricio SiuandGitHub 446a0faece Merge pull request #1168 from k2so-dev/add-junctio-template
feat(template): add junctio
2026-10-07 16:59:59 -06:00
xob0tandGitHub 56bfaea59e feat: add Graylog Open template (#1135) 2026-10-07 14:34:58 -06:00
Mauricio SiuandGitHub 9cbed1788e Merge pull request #1129 from moskoweb/obscura 2026-10-07 14:34:42 -06:00
Mauricio SiuandGitHub 7a41d04323 Merge pull request #1146 from Tekipeps/template/instatic 2026-10-07 14:32:19 -06:00
Mauricio SiuandGitHub 3b41a21613 Merge pull request #1154 from Windshiftapp/chore/windshift-v0.8.8 2026-10-07 14:31:44 -06:00
Mauricio SiuandGitHub 94e39254bf Merge pull request #1193 from phwizard/feat/ethora-core 2026-10-07 14:31:07 -06:00
Mauricio SiuandGitHub 736718b4ff Merge pull request #1130 from BryanFRD/add-lfsx
feat: add LFSX template
2026-10-07 13:34:00 -06:00
Mauricio SiuandGitHub 1373a7760b Merge pull request #1131 from whollacsek/feat/supabase-envoy-gateway
fix(supabase): move the API gateway to Envoy and close five parity gaps with official self-host
2026-10-07 13:33:42 -06:00
Mauricio SiuandGitHub 10fb6bacaf Merge pull request #1172 from ablause/feat/orca-server
feat: add Orca Server template
2026-10-07 13:27:16 -06:00
Mauricio SiuandGitHub a1f497250e Merge pull request #1184 from spacewaterbear/prefect-with-auth
feat: add auth to prefect
2026-10-07 13:27:02 -06:00
Mauricio SiuandGitHub 97648ba37b Merge pull request #1202 from sipamungkas/main
feat: add databasement template
2026-10-07 11:08:40 -06:00
Mauricio SiuandGitHub cda0f75a16 Merge pull request #1192 from dseegers/activepieces-0-91-2
Update Active pieces 0.91.2
2026-10-07 11:08:29 -06:00
Mauricio SiuandGitHub 86861a7c95 Merge pull request #1196 from forrestzhang107/dexio
feat(template): add Dexio
2026-10-07 11:06:25 -06:00
Mauricio SiuandGitHub ac45a0c2db Merge pull request #1181 from tizianozonta/feat/healthchecks-template
feat: add Healthchecks template
2026-10-07 11:06:13 -06:00
Yusuf Gundogdu b5df69fddb libredb-studio: say "named engines" for the wire-compatible total
The product's own copy rule reads a numeral in front of a bare "engines" as the
count of drivers it ships, which is twenty-six. Fifty-four is the total once the
twenty-eight engines that speak an existing driver's wire protocol are counted,
so it needs the narrower noun the upstream README uses for the same figure.
2026-10-05 18:11:13 +03:00
Yusuf Gundogdu 51b419dc23 libredb-studio: pass the generated secrets to the container
Dokploy does not substitute variables in object items of an env array, so the
three [[config.env]] tables reached the container as literal ${...} and the app
started with empty ADMIN_PASSWORD, USER_PASSWORD and JWT_SECRET. The
[config.env] table form, which every other blueprint in this repo uses,
substitutes correctly. Same change as #1201.
2026-10-05 18:03:50 +03:00
Yusuf Gundogdu 386823709e libredb-studio: move to 0.18.0
0.18.0 is the current release. The description's engine count moves with it:
this release ships twenty-six drivers reaching fifty-four named engines,
where 0.17.0 reached forty-six.
2026-10-05 18:03:50 +03:00
Ragil Burhanudin Pamungkas 68e6a27ab1 fix: correct APP_DISPLAY_TIMEZONE variable in databasement template 2026-10-05 09:46:14 +07:00
Ragil Burhanudin Pamungkas 5efe1e1103 feat: add databasement template 2026-10-05 07:44:51 +07:00
Yusuf Gündoğdu c1716ad72b libredb-studio: correct the engine count in the description 2026-10-02 17:00:43 +03:00
Forrest Zhang 5459883b47 feat(template): add Dexio (logo.svg) 2026-10-01 05:10:48 -07:00
Forrest Zhang 774850fc8c feat(template): add Dexio (meta.json) 2026-10-01 05:10:47 -07:00
Forrest Zhang e6c50bedcd feat(template): add Dexio (template.toml) 2026-10-01 05:10:46 -07:00
Forrest Zhang bd491662af feat(template): add Dexio (docker-compose.yml) 2026-10-01 05:10:45 -07:00
Suyog Dixit 6d276ca4a5 Add Feedbacks template 2026-10-01 12:10:25 +05:30
Forrest Zhang 1f1b900782 feat(template): add Dexio (logo.svg) 2026-09-30 10:04:20 -07:00
Forrest Zhang e0208cd9f3 feat(template): add Dexio (meta.json) 2026-09-30 10:04:19 -07:00
Forrest Zhang 63023253dd feat(template): add Dexio (template.toml) 2026-09-30 10:04:17 -07:00
Forrest Zhang da2bc238fa feat(template): add Dexio (docker-compose.yml) 2026-09-30 10:04:15 -07:00
Taras Filatov 444fa72771 feat: add Ethora Core template 2026-09-30 15:22:24 +01:00
Daan Seegers 44bceb5b64 update meta file for activepieces 2026-09-29 22:44:30 +02:00
Yusuf GUNDOGDU 0bf1113ad7 libredb-studio: refresh to 0.17.0 and correct the engine count
0.16.2 was current when this branch was last refreshed. The description also
said sixteen engines; 0.17.0 reaches eighteen, because Prometheus and Apache
Kafka were added since.
2026-09-29 23:20:34 +03:00
Daan Seegers 4af1d7b278 Update Active pieces 0.91.2 2026-09-29 22:17:58 +02:00
Florent ClairambaultandClaude Opus 4.8 55411395de Add SolidPing monitoring template
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-09-26 15:49:42 +02:00
spacewaterbear ca7959dad9 feat: add auth to prefect 2026-09-26 14:51:35 +02:00
Reynaldi Chernando 11089396dc fix: make Corsfix auth URL configurable 2026-09-26 14:03:32 +07:00
Chirag Aggarwal 32a7d0ac70 feat(appwrite): bump template to 2.3.0
Adds the appwrite-mqtt push broker (MQTT over WebSocket on mqtt.<domain>), replaces the removed _APP_CONSOLE_URL_SCHEME with _APP_CONSOLE_URL, adds _APP_PWNED_PASSWORDS_DSN, and moves the console to 1.1.159, orchestrator to 2.2.2 and autogravity to 0.0.11 to match the stock 2.3.0 installer.
2026-09-25 19:28:20 +01:00
Chirag Aggarwal c8df2286f9 fix(appwrite): opt out of isolated deployment so build jobs can reach the API
Dokploy v0.29.3 to v0.29.13 deploys templates with isolated deployment on unless the template sets isolated = false (older releases always isolate, v0.29.14+ never does by default). That mode attaches every service to an external <appName> network and never creates <appName>_default, so the orchestrator starts build jobs on a network that does not exist and the executor puts runtimes on a network of its own. The orchestrator cannot create or join networks itself, and the repo validator rejects a networks section, so the template opts out of isolation to keep the default network every service shares.
2026-09-25 19:28:20 +01:00
Skender f7dd6b9988 opencode template: force https on generated domain 2026-09-24 22:15:26 +01:00
Skender 0fe93d8e39 opencode template: update meta.json 2026-09-24 22:10:14 +01:00
Skender 9551602df7 opencode template: update template.toml 2026-09-24 22:10:13 +01:00
Skender f9ccaf6c34 opencode template: update docker-compose.yml 2026-09-24 22:10:11 +01:00
Skender 5308f0d04a add opencode template: opencode.svg 2026-09-24 22:05:51 +01:00
Skender 82f8a12b29 add opencode template: meta.json 2026-09-24 22:05:50 +01:00
Skender 00b6c160a0 add opencode template: template.toml 2026-09-24 22:05:49 +01:00
Skender 77b708e335 add opencode template: docker-compose.yml 2026-09-24 22:05:48 +01:00
Tiziano Zonta 50da81b19a fix: disable debug mode in Healthchecks template 2026-09-24 09:28:51 +02:00
Tiziano Zonta 3be5179a10 feat: add Healthchecks template 2026-09-24 09:13:27 +02:00
Furox-Art c13cced0f0 fix(template): align VersityGW runtime configuration 2026-09-24 03:16:31 +03:00
Reynaldi Chernando 34fd42e2e5 feat: add Corsfix self-hosting template 2026-09-21 21:23:48 +07:00
Yusuf Gundogdu 7bb611134c libredb-studio: move to 0.16.2 2026-09-21 09:50:50 +03:00
Release 4e67eaa911 feat: add Grovs template 2026-09-21 09:45:30 +03:00
Yusuf Gündoğdu a1a811bbf4 libredb-studio: bump meta version to 0.16.1 2026-09-20 13:55:01 +03:00
Yusuf Gündoğdu eb7994560f libredb-studio: bump version to 0.16.1 and add healthcheck 2026-09-20 13:55:00 +03:00
Alexandre Blause ea98830477 feat(blueprint): add orca server template
Run the headless Orca runtime (orca serve) on Dokploy. Orca publishes
no container image, so the compose builds one from the pinned upstream
release AppImage (amd64 or arm64) on Ubuntu 24.04, following the
official headless Linux server guide.

The runtime is served on one domain for both the WebSocket endpoint and
the web client. ORCA_PAIRING_ADDRESS sets the address advertised in
pairing links, and ORCA_SERVE_ARGS passes extra serve flags such as
--mobile-pairing for the Orca mobile app.
2026-09-19 20:32:39 +02:00
Furox-Art e3c611741d feat: add VersityGW template
S3-compatible gateway over a POSIX backend with versioning, flat-file IAM
and the built-in WebUI exposed on the domain; S3 API and admin API ports
stay internal per the upstream Docker guide.
2026-09-18 18:35:35 +03:00
Abdullah A e9b1f1585a adjust env 2026-09-18 15:32:21 +03:00
Abdullah A c42e1c3fc8 adjust env 2026-09-18 15:14:55 +03:00
Abdullah A a145a44964 Add OpenProject 17 AiO template 2026-09-18 14:47:42 +03:00
Douglas RamírezandGitHub 851a6601f2 chore: Update Docker image to specific version 2026-09-17 13:34:00 -05:00
Douglas RamírezandGitHub 1b2e06cb4b chore: Change port from 80 to 8080 in template.toml 2026-09-17 13:22:49 -05:00
Douglas RamírezandGitHub 78f0e98b86 chore: Update Docker image and exposed port in compose file 2026-09-17 13:20:56 -05:00
Web Artisan 259eb8a402 fix(junctio): widen the generated secret 2026-09-17 17:30:52 +03:00
Web Artisan a880b39d48 fix(junctio): generate the secret as hex 2026-09-17 17:22:04 +03:00
Web Artisan ad5a86fc61 feat(template): add junctio 2026-09-17 17:14:25 +03:00
Yusuf GUNDOGDU b7e522a9a0 libredb-studio: bump version to 0.16.0 2026-09-17 13:07:04 +03:00
Chirag Aggarwal f9c496fa57 style(appwrite): drop stray blank line to keep the diff focused 2026-09-17 10:29:35 +01:00
Chirag Aggarwal e65859bced feat(appwrite): bump template to 2.2.0
Picks up the 2.1 and 2.2 releases on top of the 2.0 rebuild: console
1.1.96 self-hosted build, orchestrator 2.2.0, the autogravity service, and
the env changes from those releases (executions are ClickHouse only, the
pool adapter and legacy logging providers are gone).
2026-09-17 10:25:33 +01:00
lilsnibbi e52b86baef fix(keyzori): simplify template and align container routing 2026-09-17 16:44:55 +10:00
Carlos Dorneles 18c3bf2858 fix: keep /dev/urandom mount recommended by Metabase docs 2026-09-16 18:28:28 -03:00
Carlos Dorneles bf7e3e9d69 fix: update Metabase template to v0.63.18
- Bump metabase/metabase image from v0.50.8 to v0.63.18
- Bump postgres from 14 to 16 and persist data with a named volume
- Generate the database password via the password helper instead of
  hardcoding it
- Add restart policy, expose port and depends_on with healthchecks
2026-09-16 18:26:53 -03:00
lilsnibbi 35b1f66c7a chore: limit Keyzori contribution to blueprint files 2026-09-16 14:20:33 +10:00
lilsnibbi e1c13b9bae chore: use latest Keyzori image in template 2026-09-16 14:02:54 +10:00
lilsnibbi b21588b34e test: cover Keyzori template deployment and persistence 2026-09-16 13:26:34 +10:00
Jeremie e8d2615c2b Add OpenLMNP template 2026-09-14 19:05:06 +02:00
lilsnibbi 63adcdadc2 feat: add Keyzori template 2026-09-14 11:47:44 +10:00
Yusuf Gundogdu 50f0b5f9d9 libredb-studio: bump version to 0.15.0 2026-09-12 03:40:12 +03:00
Vitaliy Kukharik 8e50aaeaa3 Update Autobase to version 2.11
Bump autobase service images (console_ui, console_db, console_api) to 2.11.0.
2026-09-11 20:45:10 +02:00
Stefan Ernst aa6354bda0 chore: update Windshift to v0.8.8 2026-09-11 14:21:37 +02:00
Kacper Wyczawski 2a725ce0fc feat: add OpenCloud template 2026-09-10 10:23:46 +02:00
William HollacsekandClaude Opus 5 8d416a8a87 Make sb_-only mode work, and name the S3 settings nobody documents
Clearing ANON_KEY and SERVICE_ROLE_KEY is a supported mode — Envoy guards
every legacy branch — but four places broke when you did it. storage,
studio, functions and the realtime healthcheck all read the legacy pair
directly, and storage can never use an sb_ key because it calls PostgREST
at rest:3000 and never traverses the gateway. All four now resolve
${ANON_KEY:-${ANON_KEY_ASYMMETRIC}}. Verified with docker compose config
against a real deployment env: all six land on the ES256 JWTs and the
healthcheck token is non-empty.

Storage S3 block, with the three traps: REGION is read as the S3 signing
region when STORAGE_S3_REGION is unset, and this template ships it as
"stub"; STORAGE_S3_DISABLE_CHECKSUM is needed for providers that reject
the SDK's CRC32 and appears in no upstream file; GLOBAL_S3_PROTOCOL is
in the official compose and read nowhere in supabase/storage. Also noted
that imgproxy needs no S3 config — storage hands it a presigned URL.

STORAGE_TENANT_ID is the top-level key prefix, so it is permanent.

Two more warnings from a real first deploy: the domain is interpolated at
creation, so editing the Domains tab later leaves API_EXTERNAL_URL — and
therefore every token's iss — pointing at the old host; and the ES256
six-value swap does not touch the legacy pair.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 15:48:05 -05:00
Kacper Wyczawski b8c5f2bab5 fix: actually remove some of the patches suggested by copilot because they were stupid and outdated 2026-09-09 20:46:18 +02:00
Kacper Wyczawski 914e393f51 fix: incorrect version 2026-09-09 20:40:50 +02:00
Kacper Wyczawski f1295b6518 fix: apply patches suggested by copilot 2026-09-09 20:40:01 +02:00
Kacper Wyczawski d718f761b1 fix: accidentally deleted labels 2026-09-09 20:22:59 +02:00
Kacper Wyczawski 5a8b088c49 fix: remove explicit network config 2026-09-09 20:16:50 +02:00
Kacper Wyczawski 91061251de fix: missing traeffc labels for seafile 2026-09-09 20:13:01 +02:00
Kacper Wyczawski 4d90eab114 feat: update seafile to 13.0 2026-09-09 19:39:34 +02:00
Tekena Solomon bede4dbd80 Merge branch 'template/instatic' of github.com:Tekipeps/templates into template/instatic 2026-09-09 16:15:32 +01:00
Tekena Solomon 6ae5bb5103 Merge branch 'canary' of github.com:Tekipeps/templates into template/instatic 2026-09-09 16:14:50 +01:00
Tekena Solomon e02190ab18 chore: bump Instatic to 0.0.18
Signed-off-by: Tekena Solomon <tekena157@gmail.com>
2026-09-09 16:12:03 +01:00
Guido Esser d742938c5a feat: add Prozesswerk template (text-to-BPMN, self-hosted) 2026-09-09 11:30:53 +02:00
yusuf-gundogdu 8f836f5f28 libredb-studio: bump version to 0.14.1 2026-09-08 08:51:33 +03:00
Andrés Sarrazola aefe3143ce Use canonical self-hosting documentation link 2026-09-07 16:48:19 -05:00
Andrés Sarrazola 543ce0b9a5 feat: add OpenLivery template 2026-09-07 16:28:17 -05:00
xob0t 4fd2873a67 fix: map HyperDX exponential histogram metrics 2026-09-06 13:20:34 +03:00
xob0t df88ec0972 docs: record HyperDX web validation 2026-09-06 13:13:52 +03:00
xob0t 4dd732170c feat: add tested HyperDX template 2026-09-06 13:07:55 +03:00
juancho 80a50aa0d0 feat: add Gitea with PostgreSQL Security & Privacy Settings 2026-09-05 23:28:37 -05:00
juancho a9e07bf677 fix: update Gitea with PostgreSQL blueprint template whit 1.27.3 version 2026-09-05 23:05:32 -05:00
William HollacsekandClaude Opus 5 78e1b776ad Pass SB_JWT_ISSUER to Edge Functions, and correct the ES256 instructions
Three fixes found by deploying this blueprint and testing it surface by surface.

The functions service sets SUPABASE_URL to the internal gateway address, while
Auth signs tokens with API_EXTERNAL_URL as the issuer. Supabase's own edge
function JWT helper (_shared/jwt/default.ts) derives its expected issuer from
SUPABASE_URL unless SB_JWT_ISSUER is set, so it rejects every valid token with
an issuer mismatch. Passing SB_JWT_ISSUER through fixes that, and is inert for
functions that do not read it.

The ES256 procedure had three problems. It told you to clone supabase/supabase,
which is a very large monorepo, for one 7 KB script; fetching that file is
enough and node is its only requirement. It omitted --update-env, without which
only four of the six values are printed at all — ANON_KEY_ASYMMETRIC and
SERVICE_ROLE_KEY_ASYMMETRIC reach .env alone, so "replace all six with the ones
it prints" could not be followed. And the script exits 1 after writing the keys,
because it then looks for a docker-compose.yml to patch that is not there and
need not be, since this blueprint already wires all four variables; that made a
successful run look like a failure.

Also documents that pg_graphql is not installed on a fresh database, so the
/graphql/v1 route the gateway already exposes answers with an error until one
statement is run. The hosted platform ships it enabled, so this is a real
difference for code moving across.

Verified against a live deployment: the documented steps run as written, all six
values land, and the issuer now matches so edge-function JWT verification
succeeds. Blueprint validators and generate-meta --check all pass.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017DjX4ai6xiixeV8knW9Hpa
2026-09-05 15:12:19 -05:00
Chirag Aggarwal 4699cf0de8 feat(appwrite): update template to 2.0.0
Appwrite 2.0 replaces the engine, ships the new root-path console and
defaults new installs to PostgreSQL, so the template is rebuilt from the
stock 2.0.0 installer output rather than bumped:

- PostgreSQL (appwrite/postgres) is the database; MariaDB/MongoDB and
  their init mounts are dropped.
- Combined worker/scheduler topology (appwrite-worker, appwrite-task-scheduler)
  replaces the per-queue worker containers.
- New services: orchestrator (builds), clickhouse (usage/executions),
  appwrite-geo; executor bumped to 0.29.0, console to appwrite/new.
- Console is served at / with the API on /v1 and /.well-known and the
  realtime server on /v1/realtime.
- Runtime and build containers join the stack's own Compose network and
  the builds volume is pinned per project via COMPOSE_PROJECT_NAME.
2026-09-05 16:29:25 +01:00
William HollacsekandClaude Opus 5 7fca9845cf Warn that a domain without TLS needs the http scheme
The template generates SUPABASE_PUBLIC_URL, API_EXTERNAL_URL and
ADDITIONAL_REDIRECT_URLS with https://, which is right for a public domain with
a certificate. Dokploy creates the template's domain with none, so until one is
enabled the domain answers on http only and those three values point at a
scheme that does not respond.

Measured on a live deploy: the stack reports 11/11 healthy and the gateway
answers http with Studio's 401 basic-auth challenge, while https returns 404 —
so nothing looks broken, but Studio's own calls fail, Envoy's CORS check
compares Origin against the https string and refuses, and GoTrue builds its
issuer, OAuth redirects and email links from the dead scheme.

Also records that Let's Encrypt cannot rescue a private address: an sslip.io
name pointing at a Tailscale 100.x or a LAN address cannot be validated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 20:34:39 -05:00
William HollacsekandClaude Opus 5 e309adc45b Close five parity gaps with official Supabase self-host
A multi-agent audit of the Envoy port compared the blueprint against
supabase/supabase@master, against Dokploy's own source, and against the repo's
conventions. Three findings survived an adversarial refute pass and two more
were traced to the same cause. All five are divergences from official that
predate this branch, but they sit on the surface this branch touches.

- template.toml: API_EXTERNAL_URL gains /auth/v1, matching official
  docker/.env.example:101 since supabase e7abda8d (PR #47640, 2026-07-07).
  Without it GoTrue advertises https://<domain>/callback for every OAuth and
  SAML flow, and Envoy's lds routes bare /callback to the `/` catch-all — that
  is Studio, not auth. Measured: /auth/v1/authorize returns GoTrue's 400, while
  /callback returns Studio's 401 basic-auth challenge.

- template.toml: add the /volumes/functions/deno.jsonc import map and point
  main/index.ts at it, and take official's `hello` sample. Upstream shipped
  these in 9ef9f1b8 (2026-08-14) and f5f897a2 (2026-08-28); the blueprint's
  functions volume was still at the 2023-era deno.land/std sample with
  importMapPath = null, so no function written against current Supabase docs
  could resolve @supabase/server. Also injects SUPABASE_FUNCTION_SLUG.

- docker-compose.yml: restore official's SELinux flags on the shared functions
  directory — `:z` not `:Z`, and `:ro` back on Studio's copy. `:Z` applies a
  private MCS label, so mounting one host directory into two containers with
  it revokes the first container's access on an SELinux host. Every other bind
  flag in the file already matched official; these three were the only drift.

- meta.json: version becomes 2026.08.03-3. The images are unchanged from
  official's 2026.08.03 snapshot, so 2026.08.17 advertised a state the template
  does not ship.

- template.toml: API_GW_HTTP_PORT is inert, because the port is pinned by
  `expose` and by the domain block. The comment above it said the opposite.

- instructions.md: two operational gaps the audit surfaced. Renaming kong to
  api-gw makes Dokploy reject a redeploy of an existing service until the
  domain's Service Name is edited. And the Postgres data directory is a bind
  mount, so Dokploy's Volume Backups cannot see it, deleting the service
  destroys it regardless of the delete-volumes toggle, and "redeploy with fresh
  volumes" does not reset the database.

Re-verified end to end on Docker 29.4.0: all three repo validators pass, all 11
services healthy, and the eight original checks still pass. Two new ones: the
hello sample returns 200 {"message":"Hello from Edge Functions!"} for both
sb_publishable_ and sb_secret_ keys — proving the import map resolves — and
/auth/v1/settings and /auth/v1/authorize reach GoTrue.

Note a deliberate behaviour change from official: the new sample declares
auth: ["publishable","secret"], so a legacy anon JWT now gets a 401 with an
explanatory INVALID_API_KEY body where the old sample accepted it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 20:13:49 -05:00
William HollacsekandClaude Opus 5 615f8d8d69 Move the Supabase blueprint from Kong to the Envoy API gateway
Official Supabase made Envoy the default API gateway on 2026-08-11 (PR #48153,
self-hosted release 0.8.0) and shipped a CORS fix for /pg/ routes on 2026-08-17
(PR #49136) that only Envoy carries. This blueprint still shipped Kong.

Changes:
- docker-compose.yml: rename `kong` to `api-gw`, on envoyproxy/envoy:v1.39.0.
  TCP healthcheck because the image has no curl or wget. Expose 8000 only —
  Envoy has no 8443 listener. Env vars follow official: ANON_KEY /
  SERVICE_ROLE_KEY replace SUPABASE_ANON_KEY / SUPABASE_SERVICE_KEY, every
  KONG_* is dropped, and SUPABASE_PUBLIC_URL is added for #49136. Rename the
  three internal references to the gateway, and add official's `functions`
  healthcheck.
- template.toml: swap the two Kong mounts for the four envoy ones, copied from
  supabase/supabase@master. serviceName becomes `api-gw`; KONG_HTTP_PORT
  becomes API_GW_HTTP_PORT and KONG_HTTPS_PORT is dropped.
- meta.json: version marker names the Envoy switch.
- instructions.md: Kong replaced by Envoy in all four places, plus a note that
  Studio's basic-auth credential is a SHA1+base64 hash of DASHBOARD_PASSWORD
  computed by Envoy's entrypoint at startup.

Two Dokploy adaptations, deliberate and both needed:
- No `networks:` aliases block and no `ports:` mapping — validate-docker-compose
  rejects both. The alias exists upstream only for backwards compatibility, and
  nothing here still points at `kong`.
- cds.yaml points the realtime cluster at `realtime`, not at official's
  `realtime-dev.supabase-realtime` container_name, because this blueprint sets
  no container_name. lds.template.yaml is byte-identical to official, so the
  Host header realtime uses for tenant resolution is unchanged.

Verified locally against Docker 29.4.0 / Compose v5.1.2, rendering the template
the way Dokploy does. All 11 services healthy; legacy keys work; sb_publishable_
is blocked by RLS while sb_secret_ reads the row; Studio basic auth challenges
and accepts; /realtime/v1/api/tenants and /realtime/v1/api/openapi return 403
and the /rest/v1/ root stays service-role only; an OPTIONS to /pg/ returns
access-control-allow-origin matching SUPABASE_PUBLIC_URL; a realtime channel
join over ?apikey=sb_publishable_… replies status ok; and the sample edge
function returns its response.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 14:59:48 -05:00
moskoweb 271aa8224f fix(obscura): support token auth in CDP websocket URL 2026-09-03 14:07:43 +00:00
BryanFRD fa06c0d2e2 feat: add LFSX template 2026-09-03 10:34:24 +02:00
moskoweb ef51d95292 feat(obscura): expose authenticated CDP and MCP endpoints 2026-09-02 18:04:05 +00:00
moskoweb 8a191639b6 feat: add Obscura Browser template 2026-09-02 12:52:58 +00:00
Mauricio Siu 1f1e3b4651 fix(instatic): accept both https and http public origins so the setup wizard works before HTTPS is enabled 2026-08-24 20:55:32 -06:00
Tekena Solomon 0179ab425c fix: add init container to fix Instatic storage volume permissions
Signed-off-by: Tekena Solomon <tekena157@gmail.com>
2026-08-20 04:45:21 +01:00
Tekena Solomon 1f7fd68b56 feat: add Instatic template
Instatic is a self-hosted, open-source visual CMS combining a canvas
editor, content engine, and static site publisher. Deployed as a
single container backed by SQLite, with uploads and DB on one
persistent volume.

Signed-off-by: Tekena Solomon <tekena157@gmail.com>
2026-08-20 04:32:30 +01:00
126 changed files with 6862 additions and 1416 deletions
+2 -2
View File
@@ -2,7 +2,7 @@ version: "3.8"
services:
activepieces:
image: activepieces/activepieces:0.35.0
image: activepieces/activepieces:0.91.2
restart: unless-stopped
depends_on:
@@ -32,7 +32,7 @@ services:
AP_TEMPLATES_SOURCE_URL: https://cloud.activepieces.com/api/v1/flow-templates
postgres:
image: postgres:14
image: postgres:17
restart: unless-stopped
environment:
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "activepieces",
"name": "Activepieces",
"version": "0.35.0",
"version": "0.91.2",
"description": "Open-source no-code business automation tool. An alternative to Zapier, Make.com, and Tray.",
"logo": "activepieces.svg",
"links": {
File diff suppressed because it is too large Load Diff
+2 -3
View File
@@ -1,7 +1,7 @@
{
"id": "appwrite",
"name": "Appwrite",
"version": "1.9.5",
"version": "2.3.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",
@@ -12,8 +12,7 @@
"tags": [
"database",
"firebase",
"mariadb",
"mongodb",
"postgresql",
"hosting",
"self-hosted"
]
+105 -79
View File
@@ -2,28 +2,36 @@
main_domain = "${domain}"
functions_domain = "functions.${main_domain}"
sites_domain = "sites.${main_domain}"
mqtt_domain = "mqtt.${main_domain}"
openssl_key = "${password:32}"
db_root_pw = "${password:32}"
db_user_pw = "${password:32}"
notifications_tracking_secret = "${password:32}"
db_pw = "${password:32}"
usage_pw = "${password:32}"
executor_secret = "${password:32}"
jobs_secret = "${password:32}"
geo_secret = "${password:32}"
[config]
# Build jobs and runtimes join <appName>_default, which isolated deployments never create
# (every service sits on the external <appName> network instead).
isolated = false
env = [
"_APP_ENV=production",
"_APP_EDITION=self-hosted",
"_APP_LOCALE=en",
"_APP_POOL_ADAPTER=stack",
"_APP_WORKER_PER_CORE=6",
"_APP_OPTIONS_ABUSE=enabled",
# Requires HTTPS to be enabled on the main domain in Dokploy (Domains tab).
# Makes Appwrite generate https:// URLs (e.g. APPWRITE_FUNCTION_API_ENDPOINT for
# Functions) and reject plain-HTTP API calls; over plain HTTP the console cannot log in.
"_APP_OPTIONS_FORCE_HTTPS=enabled",
"_APP_OPTIONS_ABUSE_INCREASED_LIMIT_PROJECTS=",
"_APP_OPTIONS_FORCE_HTTPS=disabled",
"_APP_OPTIONS_ROUTER_FORCE_HTTPS=disabled",
"_APP_OPTIONS_ROUTER_PROTECTION=disabled",
"_APP_ROUTER_AUTO_CERTIFICATES=enabled",
"_APP_LOCKING_ENABLED=enabled",
"_APP_OPENSSL_KEY_V1=${openssl_key}",
"_APP_NOTIFICATIONS_TRACKING_SECRET=${notifications_tracking_secret}",
"_APP_DOMAIN=${main_domain}",
"_APP_CONSOLE_DOMAIN=${main_domain}",
"_APP_CONSOLE_URL=",
"_APP_CONSOLE_TRUSTED_PROJECTS=",
"_APP_CUSTOM_DOMAIN_DENY_LIST=example.com,test.com,app.example.com",
"_APP_DOMAIN_FUNCTIONS=${functions_domain}",
@@ -41,6 +49,15 @@ env = [
"_APP_CONSOLE_SCHEMA=appwriteio",
"_APP_CONSOLE_SESSION_ALERTS=disabled",
"_APP_CONSOLE_COUNTRIES_DENYLIST=",
"_APP_CONSOLE_GITHUB_APP_ID=",
"_APP_CONSOLE_GITHUB_SECRET=",
"_APP_CONSOLE_GITLAB_APP_ID=",
"_APP_CONSOLE_GITLAB_SECRET=",
"_APP_CONSOLE_GITLAB_ENDPOINT=",
"_APP_CONSOLE_BITBUCKET_APP_ID=",
"_APP_CONSOLE_BITBUCKET_SECRET=",
"_APP_CONSOLE_GOOGLE_APP_ID=",
"_APP_CONSOLE_GOOGLE_SECRET=",
"_APP_SYSTEM_EMAIL_NAME=Appwrite",
"_APP_SYSTEM_EMAIL_ADDRESS=noreply@appwrite.io",
"_APP_SYSTEM_TEAM_EMAIL=team@appwrite.io",
@@ -49,33 +66,52 @@ env = [
"_APP_EMAIL_CERTIFICATES=",
"_APP_COMPRESSION_ENABLED=enabled",
"_APP_COMPRESSION_MIN_SIZE_BYTES=1024",
"_APP_USAGE_STATS=enabled",
"_APP_USAGE_AGGREGATION_INTERVAL=30",
"_APP_STATS_RESOURCES_INTERVAL=30",
"_APP_LOGGING_PROVIDER=",
"_APP_LOGGING_CONFIG=",
"_APP_LOGGING_CONFIG_REALTIME=",
"_APP_EXPERIMENT_LOGGING_PROVIDER=",
"_APP_EXPERIMENT_LOGGING_CONFIG=",
"_APP_LOGGING_FORMAT=pretty",
"_APP_GEO_ENDPOINT=http://appwrite-geo/v1",
"_APP_GEO_SECRET=${geo_secret}",
"_APP_REDIS_HOST=redis",
"_APP_REDIS_PORT=6379",
"_APP_REDIS_USER=",
"_APP_REDIS_PASS=",
"_APP_DB_ADAPTER=mongodb",
"_APP_DB_HOST=mongodb",
"_APP_DB_PORT=27017",
"_APP_DB_ADAPTER=postgresql",
"_APP_DB_HOST=postgresql",
"_APP_DB_PORT=5432",
"_APP_DB_SCHEMA=appwrite",
"_APP_DB_USER=user",
"_APP_DB_PASS=${db_user_pw}",
"_APP_DB_ROOT_PASS=${db_root_pw}",
"_APP_DB_PASS=${db_pw}",
"_APP_DATABASE_SHARED_TABLES=",
"_APP_DATABASE_SHARED_NAMESPACE=",
"_APP_DB_ADAPTER_VECTORSDB=",
"_APP_DB_HOST_VECTORSDB=",
"_APP_DB_PORT_VECTORSDB=",
"_APP_LIMIT_DATABASE_BATCH=100",
"_APP_DOCUMENTSDB=disabled",
"_APP_DB_ADAPTER_DOCUMENTSDB=mongodb",
"_APP_DB_HOST_DOCUMENTSDB=mongodb",
"_APP_DB_PORT_DOCUMENTSDB=27017",
"_APP_DB_SCHEMA_DOCUMENTSDB=",
"_APP_DB_USER_DOCUMENTSDB=",
"_APP_DB_PASS_DOCUMENTSDB=",
"_APP_CONNECTIONS_DATABASE_DOCUMENTSDB=",
"_APP_VECTORSDB=disabled",
"_APP_DB_ADAPTER_VECTORSDB=postgresql",
"_APP_DB_HOST_VECTORSDB=postgresql",
"_APP_DB_PORT_VECTORSDB=5432",
"_APP_DB_SCHEMA_VECTORSDB=",
"_APP_DB_USER_VECTORSDB=",
"_APP_DB_PASS_VECTORSDB=",
"_APP_CONNECTIONS_DATABASE_VECTORSDB=",
"_APP_EMBEDDING=disabled",
"_APP_USAGE_STATS=enabled",
"_APP_USAGE_PASS=${usage_pw}",
"_APP_CONNECTIONS_DB_USAGE=http://appwrite:${usage_pw}@clickhouse:8123/appwrite",
"_APP_POOL_SIZE_USAGE=2",
"_APP_CONNECTIONS_DB_EXECUTIONS=http://appwrite:${usage_pw}@clickhouse:8123/appwrite",
"_APP_POOL_SIZE_EXECUTIONS=2",
"_APP_MAINTENANCE_RETENTION_USAGE_TTL=180",
"_APP_STATS_USAGE_QUEUE_NAME=v1-stats-usage",
"_APP_STATS_RESOURCES_QUEUE_NAME=v1-stats-resources",
"_APP_STATS_RESOURCES_INTERVAL=3600",
"_APP_MQTT_REPLAY_DEPTH=5",
"_APP_MQTT_MAX_PACKET_SIZE=64000",
"_APP_SMTP_HOST=",
"_APP_SMTP_PORT=",
"_APP_SMTP_SECURE=",
@@ -84,8 +120,10 @@ env = [
"_APP_SMS_PROVIDER=",
"_APP_SMS_FROM=",
"_APP_SMS_PROJECTS_DENY_LIST=",
"_APP_PWNED_PASSWORDS_DSN=none://localhost",
"_APP_STORAGE_LIMIT=30000000",
"_APP_STORAGE_PREVIEW_LIMIT=20000000",
"_APP_AUTOGRAVITY_HOST=http://appwrite-autogravity:8080",
"_APP_STORAGE_ANTIVIRUS=disabled",
"_APP_STORAGE_ANTIVIRUS_HOST=clamav",
"_APP_STORAGE_ANTIVIRUS_PORT=3310",
@@ -112,21 +150,26 @@ env = [
"_APP_STORAGE_WASABI_REGION=eu-central-1",
"_APP_STORAGE_WASABI_BUCKET=",
"_APP_COMPUTE_SIZE_LIMIT=30000000",
"_APP_COMPUTE_BUILD_TIMEOUT=900",
"_APP_COMPUTE_BUILD_SIZE_LIMIT=2000000000",
"_APP_COMPUTE_BUILD_TIMEOUT=2700",
"_APP_COMPUTE_CPUS=0",
"_APP_COMPUTE_MEMORY=0",
"_APP_COMPUTE_INACTIVE_THRESHOLD=60",
"_APP_COMPUTE_MAINTENANCE_INTERVAL=3600",
"_APP_COMPUTE_RUNTIMES_NETWORK=dokploy-network",
"_APP_OPEN_RUNTIMES_NFT=enabled",
"_APP_FUNCTIONS_TIMEOUT=900",
"_APP_FUNCTIONS_CREATION_ABUSE_LIMIT=5000",
"_APP_FUNCTIONS_SCHEDULE_SPREAD=0",
"_APP_FUNCTIONS_RUNTIMES=node-22,python-3.12,php-8.3,ruby-3.3,dart-3.5,go-1.23,rust-1.83,bun-1.1,deno-1.46,java-21.0,dotnet-8.0",
"_APP_SITES_TIMEOUT=900",
"_APP_SITES_RUNTIMES=static-1,node-22",
"_APP_EXECUTOR_SECRET=${executor_secret}",
"_APP_EXECUTOR_HOST=http://openruntimes-executor/v1",
"_APP_EXECUTOR_IMAGES=openruntimes/node:v5-22,openruntimes/python:v5-3.12,openruntimes/php:v5-8.3,openruntimes/static:v5-1",
"_APP_OPEN_RUNTIMES_NFT=enabled",
"_APP_EXECUTOR_CONNECTION_STORAGE=local://localhost",
"_APP_JOBS_HOST=http://orchestrator:8080",
"_APP_JOBS_SECRET=${jobs_secret}",
"_APP_JOBS_ENDPOINT=http://appwrite",
"_APP_BROWSER_HOST=http://appwrite-browser:3000/v1",
"_APP_WORKER_SCREENSHOTS_ROUTER=http://appwrite",
"_APP_DOCKER_HUB_USERNAME=",
@@ -138,7 +181,6 @@ env = [
"_APP_MAINTENANCE_RETENTION_AUDIT=1209600",
"_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=15778800",
"_APP_MAINTENANCE_RETENTION_ABUSE=86400",
"_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000",
"_APP_MAINTENANCE_RETENTION_SCHEDULES=86400",
"_APP_INTERVAL_DOMAIN_VERIFICATION=120",
"_APP_INTERVAL_CLEANUP_STALE_EXECUTIONS=300",
@@ -153,60 +195,50 @@ env = [
"_APP_VCS_GITHUB_CLIENT_ID=",
"_APP_VCS_GITHUB_CLIENT_SECRET=",
"_APP_VCS_GITHUB_WEBHOOK_SECRET=",
"_APP_VCS_GITEA_ENDPOINT=",
"_APP_VCS_GITEA_BROWSER_ENDPOINT=",
"_APP_VCS_GITEA_CLIENT_ID=",
"_APP_VCS_GITEA_CLIENT_SECRET=",
"_APP_VCS_GITEA_WEBHOOK_SECRET=",
"_APP_VCS_GITLAB_ENDPOINT=",
"_APP_VCS_GITLAB_CLIENT_ID=",
"_APP_VCS_GITLAB_CLIENT_SECRET=",
"_APP_VCS_GITLAB_WEBHOOK_SECRET=",
"_APP_VCS_BITBUCKET_CLIENT_ID=",
"_APP_VCS_BITBUCKET_CLIENT_SECRET=",
"_APP_VCS_BITBUCKET_WEBHOOK_SECRET=",
"_APP_VCS_ORIGIN_CLIENT_ID=",
"_APP_VCS_ORIGIN_PRIVATE_KEY=",
"_APP_VCS_WEBHOOK_URL=",
"_APP_MIGRATION_HOST=appwrite",
"_APP_MIGRATIONS_FIREBASE_CLIENT_ID=",
"_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET=",
"_APP_ASSISTANT_OPENAI_API_KEY=",
]
[[config.mounts]]
filePath = "mongo-init.js"
content = """// mongo-init.js
// Switch to the admin database
const adminDb = db.getSiblingDB('admin');
// Get username and password from environment variables
const username = process.env.MONGO_INITDB_USERNAME;
const password = process.env.MONGO_INITDB_PASSWORD;
const database = process.env.MONGO_INITDB_DATABASE;
// Create the user
adminDb.createUser({
user: username,
pwd: password,
roles: [
{ role: 'readWrite', db: database }
]
});
"""
[[config.mounts]]
filePath = "mongo-entrypoint.sh"
content = """#!/bin/bash
set -e
# Fix keyfile permissions if mounted from volume
KEYFILE_PATH="/data/keyfile/mongo-keyfile"
if [ ! -f "$KEYFILE_PATH" ]; then
echo "Generating random MongoDB keyfile..."
mkdir -p /data/keyfile
openssl rand -base64 756 > "$KEYFILE_PATH"
fi
chmod 400 "$KEYFILE_PATH"
chown mongodb:mongodb "$KEYFILE_PATH" 2>/dev/null || chown 999:999 "$KEYFILE_PATH"
# Use MongoDB's standard entrypoint with our command
exec docker-entrypoint.sh mongod --replSet rs0 --bind_ip_all --auth --keyFile "$KEYFILE_PATH"
"""
[[config.domains]]
serviceName = "appwrite-console"
port = 3000
host = "${main_domain}"
path = "/"
[[config.domains]]
serviceName = "appwrite"
port = 80
host = "${main_domain}"
path = "/"
path = "/v1"
[[config.domains]]
serviceName = "appwrite"
port = 80
host = "${main_domain}"
path = "/.well-known"
[[config.domains]]
serviceName = "appwrite-realtime"
port = 80
host = "${main_domain}"
path = "/v1/realtime"
[[config.domains]]
serviceName = "appwrite"
@@ -221,13 +253,7 @@ host = "${functions_domain}"
path = "/"
[[config.domains]]
serviceName = "appwrite-console"
port = 80
host = "${main_domain}"
path = "/console"
[[config.domains]]
serviceName = "appwrite-realtime"
port = 80
host = "${main_domain}"
path = "/v1/realtime"
serviceName = "appwrite-mqtt"
port = 8083
host = "${mqtt_domain}"
path = "/"
+1 -1
View File
@@ -1,6 +1,6 @@
services:
autobase-console:
image: autobase/console:2.10.0
image: autobase/console:2.11.0
restart: unless-stopped
expose:
- "80"
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "autobase",
"name": "Autobase",
"version": "2.10.0",
"version": "2.11.0",
"description": "Autobase for PostgreSQL® is an open-source alternative to cloud-managed databases (self-hosted DBaaS).",
"links": {
"github": "https://github.com/vitabaks/autobase",
+2 -2
View File
@@ -2,7 +2,7 @@ version: "3.8"
services:
bentopdf:
image: bentopdf/bentopdf:latest
image: ghcr.io/alam00000/bentopdf-simple:sha-72d20bb
restart: unless-stopped
expose:
- 80
- 8080
+1 -1
View File
@@ -4,6 +4,6 @@ main_domain = "${domain}"
[config]
[[config.domains]]
serviceName = "bentopdf"
port = 80
port = 8080
host = "${main_domain}"
path = "/"
+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 400" width="400" height="400" stroke-width="18" stroke="#fff" fill="#595ce7">
<path fill-rule="evenodd" d="m200 390c-105.1 0-190-84.9-190-190 0-105.1 84.9-190 190-190 105.1 0 190 84.9 190 190 0 105.1-84.9 190-190 190z"/>
<path fill-rule="evenodd" d="m262.6 368.6c-65.2 0-117.9-75.4-117.9-168.7 0-93.3 52.7-168.7 117.9-168.7 65.1 0 117.8 75.4 117.8 168.7 0 93.3-52.7 168.7-117.8 168.7z"/>
<path fill-rule="evenodd" d="m319.9 330.7c-31.8 0-57.4-58.2-57.4-130.2 0-72 25.6-130.1 57.4-130.1 31.7 0 57.3 58.1 57.3 130.1 0 72-25.6 130.2-57.3 130.2z"/>
<path fill="#fff" fill-rule="evenodd" d="m364.5 267.5c-14.1 0-25.6-29.9-25.6-67 0-37 11.5-67 25.6-67 14.1 0 25.5 30 25.5 67 0 37.1-11.4 67-25.5 67z"/>
</svg>

After

Width:  |  Height:  |  Size: 768 B

+85
View File
@@ -0,0 +1,85 @@
version: "3.8"
services:
corsfix:
image: ghcr.io/corsfix/corsfix-app:8899bb15e71c7238285ccefc4c95a0cd47daeaf0
platform: linux/amd64
restart: unless-stopped
expose:
- "3000"
environment:
MONGODB_URI: mongodb://corsfix:${MONGODB_PASSWORD}@mongodb:27017/db?authSource=admin
REDIS_URI: redis://default:${REDIS_PASSWORD}@redis:6379
KEK_VERSION: KEK_VERSION_1
KEK_VERSION_1: ${KEK_VERSION_1}
AUTH_SECRET: ${AUTH_SECRET}
AUTH_TRUST_HOST: "true"
AUTH_URL: ${AUTH_URL}
PROXY_DOMAIN: ${PROXY_DOMAIN}
DISABLE_SIGNUP: ${DISABLE_SIGNUP:-false}
depends_on:
mongodb:
condition: service_healthy
redis:
condition: service_healthy
corsfix-proxy:
image: ghcr.io/corsfix/corsfix-proxy:8899bb15e71c7238285ccefc4c95a0cd47daeaf0
restart: unless-stopped
expose:
- "80"
environment:
MONGODB_URI: mongodb://corsfix:${MONGODB_PASSWORD}@mongodb:27017/db?authSource=admin
REDIS_URI: redis://default:${REDIS_PASSWORD}@redis:6379
KEK_VERSION_1: ${KEK_VERSION_1}
APP_DOMAIN: ${APP_DOMAIN}
RPM: ${RPM:-180}
ALLOWED_ORIGINS: ${ALLOWED_ORIGINS:-}
ALLOWED_TARGETS: ${ALLOWED_TARGETS:-}
depends_on:
mongodb:
condition: service_healthy
redis:
condition: service_healthy
mongodb:
image: mongo:8.0.17
restart: unless-stopped
environment:
MONGO_INITDB_ROOT_USERNAME: corsfix
MONGO_INITDB_ROOT_PASSWORD: ${MONGODB_PASSWORD}
MONGO_INITDB_DATABASE: db
volumes:
- mongodb-data:/data/db
- mongodb-config:/data/configdb
healthcheck:
test:
- CMD-SHELL
- >-
mongosh --quiet --username "$${MONGO_INITDB_ROOT_USERNAME}"
--password "$${MONGO_INITDB_ROOT_PASSWORD}" --authenticationDatabase admin
--eval 'quit(db.adminCommand({ ping: 1 }).ok ? 0 : 1)'
interval: 10s
timeout: 5s
retries: 10
start_period: 30s
redis:
image: redis:7.4.11-alpine
restart: unless-stopped
command: ["redis-server", "--requirepass", "${REDIS_PASSWORD}", "--appendonly", "yes"]
environment:
REDIS_PASSWORD: ${REDIS_PASSWORD}
volumes:
- redis-data:/data
healthcheck:
test: ["CMD-SHELL", "REDISCLI_AUTH=\"$${REDIS_PASSWORD}\" redis-cli ping | grep -q PONG"]
interval: 10s
timeout: 5s
retries: 10
start_period: 10s
volumes:
mongodb-data:
mongodb-config:
redis-data:
+27
View File
@@ -0,0 +1,27 @@
# Corsfix
This template deploys the Corsfix dashboard and proxy with MongoDB and Redis.
The dashboard image requires an **x86-64 / amd64 server**.
## Before deploying
1. Dokploy imports template domains without a certificate configuration, so `AUTH_URL` defaults to `http://` followed by the generated dashboard hostname. When enabling **HTTPS** and **Let's Encrypt** in the **Domains** tab, also change `AUTH_URL` in **Environment** to `https://` followed by that hostname and redeploy. This URL must match the public dashboard address, even though Dokploy terminates TLS at the edge. Enable HTTPS for **both** domains before using the playground, which uses HTTPS proxy URLs.
2. If using custom domains, point both DNS records to your server, update the domain entries, and set `APP_DOMAIN` and `PROXY_DOMAIN` in **Environment** to the matching hostnames, without `https://` or a trailing slash. Update `AUTH_URL` to the full public dashboard URL, including its `http://` or `https://` scheme.
3. Deploy, then open the dashboard domain (the `corsfix` service on port `3000`) and create your account with an email address and password. Self-hosted signup does not require an email server.
4. Set `DISABLE_SIGNUP=true` in **Environment** and redeploy after creating the accounts you need.
## Using the proxy
The second domain routes to `corsfix-proxy` on port `80`. Use the dashboard to register your application's origin and permitted target domains, manage secrets, and try requests in the playground.
`RPM` sets the self-hosted rate limit (default: `180` requests per minute). Optional `ALLOWED_ORIGINS` and `ALLOWED_TARGETS` accept comma-separated hostnames for environment-based allowlists; leave them empty to manage applications through the dashboard.
## Persistent data and upgrades
MongoDB stores users, applications, and encrypted secrets in named volumes. Redis uses a named volume with append-only persistence. Preserve these volumes and the generated environment values when upgrading.
Keep a backup of `KEK_VERSION_1`: changing or losing this encryption key makes existing saved secrets unreadable. Do not re-import the template to upgrade an existing installation, because imports generate new credentials and keys. Update the image tags in the existing Compose configuration instead. Changing `MONGODB_PASSWORD` alone does not change the password already stored in MongoDB.
The Corsfix images are pinned to the same upstream commit because the project publishes commit tags rather than numbered releases.
See the [Corsfix self-hosting documentation](https://corsfix.com/docs/open-source/self-hosting) for more information.
+13
View File
@@ -0,0 +1,13 @@
{
"id": "corsfix",
"name": "Corsfix",
"version": "8899bb15e71c7238285ccefc4c95a0cd47daeaf0",
"description": "Corsfix is an open source CORS proxy platform for fetching APIs from browser applications, with origin and target allowlists, encrypted API secrets, response caching, and a management dashboard.",
"logo": "corsfix.svg",
"links": {
"github": "https://github.com/corsfix/corsfix",
"website": "https://corsfix.com",
"docs": "https://corsfix.com/docs/open-source/self-hosting"
},
"tags": ["proxy", "developer-tools", "networking"]
}
+33
View File
@@ -0,0 +1,33 @@
[variables]
app_domain = "${domain}"
proxy_domain = "${domain}"
mongodb_password = "${hash:64}"
redis_password = "${hash:64}"
kek_version_1 = "${base64:32}"
auth_secret = "${base64:32}"
[config]
env = [
"APP_DOMAIN=${app_domain}",
"AUTH_URL=http://${app_domain}",
"PROXY_DOMAIN=${proxy_domain}",
"MONGODB_PASSWORD=${mongodb_password}",
"REDIS_PASSWORD=${redis_password}",
"KEK_VERSION_1=${kek_version_1}",
"AUTH_SECRET=${auth_secret}",
"DISABLE_SIGNUP=false",
"RPM=180",
"ALLOWED_ORIGINS=",
"ALLOWED_TARGETS=",
]
mounts = []
[[config.domains]]
serviceName = "corsfix"
port = 3000
host = "${app_domain}"
[[config.domains]]
serviceName = "corsfix-proxy"
port = 80
host = "${proxy_domain}"
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

@@ -0,0 +1,27 @@
version: "3.8"
services:
databasement:
image: davidcrty/databasement:1.8.4
restart: unless-stopped
expose:
- 2226
environment:
- APP_KEY=${APP_KEY}
- APP_URL=${APP_URL}
- DB_CONNECTION=sqlite
- DB_DATABASE=/data/database.sqlite
- ENABLE_QUEUE_WORKER=true
- TRUSTED_PROXIES=*
- LOG_CHANNEL=stderr
- APP_DISPLAY_TIMEZONE=${APP_DISPLAY_TIMEZONE}
volumes:
- databasement-data:/data
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:2226/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
volumes:
databasement-data:
+19
View File
@@ -0,0 +1,19 @@
{
"id": "databasement",
"name": "Databasement",
"version": "1.8.4",
"description": "Self-hosted database backup manager with a web UI. Schedule, backup, and restore MySQL, PostgreSQL, MariaDB, Microsoft SQL Server, MongoDB, SQLite, Firebird and Redis to S3, SFTP, Samba or local storage. SSH tunnel support.",
"logo": "databasement.png",
"links": {
"github": "https://github.com/David-Crty/databasement",
"website": "https://david-crty.github.io/databasement/",
"docs": "https://david-crty.github.io/databasement/self-hosting/docker"
},
"tags": [
"backup",
"database",
"mysql",
"postgres",
"mongodb"
]
}
+22
View File
@@ -0,0 +1,22 @@
[variables]
main_domain = "${domain}"
app_key = "${base64:32}"
timezone = "UTC"
[config]
env = [
"APP_KEY=base64:${app_key}",
"APP_URL=https://${main_domain}",
"APP_DISPLAY_TIMEZONE=${timezone}",
"TRUSTED_PROXIES=*",
"LOG_CHANNEL=stderr",
"DB_CONNECTION=sqlite",
"DB_DATABASE=/data/database.sqlite",
"ENABLE_QUEUE_WORKER=true"
]
mounts = []
[[config.domains]]
serviceName = "databasement"
port = 2226
host = "${main_domain}"
+16
View File
@@ -0,0 +1,16 @@
services:
dexio:
image: ghcr.io/dexio-wiki/dexio:1.0.0
restart: unless-stopped
environment:
- DEXIO_PUBLIC_URL=${DEXIO_PUBLIC_URL}
- DEXIO_SECRET_KEY=${DEXIO_SECRET_KEY}
- DEXIO_DB=/data/dexio.db
- DEXIO_FILES_DIR=/data/files
expose:
- 8080
volumes:
- dexio-data:/data
volumes:
dexio-data:
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-769 -852 1567 1567"><!-- Dexio mark: a small graph, hub and four nodes. Built by brand/build.py. --><rect x="-769" y="-852" width="1567" height="1567" rx="345" fill="#000000"/><path d="M79.9 0.0L20.4 -475.2L-20.4 -475.2L-79.9 0.0ZM29.1 74.4L498.1 -173.2L483.3 -211.2L-29.1 -74.4ZM-52.3 60.3L392.4 367.4L419.0 336.6L52.3 -60.3ZM-33.6 -72.5L-462.2 191.8L-445.0 228.8L33.6 72.5Z" fill="#ffffff"/><circle cx="0.0" cy="-475.2" r="87.6" fill="#ffffff"/><circle cx="490.7" cy="-192.2" r="87.6" fill="#ffffff"/><circle cx="405.7" cy="352.0" r="74.5" fill="#ffffff"/><circle cx="-453.6" cy="210.3" r="96.4" fill="#ffffff"/><circle cx="0.0" cy="0.0" r="166.5" fill="#38bdf8"/></svg>

After

Width:  |  Height:  |  Size: 723 B

+20
View File
@@ -0,0 +1,20 @@
{
"id": "dexio",
"name": "Dexio",
"version": "1.0.0",
"description": "One wiki for all your agents. AI agents read and write linked markdown pages over MCP from any machine, and people see what they know in a web app: the link graph, every page and its history.",
"logo": "logo.svg",
"links": {
"github": "https://github.com/dexio-wiki/dexio",
"website": "https://dexio.wiki",
"docs": "https://github.com/dexio-wiki/dexio/blob/main/deploy/README.md"
},
"tags": [
"wiki",
"knowledge-base",
"markdown",
"mcp",
"ai",
"agents"
]
}
+17
View File
@@ -0,0 +1,17 @@
[variables]
main_domain = "${domain}"
secret_key = "${password:64}"
[config]
env = [
"DEXIO_PUBLIC_URL=https://${main_domain}",
"DEXIO_SECRET_KEY=${secret_key}",
]
# Dexio's session cookie is HTTPS-only, so the domain asks for a certificate.
[[config.domains]]
serviceName = "dexio"
port = 8080
host = "${main_domain}"
https = true
certificateType = "letsencrypt"
+253
View File
@@ -0,0 +1,253 @@
# Ethora Core as a Dokploy template. GENERATED FILE: edit the bundle's
# deploy/compose/docker-compose.yml and run build-template.sh.
#
# Same services and start order as the bundle (config -> databases -> xmpp ->
# api, jobs -> init -> frontend), without the bundled Caddy: Dokploy's Traefik
# routes the four public hosts declared in template.toml. The scripts and
# templates are the template's mounts, which Dokploy writes under ../files/.
# Every variable comes from the .env Dokploy writes next to this file
# (template.toml, [config] env). See README.md in this directory.
x-logging: &logging
logging:
driver: json-file
options:
max-size: "20m"
max-file: "5"
x-api: &api
image: ${ETHORA_API_IMAGE:-docker.io/dappros/ethora-api:2610}
entrypoint: ["tini", "--", "bash", "/ethora/scripts/api-entrypoint.sh"]
volumes:
- config:/ethora/config:ro
- ../files/scripts:/ethora/scripts:ro
<<: *logging
services:
# ---------------------------------------------------------------- config --
config:
image: ${ETHORA_XMPP_IMAGE:-docker.io/dappros/ethora-xmpp:2610}
user: "0:0"
entrypoint: ["/bin/sh", "/ethora/scripts/render-config.sh"]
# Every value in .env reaches the renderer, so any variable of the
# installer's templates (POSTMARK_*, EMAIL_TLD_*, RATE_LIMIT_*, ...) can
# be set there. The hosts are derived here once, for caddy and xmpp too.
env_file:
- path: .env
required: false
environment:
ROOT_DOMAIN: ${ROOT_DOMAIN:?ROOT_DOMAIN is not set; run ./configure.sh or fill in .env}
API_DOMAIN: ${API_DOMAIN:-api.${ROOT_DOMAIN}}
WEB_DOMAIN: ${WEB_DOMAIN:-app.${ROOT_DOMAIN}}
XMPP_DOMAIN: ${XMPP_DOMAIN:-xmpp.${ROOT_DOMAIN}}
FILES_DOMAIN: ${FILES_DOMAIN:-files.${ROOT_DOMAIN}}
volumes:
- config:/out/config
- mysql-initdb:/out/mysql-initdb
- ../files/scripts:/ethora/scripts:ro
- ../files/templates:/ethora/templates:ro
restart: "no"
<<: *logging
# ------------------------------------------------------------- databases --
mongo:
image: mongo:6.0.8
command: ["mongod", "--replSet", "rs0", "--bind_ip_all"]
volumes:
- mongo:/data/db
- mongo-config:/data/configdb
restart: unless-stopped
healthcheck:
# A TCP connect, not mongosh: see docker-compose.enterprise.yml.
test: ["CMD", "bash", "-c", "exec 3<>/dev/tcp/127.0.0.1/27017"]
interval: 10s
timeout: 5s
retries: 30
<<: *logging
mongo-init:
image: mongo:6.0.8
entrypoint: ["bash", "/ethora/scripts/mongo-init.sh"]
volumes:
- ../files/scripts:/ethora/scripts:ro
depends_on:
mongo:
condition: service_healthy
restart: "no"
<<: *logging
mysql:
image: mysql:8.1.0
command: ["--default-authentication-plugin=mysql_native_password"]
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:?MYSQL_ROOT_PASSWORD is not set}
# ejabberd connects as root from its own container (as on a host install).
MYSQL_ROOT_HOST: "%"
volumes:
- mysql:/var/lib/mysql
- mysql-initdb:/docker-entrypoint-initdb.d:ro
depends_on:
config:
condition: service_completed_successfully
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -uroot -p\"$$MYSQL_ROOT_PASSWORD\" --silent"]
interval: 10s
timeout: 5s
retries: 30
start_period: 30s
<<: *logging
redis:
image: redis:7.4-alpine
volumes:
- redis:/data
restart: unless-stopped
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 10
<<: *logging
minio:
# Our unmodified copy of the MinIO release every install runs (AGPL-3.0);
# MinIO withdrew its public images. Set MINIO_IMAGE for a private mirror.
image: ${MINIO_IMAGE:-docker.io/dappros/minio:RELEASE.2025-09-07T16-13-09Z}
command: ["server", "/data"]
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER:?MINIO_ROOT_USER is not set}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:?MINIO_ROOT_PASSWORD is not set}
volumes:
- minio:/data
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:9000/minio/health/live"]
interval: 15s
timeout: 5s
retries: 10
<<: *logging
centrifugo:
image: centrifugo/centrifugo:v6
command: ["centrifugo", "-c", "/ethora/config/centrifugo/config.json"]
volumes:
- config:/ethora/config:ro
depends_on:
config:
condition: service_completed_successfully
ulimits:
nofile:
soft: 65535
hard: 65535
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "wget -q -O /dev/null http://127.0.0.1:8000/health || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
<<: *logging
# ------------------------------------------------------------------ xmpp --
xmpp:
image: ${ETHORA_XMPP_IMAGE:-docker.io/dappros/ethora-xmpp:2610}
entrypoint: ["/bin/sh", "/ethora/scripts/xmpp-start.sh"]
environment:
XMPP_DOMAIN: ${XMPP_DOMAIN:-xmpp.${ROOT_DOMAIN}}
XMPP_ADMIN_PASSWORD: ${XMPP_ADMIN_PASSWORD:?XMPP_ADMIN_PASSWORD is not set}
volumes:
- config:/ethora/config:ro
- ../files/scripts:/ethora/scripts:ro
# Native XMPP clients (port 5222) are not exposed by default; web and SDK
# clients connect over wss://xmpp.<root>/ws through caddy. See README.md.
depends_on:
config:
condition: service_completed_successfully
mysql:
condition: service_healthy
restart: unless-stopped
healthcheck:
# Healthy once ejabberd runs AND the admin account is ensured, which is
# what the API and init need.
test: ["CMD-SHELL", "test -f /tmp/ethora-admin-ready && /opt/ejabberd/bin/ejabberdctl status >/dev/null"]
interval: 10s
timeout: 10s
retries: 30
start_period: 30s
<<: *logging
# ------------------------------------------------------------------- api --
api:
<<: *api
command: ["api"]
depends_on:
config:
condition: service_completed_successfully
mongo-init:
condition: service_completed_successfully
redis:
condition: service_healthy
minio:
condition: service_healthy
xmpp:
condition: service_started
restart: unless-stopped
# Healthcheck: the image's own (GET /v1/ping).
jobs:
<<: *api
command: ["jobs"]
depends_on:
api:
condition: service_healthy
restart: unless-stopped
healthcheck:
disable: true
init:
<<: *api
command: ["init"]
depends_on:
api:
condition: service_healthy
xmpp:
condition: service_healthy
restart: "no"
healthcheck:
disable: true
# End-to-end check through the public URLs (scripts/verify.js):
# docker compose --profile verify run --rm verify
verify:
<<: *api
profiles: ["verify"]
command: ["verify"]
restart: "no"
healthcheck:
disable: true
# -------------------------------------------------------------- frontend --
frontend:
image: ${ETHORA_FRONTEND_IMAGE:-docker.io/dappros/ethora-frontend:2610}
entrypoint: ["/bin/sh", "/ethora/scripts/frontend-start.sh"]
command: ["serve"]
volumes:
- config:/ethora/config:ro
- ../files/scripts:/ethora/scripts:ro
depends_on:
config:
condition: service_completed_successfully
restart: unless-stopped
<<: *logging
volumes:
# Your data. Survive `docker compose down`; `down -v` deletes them.
mongo:
mysql:
minio:
redis:
# Regenerated on every start; safe to delete.
mongo-config:
config:
mysql-initdb:
+4
View File
@@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.86612 16.7203C6.86612 11.5765 11.036 7.40666 16.1798 7.40666H29.941C30.6313 7.40666 31.191 7.9663 31.191 8.65666C31.191 12.8786 30.0116 15.9059 28.0999 18C26.2039 20.0767 23.7131 21.0979 21.3351 21.5628C18.9587 22.0273 16.6127 21.9536 14.884 21.773C14.0858 21.6896 13.4086 21.5822 12.9067 21.4898L9.38309 28.0216C9.52342 29.1887 10.517 30.0932 11.7219 30.0932H29.941C30.6313 30.0932 31.191 30.6529 31.191 31.3432C31.191 32.0336 30.6313 32.5932 29.941 32.5932H11.7219C9.04014 32.5932 6.86612 30.4192 6.86612 27.7374V16.7203ZM9.36612 22.7875L11.1495 19.4816C11.4215 18.9773 12.0015 18.7226 12.5568 18.8634L12.5579 18.8637L12.5626 18.8648L12.592 18.872C12.6198 18.8787 12.6635 18.8889 12.7221 18.9021C12.8393 18.9284 13.0159 18.9662 13.2434 19.0094C13.6987 19.096 14.3548 19.2041 15.1438 19.2865C16.7322 19.4525 18.8091 19.5092 20.8555 19.1092C22.9004 18.7095 24.8323 17.8712 26.2536 16.3144C27.4955 14.954 28.4459 12.9372 28.6501 9.90666H16.1798C12.4167 9.90666 9.36612 12.9572 9.36612 16.7203V22.7875Z" fill="#0052CD"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M29.786 2.5H10.214C5.95366 2.5 2.5 5.95366 2.5 10.214V29.786C2.5 34.0463 5.95366 37.5 10.214 37.5H29.786C34.0463 37.5 37.5 34.0463 37.5 29.786V10.214C37.5 5.95366 34.0463 2.5 29.786 2.5ZM10.214 0C4.57295 0 0 4.57295 0 10.214V29.786C0 35.4271 4.57295 40 10.214 40H29.786C35.4271 40 40 35.4271 40 29.786V10.214C40 4.57295 35.4271 0 29.786 0H10.214Z" fill="#0052CD"/>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

+16
View File
@@ -0,0 +1,16 @@
{
"id": "ethora-core",
"name": "Ethora Core",
"version": "2610",
"description": "Self-hosted chat and messaging server: API, web chat and admin panel, XMPP server (ejabberd) and file storage, with SDKs for web, iOS, Android and React Native.",
"logo": "ethora.svg",
"links": {
"github": "https://github.com/dappros/ethora-install",
"website": "https://ethora.com/",
"docs": "https://github.com/dappros/ethora-install/tree/main/deploy/compose"
},
"tags": [
"chat",
"self-hosted"
]
}
File diff suppressed because it is too large Load Diff
+116
View File
@@ -0,0 +1,116 @@
version: "3.8"
services:
feedbacks:
image: softinator/feedbacks@sha256:f7d759e671b48906a4aa5deff92b4644a73a6a4239f32b4cebba5cfcef8cc97b
restart: unless-stopped
init: true
read_only: true
tmpfs:
- /tmp:size=128m,mode=1777
cap_drop: [ALL]
security_opt: [no-new-privileges:true]
environment:
NODE_ENV: production
PORT: 3000
APP_ORIGIN: ${APP_ORIGIN:?required}
DATABASE_URL: postgresql://feedbacks:${POSTGRES_PASSWORD:?required}@postgres:5432/feedbacks
DATABASE_POOL_MAX: ${DATABASE_POOL_MAX:-10}
TRUST_PROXY_HOPS: ${TRUST_PROXY_HOPS:-1}
ASSET_DRIVER: s3
ORGANIZATION_ID: ${ORGANIZATION_ID:?required}
# Defaults to the bundled SeaweedFS S3; override all S3_* to use external storage.
S3_ENDPOINT: ${S3_ENDPOINT:-https://s3:8333}
S3_REGION: ${S3_REGION:-us-east-1}
S3_BUCKET: ${S3_BUCKET:-feedbacks}
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:?required}
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:?required}
# Feedbacks requires an HTTPS S3 endpoint in production; trust the bundled SeaweedFS self-signed cert.
NODE_EXTRA_CA_CERTS: /s3-config/public.crt
TURNSTILE_SITE_KEY: ${TURNSTILE_SITE_KEY:-}
TURNSTILE_SECRET_KEY: ${TURNSTILE_SECRET_KEY:-}
GITHUB_APPS_JSON: ${GITHUB_APPS_JSON:-}
GITHUB_APP_ID: ${GITHUB_APP_ID:-}
GITHUB_APP_SLUG: ${GITHUB_APP_SLUG:-}
GITHUB_APP_PRIVATE_KEY_BASE64: ${GITHUB_APP_PRIVATE_KEY_BASE64:-}
volumes:
- feedbacks-s3-config:/s3-config:ro
expose: ["3000"]
depends_on:
postgres:
condition: service_healthy
s3-bucket:
condition: service_completed_successfully
stop_grace_period: 15s
postgres:
image: postgres:17-bookworm
restart: unless-stopped
environment:
POSTGRES_USER: feedbacks
POSTGRES_DB: feedbacks
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?required}
volumes: ["feedbacks-postgres:/var/lib/postgresql/data"]
healthcheck:
test: ["CMD-SHELL", "pg_isready -U feedbacks -d feedbacks"]
interval: 10s
timeout: 5s
retries: 10
s3-init:
image: alpine:3.22
restart: "no"
environment:
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:?required}
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:?required}
volumes:
- feedbacks-s3-config:/config
entrypoint: ["/bin/sh", "-c"]
command:
- |
set -e
if [ ! -s /config/public.crt ]; then
apk add --no-cache openssl >/dev/null
openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
-subj "/CN=s3" -addext "subjectAltName=DNS:s3" \
-addext "basicConstraints=critical,CA:TRUE" \
-keyout /config/private.key -out /config/public.crt
fi
printf '{"identities":[{"name":"feedbacks","credentials":[{"accessKey":"%s","secretKey":"%s"}],"actions":["Admin","Read","Write","List","Tagging"]}]}' \
"$$S3_ACCESS_KEY_ID" "$$S3_SECRET_ACCESS_KEY" > /config/s3.json
chmod 644 /config/*
s3:
image: chrislusf/seaweedfs:4.48
restart: unless-stopped
command: server -dir=/data -s3 -s3.port=8333 -s3.config=/config/s3.json -s3.cert.file=/config/public.crt -s3.key.file=/config/private.key
volumes:
- feedbacks-s3:/data
- feedbacks-s3-config:/config:ro
depends_on:
s3-init:
condition: service_completed_successfully
s3-bucket:
image: alpine:3.22
restart: "no"
depends_on:
- s3
environment:
S3_BUCKET: ${S3_BUCKET:-feedbacks}
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:?required}
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:?required}
volumes:
- feedbacks-s3-config:/config:ro
entrypoint: ["/bin/sh", "-c"]
command:
- |
set -e
apk add --no-cache curl >/dev/null
for i in $$(seq 1 60); do
code=$$(curl -s -o /dev/null -w '%{http_code}' --cacert /config/public.crt \
--aws-sigv4 "aws:amz:us-east-1:s3" --user "$$S3_ACCESS_KEY_ID:$$S3_SECRET_ACCESS_KEY" \
-X PUT "https://s3:8333/$$S3_BUCKET") || code=000
case "$$code" in 200|409) echo "bucket ready ($$code)"; exit 0;; esac
sleep 2
done
echo "could not create bucket (last HTTP $$code)"; exit 1
volumes:
feedbacks-postgres:
feedbacks-s3:
feedbacks-s3-config:
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

+16
View File
@@ -0,0 +1,16 @@
{
"id": "feedbacks",
"name": "Feedbacks",
"version": "0.2.1",
"description": "Self-hosted website feedback, browser evidence and MCP handoff for coding assistants. Ships with private SeaweedFS S3 storage; external S3 is optional.",
"logo": "logo.png",
"links": {
"github": "https://github.com/Softinator-TechLabs/feedbacks-oss",
"website": "https://feedbacks.softinator.ai",
"docs": "https://feedbacks.softinator.ai/docs/guide/self-host"
},
"tags": [
"collaboration",
"developer-tools"
]
}
+24
View File
@@ -0,0 +1,24 @@
[variables]
main_domain = "${domain}"
postgres_password = "${hash:64}"
organization_id = "${uuid}"
s3_access_key = "${hash:20}"
s3_secret_key = "${hash:40}"
[config]
env = [
"APP_ORIGIN=https://${main_domain}",
"POSTGRES_PASSWORD=${postgres_password}",
"ORGANIZATION_ID=${organization_id}",
"TRUST_PROXY_HOPS=1",
# Bundled SeaweedFS S3 (HTTPS with a self-signed cert). To use external S3 instead,
# add S3_ENDPOINT, S3_REGION and S3_BUCKET and replace the keys below.
"S3_ACCESS_KEY_ID=${s3_access_key}",
"S3_SECRET_ACCESS_KEY=${s3_secret_key}",
]
[[config.domains]]
serviceName = "feedbacks"
port = 3000
host = "${main_domain}"
path = "/"
+26 -12
View File
@@ -2,40 +2,54 @@ version: "3.8"
services:
gitea:
image: docker.gitea.com/gitea:1.24.4
image: docker.gitea.com/gitea:1.27.3
restart: unless-stopped
environment:
- USER_UID=1000
- USER_GID=1000
- USER_UID=${USER_UID:-1000}
- USER_GID=${USER_GID:-1000}
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=postgres:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=${GITEA_DB_PASSWORD:-gitea}
- GITEA__database__NAME=${POSTGRES_DB:-gitea}
- GITEA__database__USER=${POSTGRES_USER}
- GITEA__database__PASSWD=${POSTGRES_PASSWORD}
- GITEA__server__DOMAIN=${GITEA_DOMAIN}
- GITEA__server__SSH_DOMAIN=${GITEA_SSH_DOMAIN:-${GITEA_DOMAIN}}
- GITEA__server__ROOT_URL=https://${GITEA_DOMAIN}/
- GITEA__server__LFS_START_SERVER=true
- GITEA__service__DISABLE_REGISTRATION=${DISABLE_REGISTRATION:-false}
- GITEA__service__REQUIRE_SIGNIN_VIEW=${REQUIRE_SIGNIN_VIEW:-false}
volumes:
- gitea-data:/data
expose:
- "3000"
- "22"
depends_on:
- postgres
postgres:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:3000/"]
test: ["CMD", "wget", "-q", "--spider", "http://localhost:3000/api/healthz"]
interval: 15s
timeout: 5s
retries: 10
start_period: 20s
postgres:
image: docker.io/library/postgres:14
image: postgres:16-alpine
restart: unless-stopped
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=${GITEA_DB_PASSWORD:-gitea}
- POSTGRES_DB=gitea
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_DB=${POSTGRES_DB:-gitea}
volumes:
- pg-data:/var/lib/postgresql/data
expose:
- "5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB:-gitea}"]
interval: 5s
timeout: 5s
retries: 5
start_period: 10s
volumes:
gitea-data: {}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "gitea-postgres",
"name": "Gitea (PostgreSQL)",
"version": "1.24.4",
"version": "1.27.3",
"description": "Gitea bundled with PostgreSQL.",
"logo": "gitea.png",
"links": {
+12 -6
View File
@@ -1,6 +1,7 @@
[variables]
main_domain = "${domain}"
db_password = "${password:24}"
db_user = "${username}"
[config]
mounts = []
@@ -12,9 +13,14 @@ host = "${main_domain}"
[config.env]
USER_UID = "1000"
USER_GID = "1000"
GITEA__database__DB_TYPE = "postgres"
GITEA__database__HOST = "postgres:5432"
GITEA__database__NAME = "gitea"
GITEA__database__USER = "gitea"
GITEA__database__PASSWD = "${db_password}"
GITEA_DB_PASSWORD = "${db_password}"
GITEA_DOMAIN = "${main_domain}"
GITEA_SSH_DOMAIN = "${main_domain}"
POSTGRES_USER = "${db_user}"
POSTGRES_PASSWORD = "${db_password}"
POSTGRES_DB = "gitea"
# Security & Privacy Settings (default: false):
# Set to "true" to disable public user registration (recommended after creating the first admin user)
DISABLE_REGISTRATION = "false"
# Set to "true" to require sign-in to view repositories and explore pages (makes the instance private)
REQUIRE_SIGNIN_VIEW = "false"
+87
View File
@@ -0,0 +1,87 @@
version: "3.8"
services:
graylog:
image: graylog/graylog:7.1.9
restart: unless-stopped
depends_on:
mongodb:
condition: service_healthy
opensearch:
condition: service_healthy
entrypoint:
- /usr/bin/tini
- --
- /bin/bash
- -ec
- |
export GRAYLOG_ROOT_PASSWORD_SHA2="$$(printf '%s' "$$GRAYLOG_ADMIN_PASSWORD" | sha256sum | cut -d ' ' -f 1)"
unset GRAYLOG_ADMIN_PASSWORD
exec /docker-entrypoint.sh
environment:
GRAYLOG_ADMIN_PASSWORD: ${GRAYLOG_ADMIN_PASSWORD:?Set the admin password}
GRAYLOG_PASSWORD_SECRET: ${GRAYLOG_PASSWORD_SECRET:?Set the password secret}
GRAYLOG_HTTP_BIND_ADDRESS: 0.0.0.0:9000
GRAYLOG_HTTP_EXTERNAL_URI: ${GRAYLOG_HTTP_EXTERNAL_URI:?Set the public URL including its trailing slash}
GRAYLOG_MONGODB_URI: mongodb://mongodb:27017/graylog
GRAYLOG_ELASTICSEARCH_HOSTS: http://opensearch:9200
GRAYLOG_NODE_ID_FILE: /usr/share/graylog/data/data/node-id
GRAYLOG_SERVER_JAVA_OPTS: -Xms512m -Xmx512m
expose:
- "9000"
- "12201/tcp"
- "12201/udp"
volumes:
- graylog-data:/usr/share/graylog/data
healthcheck:
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:9000/api/system/lbstatus"]
interval: 30s
timeout: 5s
retries: 5
start_period: 120s
mongodb:
image: mongo:8.0.29
restart: unless-stopped
command: ["mongod", "--wiredTigerCacheSizeGB", "0.25"]
volumes:
- mongodb-data:/data/db
- mongodb-config:/data/configdb
healthcheck:
test: ["CMD", "mongosh", "--quiet", "--eval", "quit(db.adminCommand('ping').ok ? 0 : 1)"]
interval: 30s
timeout: 10s
retries: 5
start_period: 30s
opensearch:
image: opensearchproject/opensearch:2.19.5
restart: unless-stopped
environment:
discovery.type: single-node
action.auto_create_index: "false"
bootstrap.memory_lock: "true"
OPENSEARCH_JAVA_OPTS: -Xms512m -Xmx512m
DISABLE_INSTALL_DEMO_CONFIG: "true"
DISABLE_SECURITY_PLUGIN: "true"
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
volumes:
- opensearch-data:/usr/share/opensearch/data
healthcheck:
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:9200/_cluster/health?wait_for_status=yellow&timeout=5s"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
volumes:
graylog-data:
mongodb-data:
mongodb-config:
opensearch-data:
Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

+37
View File
@@ -0,0 +1,37 @@
# Graylog
This template runs Graylog Open with MongoDB and self-managed OpenSearch. It uses the normal Graylog login without Data Node's preflight setup.
## Before deploying
- Use an x86-64 server with AVX support for MongoDB.
- Allow at least 3 GiB of available RAM for a small installation. Graylog and OpenSearch each start with a 512 MiB Java heap. Increase their heap settings and MongoDB's cache for larger workloads.
- Set `vm.max_map_count` to at least `262144` on the Docker host. For example, run `sudo sysctl -w vm.max_map_count=262144` and persist the setting in `/etc/sysctl.d/99-graylog.conf`.
- Keep Dokploy's isolated deployment enabled. MongoDB and OpenSearch have no authentication and must stay on the private application network. Do not publish their ports.
## Login
Open the domain assigned by Dokploy. Use username `admin` and the generated `GRAYLOG_ADMIN_PASSWORD` from the service's Environment tab. The startup command hashes this password for Graylog.
When enabling HTTPS or changing the domain in Dokploy, update `GRAYLOG_HTTP_EXTERNAL_URI` to the matching URL, including the trailing slash, and redeploy. Enable HTTPS before sending credentials over an untrusted network.
Keep `GRAYLOG_PASSWORD_SECRET` unchanged after deployment. Graylog uses it to encrypt stored credentials.
## Receive logs
Create an input under **System > Inputs**. For GELF, select **GELF UDP** or **GELF TCP**, bind to `0.0.0.0`, and use port `12201`.
The template does not publish host ports. To accept logs from outside the application network, add the required port mapping to the `graylog` service in Dokploy's Compose editor and redeploy. For GELF UDP:
```yaml
ports:
- "12201:12201/udp"
```
For GELF TCP, use `12201:12201/tcp`. Choose an unused host port and restrict access to trusted log senders in your firewall. Creating an input and publishing its port are both required. HTTP domain routing does not forward TCP or UDP inputs.
## Data and upgrades
Named volumes store MongoDB configuration, indexed logs, Graylog's node ID, and its message journal. Preserve all four volumes when redeploying or upgrading, and back up MongoDB and OpenSearch together with Graylog's configuration.
Check the [Graylog compatibility matrix](https://go2docs.graylog.org/current/downloading_and_installing_graylog/compatibility_matrix.htm) before changing image versions. OpenSearch 3.x is not supported by this Graylog version.
+13
View File
@@ -0,0 +1,13 @@
{
"id": "graylog",
"name": "Graylog",
"version": "7.1.9",
"description": "Graylog Open collects, indexes, and searches logs, with dashboards and alerts. Includes MongoDB and OpenSearch.",
"logo": "graylog.png",
"links": {
"github": "https://github.com/Graylog2/graylog2-server",
"website": "https://graylog.org/",
"docs": "https://go2docs.graylog.org/"
},
"tags": ["monitoring", "logging"]
}
+17
View File
@@ -0,0 +1,17 @@
[variables]
main_domain = "${domain}"
admin_password = "${password:32}"
password_secret = "${password:96}"
[config]
env = [
"GRAYLOG_ADMIN_PASSWORD=${admin_password}",
"GRAYLOG_PASSWORD_SECRET=${password_secret}",
"GRAYLOG_HTTP_EXTERNAL_URI=http://${main_domain}/"
]
mounts = []
[[config.domains]]
serviceName = "graylog"
port = 9000
host = "${main_domain}"
+45
View File
@@ -0,0 +1,45 @@
# Template validation
Tested on 2026-09-06 using Dokploy on Linux x86-64, Docker Engine 29.1.3, and the exact image tags in this template.
## Checks performed
- Imported the Base64 payload containing `docker-compose.yml` and `template.toml` through Dokploy's `compose.import` API.
- Enabled isolated deployment and deployed through Dokploy.
- Validated Compose interpolation and syntax with `docker-compose config --quiet`.
- Confirmed all three containers became healthy.
- Requested the assigned domain through Traefik and received HTTP 200.
- Confirmed authenticated API access through Traefik returned HTTP 200 and unauthenticated access to the protected API returned HTTP 401.
- Authenticated to `/api/system` with `admin` and the generated password. The server reported `7.1.9+002c047`.
- Created a global GELF UDP input on port 12201 through `/api/system/inputs`.
- Sent a GELF message to that input over the private container network and retrieved it through Graylog's authenticated search API.
- Stopped and started the stack through Dokploy. The message remained searchable, the input remained configured, and Graylog retained its node ID.
- The instance owner tested the web interface and confirmed it works.
- Verified OpenSearch's effective `action.auto_create_index` setting is `false`. Ingested and searched a message, manually rotated the default index set from `graylog_0` to `graylog_1`, then ingested and found a second message in the new write index.
The three containers used approximately 2 GiB of RAM during this small test. This is not a throughput or production sizing benchmark.
Public TCP/UDP port mappings were not tested. The default template publishes no ingestion ports.
## Repeat the ingestion check
1. Deploy the template with isolated deployment enabled.
2. Log in with the credentials described in `instructions.md`.
3. Create a global GELF UDP input bound to `0.0.0.0:12201`.
4. From a sender with access to that input, send a GELF message. For example, using Python and replacing `GRAYLOG_INPUT_HOST` with the reachable input address:
```python
import json
import socket
message = {
"version": "1.1",
"host": "dokploy-template-test",
"short_message": "dokploy-graylog-persistence-test",
}
with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as sender:
sender.sendto(json.dumps(message).encode(), ("GRAYLOG_INPUT_HOST", 12201))
```
5. Search for `message:"dokploy-graylog-persistence-test"` in Graylog.
6. Stop and start the service through Dokploy, then repeat the search and check the input configuration. Keep the search time range wide enough to include the original message.
+452
View File
@@ -0,0 +1,452 @@
services:
postgres:
image: "postgres:16.10-alpine"
restart: "unless-stopped"
environment:
POSTGRES_USER: "grovs"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
POSTGRES_DB: "grovs_production"
command:
- "postgres"
- "-c"
- "max_connections=200"
volumes:
- "pg_data:/var/lib/postgresql/data"
healthcheck:
test:
- "CMD-SHELL"
- "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
interval: "10s"
timeout: "5s"
retries: 10
redis:
image: "redis:7.4.5-alpine"
restart: "unless-stopped"
command:
- "redis-server"
- "--appendonly"
- "yes"
- "--maxmemory-policy"
- "noeviction"
volumes:
- "redis_data:/data"
healthcheck:
test:
- "CMD"
- "redis-cli"
- "ping"
interval: "10s"
timeout: "5s"
retries: 10
clickhouse:
image: "clickhouse/clickhouse-server:25.3.6.56"
restart: "unless-stopped"
environment:
CLICKHOUSE_DB: "grovs_production"
CLICKHOUSE_USER: "grovs"
CLICKHOUSE_PASSWORD: "${CLICKHOUSE_PASSWORD}"
volumes:
- "clickhouse_data:/var/lib/clickhouse"
ulimits:
nofile:
soft: 262144
hard: 262144
healthcheck:
test:
- "CMD"
- "wget"
- "--spider"
- "-q"
- "http://localhost:8123/ping"
interval: "10s"
timeout: "5s"
retries: 30
migrate:
image: "ghcr.io/grovs-io/backend:2.3.1"
restart: "no"
environment:
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: "${ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY}"
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: "${ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT}"
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: "${ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY}"
ACTIVE_STORAGE_SERVICE: "local"
ADMIN_API_KEY: "${ADMIN_API_KEY}"
API_HOST: "api.${SERVER_HOST}"
BOOTSTRAP_ADMIN_EMAIL: "${BOOTSTRAP_ADMIN_EMAIL}"
BOOTSTRAP_ADMIN_PASSWORD: "${BOOTSTRAP_ADMIN_PASSWORD}"
CLICKHOUSE_ANALYTICS_ROLLUPS_READ_ENABLED: "true"
CLICKHOUSE_ATTRIBUTION_READ_ENABLED: "true"
CLICKHOUSE_DATABASE: "grovs_production"
CLICKHOUSE_LINK_DIMENSIONS_READ_ENABLED: "true"
CLICKHOUSE_PASSWORD: "${CLICKHOUSE_PASSWORD}"
CLICKHOUSE_PRIMARY: "true"
CLICKHOUSE_READ_ENABLED: "true"
CLICKHOUSE_ROLLUP_FAST_LANE: "true"
CLICKHOUSE_URL: "http://grovs:${CLICKHOUSE_PASSWORD}@clickhouse:8123"
CLICKHOUSE_WRITE_ENABLED: "true"
DASHBOARD_CACHE_TTL_SECONDS: "60"
DASHBOARD_HOST: "dashboard.${SERVER_HOST}"
DATABASE_URL: "postgres://grovs:${POSTGRES_PASSWORD}@postgres:5432/grovs_production"
DEFAULT_LINK_SUBTITLE: "Dynamic links, attributions, and referrals across mobile and web platforms."
DEFAULT_LINK_TITLE: "grovs"
DEFAULT_LOGO_URL: "https://appssemble-assets.s3.eu-north-1.amazonaws.com/linksquared/logo-square-new.svg"
DEFAULT_SOCIAL_PREVIEW_URL: "https://appssemble-assets.s3.eu-north-1.amazonaws.com/linksquared/social-media-placeholder.jpg"
DIAGNOSTICS_API_KEY: "${DIAGNOSTICS_API_KEY}"
DOMAIN_LIVE: "${DOMAIN_LIVE}"
DOMAIN_TEST: "${DOMAIN_TEST}"
GO_HOST: "go.${SERVER_HOST}"
GROVS_EE: "false"
GROVS_SELF_HOSTED: "true"
LINKS_PROD_HOST: "links.${DOMAIN_LIVE}"
LINKS_TEST_HOST: "links.${DOMAIN_TEST}"
MAILER_DELIVERY_METHOD: ""
MAILER_FROM: "Grovs <noreply@${SERVER_HOST}>"
MCP_CONSENT_URL: "${SERVER_HOST_PROTOCOL}dashboard.${SERVER_HOST}/mcp/authorize"
MCP_HOST: "mcp.${SERVER_HOST}"
OAUTH_CLIENT_SECRET: "${OAUTH_CLIENT_SECRET}"
OAUTH_CLIENT_UID: "${OAUTH_CLIENT_UID}"
PG_SHADOW_WRITES: "false"
POSTGRES_DB: "grovs_production"
POSTGRES_MAX_CONNECTIONS: "200"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
POSTGRES_USER: "grovs"
PREVIEW_BASE_URL: "${SERVER_HOST_PROTOCOL}preview.${SERVER_HOST}"
PREVIEW_HOST: "preview.${SERVER_HOST}"
PUBLIC_GO_PROJECT_IDENTIFIER: "go-self-hosted"
RAILS_DB_POOL: "10"
RAILS_ENV: "production"
RAILS_LOG_TO_STDOUT: "true"
RAILS_MAX_THREADS: "5"
RAILS_SERVE_STATIC_FILES: "true"
REACT_HOST: "dashboard.${SERVER_HOST}"
REACT_HOST_PROTOCOL: "${SERVER_HOST_PROTOCOL}"
REDIS_URL: "redis://redis:6379/0"
REVENUE_READS_FROM_LEDGER: "true"
S3_ASSET_PREFIX: "${SERVER_HOST_PROTOCOL}api.${SERVER_HOST}"
SDK_HOST: "sdk.${SERVER_HOST}"
SECRET_KEY_BASE: "${SECRET_KEY_BASE}"
SENT_QUOTAS_WEBHOOK_KEY: "${SENT_QUOTAS_WEBHOOK_KEY}"
SERVER_HOST: "${SERVER_HOST}"
SERVER_HOST_PROTOCOL: "${SERVER_HOST_PROTOCOL}"
SIDEKIQ_EVENTS_CONCURRENCY: "10"
SMTP_ADDRESS: "smtp.example.com"
SMTP_AUTHENTICATION: "plain"
SMTP_DOMAIN: "${SERVER_HOST}"
SMTP_ENABLE_STARTTLS_AUTO: "true"
SMTP_PASSWORD: ""
SMTP_PORT: "587"
SMTP_USERNAME: ""
WEB_CONCURRENCY: "2"
volumes:
- "storage:/app/storage"
command:
- "bash"
- "-c"
- "bin/rails db:prepare && bin/rails db:seed && bin/rails clickhouse:setup"
depends_on:
postgres:
condition: "service_healthy"
redis:
condition: "service_healthy"
clickhouse:
condition: "service_healthy"
web:
image: "ghcr.io/grovs-io/backend:2.3.1"
restart: "unless-stopped"
environment:
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: "${ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY}"
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: "${ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT}"
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: "${ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY}"
ACTIVE_STORAGE_SERVICE: "local"
ADMIN_API_KEY: "${ADMIN_API_KEY}"
API_HOST: "api.${SERVER_HOST}"
BOOTSTRAP_ADMIN_EMAIL: "${BOOTSTRAP_ADMIN_EMAIL}"
BOOTSTRAP_ADMIN_PASSWORD: "${BOOTSTRAP_ADMIN_PASSWORD}"
CLICKHOUSE_ANALYTICS_ROLLUPS_READ_ENABLED: "true"
CLICKHOUSE_ATTRIBUTION_READ_ENABLED: "true"
CLICKHOUSE_DATABASE: "grovs_production"
CLICKHOUSE_LINK_DIMENSIONS_READ_ENABLED: "true"
CLICKHOUSE_PASSWORD: "${CLICKHOUSE_PASSWORD}"
CLICKHOUSE_PRIMARY: "true"
CLICKHOUSE_READ_ENABLED: "true"
CLICKHOUSE_ROLLUP_FAST_LANE: "true"
CLICKHOUSE_URL: "http://grovs:${CLICKHOUSE_PASSWORD}@clickhouse:8123"
CLICKHOUSE_WRITE_ENABLED: "true"
DASHBOARD_CACHE_TTL_SECONDS: "60"
DASHBOARD_HOST: "dashboard.${SERVER_HOST}"
DATABASE_URL: "postgres://grovs:${POSTGRES_PASSWORD}@postgres:5432/grovs_production"
DEFAULT_LINK_SUBTITLE: "Dynamic links, attributions, and referrals across mobile and web platforms."
DEFAULT_LINK_TITLE: "grovs"
DEFAULT_LOGO_URL: "https://appssemble-assets.s3.eu-north-1.amazonaws.com/linksquared/logo-square-new.svg"
DEFAULT_SOCIAL_PREVIEW_URL: "https://appssemble-assets.s3.eu-north-1.amazonaws.com/linksquared/social-media-placeholder.jpg"
DIAGNOSTICS_API_KEY: "${DIAGNOSTICS_API_KEY}"
DOMAIN_LIVE: "${DOMAIN_LIVE}"
DOMAIN_TEST: "${DOMAIN_TEST}"
GO_HOST: "go.${SERVER_HOST}"
GROVS_EE: "false"
GROVS_SELF_HOSTED: "true"
LINKS_PROD_HOST: "links.${DOMAIN_LIVE}"
LINKS_TEST_HOST: "links.${DOMAIN_TEST}"
MAILER_DELIVERY_METHOD: ""
MAILER_FROM: "Grovs <noreply@${SERVER_HOST}>"
MCP_CONSENT_URL: "${SERVER_HOST_PROTOCOL}dashboard.${SERVER_HOST}/mcp/authorize"
MCP_HOST: "mcp.${SERVER_HOST}"
OAUTH_CLIENT_SECRET: "${OAUTH_CLIENT_SECRET}"
OAUTH_CLIENT_UID: "${OAUTH_CLIENT_UID}"
PG_SHADOW_WRITES: "false"
POSTGRES_DB: "grovs_production"
POSTGRES_MAX_CONNECTIONS: "200"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
POSTGRES_USER: "grovs"
PREVIEW_BASE_URL: "${SERVER_HOST_PROTOCOL}preview.${SERVER_HOST}"
PREVIEW_HOST: "preview.${SERVER_HOST}"
PUBLIC_GO_PROJECT_IDENTIFIER: "go-self-hosted"
RAILS_DB_POOL: "10"
RAILS_ENV: "production"
RAILS_LOG_TO_STDOUT: "true"
RAILS_MAX_THREADS: "5"
RAILS_SERVE_STATIC_FILES: "true"
REACT_HOST: "dashboard.${SERVER_HOST}"
REACT_HOST_PROTOCOL: "${SERVER_HOST_PROTOCOL}"
REDIS_URL: "redis://redis:6379/0"
REVENUE_READS_FROM_LEDGER: "true"
S3_ASSET_PREFIX: "${SERVER_HOST_PROTOCOL}api.${SERVER_HOST}"
SDK_HOST: "sdk.${SERVER_HOST}"
SECRET_KEY_BASE: "${SECRET_KEY_BASE}"
SENT_QUOTAS_WEBHOOK_KEY: "${SENT_QUOTAS_WEBHOOK_KEY}"
SERVER_HOST: "${SERVER_HOST}"
SERVER_HOST_PROTOCOL: "${SERVER_HOST_PROTOCOL}"
SIDEKIQ_EVENTS_CONCURRENCY: "10"
SMTP_ADDRESS: "smtp.example.com"
SMTP_AUTHENTICATION: "plain"
SMTP_DOMAIN: "${SERVER_HOST}"
SMTP_ENABLE_STARTTLS_AUTO: "true"
SMTP_PASSWORD: ""
SMTP_PORT: "587"
SMTP_USERNAME: ""
WEB_CONCURRENCY: "2"
volumes:
- "storage:/app/storage"
command:
- "bundle"
- "exec"
- "puma"
- "-b"
- "tcp://0.0.0.0:3000"
expose:
- 3000
labels:
- "traefik.http.services.${APP_NAME}-links.loadbalancer.server.port=3000"
- "traefik.http.routers.${APP_NAME}-links.rule=HostRegexp(`^[a-z0-9-]+\\.${DOMAIN_LIVE}$$`) || HostRegexp(`^[a-z0-9-]+\\.${DOMAIN_TEST}$$`)"
- "traefik.http.routers.${APP_NAME}-links.entrypoints=web"
- "traefik.http.routers.${APP_NAME}-links.priority=1"
- "traefik.http.routers.${APP_NAME}-links.service=${APP_NAME}-links"
- "traefik.http.routers.${APP_NAME}-links-secure.rule=HostRegexp(`^[a-z0-9-]+\\.${DOMAIN_LIVE}$$`) || HostRegexp(`^[a-z0-9-]+\\.${DOMAIN_TEST}$$`)"
- "traefik.http.routers.${APP_NAME}-links-secure.entrypoints=websecure"
- "traefik.http.routers.${APP_NAME}-links-secure.priority=1"
- "traefik.http.routers.${APP_NAME}-links-secure.service=${APP_NAME}-links"
- "traefik.http.routers.${APP_NAME}-links-secure.tls=true"
- "traefik.http.routers.${APP_NAME}-links-secure.tls.certresolver=${GROVS_CERT_RESOLVER:-}"
- "traefik.http.routers.${APP_NAME}-links-secure.tls.domains[0].main=${DOMAIN_LIVE}"
- "traefik.http.routers.${APP_NAME}-links-secure.tls.domains[0].sans=*.${DOMAIN_LIVE}"
- "traefik.http.routers.${APP_NAME}-links-secure.tls.domains[1].main=${DOMAIN_TEST}"
- "traefik.http.routers.${APP_NAME}-links-secure.tls.domains[1].sans=*.${DOMAIN_TEST}"
depends_on:
migrate:
condition: "service_completed_successfully"
healthcheck:
test:
- "CMD"
- "curl"
- "-f"
- "http://localhost:3000/up"
interval: "10s"
timeout: "5s"
retries: 30
start_period: "60s"
worker-1:
image: "ghcr.io/grovs-io/backend:2.3.1"
restart: "unless-stopped"
environment:
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: "${ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY}"
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: "${ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT}"
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: "${ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY}"
ACTIVE_STORAGE_SERVICE: "local"
ADMIN_API_KEY: "${ADMIN_API_KEY}"
API_HOST: "api.${SERVER_HOST}"
BOOTSTRAP_ADMIN_EMAIL: "${BOOTSTRAP_ADMIN_EMAIL}"
BOOTSTRAP_ADMIN_PASSWORD: "${BOOTSTRAP_ADMIN_PASSWORD}"
CLICKHOUSE_ANALYTICS_ROLLUPS_READ_ENABLED: "true"
CLICKHOUSE_ATTRIBUTION_READ_ENABLED: "true"
CLICKHOUSE_DATABASE: "grovs_production"
CLICKHOUSE_LINK_DIMENSIONS_READ_ENABLED: "true"
CLICKHOUSE_PASSWORD: "${CLICKHOUSE_PASSWORD}"
CLICKHOUSE_PRIMARY: "true"
CLICKHOUSE_READ_ENABLED: "true"
CLICKHOUSE_ROLLUP_FAST_LANE: "true"
CLICKHOUSE_URL: "http://grovs:${CLICKHOUSE_PASSWORD}@clickhouse:8123"
CLICKHOUSE_WRITE_ENABLED: "true"
DASHBOARD_CACHE_TTL_SECONDS: "60"
DASHBOARD_HOST: "dashboard.${SERVER_HOST}"
DATABASE_URL: "postgres://grovs:${POSTGRES_PASSWORD}@postgres:5432/grovs_production"
DEFAULT_LINK_SUBTITLE: "Dynamic links, attributions, and referrals across mobile and web platforms."
DEFAULT_LINK_TITLE: "grovs"
DEFAULT_LOGO_URL: "https://appssemble-assets.s3.eu-north-1.amazonaws.com/linksquared/logo-square-new.svg"
DEFAULT_SOCIAL_PREVIEW_URL: "https://appssemble-assets.s3.eu-north-1.amazonaws.com/linksquared/social-media-placeholder.jpg"
DIAGNOSTICS_API_KEY: "${DIAGNOSTICS_API_KEY}"
DOMAIN_LIVE: "${DOMAIN_LIVE}"
DOMAIN_TEST: "${DOMAIN_TEST}"
GO_HOST: "go.${SERVER_HOST}"
GROVS_EE: "false"
GROVS_SELF_HOSTED: "true"
LINKS_PROD_HOST: "links.${DOMAIN_LIVE}"
LINKS_TEST_HOST: "links.${DOMAIN_TEST}"
MAILER_DELIVERY_METHOD: ""
MAILER_FROM: "Grovs <noreply@${SERVER_HOST}>"
MCP_CONSENT_URL: "${SERVER_HOST_PROTOCOL}dashboard.${SERVER_HOST}/mcp/authorize"
MCP_HOST: "mcp.${SERVER_HOST}"
OAUTH_CLIENT_SECRET: "${OAUTH_CLIENT_SECRET}"
OAUTH_CLIENT_UID: "${OAUTH_CLIENT_UID}"
PG_SHADOW_WRITES: "false"
POSTGRES_DB: "grovs_production"
POSTGRES_MAX_CONNECTIONS: "200"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
POSTGRES_USER: "grovs"
PREVIEW_BASE_URL: "${SERVER_HOST_PROTOCOL}preview.${SERVER_HOST}"
PREVIEW_HOST: "preview.${SERVER_HOST}"
PUBLIC_GO_PROJECT_IDENTIFIER: "go-self-hosted"
RAILS_DB_POOL: "10"
RAILS_ENV: "production"
RAILS_LOG_TO_STDOUT: "true"
RAILS_MAX_THREADS: "5"
RAILS_SERVE_STATIC_FILES: "true"
REACT_HOST: "dashboard.${SERVER_HOST}"
REACT_HOST_PROTOCOL: "${SERVER_HOST_PROTOCOL}"
REDIS_URL: "redis://redis:6379/0"
REVENUE_READS_FROM_LEDGER: "true"
S3_ASSET_PREFIX: "${SERVER_HOST_PROTOCOL}api.${SERVER_HOST}"
SDK_HOST: "sdk.${SERVER_HOST}"
SECRET_KEY_BASE: "${SECRET_KEY_BASE}"
SENT_QUOTAS_WEBHOOK_KEY: "${SENT_QUOTAS_WEBHOOK_KEY}"
SERVER_HOST: "${SERVER_HOST}"
SERVER_HOST_PROTOCOL: "${SERVER_HOST_PROTOCOL}"
SIDEKIQ_EVENTS_CONCURRENCY: "10"
SMTP_ADDRESS: "smtp.example.com"
SMTP_AUTHENTICATION: "plain"
SMTP_DOMAIN: "${SERVER_HOST}"
SMTP_ENABLE_STARTTLS_AUTO: "true"
SMTP_PASSWORD: ""
SMTP_PORT: "587"
SMTP_USERNAME: ""
WEB_CONCURRENCY: "2"
volumes:
- "storage:/app/storage"
command:
- "bash"
- "-c"
- "bundle exec sidekiq -C config/sidekiq_scheduler.yml & bundle exec sidekiq -C config/sidekiq_worker.yml & bundle exec sidekiq -C config/sidekiq_batch.yml & wait -n"
depends_on:
web:
condition: "service_healthy"
worker-2:
image: "ghcr.io/grovs-io/backend:2.3.1"
restart: "unless-stopped"
environment:
ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY: "${ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY}"
ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT: "${ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT}"
ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY: "${ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY}"
ACTIVE_STORAGE_SERVICE: "local"
ADMIN_API_KEY: "${ADMIN_API_KEY}"
API_HOST: "api.${SERVER_HOST}"
BOOTSTRAP_ADMIN_EMAIL: "${BOOTSTRAP_ADMIN_EMAIL}"
BOOTSTRAP_ADMIN_PASSWORD: "${BOOTSTRAP_ADMIN_PASSWORD}"
CLICKHOUSE_ANALYTICS_ROLLUPS_READ_ENABLED: "true"
CLICKHOUSE_ATTRIBUTION_READ_ENABLED: "true"
CLICKHOUSE_DATABASE: "grovs_production"
CLICKHOUSE_LINK_DIMENSIONS_READ_ENABLED: "true"
CLICKHOUSE_PASSWORD: "${CLICKHOUSE_PASSWORD}"
CLICKHOUSE_PRIMARY: "true"
CLICKHOUSE_READ_ENABLED: "true"
CLICKHOUSE_ROLLUP_FAST_LANE: "true"
CLICKHOUSE_URL: "http://grovs:${CLICKHOUSE_PASSWORD}@clickhouse:8123"
CLICKHOUSE_WRITE_ENABLED: "true"
DASHBOARD_CACHE_TTL_SECONDS: "60"
DASHBOARD_HOST: "dashboard.${SERVER_HOST}"
DATABASE_URL: "postgres://grovs:${POSTGRES_PASSWORD}@postgres:5432/grovs_production"
DEFAULT_LINK_SUBTITLE: "Dynamic links, attributions, and referrals across mobile and web platforms."
DEFAULT_LINK_TITLE: "grovs"
DEFAULT_LOGO_URL: "https://appssemble-assets.s3.eu-north-1.amazonaws.com/linksquared/logo-square-new.svg"
DEFAULT_SOCIAL_PREVIEW_URL: "https://appssemble-assets.s3.eu-north-1.amazonaws.com/linksquared/social-media-placeholder.jpg"
DIAGNOSTICS_API_KEY: "${DIAGNOSTICS_API_KEY}"
DOMAIN_LIVE: "${DOMAIN_LIVE}"
DOMAIN_TEST: "${DOMAIN_TEST}"
GO_HOST: "go.${SERVER_HOST}"
GROVS_EE: "false"
GROVS_SELF_HOSTED: "true"
LINKS_PROD_HOST: "links.${DOMAIN_LIVE}"
LINKS_TEST_HOST: "links.${DOMAIN_TEST}"
MAILER_DELIVERY_METHOD: ""
MAILER_FROM: "Grovs <noreply@${SERVER_HOST}>"
MCP_CONSENT_URL: "${SERVER_HOST_PROTOCOL}dashboard.${SERVER_HOST}/mcp/authorize"
MCP_HOST: "mcp.${SERVER_HOST}"
OAUTH_CLIENT_SECRET: "${OAUTH_CLIENT_SECRET}"
OAUTH_CLIENT_UID: "${OAUTH_CLIENT_UID}"
PG_SHADOW_WRITES: "false"
POSTGRES_DB: "grovs_production"
POSTGRES_MAX_CONNECTIONS: "200"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
POSTGRES_USER: "grovs"
PREVIEW_BASE_URL: "${SERVER_HOST_PROTOCOL}preview.${SERVER_HOST}"
PREVIEW_HOST: "preview.${SERVER_HOST}"
PUBLIC_GO_PROJECT_IDENTIFIER: "go-self-hosted"
RAILS_DB_POOL: "10"
RAILS_ENV: "production"
RAILS_LOG_TO_STDOUT: "true"
RAILS_MAX_THREADS: "5"
RAILS_SERVE_STATIC_FILES: "true"
REACT_HOST: "dashboard.${SERVER_HOST}"
REACT_HOST_PROTOCOL: "${SERVER_HOST_PROTOCOL}"
REDIS_URL: "redis://redis:6379/0"
REVENUE_READS_FROM_LEDGER: "true"
S3_ASSET_PREFIX: "${SERVER_HOST_PROTOCOL}api.${SERVER_HOST}"
SDK_HOST: "sdk.${SERVER_HOST}"
SECRET_KEY_BASE: "${SECRET_KEY_BASE}"
SENT_QUOTAS_WEBHOOK_KEY: "${SENT_QUOTAS_WEBHOOK_KEY}"
SERVER_HOST: "${SERVER_HOST}"
SERVER_HOST_PROTOCOL: "${SERVER_HOST_PROTOCOL}"
SIDEKIQ_EVENTS_CONCURRENCY: "10"
SMTP_ADDRESS: "smtp.example.com"
SMTP_AUTHENTICATION: "plain"
SMTP_DOMAIN: "${SERVER_HOST}"
SMTP_ENABLE_STARTTLS_AUTO: "true"
SMTP_PASSWORD: ""
SMTP_PORT: "587"
SMTP_USERNAME: ""
WEB_CONCURRENCY: "2"
volumes:
- "storage:/app/storage"
command:
- "bash"
- "-c"
- "bundle exec sidekiq -C config/sidekiq_maintenance.yml & bundle exec sidekiq -C config/sidekiq_device_updates.yml & wait -n"
depends_on:
web:
condition: "service_healthy"
dashboard:
image: "ghcr.io/grovs-io/dashboard:2.3.1"
restart: "unless-stopped"
expose:
- 3000
environment:
API_URL: "${SERVER_HOST_PROTOCOL}api.${SERVER_HOST}"
OAUTH_CLIENT_UID: "${OAUTH_CLIENT_UID}"
OAUTH_CLIENT_SECRET: "${OAUTH_CLIENT_SECRET}"
HOSTNAME: "0.0.0.0"
PORT: "3000"
depends_on:
web:
condition: "service_healthy"
volumes:
pg_data: {}
redis_data: {}
clickhouse_data: {}
storage: {}
+4
View File
@@ -0,0 +1,4 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M0 5.21739C0 2.33591 2.33591 0 5.21739 0H34.7826C37.6641 0 40 2.33591 40 5.21739V34.7826C40 37.6641 37.6641 40 34.7826 40H5.21739C2.33591 40 0 37.6641 0 34.7826V5.21739Z" fill="#1F1F1F"/>
<path d="M28.5735 22.1385C26.9079 21.8068 25.3362 22.1872 24.1183 23.0271C23.2448 23.6266 22.124 23.7422 21.166 23.2796L20.6713 23.0362C19.5442 22.4915 18.8961 21.3503 18.9024 20.127V20.1057C18.9024 20.0783 18.8961 20.0449 18.8961 20.0175C18.8742 18.8337 19.5129 17.7321 20.6087 17.2026L22.8034 16.1345C23.6425 15.7267 24.6287 15.7663 25.4521 16.2015C26.2285 16.6032 27.1459 16.7705 28.1164 16.6032C29.7883 16.3171 31.1314 14.9995 31.4226 13.3745C31.8484 10.943 29.9824 8.81594 27.5842 8.7003C26.1283 8.62727 24.8009 9.42151 23.9775 10.5961C23.6018 11.1317 23.4045 11.6369 23.3262 12.1238C23.1728 13.0062 22.6124 13.767 21.7953 14.1626L18.6425 15.6933C17.8442 16.0797 16.9018 16.0858 16.1097 15.6872C15.1454 15.2064 14.0058 15.0147 12.8098 15.2399C10.7873 15.6142 9.15924 17.2026 8.78354 19.1745C8.19181 22.315 10.6683 25.0659 13.7991 25.0659C14.6382 25.0659 15.4366 24.862 16.1347 24.509C16.9174 24.1134 17.8536 24.1347 18.6394 24.5212L20.2267 25.2942C21.1441 25.7415 21.6826 26.6605 21.7076 27.6586C21.7233 28.2216 21.8328 28.8089 22.0708 29.4175C22.866 31.4077 24.7476 32.8684 26.9361 33.0266C30.6148 33.3035 33.6361 30.1326 32.9442 26.4901C32.5371 24.3326 30.7776 22.5797 28.5735 22.1385Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

+16
View File
@@ -0,0 +1,16 @@
{
"id": "grovs",
"name": "Grovs",
"version": "2.3.1",
"description": "Self-hosted deep linking, attribution and analytics for mobile and web apps.",
"logo": "logo.svg",
"links": {
"github": "https://github.com/grovs-io/self-host",
"website": "https://www.grovs.io",
"docs": "https://github.com/grovs-io/self-host/blob/main/deploy/catalogs/dokploy/README.md"
},
"tags": [
"analytics",
"developer-tools"
]
}
+76
View File
@@ -0,0 +1,76 @@
[variables]
main_domain = "${domain}"
postgres_password = "${password:32}"
clickhouse_password = "${password:32}"
secret_key_base = "${hash:64}"
active_record_encryption_primary_key = "${hash:64}"
active_record_encryption_deterministic_key = "${hash:64}"
active_record_encryption_key_derivation_salt = "${hash:64}"
admin_api_key = "${hash:64}"
diagnostics_api_key = "${hash:64}"
sent_quotas_webhook_key = "${hash:64}"
oauth_client_uid = "${hash:48}"
oauth_client_secret = "${hash:64}"
bootstrap_admin_password = "${password:24}"
[config]
env = [
"SERVER_HOST=${main_domain}",
"DOMAIN_LIVE=${main_domain}",
"DOMAIN_TEST=test.${main_domain}",
"SERVER_HOST_PROTOCOL=http://",
"GROVS_CERT_RESOLVER=",
"BOOTSTRAP_ADMIN_EMAIL=admin@${main_domain}",
"POSTGRES_PASSWORD=${postgres_password}",
"CLICKHOUSE_PASSWORD=${clickhouse_password}",
"SECRET_KEY_BASE=${secret_key_base}",
"ACTIVE_RECORD_ENCRYPTION_PRIMARY_KEY=${active_record_encryption_primary_key}",
"ACTIVE_RECORD_ENCRYPTION_DETERMINISTIC_KEY=${active_record_encryption_deterministic_key}",
"ACTIVE_RECORD_ENCRYPTION_KEY_DERIVATION_SALT=${active_record_encryption_key_derivation_salt}",
"ADMIN_API_KEY=${admin_api_key}",
"DIAGNOSTICS_API_KEY=${diagnostics_api_key}",
"SENT_QUOTAS_WEBHOOK_KEY=${sent_quotas_webhook_key}",
"OAUTH_CLIENT_UID=${oauth_client_uid}",
"OAUTH_CLIENT_SECRET=${oauth_client_secret}",
"BOOTSTRAP_ADMIN_PASSWORD=${bootstrap_admin_password}",
]
[[config.domains]]
serviceName = "dashboard"
port = 3000
host = "dashboard.${main_domain}"
[[config.domains]]
serviceName = "web"
port = 3000
host = "api.${main_domain}"
[[config.domains]]
serviceName = "web"
port = 3000
host = "sdk.${main_domain}"
[[config.domains]]
serviceName = "web"
port = 3000
host = "mcp.${main_domain}"
[[config.domains]]
serviceName = "web"
port = 3000
host = "go.${main_domain}"
[[config.domains]]
serviceName = "web"
port = 3000
host = "preview.${main_domain}"
[[config.domains]]
serviceName = "web"
port = 3000
host = "links.${main_domain}"
[[config.domains]]
serviceName = "web"
port = 3000
host = "links.test.${main_domain}"
@@ -0,0 +1,49 @@
version: "3.8"
services:
healthchecks:
image: healthchecks/healthchecks:v4.4
restart: unless-stopped
depends_on:
db:
condition: service_healthy
expose:
- 8000
environment:
DEBUG: ${DEBUG}
DB: postgres
DB_HOST: db
DB_PORT: "5432"
DB_NAME: ${DB_NAME}
DB_USER: ${DB_USER}
DB_PASSWORD: ${DB_PASSWORD}
SECRET_KEY: ${SECRET_KEY}
SITE_ROOT: ${SITE_ROOT}
SITE_NAME: ${SITE_NAME}
ALLOWED_HOSTS: ${ALLOWED_HOSTS}
PING_ENDPOINT: ${PING_ENDPOINT}
REGISTRATION_OPEN: ${REGISTRATION_OPEN}
DEFAULT_FROM_EMAIL: ${DEFAULT_FROM_EMAIL}
EMAIL_HOST: ${EMAIL_HOST}
EMAIL_PORT: ${EMAIL_PORT}
EMAIL_HOST_USER: ${EMAIL_HOST_USER}
EMAIL_HOST_PASSWORD: ${EMAIL_HOST_PASSWORD}
EMAIL_USE_TLS: ${EMAIL_USE_TLS}
db:
image: postgres:16-alpine
restart: unless-stopped
environment:
POSTGRES_DB: ${DB_NAME}
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
volumes:
- healthchecks-db:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 10s
timeout: 5s
retries: 5
volumes:
healthchecks-db:
+6
View File
@@ -0,0 +1,6 @@
<svg width="120mm" height="120mm" version="1.1" viewBox="0 0 120 120" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(-27.502 -156.01)">
<path d="m38.253 241.39 2.9915-19.772 23.014-0.13391 11.092-63.965 18.257-2e-3 7.7596 46.333-13.449 0.0645-9.8934 57.109-18.286-9e-3 -3.23-19.585z" fill="#33333f"/>
<path d="m94.923 274.5-9.4557-56.483 1.4735-8.4919 16.484 0.0429 2.4469 12.936 30.88 0.0734-2.1276 19.624-16.084 0.0801-5.347 32.207z" fill="#5cb85f"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 484 B

+13
View File
@@ -0,0 +1,13 @@
{
"id": "healthchecks",
"name": "Healthchecks",
"version": "v4.4",
"description": "Healthchecks is an open-source cron job and background task monitoring service that alerts you when your scheduled jobs fail to check in. Registration is closed by default: create the first admin by running ./manage.py createsuperuser in the healthchecks container terminal.",
"logo": "healthchecks.svg",
"links": {
"github": "https://github.com/healthchecks/healthchecks",
"website": "https://healthchecks.io/",
"docs": "https://healthchecks.io/docs/self_hosted_docker/"
},
"tags": ["monitoring", "cron", "alerting"]
}
+29
View File
@@ -0,0 +1,29 @@
[variables]
main_domain = "${domain}"
db_password = "${password:32}"
secret_key = "${password:64}"
[config]
env = [
"DEBUG=False",
"DB_NAME=healthchecks",
"DB_USER=healthchecks",
"DB_PASSWORD=${db_password}",
"SECRET_KEY=${secret_key}",
"SITE_ROOT=https://${main_domain}",
"SITE_NAME=Healthchecks",
"ALLOWED_HOSTS=${main_domain}",
"PING_ENDPOINT=https://${main_domain}/ping/",
"REGISTRATION_OPEN=False",
"DEFAULT_FROM_EMAIL=healthchecks@${main_domain}",
"EMAIL_HOST=",
"EMAIL_PORT=587",
"EMAIL_HOST_USER=",
"EMAIL_HOST_PASSWORD=",
"EMAIL_USE_TLS=True",
]
[[config.domains]]
serviceName = "healthchecks"
port = 8000
host = "${main_domain}"
+117
View File
@@ -0,0 +1,117 @@
version: "3.8"
services:
hyperdx:
image: hyperdx/hyperdx:2.38.0
restart: unless-stopped
depends_on:
mongodb:
condition: service_healthy
clickhouse:
condition: service_healthy
environment:
FRONTEND_URL: ${HYPERDX_URL:?Set the public HyperDX URL}
HYPERDX_APP_URL: ${HYPERDX_URL:?Set the public HyperDX URL}
HYPERDX_APP_PORT: "8080"
HYPERDX_API_PORT: "8000"
SERVER_URL: http://127.0.0.1:8000
OPAMP_PORT: "4320"
MONGO_URI: mongodb://mongodb:27017/hyperdx
EXPRESS_SESSION_SECRET: ${SESSION_SECRET:?Set the session secret}
HYPERDX_LOG_LEVEL: info
USAGE_STATS_ENABLED: "false"
NEXT_TELEMETRY_DISABLED: "1"
DEFAULT_CONNECTIONS: '[{"name":"Local
ClickHouse","host":"http://clickhouse:8123","username":"hyperdx","password":"${CLICKHOUSE_PASSWORD}"}]'
DEFAULT_SOURCES: '[{"from":{"databaseName":"default","tableName":"otel_logs"},"kind":"log","timestampValueExpression":"Timestamp","name":"Logs","displayedTimestampValueExpression":"Timestamp","implicitColumnExpression":"Body","serviceNameExpression":"ServiceName","bodyExpression":"Body","eventAttributesExpression":"LogAttributes","resourceAttributesExpression":"ResourceAttributes","defaultTableSelectExpression":"Timestamp,ServiceName,SeverityText,Body","severityTextExpression":"SeverityText","traceIdExpression":"TraceId","spanIdExpression":"SpanId","metadataMaterializedViews":{"keyRollupTable":"otel_logs_key_rollup_15m","kvRollupTable":"otel_logs_kv_rollup_15m","granularity":"15
minute"},"connection":"Local
ClickHouse","traceSourceId":"Traces","sessionSourceId":"Sessions","metricSourceId":"Metrics"},{"from":{"databaseName":"default","tableName":"otel_traces"},"kind":"trace","timestampValueExpression":"Timestamp","name":"Traces","displayedTimestampValueExpression":"Timestamp","implicitColumnExpression":"SpanName","serviceNameExpression":"ServiceName","eventAttributesExpression":"SpanAttributes","resourceAttributesExpression":"ResourceAttributes","defaultTableSelectExpression":"Timestamp,ServiceName,StatusCode,round(Duration/1e6),SpanName","traceIdExpression":"TraceId","spanIdExpression":"SpanId","durationExpression":"Duration","durationPrecision":9,"parentSpanIdExpression":"ParentSpanId","spanNameExpression":"SpanName","spanKindExpression":"SpanKind","statusCodeExpression":"StatusCode","statusMessageExpression":"StatusMessage","metadataMaterializedViews":{"keyRollupTable":"otel_traces_key_rollup_15m","kvRollupTable":"otel_traces_kv_rollup_15m","granularity":"15
minute"},"connection":"Local
ClickHouse","logSourceId":"Logs","sessionSourceId":"Sessions","metricSourceId":"Metrics"},{"from":{"databaseName":"default","tableName":""},"kind":"metric","timestampValueExpression":"TimeUnix","name":"Metrics","resourceAttributesExpression":"ResourceAttributes","metricTables":{"gauge":"otel_metrics_gauge","histogram":"otel_metrics_histogram","sum":"otel_metrics_sum","exponential histogram":"otel_metrics_exponential_histogram","_id":"682586a8b1f81924e628e808","id":"682586a8b1f81924e628e808"},"connection":"Local
ClickHouse","logSourceId":"Logs","traceSourceId":"Traces","sessionSourceId":"Sessions"},{"from":{"databaseName":"default","tableName":"hyperdx_sessions"},"kind":"session","timestampValueExpression":"TimestampTime","name":"Sessions","displayedTimestampValueExpression":"Timestamp","implicitColumnExpression":"Body","serviceNameExpression":"ServiceName","bodyExpression":"Body","eventAttributesExpression":"LogAttributes","resourceAttributesExpression":"ResourceAttributes","defaultTableSelectExpression":"Timestamp,ServiceName,SeverityText,Body","severityTextExpression":"SeverityText","traceIdExpression":"TraceId","spanIdExpression":"SpanId","connection":"Local
ClickHouse","logSourceId":"Logs","traceSourceId":"Traces","metricSourceId":"Metrics"}]'
expose:
- "8080"
healthcheck:
test:
- CMD
- node
- -e
- require('http').get('http://127.0.0.1:8080/api/ready',r=>process.exit(r.statusCode===200?0:1)).on('error',()=>process.exit(1))
interval: 30s
timeout: 5s
retries: 5
start_period: 60s
mongodb:
image: mongo:8.0.29
restart: unless-stopped
command:
- mongod
- --wiredTigerCacheSizeGB
- "0.25"
volumes:
- mongodb-data:/data/db
- mongodb-config:/data/configdb
healthcheck:
test:
- CMD
- mongosh
- --quiet
- --eval
- "quit(db.adminCommand('ping').ok ? 0 : 1)"
interval: 30s
timeout: 10s
retries: 5
start_period: 30s
clickhouse:
image: clickhouse/clickhouse-server:26.5.7.64-alpine
restart: unless-stopped
environment:
CLICKHOUSE_USER: hyperdx
CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD:?Set the ClickHouse password}
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: "1"
ulimits:
nofile:
soft: 262144
hard: 262144
volumes:
- clickhouse-data:/var/lib/clickhouse
- clickhouse-logs:/var/log/clickhouse-server
- ../files/clickhouse-config.xml:/etc/clickhouse-server/config.d/hyperdx.xml:ro
healthcheck:
test:
- CMD
- wget
- --quiet
- --spider
- http://127.0.0.1:8123/ping
interval: 30s
timeout: 5s
retries: 5
start_period: 60s
otel-collector:
image: clickhouse/clickstack-otel-collector:2.38.0
restart: unless-stopped
depends_on:
clickhouse:
condition: service_healthy
hyperdx:
condition: service_healthy
environment:
CLICKHOUSE_ENDPOINT: tcp://clickhouse:9000?dial_timeout=10s
CLICKHOUSE_USER: hyperdx
CLICKHOUSE_PASSWORD: ${CLICKHOUSE_PASSWORD:?Set the ClickHouse password}
HYPERDX_OTEL_EXPORTER_CLICKHOUSE_DATABASE: default
HYPERDX_OTEL_EXPORTER_CREATE_LEGACY_SCHEMA: "true"
OPAMP_SERVER_URL: http://hyperdx:4320
HYPERDX_LOG_LEVEL: info
expose:
- "4317"
- "4318"
volumes:
- otel-supervisor:/etc/otel/supervisor-data
volumes:
mongodb-data: {}
mongodb-config: {}
clickhouse-data: {}
clickhouse-logs: {}
otel-supervisor: {}
+12
View File
@@ -0,0 +1,12 @@
<svg xmlns="http://www.w3.org/2000/svg" width="260" height="260" fill="none" viewBox="0 0 260 260">
<defs>
<clipPath id="a">
<rect width="260" height="260" fill="#fff" rx="40" />
</clipPath>
</defs>
<g clip-path="url(#a)">
<path fill="#25E2A5" d="M242.166 65v130l-112.583 65.001L17 195V65L129.583 0l112.583 65Z" />
<path fill="#1E1E1E"
d="M157.698 42.893c1.754 1.284 2.573 3.92 1.976 6.361l-15.713 64.274h28.994c1.74 0 3.314 1.302 4.004 3.313.691 2.011.366 4.346-.827 5.941l-69.801 93.342c-1.391 1.86-3.617 2.267-5.371.984-1.753-1.285-2.572-3.921-1.976-6.362l15.713-64.274H85.704c-1.74 0-3.315-1.302-4.005-3.312-.69-2.011-.365-4.346.828-5.942l69.801-93.342c1.39-1.86 3.616-2.267 5.37-.983Z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 741 B

+41
View File
@@ -0,0 +1,41 @@
# HyperDX
This template deploys HyperDX with MongoDB, ClickHouse, and the ClickStack OpenTelemetry collector. It uses HyperDX's authenticated application image. Logs, traces, metrics, and session replay sources are configured automatically when you create the first account.
## Before deploying
Use an x86-64 server with AVX support for MongoDB, at least 2 CPU cores, and 4 GiB of available RAM for testing. Reserve more memory and disk space for production workloads.
Keep Dokploy's isolated deployment enabled. MongoDB has no authentication and must remain on the private application network. ClickHouse uses a generated password. Neither database needs a public port.
The ClickHouse configuration starts with a 2 GiB server memory budget and small caches. Adjust `clickhouse-config.xml` in Dokploy's file mounts for your workload and available memory. This setting is ClickHouse's accounting limit, not a hard container RAM limit.
## First login
Open the assigned domain and create the first account. HyperDX allows one initial team; invite additional users from that team after setup. Complete this step before sharing the domain.
When enabling HTTPS or changing the domain in Dokploy, set `HYPERDX_URL` to the matching origin, such as `https://hyperdx.example.com`, and redeploy. Use HTTPS before sending credentials over an untrusted network. The web interface proxies API requests internally, so you do not need to publish API port 8000.
Keep `SESSION_SECRET` stable across redeployments. If you change `CLICKHOUSE_PASSWORD` after creating your account, also update the saved ClickHouse connection in HyperDX.
## Send telemetry
Copy the ingestion API key from HyperDX's team settings. This key is different from the personal API key used to query HyperDX's API.
For senders on the private application network:
```text
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_HEADERS=authorization=<ingestion-api-key>
```
For external senders, add a domain in Dokploy for service `otel-collector`, port `4318`, enable HTTPS, and use that URL as the OTLP endpoint. HTTP/protobuf telemetry uses `/v1/logs`, `/v1/traces`, and `/v1/metrics` beneath that endpoint. The collector requires the ingestion API key after the first team is created.
For OTLP gRPC, publish an unused host port to collector port `4317` in Dokploy's Compose editor and restrict access to trusted senders. Ordinary HTTP domain routing does not configure gRPC ingestion automatically. The template publishes no host ports by default.
## Persistence
MongoDB volumes store accounts, connections, dashboards, and saved searches. ClickHouse volumes store telemetry and server logs. The collector volume retains its supervisor state. Preserve these volumes during redeployments and back up MongoDB and ClickHouse before upgrading.
Usage reporting and Next.js telemetry are disabled by default. Configure retention in ClickHouse for the volume of telemetry you expect.
+13
View File
@@ -0,0 +1,13 @@
{
"id": "hyperdx",
"name": "HyperDX",
"version": "2.38.0",
"description": "HyperDX searches and visualizes logs, traces, metrics, and session replays. Includes ClickHouse, MongoDB, and the ClickStack OpenTelemetry collector.",
"logo": "hyperdx.svg",
"links": {
"github": "https://github.com/hyperdxio/hyperdx",
"website": "https://hyperdx.io/",
"docs": "https://clickhouse.com/docs/use-cases/observability/clickstack"
},
"tags": ["monitoring", "logging", "observability"]
}
+30
View File
@@ -0,0 +1,30 @@
[variables]
main_domain = "${domain}"
session_secret = "${password:64}"
clickhouse_password = "${password:32}"
[config]
env = [
"HYPERDX_URL=http://${main_domain}",
"SESSION_SECRET=${session_secret}",
"CLICKHOUSE_PASSWORD=${clickhouse_password}"
]
[[config.domains]]
serviceName = "hyperdx"
port = 8080
host = "${main_domain}"
[[config.mounts]]
filePath = "clickhouse-config.xml"
content = """
<clickhouse>
<logger>
<level>warning</level>
</logger>
<custom_settings_prefixes>hyperdx</custom_settings_prefixes>
<max_server_memory_usage>2147483648</max_server_memory_usage>
<mark_cache_size>134217728</mark_cache_size>
<uncompressed_cache_size>67108864</uncompressed_cache_size>
</clickhouse>
"""
+27
View File
@@ -0,0 +1,27 @@
# Template validation
Tested on 2026-09-06 through Dokploy on Linux x86-64 with Docker Engine 29.1.3, using the image versions pinned in this template.
## Checks performed
- Imported the Compose and TOML files through Dokploy's Base64 import API with isolated deployment enabled.
- Confirmed Dokploy created the ClickHouse configuration file mount and all four services became healthy.
- Created the first account and logged in through the assigned domain and Traefik. HyperDX created Logs, Traces, Metrics, and Sessions sources automatically.
- Sent OTLP JSON logs, traces, and metrics to the collector over its private network, authenticated with the team's ingestion key.
- Confirmed unauthenticated ingestion returned HTTP 401.
- Retrieved the test log and trace through HyperDX's authenticated search API.
- Stopped and started the stack through Dokploy. Login, sources, and log and trace searches still worked. Confirmed the test metric value remained in ClickHouse.
- The instance owner tested the web interface and confirmed it works.
- Sent an OTLP exponential histogram, verified the saved Metrics source maps `exponential histogram` to `otel_metrics_exponential_histogram`, and discovered the metric through HyperDX's authenticated ClickHouse query proxy using that mapping.
The four containers used approximately 0.9 GiB during this small test. This does not replace the upstream recommendation of at least 4 GiB of available memory, and is not a production sizing benchmark.
Session replay ingestion and public OTLP/gRPC exposure have not been tested.
## Repeat the ingestion check
1. Deploy with isolated deployment enabled and create the first account.
2. Copy the team ingestion API key and configure your sender as described in `instructions.md`.
3. Send an OpenTelemetry log with a unique body and a trace with a unique span name. Send a gauge metric with a known value.
4. Find the log and trace in HyperDX, then check the metric.
5. Stop and start the stack through Dokploy. Confirm you can log in again and find the same data. Set a search time range that includes the original events.
+2 -2
View File
@@ -2,14 +2,14 @@ version: "3.8"
services:
instatic-init:
image: ghcr.io/corebunch/instatic:0.0.16
image: ghcr.io/corebunch/instatic:0.0.18
user: "0:0"
entrypoint: ["chown", "-R", "bun:bun", "/app/storage"]
volumes:
- instatic-storage:/app/storage
instatic:
image: ghcr.io/corebunch/instatic:0.0.16
image: ghcr.io/corebunch/instatic:0.0.18
restart: unless-stopped
env_file:
- .env
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "instatic",
"name": "Instatic",
"version": "0.0.16",
"version": "0.0.18",
"description": "Instatic is a self-hosted, open-source visual CMS combining a canvas editor, content engine, and static site publisher, producing clean semantic HTML with no framework runtime shipped to visitors.",
"logo": "instatic.svg",
"links": {
+21
View File
@@ -0,0 +1,21 @@
version: "3.8"
services:
junctio:
image: ghcr.io/k2so-dev/junctio:0.2.1
restart: unless-stopped
expose:
- 3000
environment:
JUNCTIO_SECRET: ${JUNCTIO_SECRET}
JUNCTIO_BASE_URL: ${JUNCTIO_BASE_URL}
JUNCTIO_TRUST_PROXY: ${JUNCTIO_TRUST_PROXY}
volumes:
- junctio-data:/data
- junctio-cache:/cache
tmpfs:
- /tmp
read_only: true
volumes:
junctio-data: {}
junctio-cache: {}
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

+19
View File
@@ -0,0 +1,19 @@
{
"id": "junctio",
"name": "Junctio",
"version": "0.2.1",
"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/"
},
"tags": [
"ai",
"mcp",
"gateway",
"oauth",
"developer-tools"
]
}
+16
View File
@@ -0,0 +1,16 @@
[variables]
main_domain = "${domain}"
junctio_secret = "${hash:64}"
[config]
mounts = []
[[config.domains]]
serviceName = "junctio"
port = 3000
host = "${main_domain}"
[config.env]
JUNCTIO_SECRET = "${junctio_secret}"
JUNCTIO_BASE_URL = "https://${main_domain}"
JUNCTIO_TRUST_PROXY = "true"
+65
View File
@@ -0,0 +1,65 @@
version: "3.8"
services:
keyzori:
image: ghcr.io/keyzori/keyzori:93b5d75ac8e5a4cd0740bfe1a46b5663674767fb
restart: unless-stopped
read_only: true
tmpfs:
- /tmp:rw,noexec,nosuid,size=16m
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
env_file:
- path: .env
required: false
environment:
KEYZORI_ADMIN_KEY: ${KEYZORI_ADMIN_KEY:?Set KEYZORI_ADMIN_KEY}
KEYZORI_DATABASE_URL: postgresql://keyzori:${KEYZORI_POSTGRES_PASSWORD:?Set KEYZORI_POSTGRES_PASSWORD}@postgres:5432/keyzori
KEYZORI_REDIS_URL: redis://redis:6379
expose:
- "6284"
stop_grace_period: 30s
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-q", "-T", "5", "-O", "/dev/null", "http://127.0.0.1:6284/ready"]
interval: 15s
timeout: 6s
start_period: 60s
retries: 3
postgres:
image: postgres:18.3-alpine
restart: unless-stopped
environment:
POSTGRES_USER: keyzori
POSTGRES_DB: keyzori
POSTGRES_PASSWORD: ${KEYZORI_POSTGRES_PASSWORD:?Set KEYZORI_POSTGRES_PASSWORD}
volumes:
- postgres-data:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U keyzori -d keyzori"]
interval: 5s
timeout: 5s
retries: 20
redis:
image: redis:8.6.1-alpine
restart: unless-stopped
command: ["redis-server", "--appendonly", "yes", "--maxmemory", "256mb", "--maxmemory-policy", "noeviction"]
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 5s
retries: 20
volumes:
postgres-data:
redis-data:
Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

+13
View File
@@ -0,0 +1,13 @@
{
"id": "keyzori",
"name": "Keyzori",
"version": "93b5d75ac8e5a4cd0740bfe1a46b5663674767fb",
"description": "Self-hosted software license server with customer management, device access controls, sessions, and usage metering through an HTTP API and CLI.",
"links": {
"github": "https://github.com/keyzori/keyzori",
"website": "",
"docs": "https://github.com/keyzori/keyzori/wiki"
},
"logo": "keyzori.png",
"tags": ["licensing", "security", "developer-tools"]
}
+15
View File
@@ -0,0 +1,15 @@
[variables]
main_domain = "${domain}"
admin_key = "${hash:32}"
postgres_password = "${hash:32}"
[config]
env = [
"KEYZORI_ADMIN_KEY=${admin_key}",
"KEYZORI_POSTGRES_PASSWORD=${postgres_password}",
]
[[config.domains]]
serviceName = "keyzori"
port = 6284
host = "${main_domain}"
+15
View File
@@ -0,0 +1,15 @@
version: "3.8"
services:
lfsx:
image: ghcr.io/ferrlabs/lfsx:1.14.1
restart: unless-stopped
environment:
- LFSX_AUTH=github
volumes:
- lfsx-data:/var/lib/lfsx
expose:
- "8080"
volumes:
lfsx-data: {}
+7
View File
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" fill="#1d6b52" />
<rect x="3" y="3" width="12" height="12" fill="#f3f2f2" />
<rect x="17" y="3" width="12" height="12" fill="#f3f2f2" />
<rect x="3" y="17" width="12" height="12" fill="#f3f2f2" />
<rect x="17" y="17" width="12" height="12" fill="#7fa896" />
</svg>

After

Width:  |  Height:  |  Size: 365 B

+18
View File
@@ -0,0 +1,18 @@
{
"id": "lfsx",
"name": "LFSX",
"version": "1.14.1",
"description": "Self-hosted Git LFS server that keeps large binaries off your forge's metered storage.",
"logo": "lfsx.svg",
"links": {
"github": "https://github.com/FerrLabs/LFSX",
"website": "https://lfsx.dev",
"docs": "https://lfsx.dev/docs/quickstart"
},
"tags": [
"git",
"developer-tools",
"storage",
"self-hosted"
]
}
+13
View File
@@ -0,0 +1,13 @@
[variables]
main_domain = "${domain}"
[config]
mounts = []
[[config.domains]]
serviceName = "lfsx"
port = 8080
host = "${main_domain}"
[config.env]
LFSX_PUBLIC_URL = "https://${main_domain}"
LFSX_AUTH = "github"
+15 -1
View File
@@ -1,7 +1,7 @@
version: "3.8"
services:
libredb-studio:
image: ghcr.io/libredb/libredb-studio:0.9.59
image: ghcr.io/libredb/libredb-studio:0.18.0
restart: unless-stopped
environment:
- ADMIN_EMAIL=admin@libredb.org
@@ -11,6 +11,20 @@ services:
- JWT_SECRET=${JWT_SECRET}
- STORAGE_PROVIDER=sqlite
- STORAGE_SQLITE_PATH=/app/data/libredb-storage.db
# Dokploy's auto-generated domain is HTTP (sslip.io); keep false so login works
- AUTH_COOKIE_SECURE=false
healthcheck:
test:
[
"CMD",
"node",
"-e",
"fetch('http://127.0.0.1:3000/api/db/health').then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))"
]
interval: 30s
timeout: 5s
retries: 3
start_period: 15s
volumes:
- libredb-data:/app/data
volumes:
+2 -2
View File
@@ -1,8 +1,8 @@
{
"id": "libredb-studio",
"name": "LibreDB Studio",
"version": "0.9.59",
"description": "The modern, AI-powered open-source SQL IDE. Query PostgreSQL, MySQL, Oracle, SQL Server, SQLite, MongoDB and Redis from your browser.",
"version": "0.18.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-six drivers reaching fifty-four named engines.",
"logo": "libredb-studio.svg",
"links": {
"github": "https://github.com/libredb/libredb-studio",
+1 -5
View File
@@ -8,11 +8,7 @@ jwt_secret = "${password:64}"
serviceName = "libredb-studio"
port = 3000
[[config.env]]
[config.env]
ADMIN_PASSWORD = "${admin_password}"
[[config.env]]
USER_PASSWORD = "${user_password}"
[[config.env]]
JWT_SECRET = "${jwt_secret}"
+20 -5
View File
@@ -1,7 +1,10 @@
version: "3.8"
services:
metabase:
image: metabase/metabase:v0.50.8
image: metabase/metabase:v0.63.18
restart: unless-stopped
expose:
- 3000
volumes:
- /dev/urandom:/dev/random:ro
environment:
@@ -9,17 +12,29 @@ services:
MB_DB_DBNAME: metabaseappdb
MB_DB_PORT: 5432
MB_DB_USER: metabase
MB_DB_PASS: mysecretpassword
MB_DB_PASS: ${POSTGRES_PASSWORD}
MB_DB_HOST: postgres
depends_on:
postgres:
condition: service_healthy
healthcheck:
test: curl --fail -I http://localhost:3000/api/health || exit 1
interval: 15s
timeout: 5s
retries: 5
postgres:
image: postgres:14
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_USER: metabase
POSTGRES_DB: metabaseappdb
POSTGRES_PASSWORD: mysecretpassword
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U metabase -d metabaseappdb"]
interval: 10s
timeout: 5s
retries: 5
volumes:
postgres-data:
+1 -1
View File
@@ -1,7 +1,7 @@
{
"id": "metabase",
"name": "Metabase",
"version": "v0.50.8",
"version": "v0.63.18",
"description": "Metabase is an open source business intelligence tool that allows you to ask questions and visualize data.",
"logo": "metabase.png",
"links": {
+4 -1
View File
@@ -1,8 +1,11 @@
[variables]
main_domain = "${domain}"
postgres_password = "${password:32}"
[config]
env = {}
env = [
"POSTGRES_PASSWORD=${postgres_password}"
]
mounts = []
[[config.domains]]
+41
View File
@@ -0,0 +1,41 @@
version: "3.8"
services:
obscura-cdp:
image: h4ckf0r0day/obscura:0.2.1
restart: unless-stopped
command: ["serve", "--host", "0.0.0.0", "--port", "9222", "--stealth", "--storage-dir", "/data"]
expose:
- "9222"
volumes:
- obscura-data:/data
obscura-mcp:
image: h4ckf0r0day/obscura:0.2.1
restart: unless-stopped
command: ["mcp", "--http", "--host", "0.0.0.0", "--port", "3000", "--stealth"]
environment:
OBSCURA_MCP_ALLOWED_ORIGINS: https://${OBSCURA_HOST}
expose:
- "3000"
caddy:
image: caddy:2.10.2-alpine
restart: unless-stopped
environment:
OBSCURA_HOST: ${OBSCURA_HOST}
OBSCURA_API_TOKEN: ${OBSCURA_API_TOKEN}
volumes:
- ../files/Caddyfile:/etc/caddy/Caddyfile:ro
depends_on:
- obscura-cdp
- obscura-mcp
healthcheck:
test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:2019/config/"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
volumes:
obscura-data:
+19
View File
@@ -0,0 +1,19 @@
{
"id": "obscura",
"name": "Obscura Browser",
"version": "0.2.1",
"description": "Headless browser for AI agents with authenticated remote MCP and Chrome DevTools Protocol endpoints.",
"logo": "obscura.png",
"links": {
"github": "https://github.com/h4ckf0r0day/obscura",
"website": "https://github.com/h4ckf0r0day/obscura",
"docs": "https://github.com/h4ckf0r0day/obscura/blob/master/docs/Use-the-MCP-server.md"
},
"tags": [
"ai",
"browser",
"automation",
"mcp",
"cdp"
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

+62
View File
@@ -0,0 +1,62 @@
[variables]
main_domain = "${domain}"
api_token = "${password:48}"
[config]
env = [
"OBSCURA_HOST=${main_domain}",
"OBSCURA_API_TOKEN=${api_token}",
]
[[config.domains]]
serviceName = "caddy"
port = 80
host = "${main_domain}"
[[config.mounts]]
filePath = "Caddyfile"
content = """
:80 {
@mcp path /mcp /mcp/*
@cdpVersion path /json/version /json/version/
handle @mcp {
@authorized header Authorization "Bearer {$OBSCURA_API_TOKEN}"
handle @authorized {
reverse_proxy obscura-mcp:3000
}
respond "Unauthorized" 401
}
handle @cdpVersion {
@authorized header Authorization "Bearer {$OBSCURA_API_TOKEN}"
handle @authorized {
header Content-Type application/json
respond `{"Browser":"Obscura","Protocol-Version":"1.3","webSocketDebuggerUrl":"wss://{$OBSCURA_HOST}/devtools/browser?access_token={$OBSCURA_API_TOKEN}"}` 200
}
respond "Unauthorized" 401
}
handle {
@authorizedByHeader header Authorization "Bearer {$OBSCURA_API_TOKEN}"
@authorizedByQuery {
path /devtools/*
query access_token={$OBSCURA_API_TOKEN}
}
handle @authorizedByHeader {
reverse_proxy obscura-cdp:9222
}
handle @authorizedByQuery {
reverse_proxy obscura-cdp:9222
}
respond "Unauthorized" 401
}
}
"""
+40
View File
@@ -0,0 +1,40 @@
# https://docs.opencloud.eu
#
# This Dokploy template for OpenCloud sets the default credentials to:
# USERNAME: admin
# PASSWORD: <SECRET GENERATED IN ENVIRONMENT VARIABLES>
#
# !!! IMPORTANT !!!
# Please review the environment variable settings and customize
# them prior to the first deployment!
#
# If you have already deployed once, changes to some environment
# variables may not take effect (for example, the initial admin password).
services:
opencloud:
image: opencloudeu/opencloud:7.2
restart: unless-stopped
entrypoint: /bin/sh
command: ["-c", "opencloud init || true; opencloud server"]
environment:
- OC_URL=${OC_URL:-https://localhost:9200}
- INITIAL_ADMIN_PASSWORD=${INITIAL_ADMIN_PASSWORD:-}
- IDM_ADMIN_PASSWORD=${IDM_ADMIN_PASSWORD:-${INITIAL_ADMIN_PASSWORD:-}}
- PROXY_HTTP_ADDR=${PROXY_HTTP_ADDR:-0.0.0.0:9200}
- PROXY_TLS=${PROXY_TLS:-false}
- OC_INSECURE=${OC_INSECURE:-false}
- OC_LOG_LEVEL=${OC_LOG_LEVEL:-info}
volumes:
- opencloud-config:/etc/opencloud
- opencloud-data:/var/lib/opencloud
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:9200/healthz || exit 1"]
interval: 30s
timeout: 10s
retries: 5
start_period: 45s
volumes:
opencloud-config: {}
opencloud-data: {}
+13
View File
@@ -0,0 +1,13 @@
{
"id": "opencloud",
"name": "OpenCloud",
"version": "7.2",
"description": "Open source cloud platform for secure file sync, sharing, and content collaboration",
"logo": "opencloud.svg",
"links": {
"github": "https://github.com/opencloud-eu/opencloud",
"website": "https://opencloud.eu",
"docs": "https://docs.opencloud.eu"
},
"tags": ["Storage", "Cloud", "Files", "Productivity"]
}
+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512" viewBox="0 0 512 512">
<rect x="0" y="0" width="512" height="512" rx="64" fill="#20434f"/>
<polygon points="255.98 342.75 271.89 333.57 271.89 267.12 329.08 234.1 329.08 215.78 313.18 206.6 255.6 239.84 198.83 207.06 182.93 216.24 182.93 234.56 240.12 267.58 240.12 333.59 255.98 342.75" fill="#e2baff"/>
<polygon points="401.95 150.82 256 66.56 256 66.56 256 66.56 110.05 150.82 110.05 187.5 256 103.24 401.95 187.5 401.95 150.82" fill="#e2baff"/>
<polygon points="401.95 324.5 256 408.76 110.06 324.5 110.06 361.17 256 445.43 256 445.43 256 445.43 401.95 361.17 401.95 324.5" fill="#e2baff"/>
</svg>

After

Width:  |  Height:  |  Size: 732 B

+17
View File
@@ -0,0 +1,17 @@
[variables]
main_domain = "${domain}"
admin_password = "${password:32}"
[[config.domains]]
serviceName = "opencloud"
port = 9200
host = "${main_domain}"
[config.env]
OC_URL = "https://${main_domain}"
INITIAL_ADMIN_PASSWORD = "${admin_password}"
IDM_ADMIN_PASSWORD = "${admin_password}"
PROXY_HTTP_ADDR = "0.0.0.0:9200"
PROXY_TLS = "false"
OC_INSECURE = "false"
OC_LOG_LEVEL = "info"
+44
View File
@@ -0,0 +1,44 @@
version: "3.8"
services:
opencode:
image: ghcr.io/anomalyco/opencode:1.18.32
restart: unless-stopped
entrypoint: []
# The official image is minimal (no git/node). Provision a toolchain on
# start-up so the agent can clone repos and run project commands.
# Set TOOLCHAIN_PACKAGES to "" to skip it, or to e.g. "git go" for another stack.
command:
- sh
- -c
- |
set -e
apk add --no-cache $${TOOLCHAIN_PACKAGES} >/dev/null 2>&1 || true
if [ -n "$${GIT_TOKEN}" ] && [ -n "$${GIT_REPO_URL}" ]; then
host=$$(printf '%s' "$${GIT_REPO_URL}" | sed -E 's#^https?://([^/]+)/.*#\1#')
git config --global credential.helper store
printf 'https://x-access-token:%s@%s\n' "$${GIT_TOKEN}" "$$host" > /root/.git-credentials
fi
if [ -n "$${GIT_REPO_URL}" ]; then
dir="/workspace/$$(basename "$${GIT_REPO_URL}" .git)"
[ -d "$$dir/.git" ] || git clone "$${GIT_REPO_URL}" "$$dir" || true
fi
exec opencode serve --hostname 0.0.0.0 --port 4096
working_dir: /workspace
expose:
- 4096
environment:
- OPENCODE_SERVER_USERNAME=${OPENCODE_SERVER_USERNAME}
- OPENCODE_SERVER_PASSWORD=${OPENCODE_SERVER_PASSWORD}
- TOOLCHAIN_PACKAGES=${TOOLCHAIN_PACKAGES}
- GIT_REPO_URL=${GIT_REPO_URL}
- GIT_TOKEN=${GIT_TOKEN}
volumes:
- opencode-data:/root/.local/share/opencode
- opencode-config:/root/.config/opencode
- opencode-workspace:/workspace
volumes:
opencode-data:
opencode-config:
opencode-workspace:
+19
View File
@@ -0,0 +1,19 @@
{
"id": "opencode",
"name": "OpenCode",
"version": "1.18.32",
"description": "OpenCode is an open source AI coding agent. This template runs its password-protected web UI; optionally set a repository URL to clone on start-up, then chat with, edit and run your code from the browser.",
"logo": "opencode.svg",
"links": {
"github": "https://github.com/anomalyco/opencode",
"website": "https://opencode.ai",
"docs": "https://opencode.ai/v2/docs"
},
"tags": [
"ai",
"coding",
"agent",
"development",
"self-hosted"
]
}
+7
View File
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink" width="512" height="512"><svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="512" height="512" fill="#131010"></rect>
<path d="M320 224V352H192V224H320Z" fill="#5A5858"></path>
<path fill-rule="evenodd" clip-rule="evenodd" d="M384 416H128V96H384V416ZM320 160H192V352H320V160Z" fill="white"></path>
</svg><style>@media (prefers-color-scheme: light) { :root { filter: none; } }
@media (prefers-color-scheme: dark) { :root { filter: none; } }
</style></svg>

After

Width:  |  Height:  |  Size: 612 B

+21
View File
@@ -0,0 +1,21 @@
[variables]
main_domain = "${domain}"
opencode_password = "${password:32}"
[config]
[[config.domains]]
serviceName = "opencode"
port = 4096
host = "${main_domain}"
https = true
[config.env]
OPENCODE_SERVER_USERNAME = "opencode"
OPENCODE_SERVER_PASSWORD = "${opencode_password}"
# Packages installed in the container at start-up (Alpine apk).
# Set to "" to keep the minimal image, or adapt to your stack (e.g. "git go").
TOOLCHAIN_PACKAGES = "git nodejs npm python3"
# Optional: clone a repository into /workspace on start-up.
# Leave GIT_REPO_URL empty to skip. Set GIT_TOKEN (GitHub PAT, Contents: read) for private repos.
GIT_REPO_URL = ""
GIT_TOKEN = ""
+20
View File
@@ -0,0 +1,20 @@
# OpenLivery on Dokploy
The first registration creates the agency owner and closes public sign-up
Create additional client workspaces from the dashboard
This template uses the official OpenLivery v0.4.0 images for Linux AMD64
Use an x86-64 server, or configure AMD64 emulation on an ARM server
The generated domain initially uses HTTP
Before using real client data, configure a domain and HTTPS in Dokploy, update FRONTEND_URL to that HTTPS origin and set COOKIE_SECURE=true, then redeploy
Add your own AI provider credentials in OpenLivery and configure WhatsApp Cloud API, the QR bridge or the web widget
Provider, WhatsApp and infrastructure costs are separate
Back up PostgreSQL, the backend-storage volume and the generated environment before upgrades
Keep ENCRYPTION_KEY and WHATSAPP_BRIDGE_TOKEN unchanged across restarts and upgrades
Client portals use the main domain by default
Additional client domains require DNS and proxy configuration
[Self-hosting guide](https://github.com/sarrazola/openlivery/blob/main/docs/en/self-hosting.md)
+99
View File
@@ -0,0 +1,99 @@
version: "3.8"
services:
openlivery:
image: caddy:2.10.2-alpine
restart: unless-stopped
volumes:
- ../files/Caddyfile:/etc/caddy/Caddyfile:ro
expose:
- "80"
depends_on:
api:
condition: service_healthy
web:
condition: service_healthy
db:
image: postgres:17.6-alpine
restart: unless-stopped
environment:
POSTGRES_DB: openlivery
POSTGRES_USER: openlivery
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U openlivery -d openlivery"]
interval: 5s
timeout: 5s
retries: 20
api:
image: ghcr.io/sarrazola/openlivery-api:v0.4.0
platform: linux/amd64
restart: unless-stopped
environment:
DATABASE_URL: postgresql+psycopg://openlivery:${POSTGRES_PASSWORD}@db:5432/openlivery
SECRET_KEY: ${SECRET_KEY}
ENCRYPTION_KEY: ${ENCRYPTION_KEY}
WHATSAPP_BRIDGE_TOKEN: ${WHATSAPP_BRIDGE_TOKEN}
FRONTEND_URL: ${FRONTEND_URL}
COOKIE_SECURE: ${COOKIE_SECURE}
COOKIE_SAMESITE: lax
BACKEND_URL: http://api:8000
WHATSAPP_BRIDGE_URL: http://whatsapp:3101
STORAGE_DIR: /app/backend/storage
ALLOW_MULTI_AGENCY: "false"
volumes:
- backend-storage:/app/backend/storage
depends_on:
db:
condition: service_healthy
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=3)"]
interval: 10s
timeout: 5s
retries: 12
start_period: 30s
web:
image: ghcr.io/sarrazola/openlivery-web:v0.4.0
platform: linux/amd64
restart: unless-stopped
environment:
BACKEND_INTERNAL_URL: http://api:8000
depends_on:
api:
condition: service_healthy
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3000/login').then(r => { if (!r.ok) process.exit(1) }).catch(() => process.exit(1))"]
interval: 10s
timeout: 5s
retries: 12
start_period: 30s
whatsapp:
image: ghcr.io/sarrazola/openlivery-whatsapp:v0.4.0
platform: linux/amd64
restart: unless-stopped
environment:
BACKEND_URL: http://api:8000
WHATSAPP_BRIDGE_HOST: 0.0.0.0
WHATSAPP_BRIDGE_PORT: 3101
WHATSAPP_BRIDGE_TOKEN: ${WHATSAPP_BRIDGE_TOKEN}
WHATSAPP_STORE_URL: postgres://openlivery:${POSTGRES_PASSWORD}@db:5432/openlivery?sslmode=disable&search_path=whatsmeow
WHATSAPP_LOG_LEVEL: silent
depends_on:
api:
condition: service_healthy
healthcheck:
test: ["CMD", "/app/bridge", "-healthcheck"]
interval: 10s
timeout: 5s
retries: 12
start_period: 30s
volumes:
postgres-data:
backend-storage:
Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

+13
View File
@@ -0,0 +1,13 @@
{
"id": "openlivery",
"name": "OpenLivery",
"version": "v0.4.0",
"description": "MIT-licensed WhatsApp AI agents for agencies, with separate client workspaces and branded portals in one self-hosted installation",
"logo": "logo.png",
"links": {
"github": "https://github.com/sarrazola/openlivery",
"website": "https://www.openlivery.com",
"docs": "https://github.com/sarrazola/openlivery/blob/main/docs/en/self-hosting.md"
},
"tags": ["ai", "chat", "customer-support"]
}
+34
View File
@@ -0,0 +1,34 @@
[variables]
main_domain = "${domain}"
postgres_password = "${hash:48}"
secret_key = "${hash:64}"
encryption_key = "${hash:64}"
bridge_token = "${hash:64}"
[config]
env = [
"FRONTEND_URL=http://${main_domain}",
"COOKIE_SECURE=false",
"POSTGRES_PASSWORD=${postgres_password}",
"SECRET_KEY=${secret_key}",
"ENCRYPTION_KEY=${encryption_key}",
"WHATSAPP_BRIDGE_TOKEN=${bridge_token}",
]
[[config.domains]]
serviceName = "openlivery"
port = 80
host = "${main_domain}"
[[config.mounts]]
filePath = "./Caddyfile"
content = """
:80 {
handle /api/* {
reverse_proxy api:8000
}
handle {
reverse_proxy web:3000
}
}
"""
+27
View File
@@ -0,0 +1,27 @@
services:
openlmnp:
image: manganate06/openlmnp:1.6.6
restart: unless-stopped
environment:
# APP_URL must carry the scheme: password-reset links and e-mails are built
# from it, and would otherwise point at http://localhost.
APP_URL: https://${OPENLMNP_HOST}
# Sign-up closes on its own once the first account is created.
ALLOW_REGISTRATION: auto
volumes:
# SQLite database and uploaded receipts — the only two paths worth keeping.
- openlmnp-database:/var/www/html/database
- openlmnp-storage:/var/www/html/storage
healthcheck:
# Laravel health route. Tested with PHP rather than curl: the image is built on
# Alpine and ships neither curl nor wget.
test: ["CMD", "php", "-r", "exit(@file_get_contents('http://127.0.0.1:8000/up') === false ? 1 : 0);"]
interval: 10s
timeout: 10s
retries: 10
# First boot creates the SQLite database and runs the migrations.
start_period: 90s
volumes:
openlmnp-database:
openlmnp-storage:
+18
View File
@@ -0,0 +1,18 @@
{
"id": "openlmnp",
"name": "OpenLMNP",
"version": "1.6.6",
"description": "Self-hosted accounting for French furnished rentals (LMNP): depreciation schedules, ready-to-file 2031/2033 tax forms, FEC export and Airbnb CSV import.",
"logo": "openlmnp.png",
"links": {
"github": "https://github.com/manganate006/openlmnp",
"website": "https://openlmnp.fr",
"docs": "https://github.com/manganate006/openlmnp/blob/main/docs/INSTALLATION.md"
},
"tags": [
"finance",
"accounting",
"tax",
"rental"
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

+13
View File
@@ -0,0 +1,13 @@
[variables]
main_domain = "${domain}"
[config]
env = [
"OPENLMNP_HOST=${main_domain}",
]
mounts = []
[[config.domains]]
serviceName = "openlmnp"
port = 8000
host = "${main_domain}"
+131
View File
@@ -0,0 +1,131 @@
services:
db:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_DB: openproject
POSTGRES_USER: openproject
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
volumes:
- pgdata:/var/lib/postgresql/data
cache:
image: memcached:1.6-alpine
restart: unless-stopped
web:
image: openproject/openproject:17-slim
restart: unless-stopped
command: "./docker/prod/web"
environment: &openproject-env
OPENPROJECT_HOST__NAME: ${OPENPROJECT_HOST__NAME}
SECRET_KEY_BASE: ${SECRET_KEY_BASE}
OPENPROJECT_RAILS__CACHE__STORE: "memcache"
OPENPROJECT_CACHE__EXPIRES__IN__SECONDS: ${OPENPROJECT_CACHE__EXPIRES__IN__SECONDS}
OPENPROJECT_CACHE__MEMCACHE__SERVER: "cache:11211"
OPENPROJECT_RAILS__RELATIVE__URL__ROOT: ""
DATABASE_URL: "postgres://openproject:${POSTGRES_PASSWORD}@db:5432/openproject?pool=20&encoding=unicode&reconnect=true"
RAILS_MIN_THREADS: ${RAILS_MIN_THREADS:-4}
RAILS_MAX_THREADS: ${RAILS_MAX_THREADS:-16}
OPENPROJECT_COLLABORATIVE__EDITING__HOCUSPOCUS__URL: ""
OPENPROJECT_HTTPS: "true"
# IMAP
IMAP_ENABLED: ${IMAP_ENABLED:-flase}
IMAP_HOST: ${IMAP_HOST}
IMAP_USERNAME: ${IMAP_USERNAME}
IMAP_PASSWORD: ${IMAP_PASSWORD}
IMAP_PORT: ${IMAP_PORT:-993}
IMAP_SSL: ${IMAP_SSL:-true}
IMAP_FOLDER: ${IMAP_FOLDER:-INBOX}
IMAP_SSL_VERIFICATION: "true"
IMAP_CHECK_INTERVAL: ${IMAP_CHECK_INTERVAL:-600}
IMAP_ALLOW_OVERRIDE: ${IMAP_ALLOW_OVERRIDE}
#SMTP
OPENPROJECT_EMAIL__DELIVERY__METHOD: "smtp"
OPENPROJECT_SMTP__ADDRESS: ${SMTP_HOST}
OPENPROJECT_SMTP__PORT: ${SMTP_PORT:-587}
OPENPROJECT_SMTP__DOMAIN: ${SMTP_DOMAIN}
OPENPROJECT_SMTP__AUTHENTICATION: ${SMTP_AUTHENTICATION:-plain}
OPENPROJECT_SMTP__USER__NAME: ${SMTP_USERNAME}
OPENPROJECT_SMTP__PASSWORD: ${SMTP_PASSWORD}
OPENPROJECT_SMTP__ENABLE__STARTTLS__AUTO: ${SMTP_STARTTLS:-true}
OPENPROJECT_SMTP__OPENSSL__VERIFY__MODE: ${SMTP_VERIFY_MODE:-peer}
# S3 Attachments
OPENPROJECT_ATTACHMENTS__STORAGE: ${ATTACHMENTS_STORAGE:-file} # for S3, use 'fog' instead of 'file'
OPENPROJECT_FOG_DIRECTORY: ${S3_BUCKET}
OPENPROJECT_FOG_CREDENTIALS_PROVIDER: "AWS"
OPENPROJECT_FOG_CREDENTIALS_AWS__ACCESS__KEY__ID: ${S3_ACCESS_KEY}
OPENPROJECT_FOG_CREDENTIALS_AWS__SECRET__ACCESS__KEY: ${S3_SECRET_KEY}
OPENPROJECT_FOG_CREDENTIALS_REGION: ${S3_REGION}
OPENPROJECT_FOG_CREDENTIALS_ENDPOINT: ${S3_ENDPOINT}
OPENPROJECT_FOG_CREDENTIALS_PATH__STYLE: "true"
OPENPROJECT_FOG__DOWNLOAD__URL__EXPIRES__IN: "300"
OPENPROJECT_DIRECT__UPLOADS: "true"
volumes:
- opdata:/var/openproject/assets
depends_on:
- db
- cache
- seeder
expose:
- "8080"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health_checks/default"]
interval: 10s
timeout: 5s
retries: 10
start_period: 60s
seeder:
image: openproject/openproject:17-slim
restart: on-failure
command: "./docker/prod/seeder"
environment:
<<: *openproject-env
volumes:
- opdata:/var/openproject/assets
depends_on:
- db
- cache
worker:
image: openproject/openproject:17-slim
restart: unless-stopped
command: "./docker/prod/worker"
environment:
<<: *openproject-env
volumes:
- opdata:/var/openproject/assets
depends_on:
- db
- cache
- seeder
cron:
image: openproject/openproject:17-slim
restart: unless-stopped
command: "./docker/prod/cron"
environment:
<<: *openproject-env
volumes:
- opdata:/var/openproject/assets
depends_on:
- db
- cache
- seeder
volumes:
pgdata:
opdata:
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 500"><rect width="500" height="500" style="fill:#fff"/><path d="M146.66,257.09V225.82c0-9,6-14.95,14.69-14.95s14.87,6,14.87,14.95v31.27c0,9-6.07,15-14.87,15S146.66,266.06,146.66,257.09Zm23.49.34V225.57c0-5.56-3.59-9.4-8.8-9.4s-8.63,3.84-8.63,9.4v31.86c0,5.47,3.51,9.32,8.63,9.32S170.15,262.9,170.15,257.43Z"/><path d="M209.79,250c0,3.16,0,6.07-.08,9.23-.26,7.52-4.62,12.81-11.54,12.81a10,10,0,0,1-8.45-4.1c-.26-.25-.43-.08-.43.17v19a.81.81,0,0,1-.86.85h-4.35a.81.81,0,0,1-.86-.85V229a.81.81,0,0,1,.86-.85h4.35a.81.81,0,0,1,.86.85v2.48c0,.26.17.43.43.17a10.06,10.06,0,0,1,8.45-4.19c6.84,0,11.2,5.47,11.54,13.08C209.79,243.68,209.79,246.84,209.79,250Zm-6.06,8.2c.08-3,0-6.23,0-8.46v-8.45c.08-5-2.91-8.55-7.35-8.55-4.1,0-7.09,3.42-7.09,8.55V258.2c0,5.13,3,8.55,7.09,8.55C200.74,266.75,203.81,263.33,203.73,258.2Z"/><path d="M240.81,252.05H221.33a.37.37,0,0,0-.34.34v6.24c0,4.78,3,8.12,7.26,8.12a7.18,7.18,0,0,0,7.17-6c.17-.52.43-.77.94-.77l4.28.17a.76.76,0,0,1,.76.94c-.94,6.66-5.63,10.93-13.15,10.93-8.12,0-13.33-5.21-13.33-13.07V240.52c0-7.69,5.21-13.08,13.33-13.08,8.28,0,13.41,5.39,13.41,13.08V251.2A.8.8,0,0,1,240.81,252.05ZM221,240.94v5.73a.37.37,0,0,0,.34.34h14a.37.37,0,0,0,.34-.34v-5.73c0-4.87-3-8.2-7.43-8.2C224,232.74,221,236.07,221,240.94Z"/><path d="M273.53,241.11V270.5a.81.81,0,0,1-.86.86h-4.35a.81.81,0,0,1-.86-.86V241.63c0-5.56-2.48-8.8-6.83-8.8-4.53,0-7.35,3.5-7.35,9.22V270.5a.81.81,0,0,1-.85.86h-4.36a.81.81,0,0,1-.86-.86V229a.81.81,0,0,1,.86-.85h4.36a.8.8,0,0,1,.85.85v2.82c0,.26.26.34.43.09a10.53,10.53,0,0,1,8.88-4.36C269.6,227.53,273.53,232.57,273.53,241.11Z"/><path d="M309.75,228c0,9.83-5.46,16.32-13.67,16.32h-8.8a.37.37,0,0,0-.34.34v25.8a.81.81,0,0,1-.85.86h-4.36a.81.81,0,0,1-.85-.86V212.32a.8.8,0,0,1,.85-.85h14.1C304.2,211.47,309.75,218.13,309.75,228Zm-6.06.09c0-6.92-3.51-11.36-8.63-11.36h-7.78a.37.37,0,0,0-.34.34v21.95a.37.37,0,0,0,.34.35h7.78C300.18,239.41,303.69,235.05,303.69,228.13Z"/><path d="M332.65,228.64a1,1,0,0,1,.43,1.11l-.94,4.36c-.09.6-.52.68-1.11.51a6.07,6.07,0,0,0-3.59-.34c-4.1.26-7,4.78-7,10.59V270.5a.81.81,0,0,1-.85.86h-4.36a.81.81,0,0,1-.85-.86V229a.8.8,0,0,1,.85-.85h4.36a.8.8,0,0,1,.85.85v5.13c0,.34.26.34.43.08,1.45-3.84,4-6.49,8.12-6.49A6.79,6.79,0,0,1,332.65,228.64Z"/><path d="M334.7,259V240.52c0-7.69,5.21-13.08,13.41-13.08s13.5,5.39,13.5,13.08V259c0,7.86-5.29,13.07-13.5,13.07S334.7,266.83,334.7,259Zm20.85-.34V240.94c0-4.87-3.08-8.2-7.44-8.2s-7.34,3.33-7.34,8.2v17.69c0,4.78,3,8.12,7.34,8.12S355.55,263.41,355.55,258.63Z"/><path d="M359.82,288.28v-3.59a.81.81,0,0,1,.85-.86c4.87-.17,6.92-3.5,6.92-8.71V229a.81.81,0,0,1,.86-.85h4.35a.81.81,0,0,1,.86.85v46.14c0,8.54-2.31,14-13,14A.8.8,0,0,1,359.82,288.28Zm6.58-72.37a4.23,4.23,0,1,1,8.45,0,4.23,4.23,0,1,1-8.45,0Z"/><path d="M405.61,252.05H386.13a.37.37,0,0,0-.34.34v6.24c0,4.78,3,8.12,7.26,8.12a7.19,7.19,0,0,0,7.18-6c.17-.52.43-.77.94-.77l4.27.17a.77.77,0,0,1,.77.94c-.94,6.66-5.64,10.93-13.16,10.93-8.11,0-13.33-5.21-13.33-13.07V240.52c0-7.69,5.22-13.08,13.33-13.08,8.29,0,13.42,5.39,13.42,13.08V251.2A.81.81,0,0,1,405.61,252.05Zm-19.82-11.11v5.73a.37.37,0,0,0,.34.34h14a.37.37,0,0,0,.34-.34v-5.73c0-4.87-3-8.2-7.43-8.2C388.78,232.74,385.79,236.07,385.79,240.94Z"/><path d="M411.08,259V240.52c0-7.61,5.21-13.08,13.33-13.08s13.5,5.47,13.5,11.88v.85a.81.81,0,0,1-.86.86l-4.36.17a.79.79,0,0,1-.85-.77v-.68a7.14,7.14,0,0,0-7.43-7c-4.28,0-7.27,3.33-7.27,8.2v17.6c0,4.87,3,8.21,7.27,8.21a7.14,7.14,0,0,0,7.43-7v-.6a.8.8,0,0,1,.85-.85l4.36.08a.81.81,0,0,1,.86.86v.94c0,6.66-5.3,11.87-13.5,11.87S411.08,266.83,411.08,259Z"/><path d="M457,232.66h-6.49a.37.37,0,0,0-.34.34v26.14c0,5.47,2,6.92,5.55,6.84h.86a.8.8,0,0,1,.85.85v3.67a.81.81,0,0,1-.85.86h-2.14c-6.07,0-10.25-1.79-10.25-10.42V233a.37.37,0,0,0-.34-.34h-3.34a.81.81,0,0,1-.85-.86V229a.8.8,0,0,1,.85-.85h3.34a.37.37,0,0,0,.34-.34v-9.57a.81.81,0,0,1,.85-.86h4.27a.81.81,0,0,1,.86.86v9.57a.37.37,0,0,0,.34.34H457a.81.81,0,0,1,.86.85v2.82A.81.81,0,0,1,457,232.66Z"/><path d="M84.21,270.12h0a.58.58,0,0,0,0,.1,4.58,4.58,0,0,0,9.15,0v-.11h0v-11H84.21Z" style="fill:#0770b8"/><path d="M105.57,210.93h-6.1a15.18,15.18,0,0,0-15.26,15.16v18.4H57.36A15.18,15.18,0,0,0,42.1,259.66v12.2a15.33,15.33,0,0,0,15.26,15.35h6.1a15.33,15.33,0,0,0,15.26-15.35v-12.2a4.55,4.55,0,0,0,0-.52H69.56v12.72a6.18,6.18,0,0,1-6.1,6.2h-6.1a6.18,6.18,0,0,1-6.1-6.2v-12.2a6,6,0,0,1,6.1-6h48.21a15.33,15.33,0,0,0,15.26-15.34V226.09A15.18,15.18,0,0,0,105.57,210.93Zm6.1,27.37a6.19,6.19,0,0,1-6.1,6.19H93.36v-18.4a6,6,0,0,1,6.11-6h6.1a6,6,0,0,1,6.1,6Z" style="fill:#0770b8"/></svg>

After

Width:  |  Height:  |  Size: 4.5 KiB

+13
View File
@@ -0,0 +1,13 @@
{
"id": "openproject",
"name": "OpenProject",
"version": "17",
"description": "OpenProject 17 slim: web, worker, cron, Postgres 17, memcached. Optional IMAP/SMTP and S3.",
"logo": "logo.svg",
"links": {
"github": "https://github.com/opf/openproject",
"website": "https://www.openproject.org/",
"docs": "https://www.openproject.org/docs/installation-and-operations/installation/docker-compose/"
},
"tags": ["project-management", "productivity"]
}
+39
View File
@@ -0,0 +1,39 @@
[variables]
main_domain = "${domain}"
postgres_password = "${password:32}"
secret_key_base = "${base64:64}"
[config]
env = [
"OPENPROJECT_HOST__NAME=${main_domain}",
"POSTGRES_PASSWORD=${postgres_password}",
"SECRET_KEY_BASE=${secret_key_base}",
"OPENPROJECT_HTTPS=true",
"OPENPROJECT_CACHE__EXPIRES__IN__SECONDS=3600",
"SMTP_HOST=",
"SMTP_PORT=587",
"SMTP_DOMAIN=",
"SMTP_USERNAME=",
"SMTP_PASSWORD=",
"SMTP_AUTHENTICATION=login",
"SMTP_STARTTLS=true",
"SMTP_VERIFY_MODE=peer",
"IMAP_ENABLED=false",
"IMAP_ALLOW_OVERRIDE=type,project,priority,status,responsible,assigned_to,estimated_hours,remaining_hours",
"IMAP_HOST=",
"IMAP_PORT=993",
"IMAP_USERNAME=",
"IMAP_PASSWORD=",
"IMAP_CHECK_INTERVAL=600",
"ATTACHMENTS_STORAGE=file",
"S3_BUCKET=",
"S3_ACCESS_KEY=",
"S3_SECRET_KEY=",
"S3_REGION=",
"S3_ENDPOINT=",
]
[[config.domains]]
serviceName = "web"
port = 8080
host = "${main_domain}"
+55
View File
@@ -0,0 +1,55 @@
version: "3.8"
services:
orca-server:
# Orca publishes no container image, so this builds one from the
# pinned upstream release AppImage, following the official headless
# Linux server guide (docs/reference/headless-linux-server.md).
build:
args:
ORCA_VERSION: v1.4.205
dockerfile_inline: |
FROM ubuntu:24.04
ARG ORCA_VERSION
ARG TARGETARCH
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
bash ca-certificates curl file git jq openssh-client procps \
xvfb zlib1g-dev libgtk-3-0t64 libpango-1.0-0 libcairo2 \
libnss3 libgbm1 libdrm2 libasound2t64 libcups2t64 libxkbcommon0 \
libatk1.0-0t64 libatk-bridge2.0-0t64 libatspi2.0-0t64 \
libx11-xcb1 libxcb-dri3-0 libxcomposite1 libxdamage1 libxfixes3 \
libxrandr2 libxrender1 libxss1 libxtst6 \
&& rm -rf /var/lib/apt/lists/*
RUN if [ "$$TARGETARCH" = arm64 ]; then asset=orca-linux-arm64.AppImage; else asset=orca-linux.AppImage; fi \
&& curl -fL --retry 3 -o /tmp/orca.AppImage \
"https://github.com/stablyai/orca/releases/download/$$ORCA_VERSION/$$asset" \
&& chmod +x /tmp/orca.AppImage \
&& cd /opt && /tmp/orca.AppImage --appimage-extract >/dev/null \
&& mv /opt/squashfs-root /opt/orca \
&& chmod -R a+rX /opt/orca \
&& rm /tmp/orca.AppImage
RUN useradd --create-home --shell /bin/bash orca
USER orca
WORKDIR /home/orca
ENV PATH=/home/orca/.local/bin:/opt/orca/resources/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin \
LIBGL_ALWAYS_SOFTWARE=1
# Chromium cannot create its sandbox namespaces in an unprivileged
# container; the container is the isolation boundary instead.
ENTRYPOINT ["/opt/orca/AppRun", "--no-sandbox"]
restart: unless-stopped
init: true
shm_size: "1gb"
command: serve --port 6768 --pairing-address ${ORCA_PAIRING_ADDRESS} ${ORCA_SERVE_ARGS:-}
expose:
- 6768
volumes:
- orca-home:/home/orca
healthcheck:
test: ["CMD", "bash", "-c", ": > /dev/tcp/127.0.0.1/6768"]
interval: 30s
timeout: 5s
retries: 3
start_period: 60s
volumes:
orca-home: {}
+63
View File
@@ -0,0 +1,63 @@
# Orca Server
Runs `orca serve`, the headless Orca runtime, following the official
[headless Linux server guide](https://github.com/stablyai/orca/blob/main/docs/reference/headless-linux-server.md).
Orca publishes no container image, so the service is built from the pinned
upstream release AppImage (`v1.4.205`, amd64 or arm64) on the first deploy.
The first deployment therefore takes a few extra minutes.
The domain serves the runtime WebSocket and its web client. Every client,
browser included, connects with a pairing link printed in the logs.
## Pair a client
1. Open the `orca-server` service logs in Dokploy.
2. Copy the `Pairing URL: orca://pair?code=...` line printed after
`Orca server ready`. The `Web client URL` line next to it opens the same
runtime in a browser, already paired.
3. In the Orca desktop app, open **Settings > Remote Orca Servers** and paste
the link. From a CLI:
`orca environment add --name my-server --pairing-code 'orca://pair?code=...'`.
The pairing link is a credential: share it only with the client you are
pairing. Paired devices are stored in the persistent volume, so clients
reconnect after a redeploy or an upgrade without pairing again.
## Pair the Orca mobile app
The mobile app needs a mobile-scoped link, which the default link is not.
Set `ORCA_SERVE_ARGS=--mobile-pairing` in the environment and redeploy: the
logs then print a mobile pairing QR code and link instead of the desktop one.
Scan it from the app, then clear `ORCA_SERVE_ARGS` and redeploy. Devices
already paired stay paired either way. On a phone, the `Web client URL` also
works in the browser without this step.
## HTTPS
`ORCA_PAIRING_ADDRESS` is the address advertised to clients. It defaults to
`http://<your-domain>` (plain WebSocket through Traefik; the pairing channel
itself is end-to-end encrypted). Once HTTPS is enabled on the domain, set it to
`https://<your-domain>` in the environment and redeploy so clients dial
`wss://`.
## Coding agents
The image ships Orca, git and the Linux libraries it needs, but no coding
agent. Install the agents you use from an Orca terminal on this server; they
land in `/home/orca/.local/bin`, which is on `PATH` and persisted in the
`orca-home` volume together with their credentials, your repositories and
Orca's state (`/home/orca/.config`).
Example for Claude Code: `curl -fsSL https://claude.ai/install.sh | bash`.
## Upgrade
`orca serve` never updates itself. To upgrade, change the `ORCA_VERSION`
build argument in the compose file and redeploy. State lives in the
volume, not in the image, and newer releases migrate it on load.
## Logs and secrets
D-Bus and OS keyring errors at startup are expected in a container and
harmless. Without a keyring, Orca stores its secrets unencrypted in the
`orca-home` volume: treat that volume as sensitive.

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