From d1ef07fbd24b91601734ca5d669788ad400a017e Mon Sep 17 00:00:00 2001 From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Date: Tue, 7 Jul 2026 09:51:58 -0600 Subject: [PATCH] New release (#975) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(librechat): add LibreChat blueprint with compose, toml, metadata, links and tags * fix: rename templates to template.toml * fix(librechat): rename api service to librechat in docker-compose.yml * Update blueprints/librechat/template.toml * Update blueprints/librechat/template.toml * fix(librechat): add version under [config] and remove stray [config.mounts] header * fix(librechat): remove predefined persistent volume mounts from template.toml * docs(librechat): add authentication reference link to docker-compose.yml * feat: add Rote template - Add Rote deployment template with frontend, backend, and PostgreSQL services - Configure domain routing for frontend (port 80) and backend (port 3000) - Set up automatic password generation and environment variables - Use latest image tag by default - Add logo and metadata to meta.json * fix: process meta.json to fix formatting and sorting * Update GitHub workflows to target 'canary' branch for meta validation * Update pnpm-lock.yaml to upgrade various dependencies, including '@codemirror/autocomplete', '@radix-ui/react-dialog', and React packages to their latest versions. This includes updates to '@types/react' and '@types/react-dom' for improved compatibility and performance. * Enhance GitHub workflows: add production deployment configuration and target 'canary' branch for pull requests. * Refactor GitHub workflow: comment out build preview steps for clarity and future modifications. * Remove unnecessary blank line in deploy-preview.yml for improved readability. * Refactor GitHub workflow: uncomment build preview steps for improved deployment process and clarity. * Update template.toml (#555) * Update template.toml * Update template.toml * Update template.toml * fix: change VITE_API_BASE to http:// for traefik.me compatibility * changed image from sknnr/enshrouded-dedicated-server to mornedhels/enshrouded-server for autoupdate and easier config * Add Openinary Template (#567) * feat: add Openinary template * feat: update Openinary configuration to support ALLOWED_ORIGIN and refactor domain variable * fix: correct DEFAULT_DOMAIN environment variable reference in docker-compose.yml (#562) * add rustfs template (#568) * feat: add pull request template for improved contribution guidelines * fix: update pull request template to clarify issue closing keywords * feat: add validation scripts and configuration for Docker Compose and template files - Introduced a GitHub Actions workflow to validate Docker Compose files and template.toml on pull requests. - Added helper functions for generating random values and processing variables in templates. - Implemented validation scripts for checking the structure, syntax, and best practices of Docker Compose and template files. - Created necessary TypeScript types and configuration files for the build scripts. * Add Passbolt template blueprint to Dokploy templates (#376) * feat(templates): add Passbolt blueprint for Dokploy - Add docker-compose.yml defining services for Passbolt and MariaDB - Create template.toml with configurable domain, email, and database credentials - Add meta.json with metadata, tags, and link to logo * fix(meta): sort meta.json entries * fix: passbolt template had several issues that broke deployment - env variables were using old array format, changed to new table format - mariadb healthcheck was broken (wrong command for mariadb 11) - missing volume mounts for gpg keys, jwt tokens, and database - setup instructions weren't visible to users, moved to docker-compose - email config had circular references causing warnings - tested admin user creation and confirmed working everything works now, fully tested * Update blueprints/passbolt/template.toml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: Add Kokoro TTS FastAPI template (#353) (#403) * feat: Add Kokoro TTS FastAPI template (#353) - Add CPU-optimized docker-compose.yml with source build - Add GPU-optimized docker-compose-gpu.yml for NVIDIA support - Add comprehensive template.toml with OpenAI-compatible API docs - Add kokoro-tts.svg logo and meta.json entry - Support streaming audio, timestamps, and multi-language TTS - Resolves #353 * updated the meta.json for the build errors * removed the docker-compose-gpu.yml file * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * chore: remove package-lock.json file from the app directory * chore: update Tolgee to latest version and fix SMTP config typo (#432) * chore: update Tolgee to latest version and fix SMTP config typo * Update docker-compose.yml * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * fix: improve Docker Compose validation workflow to handle subshell issues - Converted the handling of COMPOSE_FILES from a pipe to an array to ensure error propagation in the parent shell. - Updated the loop to iterate over the array for better reliability in the validation process. * refactor: enhance Docker Compose validation workflow to improve error handling - Replaced the pipe with an array to handle directory names, ensuring that errors within the loop propagate correctly to the parent shell. - Updated the loop structure for better reliability in processing the directories. * Feat: Add parseable (#460) * Add parseable * Update docker-compose.yml * Update docker-compose.yml * Update blueprints/parseable/template.toml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Mauricio Siu * feat: add ChirpStack LoRaWAN Network Server template (#486) * feat: add ChirpStack LoRaWAN Network Server template Add complete ChirpStack v4 template with: - Main ChirpStack server with web UI - UDP and Basics Station gateway bridges - REST API interface - PostgreSQL database with PostGIS extensions - Redis cache - Mosquitto MQTT broker Default configuration for EU868 region with secure random credentials. Supports all LoRaWAN frequency bands globally. * fix(chirpstack): use original configurations from chirpstack-docker repo Update template.toml to use exact configuration files from the chirpstack-docker repository instead of simplified versions: - Use original chirpstack.toml with all 15 enabled regions - Use original gateway bridge configuration with documentation links - Use complete Basics Station EU868 config with frequency plans - Keep original Mosquitto and PostgreSQL initialization scripts Template size increased from 131 to 219 lines (4.7KB) to include comprehensive default configurations that match the official setup. * feat: add all 38 region configuration files * fix(chirpstack): add volume mounts to expose config files to containers * fix(chirpstack): remove read-only flag * fix(chirpstack): correct file paths for configuration mounts in docker-compose and template files * fix: update volume paths to be on correct directory level * fix: configure template for dokploy-network with proper DNS resolution - Add dokploy-network configuration to docker-compose.yml - Replace environment variable placeholders with actual service hostnames - Change PostgreSQL DSN from $POSTGRESQL_HOST to postgres - Change Redis server from $REDIS_HOST to redis - Replace $MQTT_BROKER_HOST with mosquitto in all 39 region configurations These changes ensure Docker DNS resolution works correctly by: - Using dokploy-network (overlay) instead of bridge network - Using service names directly in TOML config files (TOML doesn't expand env vars) - Enabling proper service discovery between containers This resolves DNS resolution failures that caused ChirpStack to fail connecting to PostgreSQL and MQTT services during deployment. * fix: add missing network configurations for all services in docker-compose * feat: add internal services to config.domains for proper network configuration * Update docker-compose.yml * fix: enhance domain validation in template validator - Updated the TemplateValidator to ensure that if the 'host' field is provided, it must be a valid string. - Added comments to clarify that 'host' is optional for internal services. * refactor: remove redundant host validation in template validator - Removed the validation for the 'host' field in the TemplateValidator, as it is optional for internal services and does not require a type check if not provided. * refactor: remove internal service domain configurations from template - Eliminated the domain configurations for internal services (Postgres, Redis, Mosquitto) from the template.toml file, streamlining the configuration for better clarity and maintainability. --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Mauricio Siu * Update section title from 'Suggestions' to 'Requirements' * Feat : Add MCSManager template support (#521) (#522) * feat: Add MCSManager template support (#521) * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: Add MediaCMS template (#524) * Feat : Add Quant-Ux template -#173 (#525) * Feat : Add Quant-Ux template -#173 * Remove extra newline in docker-compose.yml * Update blueprints/quant-ux/docker-compose.yml * Update blueprints/quant-ux/docker-compose.yml * Update blueprints/quant-ux/docker-compose.yml * Update blueprints/quant-ux/docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * fix(rustdesk): use explicit ports, use port 21118 on hbbs instead of hbbr (#526) * fix: use explicit ports, use port 21118 on hbbs instead of hbbr * fix: whitespace character in rustdesk * feat: Add anytype template (#527) * add anytype template * sort * Update name field for Anytype in meta.json * Update meta.json * Update docker-compose.yml * Update blueprints/anytype/docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * refactor: remove dokploy-network configurations from multiple docker-compose files - Removed the external dokploy-network configuration from various services' docker-compose.yml files to streamline network management. - This change simplifies the setup and ensures consistency across blueprints. * chore: upgrade Infisical from v0.90.1 to v0.135.0 (#529) * chore: upgrade Infisical from v0.90.1 to v0.135.0 * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * fix: update pull request template link for clarity - Changed the link in the pull request template from 'general suggestions' to 'general requirements' to better reflect the content and ensure users follow the correct guidelines when creating templates. * chore: add section for screenshots or videos in pull request template - Introduced a new section in the pull request template to encourage contributors to include screenshots or videos, enhancing the clarity and context of their submissions. * Feat : Add MuleSoft ESB Runtime Template (#498) * added the mulesoft esb template * updated the compose and the meta.json * feat(mulesoft-esb): update image and add dynamic env configuration - Updated image to hari1367709/mule-esb:latest - Added dynamic HTTP_PORT for runtime port configuration - Added MULE_VERSION environment variable for Mule ESB version selection * updated the meta.json to use the version as latest * added a comment line to the template file * updated the mule runtime image * fix(mulesoft-esb): update ports configuration to follow guidelines * updated the port to use the env(HTTP_PORT) * Update docker-compose.yml * Update docker-compose.yml * Update blueprints/mulesoft-esb/docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat(blueprint): update trmnl-byos-laravel template (#533) * feat(blueprint): update trmnl-byos-laravel template * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat(blueprint): peerdb template (#579) * feat(blueprint): initial attempt at peerdb template * fix: entrypoint and healthcheck * fix: entrypoint * fix: temporarily remove network * fix: temporal port * chore: remove 36987 for minio * fix: remove peerdb 9900 port exposure * fix: port for console * fix: minio env fix * fix: expose peerdb and minio to dokploy network * fix(peerdb): add defaults * fix: remove extra hosts * fix: remove network entries * fix: use consistent environment variables * feat: add Bluesky PDS template (#542) * feat: Bluesky PDS template * chore: add bluesky pds svg * chore: metadata for bluesky pds * yaml > yml * pnpm lock * fix: correct rotation key config * fix volumes * fix: volumes in the pds compose * define volumes in compose * fix: 32 bit rotation key * create pds.env correctly * some extra fixes * more extra fixes * a blank line * update pnpm lock * Add dokploy-prom-monitoring-extension template with comprehensive tests and documentation (#548) * Add dokploy-prom-monitoring-extension template with comprehensive tests and documentation * Fix METRICS_CONFIG environment variable: use single-line JSON format * Fix template.toml: use correct [config.env] syntax for environment variables * Fix docker-compose.yml: add env_file reference to load environment variables * Delete blueprints/dokploy-prom-monitoring-extension/README.md * Delete test-dokploy-prom-monitoring-extension.sh --------- Co-authored-by: Sanjeevi Subramani Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: improve RustDesk template configuration (#571) * feat: improve RustDesk template configuration - Add comprehensive environment variables for RustDesk server - Add RELAY_HOST, API_SERVER, ID_SERVER, and ENCRYPTION_KEY variables - Follow Dokploy best practices (no container_name, proper port format) - Use restart: unless-stopped policy - Add encryption key generation with password helper * fix: use explicit port mapping for RustDesk services RustDesk requires explicit port bindings (host:container format) to function properly. The service uses specific ports for: - 21115-21116 (TCP/UDP): hbbs service for ID and NAT traversal - 21117-21119 (TCP): hbbr relay service Without explicit port mapping, RustDesk clients cannot establish connections to the server. This is an exception to Dokploy's general port guidelines due to RustDesk's specific networking requirements. --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: add Mumble voice chat server template (#572) * feat: add Mumble voice chat server template - Add Mumble VoIP server blueprint with docker-compose.yml - Configure environment variables for superuser password, welcome text, and max users - Add template.toml with auto-generated secure password - Follow Dokploy best practices (no container_name, proper port format) - Add Mumble metadata to meta.json with proper tags - Support for TCP and UDP on port 64738 * Update template.toml * fix: correct JSON formatting in meta.json for Mumble template entry --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Mauricio Siu * fix: update WireGuard Easy template for proper functionality (#573) * fix: update WireGuard Easy template for proper functionality - Changed to named volume (etc_wireguard) instead of host path mount - Added explicit port mappings (51820:51820/udp, 51821:51821/tcp) required for WireGuard - Updated environment variables to use correct WG_HOST and PASSWORD format - Added all required WireGuard environment variables: - WG_PORT, PORT, WG_MTU, WG_DEFAULT_DNS, WG_ALLOWED_IPS - WG_POST_UP/WG_POST_DOWN for iptables rules - Added NET_RAW capability for proper network operations - Simplified template.toml to use WIREGUARD_HOST and WIREGUARD_PASSWORD - Removed explicit networks config to enable Dokploy's isolated deployment - Template now works with Dokploy's automatic network isolation This configuration has been tested and confirmed working with isolated deployment enabled. * Update template.toml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * add: restart policy to MinIO service (#576) restart: unless-stopped is a Docker restart policy that automatically restarts a container if it stops due to an error or Docker daemon restart * Updating copilot instructions.md and AGENTS.md (#452) * docs: add copilot instructions for project development Added comprehensive documentation file (.github/copilot-instructions.md) that provides detailed guidance on the Dokploy Open Source Templates project structure, development workflow, and conventions. The document covers the project overview, key files and directories, development workflow for adding/updating templates, local development setup, CI/CD processes, and established conventions and patterns. This documentation will help onboard new contributors and ensure consistent development practices across the project. * docs(copilot-instructions): enhance project overview and development guide Updated copilot instructions to reflect expanded app capabilities (200+ apps, TypeScript integration, Fuse.js search) and detailed processes for templates, local dev, and CI/CD for improved clarity and accuracy. * refactor: remove frontend development instructions from AGENTS.md and update contributing guidelines - Removed frontend development commands from AGENTS.md to streamline the document. - Updated CONTRIBUTING.md by removing the recommendation to set `restart: unless-stopped` for services. --------- Co-authored-by: Mauricio Siu * Add trailbase template (#590) * Add trailbase * Add comment on mounting local directory * Update meta.json Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix: openpanel and migrate to v2 (#594) * refactor: update docker-compose.yml to include version and restart policy (#599) * feat(blueprint): mage ai template (#601) * feat(blueprint): template for mage-ai * fix: add healthcheck for mage-ai * docs: update copilot instructions to emphasize version pinning in docker-compose.yml Clarified the importance of pinning image versions in docker-compose.yml and explicitly stated to avoid using the `latest` tag to prevent potential issues with template functionality when upstream images change. * refactor: enhance Docker Compose validation workflow Updated the GitHub Actions workflow for validating Docker Compose files by streamlining the detection of changed blueprints and improving the validation process. Removed redundant steps and consolidated the validation of docker-compose.yml and template.toml files into a more efficient structure. Added clearer output messages for validation results and ensured that best practices are checked for each blueprint. This refactor aims to improve maintainability and clarity in the CI/CD process. * fix: update zitadel default instance features (#544) * Add Reactive Resume template (#603) * Initial plan * Add Reactive Resume template with docker-compose, template.toml, and meta.json entry Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com> * Fix MinIO storage path alignment between template.toml and docker-compose.yml Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com> * Update docker-compose.yml --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com> * [WIP] Fix mounted prometheus.yml file not working (#605) * Initial plan * Fix Prometheus mounted prometheus.yml file by adding volume mount Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com> * Update blueprints/prometheus/template.toml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * docs: update copilot instructions to enforce open source requirement Added a clear requirement stating that all services must be open source and only applications with open-source licenses (e.g., MIT, Apache, GPL, AGPL) are allowed. This update aims to ensure compliance and maintain the integrity of the project. * Fix Cap.so template MinIO deployment failure (#604) * Initial plan * Fix Cap.so MinIO image to use official quay.io image Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com> * Fix MinIO healthcheck to use curl instead of mc Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com> * Update .gitignore --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com> * Fix Discourse template manifest error - update to bitnamilegacy/discourse:3.5.0 (#606) * Initial plan * Fix Discourse template by updating to bitnamilegacy/discourse:3.5.0 Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com> * Remove pull request trigger from deploy-preview workflow * Enhance copilot instructions by adding verification steps for Docker images and clarifying URL variable usage. Emphasize the importance of verifying image existence before committing to prevent deployment failures. * Add Easy!Appointments template (#608) * Initial plan * Add Easyappointments template with docker-compose, template.toml, and meta.json entry Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com> * Update blueprints/easyappointments/template.toml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update template.toml --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Add Dolibarr ERP & CRM template (#610) * Initial plan * Add Dolibarr ERP & CRM template Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com> * Update template.toml * Update blueprints/dolibarr/docker-compose.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * feat: add Syncthing Template (#636) * Adiciona template do Syncthing com arquivos de configuração e ícone * Remove versão do Docker Compose do template do Syncthing * Update Umami to version v2.20.2 (#641) * Feat : Add InstantDB template (#224) (#530) * feat: add InstantDB template * added the server service also * removed the external network * Update docker-compose.yml * Update blueprints/instantdb/docker-compose.yml * Update blueprints/instantdb/docker-compose.yml * Update docker-compose.yml * Update blueprints/instantdb/template.toml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * [New Template] Added Lavalink template for dokploy (#535) * Add initial Lavalink configuration template * Added lavalink.svg logo * Create docker-compose.yml for Lavalink setup Add Docker Compose configuration for Lavalink service. * Modify healthcheck interval in docker-compose.yml Increased healthcheck interval from 10s to 100s. * Add Lavalink metadata to meta.json Added metadata for Lavalink audio sending node. * Update server_port variable to use ${port} * Change server port variable to randomPort * Change port variable to randomPort in template.toml * Change port variable in template.toml * Update server port in template.toml * Fix formatting in template.toml for server config * style: Reformat lavalink entry in meta.json. * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * chore(blueprint): update Appwrite services to v1.8 (#383) * Update Appwrite version docker images and environment variables * Add separate domains for functions and sites, update environment variables, replace insecure default passwords * Update Appwrite version from 1.6.1 to 1.7.4 in `meta.json` * Fix envs and update domains * Add missing volume mounts for sites * Fix config file syntax * Update runtimes network configuration in template.toml * Update Appwrite to 1.8 * Update appwrite image version to 1.8.0 * Add logging configuration to docker-compose * New Templates (#586) * feat(librechat): add LibreChat blueprint with compose, toml, metadata, links and tags * fix: rename templates to template.toml * fix(librechat): rename api service to librechat in docker-compose.yml * Update blueprints/librechat/template.toml * Update blueprints/librechat/template.toml * fix(librechat): add version under [config] and remove stray [config.mounts] header * fix(librechat): remove predefined persistent volume mounts from template.toml * docs(librechat): add authentication reference link to docker-compose.yml * feat: add Rote template - Add Rote deployment template with frontend, backend, and PostgreSQL services - Configure domain routing for frontend (port 80) and backend (port 3000) - Set up automatic password generation and environment variables - Use latest image tag by default - Add logo and metadata to meta.json * fix: process meta.json to fix formatting and sorting * Update GitHub workflows to target 'canary' branch for meta validation * Update pnpm-lock.yaml to upgrade various dependencies, including '@codemirror/autocomplete', '@radix-ui/react-dialog', and React packages to their latest versions. This includes updates to '@types/react' and '@types/react-dom' for improved compatibility and performance. * Enhance GitHub workflows: add production deployment configuration and target 'canary' branch for pull requests. * Refactor GitHub workflow: comment out build preview steps for clarity and future modifications. * Remove unnecessary blank line in deploy-preview.yml for improved readability. * Refactor GitHub workflow: uncomment build preview steps for improved deployment process and clarity. * Update template.toml (#555) * Update template.toml * Update template.toml * Update template.toml * fix: change VITE_API_BASE to http:// for traefik.me compatibility * changed image from sknnr/enshrouded-dedicated-server to mornedhels/enshrouded-server for autoupdate and easier config * Add Openinary Template (#567) * feat: add Openinary template * feat: update Openinary configuration to support ALLOWED_ORIGIN and refactor domain variable * fix: correct DEFAULT_DOMAIN environment variable reference in docker-compose.yml (#562) * add rustfs template (#568) * feat: add pull request template for improved contribution guidelines * fix: update pull request template to clarify issue closing keywords * feat: add validation scripts and configuration for Docker Compose and template files - Introduced a GitHub Actions workflow to validate Docker Compose files and template.toml on pull requests. - Added helper functions for generating random values and processing variables in templates. - Implemented validation scripts for checking the structure, syntax, and best practices of Docker Compose and template files. - Created necessary TypeScript types and configuration files for the build scripts. * Add Passbolt template blueprint to Dokploy templates (#376) * feat(templates): add Passbolt blueprint for Dokploy - Add docker-compose.yml defining services for Passbolt and MariaDB - Create template.toml with configurable domain, email, and database credentials - Add meta.json with metadata, tags, and link to logo * fix(meta): sort meta.json entries * fix: passbolt template had several issues that broke deployment - env variables were using old array format, changed to new table format - mariadb healthcheck was broken (wrong command for mariadb 11) - missing volume mounts for gpg keys, jwt tokens, and database - setup instructions weren't visible to users, moved to docker-compose - email config had circular references causing warnings - tested admin user creation and confirmed working everything works now, fully tested * Update blueprints/passbolt/template.toml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: Add Kokoro TTS FastAPI template (#353) (#403) * feat: Add Kokoro TTS FastAPI template (#353) - Add CPU-optimized docker-compose.yml with source build - Add GPU-optimized docker-compose-gpu.yml for NVIDIA support - Add comprehensive template.toml with OpenAI-compatible API docs - Add kokoro-tts.svg logo and meta.json entry - Support streaming audio, timestamps, and multi-language TTS - Resolves #353 * updated the meta.json for the build errors * removed the docker-compose-gpu.yml file * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * chore: remove package-lock.json file from the app directory * chore: update Tolgee to latest version and fix SMTP config typo (#432) * chore: update Tolgee to latest version and fix SMTP config typo * Update docker-compose.yml * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * fix: improve Docker Compose validation workflow to handle subshell issues - Converted the handling of COMPOSE_FILES from a pipe to an array to ensure error propagation in the parent shell. - Updated the loop to iterate over the array for better reliability in the validation process. * refactor: enhance Docker Compose validation workflow to improve error handling - Replaced the pipe with an array to handle directory names, ensuring that errors within the loop propagate correctly to the parent shell. - Updated the loop structure for better reliability in processing the directories. * Feat: Add parseable (#460) * Add parseable * Update docker-compose.yml * Update docker-compose.yml * Update blueprints/parseable/template.toml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Mauricio Siu * feat: add ChirpStack LoRaWAN Network Server template (#486) * feat: add ChirpStack LoRaWAN Network Server template Add complete ChirpStack v4 template with: - Main ChirpStack server with web UI - UDP and Basics Station gateway bridges - REST API interface - PostgreSQL database with PostGIS extensions - Redis cache - Mosquitto MQTT broker Default configuration for EU868 region with secure random credentials. Supports all LoRaWAN frequency bands globally. * fix(chirpstack): use original configurations from chirpstack-docker repo Update template.toml to use exact configuration files from the chirpstack-docker repository instead of simplified versions: - Use original chirpstack.toml with all 15 enabled regions - Use original gateway bridge configuration with documentation links - Use complete Basics Station EU868 config with frequency plans - Keep original Mosquitto and PostgreSQL initialization scripts Template size increased from 131 to 219 lines (4.7KB) to include comprehensive default configurations that match the official setup. * feat: add all 38 region configuration files * fix(chirpstack): add volume mounts to expose config files to containers * fix(chirpstack): remove read-only flag * fix(chirpstack): correct file paths for configuration mounts in docker-compose and template files * fix: update volume paths to be on correct directory level * fix: configure template for dokploy-network with proper DNS resolution - Add dokploy-network configuration to docker-compose.yml - Replace environment variable placeholders with actual service hostnames - Change PostgreSQL DSN from $POSTGRESQL_HOST to postgres - Change Redis server from $REDIS_HOST to redis - Replace $MQTT_BROKER_HOST with mosquitto in all 39 region configurations These changes ensure Docker DNS resolution works correctly by: - Using dokploy-network (overlay) instead of bridge network - Using service names directly in TOML config files (TOML doesn't expand env vars) - Enabling proper service discovery between containers This resolves DNS resolution failures that caused ChirpStack to fail connecting to PostgreSQL and MQTT services during deployment. * fix: add missing network configurations for all services in docker-compose * feat: add internal services to config.domains for proper network configuration * Update docker-compose.yml * fix: enhance domain validation in template validator - Updated the TemplateValidator to ensure that if the 'host' field is provided, it must be a valid string. - Added comments to clarify that 'host' is optional for internal services. * refactor: remove redundant host validation in template validator - Removed the validation for the 'host' field in the TemplateValidator, as it is optional for internal services and does not require a type check if not provided. * refactor: remove internal service domain configurations from template - Eliminated the domain configurations for internal services (Postgres, Redis, Mosquitto) from the template.toml file, streamlining the configuration for better clarity and maintainability. --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Mauricio Siu * Update section title from 'Suggestions' to 'Requirements' * Feat : Add MCSManager template support (#521) (#522) * feat: Add MCSManager template support (#521) * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: Add MediaCMS template (#524) * Feat : Add Quant-Ux template -#173 (#525) * Feat : Add Quant-Ux template -#173 * Remove extra newline in docker-compose.yml * Update blueprints/quant-ux/docker-compose.yml * Update blueprints/quant-ux/docker-compose.yml * Update blueprints/quant-ux/docker-compose.yml * Update blueprints/quant-ux/docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * fix(rustdesk): use explicit ports, use port 21118 on hbbs instead of hbbr (#526) * fix: use explicit ports, use port 21118 on hbbs instead of hbbr * fix: whitespace character in rustdesk * feat: Add anytype template (#527) * add anytype template * sort * Update name field for Anytype in meta.json * Update meta.json * Update docker-compose.yml * Update blueprints/anytype/docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * refactor: remove dokploy-network configurations from multiple docker-compose files - Removed the external dokploy-network configuration from various services' docker-compose.yml files to streamline network management. - This change simplifies the setup and ensures consistency across blueprints. * chore: upgrade Infisical from v0.90.1 to v0.135.0 (#529) * chore: upgrade Infisical from v0.90.1 to v0.135.0 * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * fix: update pull request template link for clarity - Changed the link in the pull request template from 'general suggestions' to 'general requirements' to better reflect the content and ensure users follow the correct guidelines when creating templates. * chore: add section for screenshots or videos in pull request template - Introduced a new section in the pull request template to encourage contributors to include screenshots or videos, enhancing the clarity and context of their submissions. * Feat : Add MuleSoft ESB Runtime Template (#498) * added the mulesoft esb template * updated the compose and the meta.json * feat(mulesoft-esb): update image and add dynamic env configuration - Updated image to hari1367709/mule-esb:latest - Added dynamic HTTP_PORT for runtime port configuration - Added MULE_VERSION environment variable for Mule ESB version selection * updated the meta.json to use the version as latest * added a comment line to the template file * updated the mule runtime image * fix(mulesoft-esb): update ports configuration to follow guidelines * updated the port to use the env(HTTP_PORT) * Update docker-compose.yml * Update docker-compose.yml * Update blueprints/mulesoft-esb/docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat(blueprint): update trmnl-byos-laravel template (#533) * feat(blueprint): update trmnl-byos-laravel template * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat(blueprint): peerdb template (#579) * feat(blueprint): initial attempt at peerdb template * fix: entrypoint and healthcheck * fix: entrypoint * fix: temporarily remove network * fix: temporal port * chore: remove 36987 for minio * fix: remove peerdb 9900 port exposure * fix: port for console * fix: minio env fix * fix: expose peerdb and minio to dokploy network * fix(peerdb): add defaults * fix: remove extra hosts * fix: remove network entries * fix: use consistent environment variables * feat: add Bluesky PDS template (#542) * feat: Bluesky PDS template * chore: add bluesky pds svg * chore: metadata for bluesky pds * yaml > yml * pnpm lock * fix: correct rotation key config * fix volumes * fix: volumes in the pds compose * define volumes in compose * fix: 32 bit rotation key * create pds.env correctly * some extra fixes * more extra fixes * a blank line * update pnpm lock * Add dokploy-prom-monitoring-extension template with comprehensive tests and documentation (#548) * Add dokploy-prom-monitoring-extension template with comprehensive tests and documentation * Fix METRICS_CONFIG environment variable: use single-line JSON format * Fix template.toml: use correct [config.env] syntax for environment variables * Fix docker-compose.yml: add env_file reference to load environment variables * Delete blueprints/dokploy-prom-monitoring-extension/README.md * Delete test-dokploy-prom-monitoring-extension.sh --------- Co-authored-by: Sanjeevi Subramani Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: improve RustDesk template configuration (#571) * feat: improve RustDesk template configuration - Add comprehensive environment variables for RustDesk server - Add RELAY_HOST, API_SERVER, ID_SERVER, and ENCRYPTION_KEY variables - Follow Dokploy best practices (no container_name, proper port format) - Use restart: unless-stopped policy - Add encryption key generation with password helper * fix: use explicit port mapping for RustDesk services RustDesk requires explicit port bindings (host:container format) to function properly. The service uses specific ports for: - 21115-21116 (TCP/UDP): hbbs service for ID and NAT traversal - 21117-21119 (TCP): hbbr relay service Without explicit port mapping, RustDesk clients cannot establish connections to the server. This is an exception to Dokploy's general port guidelines due to RustDesk's specific networking requirements. --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: add Mumble voice chat server template (#572) * feat: add Mumble voice chat server template - Add Mumble VoIP server blueprint with docker-compose.yml - Configure environment variables for superuser password, welcome text, and max users - Add template.toml with auto-generated secure password - Follow Dokploy best practices (no container_name, proper port format) - Add Mumble metadata to meta.json with proper tags - Support for TCP and UDP on port 64738 * Update template.toml * fix: correct JSON formatting in meta.json for Mumble template entry --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Mauricio Siu * fix: update WireGuard Easy template for proper functionality (#573) * fix: update WireGuard Easy template for proper functionality - Changed to named volume (etc_wireguard) instead of host path mount - Added explicit port mappings (51820:51820/udp, 51821:51821/tcp) required for WireGuard - Updated environment variables to use correct WG_HOST and PASSWORD format - Added all required WireGuard environment variables: - WG_PORT, PORT, WG_MTU, WG_DEFAULT_DNS, WG_ALLOWED_IPS - WG_POST_UP/WG_POST_DOWN for iptables rules - Added NET_RAW capability for proper network operations - Simplified template.toml to use WIREGUARD_HOST and WIREGUARD_PASSWORD - Removed explicit networks config to enable Dokploy's isolated deployment - Template now works with Dokploy's automatic network isolation This configuration has been tested and confirmed working with isolated deployment enabled. * Update template.toml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * add: restart policy to MinIO service (#576) restart: unless-stopped is a Docker restart policy that automatically restarts a container if it stops due to an error or Docker daemon restart --------- Co-authored-by: Sunil Shrestha Co-authored-by: Rabithua Co-authored-by: Mauricio Siu Co-authored-by: Scan <103391616+scanash00@users.noreply.github.com> Co-authored-by: Crackvignoule Co-authored-by: florianheysen <39408021+florianheysen@users.noreply.github.com> Co-authored-by: Thiago MadPin Co-authored-by: BlinkStrike <18644035+BlinkStrike@users.noreply.github.com> Co-authored-by: M Jupri Amin <127651222+Juupeee@users.noreply.github.com> Co-authored-by: Harikrishnan Dhanasekaran Co-authored-by: Kamil Dzieniszewski Co-authored-by: Nick Anderson Co-authored-by: lefolalan Co-authored-by: Chris <31969757+ChrisvanChip@users.noreply.github.com> Co-authored-by: kipavy <88386090+kipavy@users.noreply.github.com> Co-authored-by: Benjamin Nussbaum Co-authored-by: Khiet Tam Nguyen <86177399+nktnet1@users.noreply.github.com> Co-authored-by: Vidhya LKG for IT <24915474+VidhyaSanjeevi@users.noreply.github.com> Co-authored-by: Sanjeevi Subramani Co-authored-by: Muzaffer Kadir YILMAZ <34358176+muzafferkadir@users.noreply.github.com> Co-authored-by: Jemg * Remove `container_name` from all containers * Remove expliced networks * Update blueprints/appwrite/docker-compose.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update password variables to use 32-character length * Update Appwrite description and tags in meta.json * Fix JSON formatting in meta.json by adding missing closing bracket * Fix formatting in meta.json by removing trailing spaces in tags array * Add missing SMS and Backblaze storage configuration options in template.toml * Update docker-compose.yml --------- Co-authored-by: Pascal Oberbeck Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Sunil Shrestha Co-authored-by: Rabithua Co-authored-by: Mauricio Siu Co-authored-by: Scan <103391616+scanash00@users.noreply.github.com> Co-authored-by: Crackvignoule Co-authored-by: florianheysen <39408021+florianheysen@users.noreply.github.com> Co-authored-by: Thiago MadPin Co-authored-by: BlinkStrike <18644035+BlinkStrike@users.noreply.github.com> Co-authored-by: M Jupri Amin <127651222+Juupeee@users.noreply.github.com> Co-authored-by: Harikrishnan Dhanasekaran Co-authored-by: Kamil Dzieniszewski Co-authored-by: Nick Anderson Co-authored-by: lefolalan Co-authored-by: Chris <31969757+ChrisvanChip@users.noreply.github.com> Co-authored-by: kipavy <88386090+kipavy@users.noreply.github.com> Co-authored-by: Benjamin Nussbaum Co-authored-by: Khiet Tam Nguyen <86177399+nktnet1@users.noreply.github.com> Co-authored-by: Vidhya LKG for IT <24915474+VidhyaSanjeevi@users.noreply.github.com> Co-authored-by: Sanjeevi Subramani Co-authored-by: Muzaffer Kadir YILMAZ <34358176+muzafferkadir@users.noreply.github.com> Co-authored-by: Jemg Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Mauricio Siu * feat: emqx template (MQTT Broker) (#556) * feat: template for emqx * chore: process meta * fix: use websocket on port 443 instead of 8084 * docs: improve comments for emqx template * fix: use emqx service name * fix: use dummy domain instead of traefik * fix: explicitly list dokplok-network * fix(emqx): restart unless stopped * fix(emqx): add healthcheck * Dokploy Deployment for Mautic 5 (#564) * first draft * second * try 3 * 4 * Update docker-compose.yml * Update template.toml * Enhance healthchecks and service dependencies in Docker Compose Updated healthcheck configurations for Mautic and MySQL services to improve service reliability. Added conditions to ensure services wait for dependencies to be healthy before starting. * Update Mautic docker-compose with health checks and roles * fix: searxng template (#651) * fix: use major version for openpanel (#680) * Feat/minepanel template (#657) * feat: add Minepanel template * fix: pin images to v1.7.1 and use http for URLs * fix: remove explicit ports, Dokploy handles proxying * chore: process and sort meta.json * fix: consolidate domain variables to main_domain * fix: add version field to docker-compose.yml * Add Komari Monitor template with Docker Compose, icon, and metadata (#XXX) (#623) * Introduce Komari Monitor, a self-hosted server monitoring tool, with its corresponding Docker Compose configuration, icon, and metadata entry. * Add template.toml for configuration and environment variables. * Include necessary links for GitHub and documentation. * Add Misaka Danmu Server template with Docker Compose, icon, and metadata (#624) * Introduce Misaka Danmu Server, a self-hosted danmaku server for live streaming, with its corresponding Docker Compose configuration, icon, and metadata entry. * Add template.toml for configuration and environment variables. * Include necessary links for GitHub and documentation. * fix: pyrodactyl no longer uses main tag for it's latest release (#626) * fix: pyrodactyl no longer uses main tag for it's latest release * Remove custom network settings from docker-compose Removed custom network configuration from docker-compose. * Update MariaDB and Pyrodactyl images in Docker Compose * Add Jenkins blueprint template configuration (#634) - Created a new TOML configuration file for Jenkins blueprint. - Defined main domain variable and service configuration for Jenkins. - Set serviceName to "jenkins" with port 8080 and host as the main domain. * Update Autobase to version 2.5 (#647) * Update Autobase to version 2.5 Bump the autobase-console Docker image from version 2.2.0 to 2.5.2 in docker-compose.yml to use the latest features and fixes. * Update docker-compose.yml * Update docker-compose.yml * Update meta.json * Update Autobase description in meta.json Revised the Autobase package description to clarify it as a self-hosted DBaaS alternative to cloud-managed databases. * Add Cloudreve template (#649) Self-hosted file management and sharing system with multi-cloud storage support. Includes PostgreSQL and Redis for database and caching. * Update to Umami 3.0.3 (#668) * Update Umami version from v2.20.2 to v3.0.3 * Update Umami Docker image to version 3.0.3 * fix: tailscale exitnode authkey env (#669) * Add qbitwebui (#675) * Add qBittorrent Web UI template * Fix healthcheck bug * Create INSTRUCTIONS.md * Rename INSTRUCTIONS.md to instructions.md * feat: add Moltbot template (#683) * feat: add Moltbot template Add template for Moltbot - a WhatsApp gateway CLI with Pi RPC agent. - Uses official ghcr.io/moltbot/moltbot:latest image - Exposes ports 18789 (gateway) and 18790 (bridge) - Includes persistent volumes for config and workspace - Auto-generates gateway token - Optional Claude AI integration support Co-Authored-By: Claude * Update docker-compose.yml * Enhance Moltbot configuration in docker-compose and template files - Added CLAWDBOT_GATEWAY_URL and OPENROUTER_API_KEY to docker-compose.yml - Updated service binding to 'auto' and added init: true for improved service management - Defined CLAWDBOT_GATEWAY_PORT and CLAWDBOT_BRIDGE_PORT in template.toml - Included CLAWDBOT_PLUGINS for plugin configuration in template.toml * Add Moltbot entry to meta.json - Introduced a new entry for Moltbot, a WhatsApp gateway CLI with Pi RPC agent. - Included details such as version, description, logo, links, and relevant tags for better discoverability and integration. --------- Co-authored-by: Claude Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Mauricio Siu * feat: add Openclaw template (#694) * feat: rename Moltbot to Openclaw and update related configurations * fix: update Openclaw image version to 2026.1.29 in docker-compose.yml * fix: correct environment variable name for Openclaw gateway * fix: correct volume path for Openclaw workspace in docker-compose.yml * feat: rename Moltbot to Openclaw and update metadata * fix: moving 'openclaw' entry below so the file looks sorted * fix: add missing newline at end of meta.json * fix: update docker-compose.yml to use 'expose' instead of 'ports' and change bind option to 'lan' * feat: update Openclaw service configuration in docker-compose.yml and template.toml - Changed service name from 'openclaw-gateway' to 'openclaw' and updated image version. - Enhanced environment variables for better configuration management. - Added a new 'browser' service with health checks and updated volume paths. * refactor: update environment variable configuration in docker-compose.yml for Openclaw service --------- Co-authored-by: Mauricio Siu * fix: cloudflared documentation links & env variables (#699) * feat(blueprint): Cloudflare DDNS (#689) * feat: added Cloudflare DDNS template * fix: make CLOUDFLARE_API_TOKEN and DOMAINS mandatory env * Fix realtime service name resolution (#563) Expose the CONTAINER_PREFIX environment variable to kong service, then utilize it to format the URL of realtime service. * fix(habitica): add user to mongodb replicaset to enable Dokploy DB backups (#574) * fix: use environment variables from configuration in habitica-server * feat: add users to mongodb replicaSet This commit adds admin and habitica users + enables replicaSet auth by introducing a keyfile. Dokploy DB backups require specifying an user and password, so this enables that feature for Habitica app. * chore: less retries * chore: do not start server until mongo is healthy * fix: ensure habitica user exists for habitica db * fix: remove BASE_URL to prevent infinite redirects * fix: add missing ADMIN_EMAIL --------- Co-authored-by: Jorge Gómez Zarzosa * Refactor wg-easy service configuration to work with latest wg-easy v15 (#598) * New Templates (#586) * feat(librechat): add LibreChat blueprint with compose, toml, metadata, links and tags * fix: rename templates to template.toml * fix(librechat): rename api service to librechat in docker-compose.yml * Update blueprints/librechat/template.toml * Update blueprints/librechat/template.toml * fix(librechat): add version under [config] and remove stray [config.mounts] header * fix(librechat): remove predefined persistent volume mounts from template.toml * docs(librechat): add authentication reference link to docker-compose.yml * feat: add Rote template - Add Rote deployment template with frontend, backend, and PostgreSQL services - Configure domain routing for frontend (port 80) and backend (port 3000) - Set up automatic password generation and environment variables - Use latest image tag by default - Add logo and metadata to meta.json * fix: process meta.json to fix formatting and sorting * Update GitHub workflows to target 'canary' branch for meta validation * Update pnpm-lock.yaml to upgrade various dependencies, including '@codemirror/autocomplete', '@radix-ui/react-dialog', and React packages to their latest versions. This includes updates to '@types/react' and '@types/react-dom' for improved compatibility and performance. * Enhance GitHub workflows: add production deployment configuration and target 'canary' branch for pull requests. * Refactor GitHub workflow: comment out build preview steps for clarity and future modifications. * Remove unnecessary blank line in deploy-preview.yml for improved readability. * Refactor GitHub workflow: uncomment build preview steps for improved deployment process and clarity. * Update template.toml (#555) * Update template.toml * Update template.toml * Update template.toml * fix: change VITE_API_BASE to http:// for traefik.me compatibility * changed image from sknnr/enshrouded-dedicated-server to mornedhels/enshrouded-server for autoupdate and easier config * Add Openinary Template (#567) * feat: add Openinary template * feat: update Openinary configuration to support ALLOWED_ORIGIN and refactor domain variable * fix: correct DEFAULT_DOMAIN environment variable reference in docker-compose.yml (#562) * add rustfs template (#568) * feat: add pull request template for improved contribution guidelines * fix: update pull request template to clarify issue closing keywords * feat: add validation scripts and configuration for Docker Compose and template files - Introduced a GitHub Actions workflow to validate Docker Compose files and template.toml on pull requests. - Added helper functions for generating random values and processing variables in templates. - Implemented validation scripts for checking the structure, syntax, and best practices of Docker Compose and template files. - Created necessary TypeScript types and configuration files for the build scripts. * Add Passbolt template blueprint to Dokploy templates (#376) * feat(templates): add Passbolt blueprint for Dokploy - Add docker-compose.yml defining services for Passbolt and MariaDB - Create template.toml with configurable domain, email, and database credentials - Add meta.json with metadata, tags, and link to logo * fix(meta): sort meta.json entries * fix: passbolt template had several issues that broke deployment - env variables were using old array format, changed to new table format - mariadb healthcheck was broken (wrong command for mariadb 11) - missing volume mounts for gpg keys, jwt tokens, and database - setup instructions weren't visible to users, moved to docker-compose - email config had circular references causing warnings - tested admin user creation and confirmed working everything works now, fully tested * Update blueprints/passbolt/template.toml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: Add Kokoro TTS FastAPI template (#353) (#403) * feat: Add Kokoro TTS FastAPI template (#353) - Add CPU-optimized docker-compose.yml with source build - Add GPU-optimized docker-compose-gpu.yml for NVIDIA support - Add comprehensive template.toml with OpenAI-compatible API docs - Add kokoro-tts.svg logo and meta.json entry - Support streaming audio, timestamps, and multi-language TTS - Resolves #353 * updated the meta.json for the build errors * removed the docker-compose-gpu.yml file * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * chore: remove package-lock.json file from the app directory * chore: update Tolgee to latest version and fix SMTP config typo (#432) * chore: update Tolgee to latest version and fix SMTP config typo * Update docker-compose.yml * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * fix: improve Docker Compose validation workflow to handle subshell issues - Converted the handling of COMPOSE_FILES from a pipe to an array to ensure error propagation in the parent shell. - Updated the loop to iterate over the array for better reliability in the validation process. * refactor: enhance Docker Compose validation workflow to improve error handling - Replaced the pipe with an array to handle directory names, ensuring that errors within the loop propagate correctly to the parent shell. - Updated the loop structure for better reliability in processing the directories. * Feat: Add parseable (#460) * Add parseable * Update docker-compose.yml * Update docker-compose.yml * Update blueprints/parseable/template.toml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Mauricio Siu * feat: add ChirpStack LoRaWAN Network Server template (#486) * feat: add ChirpStack LoRaWAN Network Server template Add complete ChirpStack v4 template with: - Main ChirpStack server with web UI - UDP and Basics Station gateway bridges - REST API interface - PostgreSQL database with PostGIS extensions - Redis cache - Mosquitto MQTT broker Default configuration for EU868 region with secure random credentials. Supports all LoRaWAN frequency bands globally. * fix(chirpstack): use original configurations from chirpstack-docker repo Update template.toml to use exact configuration files from the chirpstack-docker repository instead of simplified versions: - Use original chirpstack.toml with all 15 enabled regions - Use original gateway bridge configuration with documentation links - Use complete Basics Station EU868 config with frequency plans - Keep original Mosquitto and PostgreSQL initialization scripts Template size increased from 131 to 219 lines (4.7KB) to include comprehensive default configurations that match the official setup. * feat: add all 38 region configuration files * fix(chirpstack): add volume mounts to expose config files to containers * fix(chirpstack): remove read-only flag * fix(chirpstack): correct file paths for configuration mounts in docker-compose and template files * fix: update volume paths to be on correct directory level * fix: configure template for dokploy-network with proper DNS resolution - Add dokploy-network configuration to docker-compose.yml - Replace environment variable placeholders with actual service hostnames - Change PostgreSQL DSN from $POSTGRESQL_HOST to postgres - Change Redis server from $REDIS_HOST to redis - Replace $MQTT_BROKER_HOST with mosquitto in all 39 region configurations These changes ensure Docker DNS resolution works correctly by: - Using dokploy-network (overlay) instead of bridge network - Using service names directly in TOML config files (TOML doesn't expand env vars) - Enabling proper service discovery between containers This resolves DNS resolution failures that caused ChirpStack to fail connecting to PostgreSQL and MQTT services during deployment. * fix: add missing network configurations for all services in docker-compose * feat: add internal services to config.domains for proper network configuration * Update docker-compose.yml * fix: enhance domain validation in template validator - Updated the TemplateValidator to ensure that if the 'host' field is provided, it must be a valid string. - Added comments to clarify that 'host' is optional for internal services. * refactor: remove redundant host validation in template validator - Removed the validation for the 'host' field in the TemplateValidator, as it is optional for internal services and does not require a type check if not provided. * refactor: remove internal service domain configurations from template - Eliminated the domain configurations for internal services (Postgres, Redis, Mosquitto) from the template.toml file, streamlining the configuration for better clarity and maintainability. --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Mauricio Siu * Update section title from 'Suggestions' to 'Requirements' * Feat : Add MCSManager template support (#521) (#522) * feat: Add MCSManager template support (#521) * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: Add MediaCMS template (#524) * Feat : Add Quant-Ux template -#173 (#525) * Feat : Add Quant-Ux template -#173 * Remove extra newline in docker-compose.yml * Update blueprints/quant-ux/docker-compose.yml * Update blueprints/quant-ux/docker-compose.yml * Update blueprints/quant-ux/docker-compose.yml * Update blueprints/quant-ux/docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * fix(rustdesk): use explicit ports, use port 21118 on hbbs instead of hbbr (#526) * fix: use explicit ports, use port 21118 on hbbs instead of hbbr * fix: whitespace character in rustdesk * feat: Add anytype template (#527) * add anytype template * sort * Update name field for Anytype in meta.json * Update meta.json * Update docker-compose.yml * Update blueprints/anytype/docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * refactor: remove dokploy-network configurations from multiple docker-compose files - Removed the external dokploy-network configuration from various services' docker-compose.yml files to streamline network management. - This change simplifies the setup and ensures consistency across blueprints. * chore: upgrade Infisical from v0.90.1 to v0.135.0 (#529) * chore: upgrade Infisical from v0.90.1 to v0.135.0 * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * fix: update pull request template link for clarity - Changed the link in the pull request template from 'general suggestions' to 'general requirements' to better reflect the content and ensure users follow the correct guidelines when creating templates. * chore: add section for screenshots or videos in pull request template - Introduced a new section in the pull request template to encourage contributors to include screenshots or videos, enhancing the clarity and context of their submissions. * Feat : Add MuleSoft ESB Runtime Template (#498) * added the mulesoft esb template * updated the compose and the meta.json * feat(mulesoft-esb): update image and add dynamic env configuration - Updated image to hari1367709/mule-esb:latest - Added dynamic HTTP_PORT for runtime port configuration - Added MULE_VERSION environment variable for Mule ESB version selection * updated the meta.json to use the version as latest * added a comment line to the template file * updated the mule runtime image * fix(mulesoft-esb): update ports configuration to follow guidelines * updated the port to use the env(HTTP_PORT) * Update docker-compose.yml * Update docker-compose.yml * Update blueprints/mulesoft-esb/docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat(blueprint): update trmnl-byos-laravel template (#533) * feat(blueprint): update trmnl-byos-laravel template * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat(blueprint): peerdb template (#579) * feat(blueprint): initial attempt at peerdb template * fix: entrypoint and healthcheck * fix: entrypoint * fix: temporarily remove network * fix: temporal port * chore: remove 36987 for minio * fix: remove peerdb 9900 port exposure * fix: port for console * fix: minio env fix * fix: expose peerdb and minio to dokploy network * fix(peerdb): add defaults * fix: remove extra hosts * fix: remove network entries * fix: use consistent environment variables * feat: add Bluesky PDS template (#542) * feat: Bluesky PDS template * chore: add bluesky pds svg * chore: metadata for bluesky pds * yaml > yml * pnpm lock * fix: correct rotation key config * fix volumes * fix: volumes in the pds compose * define volumes in compose * fix: 32 bit rotation key * create pds.env correctly * some extra fixes * more extra fixes * a blank line * update pnpm lock * Add dokploy-prom-monitoring-extension template with comprehensive tests and documentation (#548) * Add dokploy-prom-monitoring-extension template with comprehensive tests and documentation * Fix METRICS_CONFIG environment variable: use single-line JSON format * Fix template.toml: use correct [config.env] syntax for environment variables * Fix docker-compose.yml: add env_file reference to load environment variables * Delete blueprints/dokploy-prom-monitoring-extension/README.md * Delete test-dokploy-prom-monitoring-extension.sh --------- Co-authored-by: Sanjeevi Subramani Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: improve RustDesk template configuration (#571) * feat: improve RustDesk template configuration - Add comprehensive environment variables for RustDesk server - Add RELAY_HOST, API_SERVER, ID_SERVER, and ENCRYPTION_KEY variables - Follow Dokploy best practices (no container_name, proper port format) - Use restart: unless-stopped policy - Add encryption key generation with password helper * fix: use explicit port mapping for RustDesk services RustDesk requires explicit port bindings (host:container format) to function properly. The service uses specific ports for: - 21115-21116 (TCP/UDP): hbbs service for ID and NAT traversal - 21117-21119 (TCP): hbbr relay service Without explicit port mapping, RustDesk clients cannot establish connections to the server. This is an exception to Dokploy's general port guidelines due to RustDesk's specific networking requirements. --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: add Mumble voice chat server template (#572) * feat: add Mumble voice chat server template - Add Mumble VoIP server blueprint with docker-compose.yml - Configure environment variables for superuser password, welcome text, and max users - Add template.toml with auto-generated secure password - Follow Dokploy best practices (no container_name, proper port format) - Add Mumble metadata to meta.json with proper tags - Support for TCP and UDP on port 64738 * Update template.toml * fix: correct JSON formatting in meta.json for Mumble template entry --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Mauricio Siu * fix: update WireGuard Easy template for proper functionality (#573) * fix: update WireGuard Easy template for proper functionality - Changed to named volume (etc_wireguard) instead of host path mount - Added explicit port mappings (51820:51820/udp, 51821:51821/tcp) required for WireGuard - Updated environment variables to use correct WG_HOST and PASSWORD format - Added all required WireGuard environment variables: - WG_PORT, PORT, WG_MTU, WG_DEFAULT_DNS, WG_ALLOWED_IPS - WG_POST_UP/WG_POST_DOWN for iptables rules - Added NET_RAW capability for proper network operations - Simplified template.toml to use WIREGUARD_HOST and WIREGUARD_PASSWORD - Removed explicit networks config to enable Dokploy's isolated deployment - Template now works with Dokploy's automatic network isolation This configuration has been tested and confirmed working with isolated deployment enabled. * Update template.toml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * add: restart policy to MinIO service (#576) restart: unless-stopped is a Docker restart policy that automatically restarts a container if it stops due to an error or Docker daemon restart --------- Co-authored-by: Sunil Shrestha Co-authored-by: Rabithua Co-authored-by: Mauricio Siu Co-authored-by: Scan <103391616+scanash00@users.noreply.github.com> Co-authored-by: Crackvignoule Co-authored-by: florianheysen <39408021+florianheysen@users.noreply.github.com> Co-authored-by: Thiago MadPin Co-authored-by: BlinkStrike <18644035+BlinkStrike@users.noreply.github.com> Co-authored-by: M Jupri Amin <127651222+Juupeee@users.noreply.github.com> Co-authored-by: Harikrishnan Dhanasekaran Co-authored-by: Kamil Dzieniszewski Co-authored-by: Nick Anderson Co-authored-by: lefolalan Co-authored-by: Chris <31969757+ChrisvanChip@users.noreply.github.com> Co-authored-by: kipavy <88386090+kipavy@users.noreply.github.com> Co-authored-by: Benjamin Nussbaum Co-authored-by: Khiet Tam Nguyen <86177399+nktnet1@users.noreply.github.com> Co-authored-by: Vidhya LKG for IT <24915474+VidhyaSanjeevi@users.noreply.github.com> Co-authored-by: Sanjeevi Subramani Co-authored-by: Muzaffer Kadir YILMAZ <34358176+muzafferkadir@users.noreply.github.com> Co-authored-by: Jemg * Refactor wg-easy service configuration in docker-compose Updated environment variables for wg-easy v15 * Refactor wg-easy service configuration in docker-compose Updated environment variables for wg-easy v15 --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Sunil Shrestha Co-authored-by: Rabithua Co-authored-by: Mauricio Siu Co-authored-by: Scan <103391616+scanash00@users.noreply.github.com> Co-authored-by: Crackvignoule Co-authored-by: florianheysen <39408021+florianheysen@users.noreply.github.com> Co-authored-by: Thiago MadPin Co-authored-by: BlinkStrike <18644035+BlinkStrike@users.noreply.github.com> Co-authored-by: M Jupri Amin <127651222+Juupeee@users.noreply.github.com> Co-authored-by: Harikrishnan Dhanasekaran Co-authored-by: Kamil Dzieniszewski Co-authored-by: Nick Anderson Co-authored-by: lefolalan Co-authored-by: Chris <31969757+ChrisvanChip@users.noreply.github.com> Co-authored-by: kipavy <88386090+kipavy@users.noreply.github.com> Co-authored-by: Benjamin Nussbaum Co-authored-by: Khiet Tam Nguyen <86177399+nktnet1@users.noreply.github.com> Co-authored-by: Vidhya LKG for IT <24915474+VidhyaSanjeevi@users.noreply.github.com> Co-authored-by: Sanjeevi Subramani Co-authored-by: Muzaffer Kadir YILMAZ <34358176+muzafferkadir@users.noreply.github.com> Co-authored-by: Jemg * feat(blueprint): strapi template (#616) * feat(blueprint): strapi template * feat: strapi meta.json * fix: strapi extra colon * fix: docker syntax for expose and depends_on * fix: change image base * fix: strapi healthcheck * fix: add jwt secret and admin jwt secret to strapi * fix: strapi healthcheck start interval * fix(template): strapi v5.33.0 * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> Co-authored-by: Mauricio Siu * feat: Add Pulse monitoring template (#617) * feat: Add Pulse monitoring template - Add docker-compose.yml with healthcheck and Docker socket access - Add template.toml with domain and authentication variables - Add pulse.svg logo - Add meta.json entry with monitoring, proxmox, docker tags - Supports Proxmox VE, PBS, and Docker monitoring with real-time metrics * fix: Update Pulse docs link to GitHub repository - Replace non-existent docs.pulse.rcourtman.com with GitHub docs path - Use canonical documentation location in Pulse repository * update pulse links * Update blueprints/pulse/docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * Fix Obsidian LiveSync template links pointing to CouchDB instead of plugin (#621) * Initial plan * Fix Obsidian LiveSync template links to point to correct project Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Siumauricio <47042324+Siumauricio@users.noreply.github.com> * feat: add SeaweedFS template (#630) * feat: add SeaweedFS template * chore: add specific seaweedfs version * Update image versions in docker-compose for AList, Appsmith, and Budibase (#639) * Update image versions in the docker-compose and meta.json files for AList, Appsmith, and Budibase. * Update MinIO image version in docker-compose Pins a specific MinIO image version RELEASE.2025-09-07T16-13-09Z * refactor: add * docs: update CONTRIBUTING.md with pull request guidelines - Added guidelines for keeping pull requests small and focused. - Emphasized the importance of testing contributions before submission to maintain a tidy PR queue. * Add/trilium next (#671) * feat/add trilium next template * fix: test verify to pr * fix: fix validation error in docker-compose * fix: static version to trilium image --------- Co-authored-by: jbello * feat: add wuzapi template (#679) * feat: add wuzapi template * chore: remove temporary meta_entry.json * fix(wuzapi): remove explicit networks and simplify depends_on for Dokploy compatibility * fix(wuzapi): remove invalid config.mounts from template.toml * Update Docker images for wuzapi and PostgreSQL fixed the version of the wuzapi docker image. * feat: add PostgreSQL with PgDog template (#681) * feat: add PostgreSQL with PgDog template Add postgres-pgdog template providing PostgreSQL database with PgDog connection pooler, load balancer, and horizontal scaling proxy. Modern alternative to PgBouncer with multi-threading support. - Configurable PostgreSQL (default: 18-alpine) and PgDog (default: v0.1.26) images - Optional admin interface on port 6433 - Includes healthcheck and dependency management * 🐛 fix(postgres-pgdog): add config mounts and fix postgres volume path - Add [[config.mounts]] for pgdog.toml and users.toml - Mount config files from ../files/ in docker-compose - Change postgres volume to /var/lib/postgresql (postgres 18+ standard) - Add explicit command with config paths to prevent warnings * 🐛 fix(postgres-pgdog): correct binary path and use default config locations - Mount configs to /pgdog/ (default WorkingDir) instead of /etc/pgdog/ - Remove explicit command (binary is /usr/local/bin/pgdog, not /pgdog/pgdog) - Use image's default CMD with default config paths * 🐛 fix(postgres-pgdog): remove invalid admin_port config field - Remove admin_port from [general] section (not a valid field) - Admin DB uses same port 6432 with special database name - Remove commented admin domain config * 🐛 fix(postgres-pgdog): enable external access via fixed port mapping - Add fixed port 6432:6432 to postgres-pgdog service - Remove HTTP domain config (incompatible with TCP protocol) - Add comment for internal-only option Fixes UnsupportedStartup errors when using domain config for PostgreSQL protocol access. * 🐛 fix(postgres-pgdog): use standard port format per convention - Change port mapping from '6432:6432' to '6432' format - Follows Dokploy template convention for port declarations - External access requires checking Dokploy UI for assigned host port * 📝 docs(postgres-pgdog): clarify port settings comment * 🐛 fix(postgres-pgdog): default to internal access with opt-in external port - Remove obsolete version field - Port mapping commented by default for security - Users uncomment to enable external access on port 6432 * Add IPFS Kubo template (#703) * Add IPFS Kubo template * Update init cmds * Remove port forwarding * uptime-kuma: Bump version to 2.1.0 (#706) * Bump version to 2.1.0 * Update meta.json with new version number * feat(blueprint): update trmnl-byos-laravel template (#704) * upgrade nextcloud img version (#705) * fix docker-compose variables and update github link (#701) Co-authored-by: Aaron McGuire * Update InvoiceShelf compose to suit new changes (#693) https://github.com/InvoiceShelf/docker/blob/89bf78cec6fae54db76f84e0a4dc6255a8da710e/upgrade-guide.md * fix: superset template fixed versions, postgres volume mount and network instructions (#595) * fix: superset version fixed, tweak network instructions * chore: simplify mapbox key * fix: volume mount * deps: bump superset to 6.0.0 * feat: Add imgproxy template (#714) * feat: Add imgproxy template * fix: Configure docker-compose to match requirements * fix: Process meta * fix: Change logo name * fix: Remove incorrect mounts * fix: Expose 80 port instead of direct mapping * fix: Change nginx cache keys default zone size and correct format negotiation * fix: Escaping * feat: update to new Evolution API image source and pin it to the latest version (#644) * feat: Enhanced Nextcloud template with Redis, automated config, and improved setup (#672) * Update docker-compose.yml * fix: stable nextcloud, add redis, auto config, fixed mariadb * fix: meta nextcloud * fix: vars * fix: non capital * fix: template.toml * fix: env vars * fix: var naming * fix: command * fix: command * another try * keep it simple * fix toml * retry classic * add: admin user * no aito install * feat: automated fixes * fix file pasth * fix: manual script * fix: script * fix: png logo * fix: meta logo data --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * feat: add MediaFetch template (#688) * feat: add MediaFetch template * Corrected .toml * .toml * feat: add unleash template (#691) * feat: add unleash template * feat: update unleash template to version 7.4.0 and fix formatting * feat: update database user in unleash template from postgres to unleash * Update Notifuse template: replace PASETO with SECRET_KEY auth (#696) * Update Notifuse template: replace PASETO with SECRET_KEY auth * Update docker-compose.yml --------- Co-authored-by: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com> * Change convex port mapping to expose and bump version (#730) * chore: update convex backend and dashboard images, switch from port mapping to expose in docker-compose.yml * fix: set default value for DISABLE_BEACON in docker-compose.yml * Update grafana 12.4 (#731) * Update grafana 12.4 * Update meta.json * feat(blueprint): add Verdaccio - private node.js package registry (#735) * feat: add tuwunel template for matrix (re-made) (#733) * feat: add tuwunel template for matrix * fix: replace HTML placeholder with actual SVG logo for tuwunel * fix: remove enforcement and rename logo * fix(cloudflared): opt-out of isolated deployment (#856) Cloudflared requires network_mode: host which is mutually exclusive with Docker networks. Setting isolated = false prevents Dokploy from injecting networks into this compose. Fixes https://github.com/Dokploy/dokploy/issues/4366 * Update Plunk template to use next version (#622) * Update Plunk template to use next version * Add domain configuration to config.env * Remove NTFY from Plunk * Added the frappe lending template (#665) * added the frappe lending template * removed the external network * Add go2rtc (#720) * Add go2rtc * Update blueprints/go2rtc/docker-compose.yml Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Update blueprints/go2rtc/template.toml Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Apply suggestion from @greptile-apps[bot] Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Update docker-compose.yml * Update template.toml * Update docker-compose.yml * Update docker-compose.yml --------- Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> * Update Meilisearch 1.35.1 and fix Cyberchef logo (#722) * fix: update CyberChef logo from SVG to PNG and remove old SVG file * fix: update Meilisearch version to v1.35.1 --------- Co-authored-by: Sunil Shrestha Co-authored-by: Rabithua Co-authored-by: Mauricio Siu Co-authored-by: Scan <103391616+scanash00@users.noreply.github.com> Co-authored-by: Crackvignoule Co-authored-by: florianheysen <39408021+florianheysen@users.noreply.github.com> Co-authored-by: Thiago MadPin Co-authored-by: BlinkStrike <18644035+BlinkStrike@users.noreply.github.com> Co-authored-by: M Jupri Amin <127651222+Juupeee@users.noreply.github.com> Co-authored-by: Harikrishnan Dhanasekaran Co-authored-by: Kamil Dzieniszewski Co-authored-by: Nick Anderson Co-authored-by: lefolalan Co-authored-by: Chris <31969757+ChrisvanChip@users.noreply.github.com> Co-authored-by: kipavy <88386090+kipavy@users.noreply.github.com> Co-authored-by: Benjamin Nussbaum Co-authored-by: Khiet Tam Nguyen <86177399+nktnet1@users.noreply.github.com> Co-authored-by: Vidhya LKG for IT <24915474+VidhyaSanjeevi@users.noreply.github.com> Co-authored-by: Sanjeevi Subramani Co-authored-by: Muzaffer Kadir YILMAZ <34358176+muzafferkadir@users.noreply.github.com> Co-authored-by: Jemg Co-authored-by: Jainil Prajapati <86187588+jaainil@users.noreply.github.com> Co-authored-by: Ye Liu Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: Carl-Gerhard Lindesvärd <1987198+lindesvard@users.noreply.github.com> Co-authored-by: Huy Pham Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: Louan Fontenele Co-authored-by: Alexey Fedorov Co-authored-by: 0zul <26915998+0zul@users.noreply.github.com> Co-authored-by: Pascal Oberbeck <35005267+poberbeck@users.noreply.github.com> Co-authored-by: Pascal Oberbeck Co-authored-by: Christus Vincent Co-authored-by: Huba Tuba <57007485+floxay@users.noreply.github.com> Co-authored-by: Pablo Moraga Sandoval <72164630+Ketbome@users.noreply.github.com> Co-authored-by: Firefly <77047823+Yuri-NagaSaki@users.noreply.github.com> Co-authored-by: Naterfute <106989409+naterfute@users.noreply.github.com> Co-authored-by: Vitaliy Kukharik <37010174+vitabaks@users.noreply.github.com> Co-authored-by: aurorarissime Co-authored-by: фырат ёздэн <31664778+fir4tozden@users.noreply.github.com> Co-authored-by: JoshuaRileyDev <59296334+JoshuaRileyDev@users.noreply.github.com> Co-authored-by: Claude Co-authored-by: vabs Co-authored-by: Jorge Gómez Zarzosa <34076979+jorgegomzar@users.noreply.github.com> Co-authored-by: Jorge Gómez Zarzosa Co-authored-by: Benjamin Robinet Co-authored-by: Naim Hasim Co-authored-by: kadma Co-authored-by: José F. Bello <45277800+bellolongart@users.noreply.github.com> Co-authored-by: jbello Co-authored-by: Harshal Rathore <76205196+HarshalRathore@users.noreply.github.com> Co-authored-by: Vinicios Lugli Co-authored-by: Kien Ngo Co-authored-by: Simon <97951171+SimonSchroffner@users.noreply.github.com> Co-authored-by: Aaron McGuire <89317236+Aaron-McGuire@users.noreply.github.com> Co-authored-by: Aaron McGuire Co-authored-by: Andrew Wong Co-authored-by: Vladyslav Prosolupov Co-authored-by: Matheus Felipe Co-authored-by: Sina Sebastian Eetezadi Co-authored-by: Luke Dunsmore Co-authored-by: Dipanda Aser Co-authored-by: Pierre Co-authored-by: marcbodea Co-authored-by: Wladi Co-authored-by: Adrian Alfred C. Bonpin Co-authored-by: Dries Augustyns Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- blueprints/cloudflared/template.toml | 1 + blueprints/cyberchef/cyberchef.png | Bin 0 -> 14616 bytes blueprints/cyberchef/cyberchef.svg | Bin 43309 -> 0 bytes blueprints/frappe-lending/docker-compose.yml | 550 +++++++++++++++++++ blueprints/frappe-lending/frappe-lending.png | Bin 0 -> 2985 bytes blueprints/frappe-lending/template.toml | 29 + blueprints/go2rtc/docker-compose.yml | 24 + blueprints/go2rtc/go2rtc.png | Bin 0 -> 35192 bytes blueprints/go2rtc/template.toml | 13 + blueprints/meilisearch/docker-compose.yml | 3 +- blueprints/meilisearch/template.toml | 3 +- blueprints/plunk/docker-compose.yml | 186 +++++-- blueprints/plunk/template.toml | 120 +++- meta.json | 60 +- 14 files changed, 911 insertions(+), 78 deletions(-) create mode 100644 blueprints/cyberchef/cyberchef.png delete mode 100644 blueprints/cyberchef/cyberchef.svg create mode 100644 blueprints/frappe-lending/docker-compose.yml create mode 100644 blueprints/frappe-lending/frappe-lending.png create mode 100644 blueprints/frappe-lending/template.toml create mode 100644 blueprints/go2rtc/docker-compose.yml create mode 100644 blueprints/go2rtc/go2rtc.png create mode 100644 blueprints/go2rtc/template.toml diff --git a/blueprints/cloudflared/template.toml b/blueprints/cloudflared/template.toml index 7d2557cc..2b4d5239 100644 --- a/blueprints/cloudflared/template.toml +++ b/blueprints/cloudflared/template.toml @@ -1,6 +1,7 @@ variables = {} [config] +isolated = false domains = [] mounts = [] diff --git a/blueprints/cyberchef/cyberchef.png b/blueprints/cyberchef/cyberchef.png new file mode 100644 index 0000000000000000000000000000000000000000..4a3dfc32ce6578c7bb4e890b9f46f681c35b77c7 GIT binary patch literal 14616 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 sOW2o+(%anOm##0hPX2OvWLgtwyb224!<~g=` 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 GtbYLsJmQ@I diff --git a/blueprints/frappe-lending/docker-compose.yml b/blueprints/frappe-lending/docker-compose.yml new file mode 100644 index 00000000..60972a3b --- /dev/null +++ b/blueprints/frappe-lending/docker-compose.yml @@ -0,0 +1,550 @@ +x-custom-image: &custom_image + image: ${IMAGE_NAME:-frappe/erpnext}:${VERSION:-v15} + pull_policy: ${PULL_POLICY:-always} + deploy: + restart_policy: + condition: always + +services: + backend: + <<: *custom_image + entrypoint: ["bash", "-c"] + command: + - > + cd /home/frappe/frappe-bench; + if [ -d "apps/lending" ] && ! ./env/bin/pip show lending > /dev/null 2>&1; then + echo "Installing lending app in Python environment..."; + ./env/bin/pip install -e apps/lending || echo "Failed to install lending"; + fi; + echo "Waiting for site to be ready..."; + export start=`date +%s`; + while [ ! -f "sites/sites.txt" ] || [ ! -d "sites/${SITE_NAME}" ] || [ ! -f "sites/${SITE_NAME}/site_config.json" ]; do + echo "Waiting for site ${SITE_NAME} to be created and ready..."; + sleep 2; + if (( `date +%s`-start > 300 )); then + echo "Timeout waiting for site to be ready"; + echo "Checking sites directory:"; + ls -la sites/ || echo "sites directory not found"; + echo "Checking sites.txt:"; + cat sites/sites.txt 2>/dev/null || echo "sites.txt not found"; + break; + fi + done; + if [ -f "sites/sites.txt" ] && [ -d "sites/${SITE_NAME}" ] && [ -f "sites/${SITE_NAME}/site_config.json" ]; then + echo "Site ${SITE_NAME} is ready!"; + echo "sites.txt contents:"; + cat sites/sites.txt; + echo "Verifying site is accessible via bench..."; + bench --site ${SITE_NAME} list-apps > /dev/null 2>&1 && echo "Site is accessible via bench" || echo "Warning: Site accessibility check via bench failed"; + echo "Site directory structure:"; + ls -la sites/${SITE_NAME}/ | head -10; + if [ -n "${MAIN_DOMAIN}" ]; then + echo "Updating host_name and SSL settings to https://${MAIN_DOMAIN} (ensuring correct domain for emails)..."; + bench --site ${SITE_NAME} set-config host_name "https://${MAIN_DOMAIN}" || echo "Warning: Could not update host_name"; + bench --site ${SITE_NAME} set-config host_url "https://${MAIN_DOMAIN}" || echo "Warning: Could not update host_url"; + bench --site ${SITE_NAME} set-config use_ssl 1 || echo "Warning: Could not set use_ssl"; + echo "Verifying configuration..."; + bench --site ${SITE_NAME} get-config host_name 2>/dev/null || echo "Could not read host_name (this is OK if site is not fully initialized)"; + echo "Clearing cache to apply new domain settings..."; + bench --site ${SITE_NAME} clear-cache || echo "Warning: Could not clear cache"; + bench --site ${SITE_NAME} clear-website-cache || echo "Warning: Could not clear website cache"; + fi; + else + echo "Warning: Site may not be fully ready, but starting backend anyway"; + fi; + echo "Starting bench serve (production-ready)"; + export PYTHONUNBUFFERED=1; + bench serve --port 8000 2>&1 | awk '!/127\.0\.0\.1.*400/ {print}' || bench serve --port 8000; + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + environment: + SITE_NAME: ${SITE_NAME} + FRAPPE_SITE_NAME_HEADER: "" + MAIN_DOMAIN: ${MAIN_DOMAIN} + depends_on: + configurator: + condition: service_completed_successfully + required: true + create-site: + condition: service_completed_successfully + required: true + healthcheck: + test: + - CMD + - wait-for-it + - '0.0.0.0:8000' + interval: 2s + timeout: 10s + retries: 30 + + frontend: + <<: *custom_image + entrypoint: ["bash", "-c"] + command: + - > + echo "Starting Nginx with port_in_redirect fix..."; + nginx-entrypoint.sh & + NGINX_PID=$!; + sleep 3; + if [ -f /etc/nginx/conf.d/frappe.conf ]; then + if ! grep -q "port_in_redirect off" /etc/nginx/conf.d/frappe.conf; then + echo "Applying port_in_redirect fix to prevent :8080 in URLs..."; + sed -i 's/listen 8080;/listen 8080;\n port_in_redirect off;\n absolute_redirect off;/' /etc/nginx/conf.d/frappe.conf; + echo "Nginx config updated - reloading..."; + sleep 1; + nginx -s reload 2>/dev/null || echo "Nginx will use updated config on next reload"; + else + echo "Nginx config already has port_in_redirect settings"; + fi + else + echo "Warning: frappe.conf not found yet, will check again"; + sleep 2; + if [ -f /etc/nginx/conf.d/frappe.conf ]; then + if ! grep -q "port_in_redirect off" /etc/nginx/conf.d/frappe.conf; then + sed -i 's/listen 8080;/listen 8080;\n port_in_redirect off;\n absolute_redirect off;/' /etc/nginx/conf.d/frappe.conf; + nginx -s reload 2>/dev/null || true; + fi + fi + fi; + wait $NGINX_PID + depends_on: + backend: + condition: service_started + required: true + websocket: + condition: service_started + required: true + environment: + BACKEND: backend:8000 + FRAPPE_SITE_NAME_HEADER: "" + SOCKETIO: websocket:9000 + UPSTREAM_REAL_IP_ADDRESS: 127.0.0.1 + UPSTREAM_REAL_IP_HEADER: X-Forwarded-For + UPSTREAM_REAL_IP_RECURSIVE: "off" + USE_X_FORWARDED_HOST: "1" + PROXY_FIX: "1" + X_FORWARDED_PROTO: "https" + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + + healthcheck: + test: + - CMD-SHELL + - curl -fsS http://127.0.0.1:8080/login || exit 1 + interval: 30s + timeout: 5s + retries: 3 + + queue-default: + <<: *custom_image + entrypoint: ["bash", "-c"] + command: + - > + cd /home/frappe/frappe-bench; + export start=`date +%s`; + while [ ! -d "apps/lending" ]; do + echo "Waiting for apps to be available..."; + sleep 2; + if (( `date +%s`-start > 300 )); then + echo "Timeout waiting for apps"; + break; + fi; + done; + if [ -d "apps/lending" ] && ! ./env/bin/pip show lending > /dev/null 2>&1; then + echo "Installing lending app in Python environment..."; + ./env/bin/pip install -e apps/lending || echo "Failed to install lending"; + fi; + exec bench worker --queue default + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + healthcheck: + test: + - CMD + - wait-for-it + - 'redis-queue:6379' + interval: 2s + timeout: 10s + retries: 30 + depends_on: + configurator: + condition: service_completed_successfully + required: true + + queue-long: + <<: *custom_image + entrypoint: ["bash", "-c"] + command: + - > + cd /home/frappe/frappe-bench; + export start=`date +%s`; + while [ ! -d "apps/lending" ]; do + echo "Waiting for apps to be available..."; + sleep 2; + if (( `date +%s`-start > 300 )); then + echo "Timeout waiting for apps"; + break; + fi; + done; + if [ -d "apps/lending" ] && ! ./env/bin/pip show lending > /dev/null 2>&1; then + echo "Installing lending app in Python environment..."; + ./env/bin/pip install -e apps/lending || echo "Failed to install lending"; + fi; + exec bench worker --queue long + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + healthcheck: + test: + - CMD + - wait-for-it + - 'redis-queue:6379' + interval: 2s + timeout: 10s + retries: 30 + depends_on: + configurator: + condition: service_completed_successfully + required: true + + queue-short: + <<: *custom_image + entrypoint: ["bash", "-c"] + command: + - > + cd /home/frappe/frappe-bench; + export start=`date +%s`; + while [ ! -d "apps/lending" ]; do + echo "Waiting for apps to be available..."; + sleep 2; + if (( `date +%s`-start > 300 )); then + echo "Timeout waiting for apps"; + break; + fi; + done; + if [ -d "apps/lending" ] && ! ./env/bin/pip show lending > /dev/null 2>&1; then + echo "Installing lending app in Python environment..."; + ./env/bin/pip install -e apps/lending || echo "Failed to install lending"; + fi; + exec bench worker --queue short + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + healthcheck: + test: + - CMD + - wait-for-it + - 'redis-queue:6379' + interval: 2s + timeout: 10s + retries: 30 + depends_on: + configurator: + condition: service_completed_successfully + required: true + + scheduler: + <<: *custom_image + entrypoint: ["bash", "-c"] + command: + - > + cd /home/frappe/frappe-bench; + export start=`date +%s`; + while [ ! -d "apps/lending" ]; do + echo "Waiting for apps to be available..."; + sleep 2; + if (( `date +%s`-start > 300 )); then + echo "Timeout waiting for apps"; + break; + fi; + done; + if [ -d "apps/lending" ] && ! ./env/bin/pip show lending > /dev/null 2>&1; then + echo "Installing lending app in Python environment..."; + ./env/bin/pip install -e apps/lending || echo "Failed to install lending"; + fi; + exec bench schedule + healthcheck: + test: + - CMD + - wait-for-it + - 'redis-queue:6379' + interval: 2s + timeout: 10s + retries: 30 + depends_on: + configurator: + condition: service_completed_successfully + required: true + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + + websocket: + <<: *custom_image + healthcheck: + test: + - CMD + - wait-for-it + - '0.0.0.0:9000' + interval: 2s + timeout: 10s + retries: 30 + command: + - node + - /home/frappe/frappe-bench/apps/frappe/socketio.js + depends_on: + configurator: + condition: service_completed_successfully + required: true + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + + configurator: + <<: *custom_image + deploy: + mode: replicated + replicas: ${CONFIGURE:-0} + restart_policy: + condition: none + entrypoint: ["bash", "-c"] + command: + - > + [[ $${REGENERATE_APPS_TXT} == "1" ]] && ls -1 apps > sites/apps.txt; + [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".db_host // empty"` ]] && exit 0; + bench set-config -g db_host $$DB_HOST; + bench set-config -gp db_port $$DB_PORT; + bench set-config -g redis_cache "redis://$$REDIS_CACHE"; + bench set-config -g redis_queue "redis://$$REDIS_QUEUE"; + bench set-config -g redis_socketio "redis://$$REDIS_QUEUE"; + bench set-config -gp socketio_port $$SOCKETIO_PORT; + environment: + DB_HOST: "${DB_HOST:-db}" + DB_PORT: "3306" + REDIS_CACHE: redis-cache:6379 + REDIS_QUEUE: redis-queue:6379 + SOCKETIO_PORT: "9000" + REGENERATE_APPS_TXT: "${REGENERATE_APPS_TXT:-0}" + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + + create-site: + <<: *custom_image + deploy: + mode: replicated + replicas: ${CREATE_SITE:-0} + restart_policy: + condition: none + entrypoint: ["bash", "-c"] + command: + - > + wait-for-it -t 120 $$DB_HOST:$$DB_PORT; + wait-for-it -t 120 redis-cache:6379; + wait-for-it -t 120 redis-queue:6379; + export start=`date +%s`; + until [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".db_host // empty"` ]] && \ + [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".redis_cache // empty"` ]] && \ + [[ -n `grep -hs ^ sites/common_site_config.json | jq -r ".redis_queue // empty"` ]]; + do + echo "Waiting for sites/common_site_config.json to be created"; + sleep 5; + if (( `date +%s`-start > 120 )); then + echo "could not find sites/common_site_config.json with required keys"; + exit 1 + fi + done; + echo "sites/common_site_config.json found"; + cd /home/frappe/frappe-bench; + if [ -d "sites/${SITE_NAME}" ] && [ -f "sites/${SITE_NAME}/site_config.json" ]; then + echo "Site ${SITE_NAME} already exists, skipping creation"; + bench use $${SITE_NAME} || echo "Warning: Could not set current site"; + echo "$${SITE_NAME}" > sites/sites.txt || echo "Warning: Could not update sites.txt"; + bench set-config -g default_site $${SITE_NAME} || echo "Warning: Could not set default site"; + if [ -n "$${ADMIN_PASSWORD}" ]; then + echo "Updating admin password for existing site..."; + bench --site $${SITE_NAME} set-admin-password $${ADMIN_PASSWORD} || echo "Warning: Could not update admin password (may need to be done manually)"; + fi; + if [ -n "$${MAIN_DOMAIN}" ]; then + echo "Setting host_name and SSL settings to https://${MAIN_DOMAIN} (with HTTPS)..."; + bench --site $${SITE_NAME} set-config host_name "https://$${MAIN_DOMAIN}" || echo "Warning: Could not set host_name"; + bench --site $${SITE_NAME} set-config host_url "https://$${MAIN_DOMAIN}" || echo "Warning: Could not set host_url"; + bench --site $${SITE_NAME} set-config use_ssl 1 || echo "Warning: Could not set use_ssl"; + echo "Clearing cache to apply new domain settings..."; + bench --site $${SITE_NAME} clear-cache || echo "Warning: Could not clear cache"; + bench --site $${SITE_NAME} clear-website-cache || echo "Warning: Could not clear website cache"; + fi; + echo "Verifying existing site is accessible..."; + bench --site $${SITE_NAME} list-apps > /dev/null 2>&1 && echo "Existing site is accessible and working" || echo "Warning: Site accessibility check failed"; + exit 0; + fi; + if [ ! -d "apps/lending" ]; then + echo "Cloning lending app..."; + git clone https://github.com/frappe/lending.git apps/lending || echo "Failed to clone lending app"; + fi; + if [ -d "apps/lending" ]; then + echo "Installing lending app in Python environment..."; + ./env/bin/pip install -e apps/lending || echo "Failed to install lending app"; + fi; + echo "Regenerating apps.txt to include all apps..."; + ls -1 apps > sites/apps.txt || (echo "frappe" > sites/apps.txt && echo "lending" >> sites/apps.txt); + echo "apps.txt contents:"; + cat sites/apps.txt; + bench set-mariadb-host $${DB_HOST:-db}; + bench new-site --mariadb-user-host-login-scope='%' --admin-password=$${ADMIN_PASSWORD} --db-root-username=root --db-root-password=$${DB_ROOT_PASSWORD} $${INSTALL_APP_ARGS} $${SITE_NAME}; + if [ ! -d "sites/${SITE_NAME}" ]; then + echo "ERROR: Site ${SITE_NAME} was not created successfully"; + exit 1; + fi; + echo "Site ${SITE_NAME} created successfully"; + bench use $${SITE_NAME}; + echo "Current site set to: $${SITE_NAME}"; + if [ -d "apps/lending" ]; then + echo "Installing lending app on site..."; + bench --site $${SITE_NAME} install-app lending || echo "Lending app may already be installed or failed to install"; + fi; + echo "Building assets for all apps (this ensures lending JS is available)..."; + bench build --apps lending || echo "Asset build completed"; + echo "Clearing all caches..."; + bench --site $${SITE_NAME} clear-cache || echo "Cache cleared"; + bench --site $${SITE_NAME} clear-website-cache || echo "Website cache cleared"; + echo "Creating sites.txt for site resolution..."; + echo "$${SITE_NAME}" > sites/sites.txt || echo "Warning: Could not create sites.txt"; + echo "Site registered in sites.txt:"; + cat sites/sites.txt || echo "sites.txt not found"; + echo "Verifying site directory and config exist..."; + if [ -d "sites/${SITE_NAME}" ] && [ -f "sites/${SITE_NAME}/site_config.json" ]; then + echo "Site directory and config verified successfully"; + else + echo "Warning: Site directory or config file missing"; + ls -la sites/${SITE_NAME}/ 2>/dev/null || echo "Site directory listing failed"; + fi; + echo "Setting default site in common_site_config.json..."; + bench set-config -g default_site $${SITE_NAME} || echo "Warning: Could not set default site"; + if [ -n "$${MAIN_DOMAIN}" ]; then + echo "Setting host_name and SSL settings to https://${MAIN_DOMAIN} (with HTTPS)..."; + bench --site $${SITE_NAME} set-config host_name "https://$${MAIN_DOMAIN}" || echo "Warning: Could not set host_name"; + bench --site $${SITE_NAME} set-config host_url "https://$${MAIN_DOMAIN}" || echo "Warning: Could not set host_url"; + bench --site $${SITE_NAME} set-config use_ssl 1 || echo "Warning: Could not set use_ssl"; + echo "Clearing cache to apply new domain settings..."; + bench --site $${SITE_NAME} clear-cache || echo "Warning: Could not clear cache"; + bench --site $${SITE_NAME} clear-website-cache || echo "Warning: Could not clear website cache"; + fi; + echo "Verifying site is accessible..."; + bench --site $${SITE_NAME} list-apps > /dev/null 2>&1 && echo "Site is accessible and working" || echo "Warning: Site accessibility check failed"; + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + environment: + SITE_NAME: ${SITE_NAME} + MAIN_DOMAIN: ${main_domain} + ADMIN_PASSWORD: ${ADMIN_PASSWORD} + DB_HOST: ${DB_HOST:-db} + DB_PORT: "${DB_PORT:-3306}" + DB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} + INSTALL_APP_ARGS: ${INSTALL_APP_ARGS} + + migration: + <<: *custom_image + deploy: + mode: replicated + replicas: ${MIGRATE:-0} + restart_policy: + condition: none + entrypoint: ["bash", "-c"] + command: + - > + curl -f http://${SITE_NAME}:8080/api/method/ping || echo "Site busy" && exit 0; + bench --site all set-config -p maintenance_mode 1; + bench --site all set-config -p pause_scheduler 1; + bench --site all migrate; + bench --site all set-config -p maintenance_mode 0; + bench --site all set-config -p pause_scheduler 0; + volumes: + - sites:/home/frappe/frappe-bench/sites + - apps:/home/frappe/frappe-bench/apps + + db: + image: mariadb:10.6 + deploy: + mode: replicated + replicas: ${ENABLE_DB:-0} + restart_policy: + condition: always + healthcheck: + test: mysqladmin ping -h localhost --password=${DB_ROOT_PASSWORD} + interval: 1s + retries: 20 + command: + - --character-set-server=utf8mb4 + - --collation-server=utf8mb4_unicode_ci + - --skip-character-set-client-handshake + - --skip-innodb-read-only-compressed + environment: + - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD} + - MARIADB_ROOT_PASSWORD=${DB_ROOT_PASSWORD} + volumes: + - db-data:/var/lib/mysql + + redis-cache: + deploy: + restart_policy: + condition: always + image: redis:6.2-alpine + volumes: + - redis-cache-data:/data + healthcheck: + test: + - CMD + - redis-cli + - ping + interval: 5s + timeout: 5s + retries: 3 + + redis-queue: + deploy: + restart_policy: + condition: always + image: redis:6.2-alpine + volumes: + - redis-queue-data:/data + healthcheck: + test: + - CMD + - redis-cli + - ping + interval: 5s + timeout: 5s + retries: 3 + + redis-socketio: + deploy: + restart_policy: + condition: always + image: redis:6.2-alpine + volumes: + - redis-socketio-data:/data + healthcheck: + test: + - CMD + - redis-cli + - ping + interval: 5s + timeout: 5s + retries: 3 + +volumes: + db-data: + redis-cache-data: + redis-queue-data: + redis-socketio-data: + sites: + driver_opts: + type: "${SITE_VOLUME_TYPE}" + o: "${SITE_VOLUME_OPTS}" + device: "${SITE_VOLUME_DEV}" + apps: + diff --git a/blueprints/frappe-lending/frappe-lending.png b/blueprints/frappe-lending/frappe-lending.png new file mode 100644 index 0000000000000000000000000000000000000000..e94e65a6e91233b476d6c394ee356aabb6b133be GIT binary patch literal 2985 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 GHum3@T!&}? literal 0 HcmV?d00001 diff --git a/blueprints/frappe-lending/template.toml b/blueprints/frappe-lending/template.toml new file mode 100644 index 00000000..71612960 --- /dev/null +++ b/blueprints/frappe-lending/template.toml @@ -0,0 +1,29 @@ +[variables] +main_domain = "${domain}" +site_name = "frappe.lending" +db_root_password = "${password:32}" +admin_password = "${password:32}" + +[config] +env = [ + "SITE_NAME=${site_name}", + "ADMIN_PASSWORD=${admin_password}", + "DB_ROOT_PASSWORD=${db_root_password}", + "MIGRATE=1", + "ENABLE_DB=1", + "DB_HOST=db", + "CREATE_SITE=1", + "CONFIGURE=1", + "REGENERATE_APPS_TXT=1", + "INSTALL_APP_ARGS=--install-app erpnext --install-app lending", + "IMAGE_NAME=frappe/erpnext", + "VERSION=latest", + "FRAPPE_SITE_NAME_HEADER=", + "MAIN_DOMAIN=${main_domain}", +] +mounts = [] + +[[config.domains]] +serviceName = "frontend" +port = 8_080 +host = "${main_domain}" diff --git a/blueprints/go2rtc/docker-compose.yml b/blueprints/go2rtc/docker-compose.yml new file mode 100644 index 00000000..947c0feb --- /dev/null +++ b/blueprints/go2rtc/docker-compose.yml @@ -0,0 +1,24 @@ +version: "3.8" + +services: + go2rtc: + image: alexxit/go2rtc:1.9.14 + restart: unless-stopped + + # To use a local webcam, add the device to the service: + # devices: + # - /dev/video0:/dev/video0 # Adjust path if your device is at /dev/video1, etc. + + expose: + - 1984 # Web UI + - 8554 # RTSP + - 8555 # WebRTC + + environment: + - TZ=${TZ} + + volumes: + - go2rtc-config:/config + +volumes: + go2rtc-config: {} diff --git a/blueprints/go2rtc/go2rtc.png b/blueprints/go2rtc/go2rtc.png new file mode 100644 index 0000000000000000000000000000000000000000..a9a81a3c12463dc49045ced599fbd847edb396c2 GIT binary patch literal 35192 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 ZgkPX7A+5GQ)VKfu002ovPDHLkV1nfq0)GGi literal 0 HcmV?d00001 diff --git a/blueprints/go2rtc/template.toml b/blueprints/go2rtc/template.toml new file mode 100644 index 00000000..f650f2fc --- /dev/null +++ b/blueprints/go2rtc/template.toml @@ -0,0 +1,13 @@ +[variables] +main_domain = "${domain}" + +[config] +[[config.domains]] +serviceName = "go2rtc" +port = 1984 +host = "${main_domain}" + +env = [ + "TZ=${TZ}" +] + diff --git a/blueprints/meilisearch/docker-compose.yml b/blueprints/meilisearch/docker-compose.yml index ae5ebcb1..db87310f 100644 --- a/blueprints/meilisearch/docker-compose.yml +++ b/blueprints/meilisearch/docker-compose.yml @@ -2,12 +2,11 @@ version: "3.8" services: meilisearch: - image: getmeili/meilisearch:v1.8.3 + image: getmeili/meilisearch:v1.35.1 volumes: - meili_data:/meili_data environment: MEILI_MASTER_KEY: ${MEILI_MASTER_KEY} - MEILI_ENV: ${MEILI_ENV} volumes: meili_data: diff --git a/blueprints/meilisearch/template.toml b/blueprints/meilisearch/template.toml index b1bdb5f9..5b1b94eb 100644 --- a/blueprints/meilisearch/template.toml +++ b/blueprints/meilisearch/template.toml @@ -11,5 +11,4 @@ port = 7_700 host = "${main_domain}" [config.env] -MEILI_ENV = "development" -MEILI_MASTER_KEY = "${master_key}" +MEILI_MASTER_KEY = "${master_key}" \ No newline at end of file diff --git a/blueprints/plunk/docker-compose.yml b/blueprints/plunk/docker-compose.yml index 914001cf..9991d855 100644 --- a/blueprints/plunk/docker-compose.yml +++ b/blueprints/plunk/docker-compose.yml @@ -1,58 +1,166 @@ -# IMPORTANT: Plunk requires HTTPS to work properly -# go to the "Domains" tab and enable HTTPS for your domain +# Plunk Self-Hosting Docker Compose for Dokploy +# This setup runs all Plunk services with nginx reverse proxy +# +# IMPORTANT: This template requires multiple subdomains: +# - api.yourdomain.com -> API Server +# - app.yourdomain.com -> Web Dashboard +# - www.yourdomain.com -> Landing Page +# - docs.yourdomain.com -> Documentation +# - minio.yourdomain.com -> Minio Console (optional) +# +# All domains will be automatically configured in Dokploy services: - plunk: - image: driaug/plunk - expose: - - "3000" - depends_on: - db: - condition: service_healthy - redis: - condition: service_started - environment: - REDIS_URL: ${REDIS_URL} - DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB} - JWT_SECRET: ${JWT_SECRET} - AWS_REGION: ${AWS_REGION} - AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID} - AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY} - AWS_SES_CONFIGURATION_SET: ${AWS_SES_CONFIGURATION_SET} - APP_URI: ${APP_URI} - NEXT_PUBLIC_API_URI: ${APP_URI}/api - API_URI: ${APP_URI}/api - DISABLE_SIGNUPS: ${DISABLE_SIGNUPS} - entrypoint: ["/app/entry.sh"] - restart: unless-stopped + # ============================================ + # Infrastructure Services + # ============================================ - db: - image: postgres:alpine + postgres: + image: postgres:16-alpine + restart: unless-stopped environment: - POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} - POSTGRES_USER: ${POSTGRES_USER} - POSTGRES_DB: ${POSTGRES_DB} + POSTGRES_DB: plunk + POSTGRES_USER: plunk + POSTGRES_PASSWORD: ${DB_PASSWORD} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] + test: ["CMD-SHELL", "pg_isready -U plunk"] interval: 10s + timeout: 5s retries: 5 - timeout: 10s - restart: unless-stopped - expose: - - 5432 redis: - image: redis:alpine + image: redis:7-alpine restart: unless-stopped - expose: - - 6379 + command: redis-server --appendonly yes volumes: - redis_data:/data + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + + minio: + image: minio/minio:latest + restart: unless-stopped + command: server /data --console-address ":9001" + environment: + MINIO_ROOT_USER: ${MINIO_ROOT_USER} + MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD} + volumes: + - minio_data:/data + ports: + - 9000 + - 9001 + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] + interval: 30s + timeout: 20s + retries: 3 + + # ============================================ + # Plunk Application + # ============================================ + + plunk: + image: ghcr.io/useplunk/plunk:latest + restart: unless-stopped + environment: + # Service mode - runs all services in one container + SERVICE: all + NODE_ENV: production + + # Database + DATABASE_URL: postgresql://plunk:${DB_PASSWORD}@postgres:5432/plunk + DIRECT_DATABASE_URL: postgresql://plunk:${DB_PASSWORD}@postgres:5432/plunk + + # Redis + REDIS_URL: ${REDIS_URL} + + # Security + JWT_SECRET: ${JWT_SECRET} + + # Nginx configuration + NGINX_PORT: ${NGINX_PORT} + + # Domain configuration (subdomain-based routing) + API_DOMAIN: ${API_DOMAIN} + DASHBOARD_DOMAIN: ${DASHBOARD_DOMAIN} + LANDING_DOMAIN: ${LANDING_DOMAIN} + WIKI_DOMAIN: ${WIKI_DOMAIN} + USE_HTTPS: ${USE_HTTPS} + + # AWS SES (for sending emails) - REQUIRED + AWS_SES_REGION: ${AWS_SES_REGION} + AWS_SES_ACCESS_KEY_ID: ${AWS_SES_ACCESS_KEY_ID} + AWS_SES_SECRET_ACCESS_KEY: ${AWS_SES_SECRET_ACCESS_KEY} + SES_CONFIGURATION_SET: ${SES_CONFIGURATION_SET} + SES_CONFIGURATION_SET_NO_TRACKING: ${SES_CONFIGURATION_SET_NO_TRACKING} + + # Optional: OAuth + GITHUB_OAUTH_CLIENT: ${GITHUB_OAUTH_CLIENT} + GITHUB_OAUTH_SECRET: ${GITHUB_OAUTH_SECRET} + GOOGLE_OAUTH_CLIENT: ${GOOGLE_OAUTH_CLIENT} + GOOGLE_OAUTH_SECRET: ${GOOGLE_OAUTH_SECRET} + + # Optional: Stripe + STRIPE_SK: ${STRIPE_SK} + STRIPE_WEBHOOK_SECRET: ${STRIPE_WEBHOOK_SECRET} + STRIPE_PRICE_ONBOARDING: ${STRIPE_PRICE_ONBOARDING} + STRIPE_PRICE_EMAIL_USAGE: ${STRIPE_PRICE_EMAIL_USAGE} + STRIPE_METER_EVENT_NAME: ${STRIPE_METER_EVENT_NAME} + + # S3-compatible storage (Minio) + S3_ENDPOINT: ${S3_ENDPOINT} + S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID} + S3_ACCESS_KEY_SECRET: ${S3_ACCESS_KEY_SECRET} + S3_BUCKET: ${S3_BUCKET} + S3_PUBLIC_URL: ${S3_PUBLIC_URL} + S3_FORCE_PATH_STYLE: ${S3_FORCE_PATH_STYLE} + + # SMTP Server (for sending emails via SMTP) + SMTP_DOMAIN: ${SMTP_DOMAIN} + PORT_SECURE: ${PORT_SECURE} + PORT_SUBMISSION: ${PORT_SUBMISSION} + + # Internal + PLUNK_API_KEY: ${PLUNK_API_KEY} + PLUNK_FROM_ADDRESS: ${PLUNK_FROM_ADDRESS} + + volumes: + # Mount Traefik certificates for SSL + - /etc/dokploy/traefik/dynamic/acme.json:/certs/acme.json:ro + + ports: + # Main nginx port (handles all subdomain routing) + - 80 + # SMTP ports (for email relay) + - 465 + - 587 + + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + minio: + condition: service_healthy + + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:80/"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 60s volumes: postgres_data: driver: local redis_data: - driver: local \ No newline at end of file + driver: local + minio_data: + driver: local + plunk_data: + driver: local diff --git a/blueprints/plunk/template.toml b/blueprints/plunk/template.toml index 831f2c47..ce92c1fe 100644 --- a/blueprints/plunk/template.toml +++ b/blueprints/plunk/template.toml @@ -1,30 +1,120 @@ [variables] -main_domain = "${domain}" -postgres_user = "plunk" -postgres_db = "plunk" +# Generate unique domains for each service +api_domain = "${domain}" +dashboard_domain = "${domain}" +landing_domain = "${domain}" +wiki_domain = "${domain}" +minio_domain = "${domain}" + +# Database credentials +postgres_password = "${password:32}" + +# Security +jwt_secret = "${password:64}" + +# Minio credentials +minio_root_user = "plunk" +minio_root_password = "${password:32}" [config] isolated = true +# API Domain [[config.domains]] serviceName = "plunk" -port = 3000 -host = "${main_domain}" +port = 80 +host = "${api_domain}" +path = "/" + +# Dashboard Domain +[[config.domains]] +serviceName = "plunk" +port = 80 +host = "${dashboard_domain}" +path = "/" + +# Landing Page Domain +[[config.domains]] +serviceName = "plunk" +port = 80 +host = "${landing_domain}" +path = "/" + +# Documentation Domain +[[config.domains]] +serviceName = "plunk" +port = 80 +host = "${wiki_domain}" +path = "/" + +# Minio Console Domain (optional) +[[config.domains]] +serviceName = "minio" +port = 9001 +host = "${minio_domain}" path = "/" [config.env] -POSTGRES_USER = "${postgres_user}" -POSTGRES_DB = "${postgres_db}" -POSTGRES_PASSWORD = "${password:32}" +# Database +DB_PASSWORD = "${postgres_password}" +# Redis REDIS_URL = "redis://redis:6379" -JWT_SECRET = "${password:64}" -APP_URI = "https://${main_domain}" +# Security +JWT_SECRET = "${jwt_secret}" -AWS_REGION = "" -AWS_ACCESS_KEY_ID = "" -AWS_SECRET_ACCESS_KEY = "" -AWS_SES_CONFIGURATION_SET = "" +# Nginx configuration +NGINX_PORT = "80" -DISABLE_SIGNUPS = "False" \ No newline at end of file +# Domain configuration (subdomain-based routing) +API_DOMAIN = "${api_domain}" +DASHBOARD_DOMAIN = "${dashboard_domain}" +LANDING_DOMAIN = "${landing_domain}" +WIKI_DOMAIN = "${wiki_domain}" +USE_HTTPS = "true" + +# AWS SES (Required - users must configure these for email to work) +AWS_SES_REGION = "us-east-1" +AWS_SES_ACCESS_KEY_ID = "" +AWS_SES_SECRET_ACCESS_KEY = "" +SES_CONFIGURATION_SET = "" + +# S3-compatible storage (Minio) +MINIO_ROOT_USER = "${minio_root_user}" +MINIO_ROOT_PASSWORD = "${minio_root_password}" +S3_ENDPOINT = "http://minio:9000" +S3_ACCESS_KEY_ID = "${minio_root_user}" +S3_ACCESS_KEY_SECRET = "${minio_root_password}" +S3_BUCKET = "uploads" +S3_PUBLIC_URL = "https://${minio_domain}/uploads" +S3_FORCE_PATH_STYLE = "true" + +# Minio ports +MINIO_API_PORT = "9000" +MINIO_CONSOLE_PORT = "9001" + +# SMTP Server ports +PORT_SECURE = "465" +PORT_SUBMISSION = "587" + +# Notifications (ntfy.sh) +NTFY_URL = "http://ntfy/plunk-notifications" + +# Optional: OAuth (leave empty if not using) +GITHUB_OAUTH_CLIENT = "" +GITHUB_OAUTH_SECRET = "" +GOOGLE_OAUTH_CLIENT = "" +GOOGLE_OAUTH_SECRET = "" + +# Optional: Stripe (leave empty if not using) +STRIPE_SK = "" +STRIPE_WEBHOOK_SECRET = "" +STRIPE_PRICE_ONBOARDING = "" +STRIPE_PRICE_EMAIL_USAGE = "" +STRIPE_METER_EVENT_NAME = "emails" + +# Internal +PLUNK_API_KEY = "" +PLUNK_FROM_ADDRESS = "" +SMTP_DOMAIN = "" \ No newline at end of file diff --git a/meta.json b/meta.json index 3ae0cb5e..8be7825d 100644 --- a/meta.json +++ b/meta.json @@ -1685,7 +1685,7 @@ "name": "CyberChef", "version": "latest", "description": "CyberChef is a web application for encryption, encoding, compression, and data analysis, developed by GCHQ.", - "logo": "cyberchef.svg", + "logo": "cyberchef.png", "links": { "github": "https://github.com/gchq/CyberChef", "website": "https://gchq.github.io/CyberChef/", @@ -2543,6 +2543,26 @@ "performace" ] }, + { + "id": "frappe-lending", + "name": "Frappe Lending", + "version": "latest", + "description": "A comprehensive loan management system built on Frappe Framework. 100% open source and customizable for managing loans, repayments, and lending operations.", + "logo": "frappe-lending.png", + "links": { + "github": "https://github.com/frappe/lending", + "docs": "https://docs.frappe.io/lending", + "website": "https://frappe.io" + }, + "tags": [ + "lending", + "finance", + "loans", + "payments", + "accounting", + "self-hosted" + ] + }, { "id": "freescout", "name": "FreeScout", @@ -2810,6 +2830,24 @@ "api" ] }, + { + "id": "go2rtc", + "name": "go2rtc", + "version": "latest", + "description": "Ultimate camera streaming application with support for dozens formats and protocols.", + "logo": "go2rtc.png", + "links": { + "github": "https://github.com/AlexxIT/go2rtc", + "website": "https://go2rtc.org/", + "docs": "https://go2rtc.org/" + }, + "tags": [ + "streaming", + "webrtc", + "video", + "home assistant" + ] + }, { "id": "gotenberg", "name": "Gotenberg", @@ -3968,7 +4006,7 @@ { "id": "meilisearch", "name": "Meilisearch", - "version": "v1.8.3", + "version": "v1.35.1", "description": "Meilisearch is a free and open-source search engine that allows you to easily add search functionality to your web applications.", "logo": "meilisearch.png", "links": { @@ -5952,24 +5990,6 @@ "media" ] }, - { - "id": "strapi", - "name": "Strapi", - "version": "v5.33.0", - "description": "Open-source headless CMS to build powerful APIs with built-in content management.", - "logo": "strapi.svg", - "links": { - "github": "https://github.com/strapi/strapi", - "discord": "https://discord.com/invite/strapi", - "docs": "https://docs.strapi.io", - "website": "https://strapi.io" - }, - "tags": [ - "headless", - "cms", - "content-management" - ] - }, { "id": "supabase", "name": "SupaBase",