diff --git a/.gitignore b/.gitignore
index c0cadd7c..2f8606a3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,3 @@
node_modules
package-lock.json
meta.json.backup.*
-
diff --git a/AGENTS.md b/AGENTS.md
index c34d6beb..753da746 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -170,6 +170,16 @@ This document provides essential context for AI models interacting with this pro
- **Env:** Array of strings: `env = ["KEY=VALUE", "DB_PASSWORD=${db_pass}"]`
- **Available helpers:** `${domain}`, `${password:length}`, `${base64:length}`, `${hash:length}`, `${uuid}`, `${randomPort}`, `${email}`, `${username}`, `${timestamp}`, `${timestamps:datetime}`, `${timestampms:datetime}`, `${jwt:secret_var:payload_var}`
- **JWT helper example:** `${jwt:mysecret:mypayload}` with payload containing `exp: ${timestamps:2030-01-01T00:00:00Z}`
+ - **Volume bind mounts (in docker-compose.yml):** When mounting host paths, do NOT use absolute paths like `"/folder:/path/in/container"`. Use relative paths instead:
+ ```yaml
+ # Invalid
+ volumes:
+ - "/folder:/path/in/container" ❌
+ # Valid
+ volumes:
+ - "../files/my-database:/var/lib/mysql" ✅
+ - "../files/my-configs:/etc/my-app/config" ✅
+ ```
- **meta.json Requirements:**
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2671d5af..967ef6f2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -20,6 +20,11 @@ This project adheres to the [Contributor Covenant Code of Conduct](https://www.c
For larger changes or questions, open an issue first to discuss your ideas.
+### Pull Request Guidelines
+
+- **Keep PRs small and focused.** Avoid very large PRs; prefer several smaller PRs (e.g., one template or one logical change per PR). This speeds up review and keeps the history clear.
+- **Test before submitting.** Any PR that has not been tested by the contributor will be closed. This keeps the PR queue tidy and ensures that only contributions that have been verified by their authors are considered.
+
## Adding a New Template
To add a new template, follow these steps:
diff --git a/blueprints/ackee/instructions.md b/blueprints/ackee/instructions.md
new file mode 100644
index 00000000..b107d360
--- /dev/null
+++ b/blueprints/ackee/instructions.md
@@ -0,0 +1,4 @@
+
+## Instructions
+
+We don't have nothing to show here....
diff --git a/blueprints/appwrite/docker-compose.yml b/blueprints/appwrite/docker-compose.yml
index 130bb5d3..cb622284 100644
--- a/blueprints/appwrite/docker-compose.yml
+++ b/blueprints/appwrite/docker-compose.yml
@@ -6,31 +6,32 @@ x-logging: &x-logging
options:
max-file: "5"
max-size: "10m"
-
services:
appwrite:
- image: appwrite/appwrite:1.6.1
- container_name: appwrite
+ image: appwrite/appwrite:1.8.0
<<: *x-logging
restart: unless-stopped
- networks:
- - dokploy-network
labels:
- traefik.enable=true
- traefik.constraint-label-stack=appwrite
volumes:
- appwrite-uploads:/storage/uploads:rw
+ - appwrite-imports:/storage/imports:rw
- appwrite-cache:/storage/cache:rw
- appwrite-config:/storage/config:rw
- appwrite-certificates:/storage/certificates:rw
- appwrite-functions:/storage/functions:rw
+ - appwrite-sites:/storage/sites:rw
+ - appwrite-builds:/storage/builds:rw
depends_on:
- mariadb
- redis
+ # - clamav
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_LOCALE
+ - _APP_COMPRESSION_MIN_SIZE_BYTES
- _APP_CONSOLE_WHITELIST_ROOT
- _APP_CONSOLE_WHITELIST_EMAILS
- _APP_CONSOLE_SESSION_ALERTS
@@ -43,10 +44,14 @@ services:
- _APP_OPTIONS_ABUSE
- _APP_OPTIONS_ROUTER_PROTECTION
- _APP_OPTIONS_FORCE_HTTPS
- - _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS
+ - _APP_OPTIONS_ROUTER_FORCE_HTTPS
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- - _APP_DOMAIN_TARGET
+ - _APP_DOMAIN_TARGET_CNAME
+ - _APP_DOMAIN_TARGET_AAAA
+ - _APP_DOMAIN_TARGET_A
+ - _APP_DOMAIN_TARGET_CAA
+ - _APP_DNS
- _APP_DOMAIN_FUNCTIONS
- _APP_REDIS_HOST
- _APP_REDIS_PORT
@@ -73,6 +78,7 @@ services:
- _APP_STORAGE_S3_SECRET
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
+ - _APP_STORAGE_S3_ENDPOINT
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
@@ -89,21 +95,26 @@ services:
- _APP_STORAGE_WASABI_SECRET
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_WASABI_BUCKET
- - _APP_FUNCTIONS_SIZE_LIMIT
+ - _APP_COMPUTE_SIZE_LIMIT
- _APP_FUNCTIONS_TIMEOUT
- - _APP_FUNCTIONS_BUILD_TIMEOUT
- - _APP_FUNCTIONS_CPUS
- - _APP_FUNCTIONS_MEMORY
+ - _APP_SITES_TIMEOUT
+ - _APP_COMPUTE_BUILD_TIMEOUT
+ - _APP_COMPUTE_CPUS
+ - _APP_COMPUTE_MEMORY
- _APP_FUNCTIONS_RUNTIMES
+ - _APP_SITES_RUNTIMES
+ - _APP_DOMAIN_SITES
- _APP_EXECUTOR_SECRET
- _APP_EXECUTOR_HOST
- _APP_LOGGING_CONFIG
- _APP_MAINTENANCE_INTERVAL
- _APP_MAINTENANCE_DELAY
+ - _APP_MAINTENANCE_START_TIME
- _APP_MAINTENANCE_RETENTION_EXECUTION
- _APP_MAINTENANCE_RETENTION_CACHE
- _APP_MAINTENANCE_RETENTION_ABUSE
- _APP_MAINTENANCE_RETENTION_AUDIT
+ - _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
- _APP_MAINTENANCE_RETENTION_SCHEDULES
- _APP_SMS_PROVIDER
@@ -120,94 +131,25 @@ services:
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
- _APP_ASSISTANT_OPENAI_API_KEY
-
appwrite-console:
- image: appwrite/console:5.0.12
- container_name: appwrite-console
<<: *x-logging
+ image: appwrite/console:7.4.7
restart: unless-stopped
- networks:
- - dokploy-network
labels:
- "traefik.enable=true"
- "traefik.constraint-label-stack=appwrite"
- environment:
- - _APP_ENV
- - _APP_WORKER_PER_CORE
- - _APP_LOCALE
- - _APP_CONSOLE_WHITELIST_ROOT
- - _APP_CONSOLE_WHITELIST_EMAILS
- - _APP_CONSOLE_SESSION_ALERTS
- - _APP_CONSOLE_WHITELIST_IPS
- - _APP_CONSOLE_HOSTNAMES
- - _APP_SYSTEM_EMAIL_NAME
- - _APP_SYSTEM_EMAIL_ADDRESS
- - _APP_EMAIL_SECURITY
- - _APP_SYSTEM_RESPONSE_FORMAT
- - _APP_OPTIONS_ABUSE
- - _APP_OPTIONS_ROUTER_PROTECTION
- - _APP_OPTIONS_FORCE_HTTPS
- - _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS
- - _APP_OPENSSL_KEY_V1
- - _APP_DOMAIN
- - _APP_DOMAIN_TARGET
- - _APP_DOMAIN_FUNCTIONS
- - _APP_REDIS_HOST
- - _APP_REDIS_PORT
- - _APP_REDIS_USER
- - _APP_REDIS_PASS
- - _APP_DB_HOST
- - _APP_DB_PORT
- - _APP_DB_SCHEMA
- - _APP_DB_USER
- - _APP_DB_PASS
- - _APP_SMTP_HOST
- - _APP_SMTP_PORT
- - _APP_SMTP_SECURE
- - _APP_SMTP_USERNAME
- - _APP_SMTP_PASSWORD
- - _APP_USAGE_STATS
- - _APP_STORAGE_LIMIT
- - _APP_STORAGE_PREVIEW_LIMIT
- - _APP_STORAGE_ANTIVIRUS
- - _APP_STORAGE_ANTIVIRUS_HOST
- - _APP_STORAGE_ANTIVIRUS_PORT
- - _APP_STORAGE_DEVICE
- - _APP_STORAGE_S3_ACCESS_KEY
- - _APP_STORAGE_S3_SECRET
- - _APP_STORAGE_S3_REGION
- - _APP_STORAGE_S3_BUCKET
- - _APP_STORAGE_DO_SPACES_ACCESS_KEY
- - _APP_STORAGE_DO_SPACES_SECRET
- - _APP_STORAGE_DO_SPACES_REGION
- - _APP_STORAGE_DO_SPACES_BUCKET
- - _APP_STORAGE_BACKBLAZE_ACCESS_KEY
- - _APP_STORAGE_BACKBLAZE_SECRET
- - _APP_STORAGE_BACKBLAZE_REGION
- - _APP_STORAGE_BACKBLAZE_BUCKET
- - _APP_STORAGE_LINODE_ACCESS_KEY
- - _APP_STORAGE_LINODE_SECRET
- - _APP_STORAGE_LINODE_REGION
- - _APP_STORAGE_LINODE_BUCKET
- - _APP_STORAGE_WASABI_ACCESS_KEY
- - _APP_STORAGE_WASABI_SECRET
- - _APP_STORAGE_WASABI_REGION
- - _APP_STORAGE_WASABI_BUCKET
appwrite-realtime:
- image: appwrite/appwrite:1.6.1
+ image: appwrite/appwrite:1.8.0
entrypoint: realtime
- container_name: appwrite-realtime
<<: *x-logging
restart: unless-stopped
- networks:
- - dokploy-network
+ labels:
+ - "traefik.enable=true"
+ - "traefik.constraint-label-stack=appwrite"
depends_on:
- mariadb
- redis
- labels:
- - "traefik.enable=true"
- - "traefik.constraint-label-stack=appwrite"
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
@@ -227,13 +169,10 @@ services:
- _APP_LOGGING_CONFIG
appwrite-worker-audits:
- image: appwrite/appwrite:1.6.1
+ image: appwrite/appwrite:1.8.0
entrypoint: worker-audits
<<: *x-logging
- container_name: appwrite-worker-audits
restart: unless-stopped
- networks:
- - dokploy-network
depends_on:
- redis
- mariadb
@@ -253,13 +192,10 @@ services:
- _APP_LOGGING_CONFIG
appwrite-worker-webhooks:
- image: appwrite/appwrite:1.6.1
+ image: appwrite/appwrite:1.8.0
entrypoint: worker-webhooks
<<: *x-logging
- container_name: appwrite-worker-webhooks
restart: unless-stopped
- networks:
- - dokploy-network
depends_on:
- redis
- mariadb
@@ -281,13 +217,10 @@ services:
- _APP_LOGGING_CONFIG
appwrite-worker-deletes:
- image: appwrite/appwrite:1.6.1
+ image: appwrite/appwrite:1.8.0
entrypoint: worker-deletes
<<: *x-logging
- container_name: appwrite-worker-deletes
restart: unless-stopped
- networks:
- - dokploy-network
depends_on:
- redis
- mariadb
@@ -295,6 +228,7 @@ services:
- appwrite-uploads:/storage/uploads:rw
- appwrite-cache:/storage/cache:rw
- appwrite-functions:/storage/functions:rw
+ - appwrite-sites:/storage/sites:rw
- appwrite-builds:/storage/builds:rw
- appwrite-certificates:/storage/certificates:rw
environment:
@@ -315,6 +249,7 @@ services:
- _APP_STORAGE_S3_SECRET
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
+ - _APP_STORAGE_S3_ENDPOINT
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
@@ -336,16 +271,16 @@ services:
- _APP_EXECUTOR_HOST
- _APP_MAINTENANCE_RETENTION_ABUSE
- _APP_MAINTENANCE_RETENTION_AUDIT
+ - _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
- _APP_MAINTENANCE_RETENTION_EXECUTION
+ - _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
+ - _APP_EMAIL_CERTIFICATES
appwrite-worker-databases:
- image: appwrite/appwrite:1.6.1
+ image: appwrite/appwrite:1.8.0
entrypoint: worker-databases
<<: *x-logging
- container_name: appwrite-worker-databases
restart: unless-stopped
- networks:
- - dokploy-network
depends_on:
- redis
- mariadb
@@ -365,19 +300,18 @@ services:
- _APP_LOGGING_CONFIG
appwrite-worker-builds:
- image: appwrite/appwrite:1.6.1
+ image: appwrite/appwrite:1.8.0
entrypoint: worker-builds
<<: *x-logging
- container_name: appwrite-worker-builds
restart: unless-stopped
- networks:
- - dokploy-network
depends_on:
- redis
- mariadb
volumes:
- appwrite-functions:/storage/functions:rw
+ - appwrite-sites:/storage/sites:rw
- appwrite-builds:/storage/builds:rw
+ - appwrite-uploads:/storage/uploads:rw
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
@@ -398,18 +332,20 @@ services:
- _APP_VCS_GITHUB_PRIVATE_KEY
- _APP_VCS_GITHUB_APP_ID
- _APP_FUNCTIONS_TIMEOUT
- - _APP_FUNCTIONS_BUILD_TIMEOUT
- - _APP_FUNCTIONS_CPUS
- - _APP_FUNCTIONS_MEMORY
- - _APP_FUNCTIONS_SIZE_LIMIT
+ - _APP_SITES_TIMEOUT
+ - _APP_COMPUTE_BUILD_TIMEOUT
+ - _APP_COMPUTE_CPUS
+ - _APP_COMPUTE_MEMORY
+ - _APP_COMPUTE_SIZE_LIMIT
- _APP_OPTIONS_FORCE_HTTPS
- - _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS
+ - _APP_OPTIONS_ROUTER_FORCE_HTTPS
- _APP_DOMAIN
- _APP_STORAGE_DEVICE
- _APP_STORAGE_S3_ACCESS_KEY
- _APP_STORAGE_S3_SECRET
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
+ - _APP_STORAGE_S3_ENDPOINT
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
@@ -426,15 +362,13 @@ services:
- _APP_STORAGE_WASABI_SECRET
- _APP_STORAGE_WASABI_REGION
- _APP_STORAGE_WASABI_BUCKET
+ - _APP_DOMAIN_SITES
appwrite-worker-certificates:
- image: appwrite/appwrite:1.6.1
+ image: appwrite/appwrite:1.8.0
entrypoint: worker-certificates
<<: *x-logging
- container_name: appwrite-worker-certificates
restart: unless-stopped
- networks:
- - dokploy-network
depends_on:
- redis
- mariadb
@@ -446,7 +380,11 @@ services:
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- - _APP_DOMAIN_TARGET
+ - _APP_DOMAIN_TARGET_CNAME
+ - _APP_DOMAIN_TARGET_AAAA
+ - _APP_DOMAIN_TARGET_A
+ - _APP_DOMAIN_TARGET_CAA
+ - _APP_DNS
- _APP_DOMAIN_FUNCTIONS
- _APP_EMAIL_CERTIFICATES
- _APP_REDIS_HOST
@@ -461,13 +399,10 @@ services:
- _APP_LOGGING_CONFIG
appwrite-worker-functions:
- image: appwrite/appwrite:1.6.1
+ image: appwrite/appwrite:1.8.0
entrypoint: worker-functions
<<: *x-logging
- container_name: appwrite-worker-functions
restart: unless-stopped
- networks:
- - dokploy-network
depends_on:
- redis
- mariadb
@@ -488,9 +423,10 @@ services:
- _APP_DB_USER
- _APP_DB_PASS
- _APP_FUNCTIONS_TIMEOUT
- - _APP_FUNCTIONS_BUILD_TIMEOUT
- - _APP_FUNCTIONS_CPUS
- - _APP_FUNCTIONS_MEMORY
+ - _APP_SITES_TIMEOUT
+ - _APP_COMPUTE_BUILD_TIMEOUT
+ - _APP_COMPUTE_CPUS
+ - _APP_COMPUTE_MEMORY
- _APP_EXECUTOR_SECRET
- _APP_EXECUTOR_HOST
- _APP_USAGE_STATS
@@ -499,13 +435,10 @@ services:
- _APP_LOGGING_CONFIG
appwrite-worker-mails:
- image: appwrite/appwrite:1.6.1
+ image: appwrite/appwrite:1.8.0
entrypoint: worker-mails
<<: *x-logging
- container_name: appwrite-worker-mails
restart: unless-stopped
- networks:
- - dokploy-network
depends_on:
- redis
environment:
@@ -529,15 +462,14 @@ services:
- _APP_SMTP_USERNAME
- _APP_SMTP_PASSWORD
- _APP_LOGGING_CONFIG
+ - _APP_DOMAIN
+ - _APP_OPTIONS_FORCE_HTTPS
appwrite-worker-messaging:
- image: appwrite/appwrite:1.6.1
+ image: appwrite/appwrite:1.8.0
entrypoint: worker-messaging
- container_name: appwrite-worker-messaging
<<: *x-logging
restart: unless-stopped
- networks:
- - dokploy-network
volumes:
- appwrite-uploads:/storage/uploads:rw
depends_on:
@@ -563,6 +495,7 @@ services:
- _APP_STORAGE_S3_SECRET
- _APP_STORAGE_S3_REGION
- _APP_STORAGE_S3_BUCKET
+ - _APP_STORAGE_S3_ENDPOINT
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
- _APP_STORAGE_DO_SPACES_SECRET
- _APP_STORAGE_DO_SPACES_REGION
@@ -581,13 +514,12 @@ services:
- _APP_STORAGE_WASABI_BUCKET
appwrite-worker-migrations:
- image: appwrite/appwrite:1.6.1
+ image: appwrite/appwrite:1.8.0
entrypoint: worker-migrations
<<: *x-logging
- container_name: appwrite-worker-migrations
restart: unless-stopped
- networks:
- - dokploy-network
+ volumes:
+ - appwrite-imports:/storage/imports:rw
depends_on:
- mariadb
environment:
@@ -595,7 +527,11 @@ services:
- _APP_WORKER_PER_CORE
- _APP_OPENSSL_KEY_V1
- _APP_DOMAIN
- - _APP_DOMAIN_TARGET
+ - _APP_DOMAIN_TARGET_CNAME
+ - _APP_DOMAIN_TARGET_AAAA
+ - _APP_DOMAIN_TARGET_A
+ - _APP_DOMAIN_TARGET_CAA
+ - _APP_DNS
- _APP_EMAIL_SECURITY
- _APP_REDIS_HOST
- _APP_REDIS_PORT
@@ -611,20 +547,21 @@ services:
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
appwrite-task-maintenance:
- image: appwrite/appwrite:1.6.1
+ image: appwrite/appwrite:1.8.0
entrypoint: maintenance
<<: *x-logging
- container_name: appwrite-task-maintenance
restart: unless-stopped
- networks:
- - dokploy-network
depends_on:
- redis
environment:
- _APP_ENV
- _APP_WORKER_PER_CORE
- _APP_DOMAIN
- - _APP_DOMAIN_TARGET
+ - _APP_DOMAIN_TARGET_CNAME
+ - _APP_DOMAIN_TARGET_AAAA
+ - _APP_DOMAIN_TARGET_A
+ - _APP_DOMAIN_TARGET_CAA
+ - _APP_DNS
- _APP_DOMAIN_FUNCTIONS
- _APP_OPENSSL_KEY_V1
- _APP_REDIS_HOST
@@ -641,17 +578,15 @@ services:
- _APP_MAINTENANCE_RETENTION_CACHE
- _APP_MAINTENANCE_RETENTION_ABUSE
- _APP_MAINTENANCE_RETENTION_AUDIT
+ - _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
- _APP_MAINTENANCE_RETENTION_SCHEDULES
- appwrite-worker-usage:
- image: appwrite/appwrite:1.6.1
- entrypoint: worker-usage
- container_name: appwrite-worker-usage
+ appwrite-task-stats-resources:
+ image: appwrite/appwrite:1.8.0
+ entrypoint: stats-resources
<<: *x-logging
restart: unless-stopped
- networks:
- - dokploy-network
depends_on:
- redis
- mariadb
@@ -670,15 +605,39 @@ services:
- _APP_REDIS_PASS
- _APP_USAGE_STATS
- _APP_LOGGING_CONFIG
- - _APP_USAGE_AGGREGATION_INTERVAL
+ - _APP_DATABASE_SHARED_TABLES
+ - _APP_STATS_RESOURCES_INTERVAL
- appwrite-worker-usage-dump:
- image: appwrite/appwrite:1.6.1
- entrypoint: worker-usage-dump
- container_name: appwrite-worker-usage-dump
+ appwrite-worker-stats-resources:
+ image: appwrite/appwrite:1.8.0
+ entrypoint: worker-stats-resources
<<: *x-logging
- networks:
- - dokploy-network
+ restart: unless-stopped
+ depends_on:
+ - redis
+ - mariadb
+ environment:
+ - _APP_ENV
+ - _APP_WORKER_PER_CORE
+ - _APP_OPENSSL_KEY_V1
+ - _APP_DB_HOST
+ - _APP_DB_PORT
+ - _APP_DB_SCHEMA
+ - _APP_DB_USER
+ - _APP_DB_PASS
+ - _APP_REDIS_HOST
+ - _APP_REDIS_PORT
+ - _APP_REDIS_USER
+ - _APP_REDIS_PASS
+ - _APP_USAGE_STATS
+ - _APP_LOGGING_CONFIG
+ - _APP_STATS_RESOURCES_INTERVAL
+
+ appwrite-worker-stats-usage:
+ image: appwrite/appwrite:1.8.0
+ entrypoint: worker-stats-usage
+ <<: *x-logging
+ restart: unless-stopped
depends_on:
- redis
- mariadb
@@ -700,13 +659,10 @@ services:
- _APP_USAGE_AGGREGATION_INTERVAL
appwrite-task-scheduler-functions:
- image: appwrite/appwrite:1.6.1
+ image: appwrite/appwrite:1.8.0
entrypoint: schedule-functions
- container_name: appwrite-task-scheduler-functions
<<: *x-logging
restart: unless-stopped
- networks:
- - dokploy-network
depends_on:
- mariadb
- redis
@@ -725,13 +681,10 @@ services:
- _APP_DB_PASS
appwrite-task-scheduler-executions:
- image: appwrite/appwrite:1.6.1
+ image: appwrite/appwrite:1.8.0
entrypoint: schedule-executions
- container_name: appwrite-task-scheduler-executions
<<: *x-logging
restart: unless-stopped
- networks:
- - dokploy-network
depends_on:
- mariadb
- redis
@@ -750,13 +703,10 @@ services:
- _APP_DB_PASS
appwrite-task-scheduler-messages:
- image: appwrite/appwrite:1.6.1
+ image: appwrite/appwrite:1.8.0
entrypoint: schedule-messages
- container_name: appwrite-task-scheduler-messages
<<: *x-logging
restart: unless-stopped
- networks:
- - dokploy-network
depends_on:
- mariadb
- redis
@@ -775,44 +725,48 @@ services:
- _APP_DB_PASS
appwrite-assistant:
- image: appwrite/assistant:0.4.0
- container_name: appwrite-assistant
+ image: appwrite/assistant:0.8.3
<<: *x-logging
restart: unless-stopped
- networks:
- - dokploy-network
environment:
- _APP_ASSISTANT_OPENAI_API_KEY
+ appwrite-browser:
+ image: appwrite/browser:0.2.4
+ <<: *x-logging
+ restart: unless-stopped
+
openruntimes-executor:
- container_name: openruntimes-executor
hostname: exc1
<<: *x-logging
restart: unless-stopped
stop_signal: SIGINT
- image: openruntimes/executor:0.6.11
- networks:
- - dokploy-network
+ image: openruntimes/executor:0.7.22
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- appwrite-builds:/storage/builds:rw
- appwrite-functions:/storage/functions:rw
+ - appwrite-sites:/storage/sites:rw
+ # Host mount necessary to share files between executor and runtimes.
+ # It's not possible to share mount file between 2 containers without host mount (copying is too slow)
- /tmp:/tmp:rw
environment:
- - OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_FUNCTIONS_INACTIVE_THRESHOLD
- - OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_FUNCTIONS_MAINTENANCE_INTERVAL
- - OPR_EXECUTOR_NETWORK=$_APP_FUNCTIONS_RUNTIMES_NETWORK
+ - OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_COMPUTE_INACTIVE_THRESHOLD
+ - OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_COMPUTE_MAINTENANCE_INTERVAL
+ - OPR_EXECUTOR_NETWORK=$_APP_COMPUTE_RUNTIMES_NETWORK
- OPR_EXECUTOR_DOCKER_HUB_USERNAME=$_APP_DOCKER_HUB_USERNAME
- OPR_EXECUTOR_DOCKER_HUB_PASSWORD=$_APP_DOCKER_HUB_PASSWORD
- OPR_EXECUTOR_ENV=$_APP_ENV
- - OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES
+ - OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES,$_APP_SITES_RUNTIMES
- OPR_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET
+ - OPR_EXECUTOR_RUNTIME_VERSIONS=v5
- OPR_EXECUTOR_LOGGING_CONFIG=$_APP_LOGGING_CONFIG
- OPR_EXECUTOR_STORAGE_DEVICE=$_APP_STORAGE_DEVICE
- OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=$_APP_STORAGE_S3_ACCESS_KEY
- OPR_EXECUTOR_STORAGE_S3_SECRET=$_APP_STORAGE_S3_SECRET
- OPR_EXECUTOR_STORAGE_S3_REGION=$_APP_STORAGE_S3_REGION
- OPR_EXECUTOR_STORAGE_S3_BUCKET=$_APP_STORAGE_S3_BUCKET
+ - OPR_EXECUTOR_STORAGE_S3_ENDPOINT=$_APP_STORAGE_S3_ENDPOINT
- OPR_EXECUTOR_STORAGE_DO_SPACES_ACCESS_KEY=$_APP_STORAGE_DO_SPACES_ACCESS_KEY
- OPR_EXECUTOR_STORAGE_DO_SPACES_SECRET=$_APP_STORAGE_DO_SPACES_SECRET
- OPR_EXECUTOR_STORAGE_DO_SPACES_REGION=$_APP_STORAGE_DO_SPACES_REGION
@@ -831,12 +785,9 @@ services:
- OPR_EXECUTOR_STORAGE_WASABI_BUCKET=$_APP_STORAGE_WASABI_BUCKET
mariadb:
- image: mariadb:10.11
- container_name: appwrite-mariadb
+ image: mariadb:10.11 # fix issues when upgrading using: mysql_upgrade -u root -p
<<: *x-logging
restart: unless-stopped
- networks:
- - dokploy-network
volumes:
- appwrite-mariadb:/var/lib/mysql:rw
environment:
@@ -849,39 +800,30 @@ services:
redis:
image: redis:7.2.4-alpine
- container_name: appwrite-redis
<<: *x-logging
restart: unless-stopped
command: >
redis-server
- --maxmemory 512mb
- --maxmemory-policy allkeys-lru
- --maxmemory-samples 5
- networks:
- - dokploy-network
+ --maxmemory 512mb
+ --maxmemory-policy allkeys-lru
+ --maxmemory-samples 5
volumes:
- appwrite-redis:/data:rw
-# Uncomment and configure if ClamAV is needed
-# clamav:
-# image: appwrite/clamav:1.2.0
-# container_name: appwrite-clamav
-# restart: unless-stopped
-# networks:
-# - dokploy-network
-# volumes:
-# - appwrite-uploads:/storage/uploads
+ # clamav:
+ # image: appwrite/clamav:1.2.0
+ # restart: unless-stopped
+ # volumes:
+ # - appwrite-uploads:/storage/uploads
volumes:
appwrite-mariadb:
appwrite-redis:
appwrite-cache:
appwrite-uploads:
+ appwrite-imports:
appwrite-certificates:
appwrite-functions:
+ appwrite-sites:
appwrite-builds:
appwrite-config:
-
-networks:
- dokploy-network:
- external: true
diff --git a/blueprints/appwrite/template.toml b/blueprints/appwrite/template.toml
index 3188ea17..cca2d43d 100644
--- a/blueprints/appwrite/template.toml
+++ b/blueprints/appwrite/template.toml
@@ -1,5 +1,11 @@
[variables]
main_domain = "${domain}"
+functions_domain = "functions.${main_domain}"
+sites_domain = "sites.${main_domain}"
+openssl_key = "${password:32}"
+db_root_pw = "${password:32}"
+db_user_pw = "${password:32}"
+executor_secret = "${password:32}"
[config]
env = [
@@ -8,11 +14,19 @@ env = [
"_APP_OPTIONS_ABUSE=enabled",
"_APP_OPTIONS_FORCE_HTTPS=disabled",
"_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=disabled",
+ "_APP_OPTIONS_ROUTER_FORCE_HTTPS=disabled",
"_APP_OPTIONS_ROUTER_PROTECTION=disabled",
- "_APP_OPENSSL_KEY_V1=your-secret-key",
+ "_APP_OPENSSL_KEY_V1=${openssl_key}",
"_APP_DOMAIN=${main_domain}",
- "_APP_DOMAIN_FUNCTIONS=${main_domain}",
- "_APP_DOMAIN_TARGET=${main_domain}",
+ "_APP_CUSTOM_DOMAIN_DENY_LIST=example.com,test.com,app.example.com",
+ "_APP_DOMAIN_FUNCTIONS=${functions_domain}",
+ "_APP_DOMAIN_SITES=${sites_domain}",
+ "_APP_DOMAIN_TARGET=localhost",
+ "_APP_DOMAIN_TARGET_CNAME=localhost",
+ "_APP_DOMAIN_TARGET_AAAA=::1",
+ "_APP_DOMAIN_TARGET_A=127.0.0.1",
+ "_APP_DOMAIN_TARGET_CAA=",
+ "_APP_DNS=8.8.8.8",
"_APP_CONSOLE_WHITELIST_ROOT=enabled",
"_APP_CONSOLE_WHITELIST_EMAILS=",
"_APP_CONSOLE_WHITELIST_IPS=",
@@ -32,6 +46,8 @@ env = [
"_APP_USAGE_DATABASE_INTERVAL=900",
"_APP_WORKER_PER_CORE=6",
"_APP_CONSOLE_SESSION_ALERTS=disabled",
+ "_APP_COMPRESSION_ENABLED=enabled",
+ "_APP_COMPRESSION_MIN_SIZE_BYTES=1024",
"_APP_REDIS_HOST=redis",
"_APP_REDIS_PORT=6379",
"_APP_REDIS_USER=",
@@ -40,8 +56,8 @@ env = [
"_APP_DB_PORT=3306",
"_APP_DB_SCHEMA=appwrite",
"_APP_DB_USER=user",
- "_APP_DB_PASS=password",
- "_APP_DB_ROOT_PASS=rootsecretpassword",
+ "_APP_DB_PASS=${db_user_pw}",
+ "_APP_DB_ROOT_PASS=${db_root_pw}",
"_APP_INFLUXDB_HOST=influxdb",
"_APP_INFLUXDB_PORT=8086",
"_APP_STATSD_HOST=telegraf",
@@ -63,6 +79,7 @@ env = [
"_APP_STORAGE_S3_SECRET=",
"_APP_STORAGE_S3_REGION=us-east-1",
"_APP_STORAGE_S3_BUCKET=",
+ "_APP_STORAGE_S3_ENDPOINT=",
"_APP_STORAGE_DO_SPACES_ACCESS_KEY=",
"_APP_STORAGE_DO_SPACES_SECRET=",
"_APP_STORAGE_DO_SPACES_REGION=us-east-1",
@@ -80,27 +97,36 @@ env = [
"_APP_STORAGE_WASABI_REGION=eu-central-1",
"_APP_STORAGE_WASABI_BUCKET=",
"_APP_FUNCTIONS_SIZE_LIMIT=30000000",
+ "_APP_COMPUTE_SIZE_LIMIT=30000000",
"_APP_FUNCTIONS_BUILD_SIZE_LIMIT=2000000000",
"_APP_FUNCTIONS_TIMEOUT=900",
"_APP_FUNCTIONS_BUILD_TIMEOUT=900",
+ "_APP_COMPUTE_BUILD_TIMEOUT=900",
"_APP_FUNCTIONS_CONTAINERS=10",
"_APP_FUNCTIONS_CPUS=0",
+ "_APP_COMPUTE_CPUS=0",
"_APP_FUNCTIONS_MEMORY=0",
+ "_APP_COMPUTE_MEMORY=0",
"_APP_FUNCTIONS_MEMORY_SWAP=0",
"_APP_FUNCTIONS_RUNTIMES=node-16.0,php-8.0,python-3.9,ruby-3.0",
- "_APP_EXECUTOR_SECRET=your-secret-key",
+ "_APP_EXECUTOR_SECRET=${executor_secret}",
"_APP_EXECUTOR_HOST=http://exc1/v1",
"_APP_EXECUTOR_RUNTIME_NETWORK=appwrite_runtimes",
"_APP_FUNCTIONS_ENVS=node-16.0,php-7.4,python-3.9,ruby-3.0",
"_APP_FUNCTIONS_INACTIVE_THRESHOLD=60",
+ "_APP_COMPUTE_INACTIVE_THRESHOLD=60",
"DOCKERHUB_PULL_USERNAME=",
"DOCKERHUB_PULL_PASSWORD=",
"DOCKERHUB_PULL_EMAIL=",
"OPEN_RUNTIMES_NETWORK=appwrite_runtimes",
- "_APP_FUNCTIONS_RUNTIMES_NETWORK=runtimes",
+ "_APP_FUNCTIONS_RUNTIMES_NETWORK=dokploy-network",
+ "_APP_COMPUTE_RUNTIMES_NETWORK=dokploy-network",
"_APP_DOCKER_HUB_USERNAME=",
"_APP_DOCKER_HUB_PASSWORD=",
"_APP_FUNCTIONS_MAINTENANCE_INTERVAL=3600",
+ "_APP_COMPUTE_MAINTENANCE_INTERVAL=3600",
+ "_APP_SITES_TIMEOUT=900",
+ "_APP_SITES_RUNTIMES=static-1,node-22,flutter-3.29",
"_APP_VCS_GITHUB_APP_NAME=",
"_APP_VCS_GITHUB_PRIVATE_KEY=",
"_APP_VCS_GITHUB_APP_ID=",
@@ -109,9 +135,11 @@ env = [
"_APP_VCS_GITHUB_WEBHOOK_SECRET=",
"_APP_MAINTENANCE_INTERVAL=86400",
"_APP_MAINTENANCE_DELAY=0",
+ "_APP_MAINTENANCE_START_TIME=00:00",
"_APP_MAINTENANCE_RETENTION_CACHE=2592000",
"_APP_MAINTENANCE_RETENTION_EXECUTION=1209600",
"_APP_MAINTENANCE_RETENTION_AUDIT=1209600",
+ "_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=15778800",
"_APP_MAINTENANCE_RETENTION_ABUSE=86400",
"_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000",
"_APP_MAINTENANCE_RETENTION_SCHEDULES=86400",
@@ -130,6 +158,18 @@ port = 80
host = "${main_domain}"
path = "/"
+[[config.domains]]
+serviceName = "appwrite"
+port = 80
+host = "${sites_domain}"
+path = "/"
+
+[[config.domains]]
+serviceName = "appwrite"
+port = 80
+host = "${functions_domain}"
+path = "/"
+
[[config.domains]]
serviceName = "appwrite-console"
port = 80
diff --git a/blueprints/autobase/docker-compose.yml b/blueprints/autobase/docker-compose.yml
index 07b99485..13b23d57 100644
--- a/blueprints/autobase/docker-compose.yml
+++ b/blueprints/autobase/docker-compose.yml
@@ -1,6 +1,6 @@
services:
autobase-console:
- image: autobase/console:2.3.0
+ image: autobase/console:2.5.2
restart: unless-stopped
ports:
- "80"
diff --git a/blueprints/cloudflare-ddns/cloudflare-ddns.svg b/blueprints/cloudflare-ddns/cloudflare-ddns.svg
new file mode 100644
index 00000000..efe800bc
--- /dev/null
+++ b/blueprints/cloudflare-ddns/cloudflare-ddns.svg
@@ -0,0 +1,8 @@
+
diff --git a/blueprints/cloudflare-ddns/docker-compose.yml b/blueprints/cloudflare-ddns/docker-compose.yml
new file mode 100644
index 00000000..179139d8
--- /dev/null
+++ b/blueprints/cloudflare-ddns/docker-compose.yml
@@ -0,0 +1,16 @@
+# For more details, see:
+# - https://github.com/favonia/cloudflare-ddns
+services:
+ cloudflare-ddns:
+ image: favonia/cloudflare-ddns:1
+ network_mode: host
+ restart: unless-stopped
+ user: "1000:1000"
+ read_only: true
+ cap_drop: [all]
+ security_opt: [no-new-privileges:true]
+ environment:
+ - CLOUDFLARE_API_TOKEN=${CLOUDFLARE_API_TOKEN:?}
+ - DOMAINS=${DOMAINS:?}
+ - PROXIED=false
+ - IP6_PROVIDER=none
diff --git a/blueprints/cloudflare-ddns/template.toml b/blueprints/cloudflare-ddns/template.toml
new file mode 100644
index 00000000..f40da5ad
--- /dev/null
+++ b/blueprints/cloudflare-ddns/template.toml
@@ -0,0 +1,9 @@
+variables = {}
+
+[config]
+domains = []
+mounts = []
+
+[config.env]
+CLOUDFLARE_API_TOKEN = ""
+DOMAINS = "example.org,www.example.org,example.io"
diff --git a/blueprints/cloudflared/docker-compose.yml b/blueprints/cloudflared/docker-compose.yml
index d9fc2741..b6bf5458 100644
--- a/blueprints/cloudflared/docker-compose.yml
+++ b/blueprints/cloudflared/docker-compose.yml
@@ -3,14 +3,14 @@ services:
image: 'cloudflare/cloudflared:latest'
environment:
# Don't forget to set this in your Dokploy Environment
- - 'TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}'
+ - 'TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN:?}'
network_mode: host
restart: unless-stopped
command: [
"tunnel",
# More tunnel run parameters here:
- # https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/configure-tunnels/tunnel-run-parameters/
+ # https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/configure-tunnels/cloudflared-parameters/run-parameters/
"--no-autoupdate",
#"--protocol", "http2",
diff --git a/blueprints/cloudflared/template.toml b/blueprints/cloudflared/template.toml
index 242197bd..7d2557cc 100644
--- a/blueprints/cloudflared/template.toml
+++ b/blueprints/cloudflared/template.toml
@@ -2,5 +2,7 @@ variables = {}
[config]
domains = []
-env = ["CLOUDFLARE_TUNNEL_TOKEN=\"\""]
mounts = []
+
+[config.env]
+CLOUDFLARE_TUNNEL_TOKEN = ""
diff --git a/blueprints/cloudreve/cloudreve.png b/blueprints/cloudreve/cloudreve.png
new file mode 100644
index 00000000..28020b06
Binary files /dev/null and b/blueprints/cloudreve/cloudreve.png differ
diff --git a/blueprints/cloudreve/docker-compose.yml b/blueprints/cloudreve/docker-compose.yml
new file mode 100644
index 00000000..f90f3685
--- /dev/null
+++ b/blueprints/cloudreve/docker-compose.yml
@@ -0,0 +1,48 @@
+version: "3.8"
+
+services:
+ cloudreve:
+ image: cloudreve/cloudreve:4.10.1
+ depends_on:
+ postgresql:
+ condition: service_healthy
+ redis:
+ condition: service_started
+ restart: unless-stopped
+ environment:
+ - CR_CONF_Database.Type=postgres
+ - CR_CONF_Database.Host=postgresql
+ - CR_CONF_Database.User=${POSTGRES_USER}
+ - CR_CONF_Database.Password=${POSTGRES_PASSWORD}
+ - CR_CONF_Database.Name=${POSTGRES_DB}
+ - CR_CONF_Database.Port=5432
+ - CR_CONF_Redis.Server=redis:6379
+ volumes:
+ - cloudreve_data:/cloudreve/data
+
+ postgresql:
+ image: postgres:17
+ restart: unless-stopped
+ environment:
+ - POSTGRES_USER
+ - POSTGRES_PASSWORD
+ - POSTGRES_DB
+ volumes:
+ - postgres_data:/var/lib/postgresql/data
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+ start_period: 30s
+
+ redis:
+ image: redis:8.4.0
+ restart: unless-stopped
+ volumes:
+ - redis_data:/data
+
+volumes:
+ cloudreve_data:
+ postgres_data:
+ redis_data:
diff --git a/blueprints/cloudreve/template.toml b/blueprints/cloudreve/template.toml
new file mode 100644
index 00000000..a5acf6b4
--- /dev/null
+++ b/blueprints/cloudreve/template.toml
@@ -0,0 +1,16 @@
+[variables]
+main_domain = "${domain}"
+db_password = "${password:32}"
+db_user = "cloudreve"
+db_name = "cloudreve"
+
+[config]
+[[config.domains]]
+serviceName = "cloudreve"
+port = 5212
+host = "${main_domain}"
+
+[config.env]
+POSTGRES_PASSWORD = "${db_password}"
+POSTGRES_USER = "${db_user}"
+POSTGRES_DB = "${db_name}"
diff --git a/blueprints/emqx/docker-compose.yml b/blueprints/emqx/docker-compose.yml
new file mode 100644
index 00000000..4b11f010
--- /dev/null
+++ b/blueprints/emqx/docker-compose.yml
@@ -0,0 +1,58 @@
+# This templates requires additional traefik port mapping and entry point
+# for port 8883 (mqtts over TCP)
+#
+# For the full instructions, refer to:
+# - https://github.com/Dokploy/dokploy/discussions/3126
+#
+# The initial login credentials are:
+# - USERNAME: admin
+# - PASSWORD: public
+
+services:
+ emqx:
+ image: emqx/emqx-enterprise:6.0.1
+ hostname: node1.emqx.com
+ environment:
+ EMQX_NODE_NAME: emqx@node1.emqx.com
+ expose:
+ - 1883 # MQTT
+ - 8083 # WS
+ - 18083 # Dashboard
+ volumes:
+ - emqx_data:/opt/emqx/data
+ - emqx_log:/opt/emqx/log
+ networks:
+ dokploy-network:
+ aliases:
+ - emqx-service
+ restart: unless-stopped
+ healthcheck:
+ test: ["CMD", "/opt/emqx/bin/emqx_ctl", "status"]
+ interval: 30s
+ timeout: 5s
+ retries: 3
+ labels:
+ # MQTT over TLS
+ - "traefik.tcp.routers.emqx-mqtts.entrypoints=mqtts"
+ - "traefik.tcp.routers.emqx-mqtts.rule=HostSNI(`broker.yourdomain.com`)" # Change domain
+ - "traefik.tcp.routers.emqx-mqtts.tls.certresolver=letsencrypt"
+ - "traefik.tcp.routers.emqx-mqtts.service=emqx-service"
+ - "traefik.tcp.services.emqx-service.loadbalancer.server.port=1883"
+
+ #
+ # Optional Web UI:
+ # - https://github.com/emqx/MQTTX/tree/main/web
+ #
+ # mqttx-web:
+ # image: emqx/mqttx-web:latest
+ # expose:
+ # - 80
+ #
+
+volumes:
+ emqx_data:
+ emqx_log:
+
+networks:
+ dokploy-network:
+ external: true
diff --git a/blueprints/emqx/emqx.svg b/blueprints/emqx/emqx.svg
new file mode 100644
index 00000000..ce0c1ec9
--- /dev/null
+++ b/blueprints/emqx/emqx.svg
@@ -0,0 +1,6 @@
+
diff --git a/blueprints/emqx/template.toml b/blueprints/emqx/template.toml
new file mode 100644
index 00000000..5fc03e5f
--- /dev/null
+++ b/blueprints/emqx/template.toml
@@ -0,0 +1,11 @@
+[variables]
+
+[[config.domains]]
+serviceName = "emqx"
+port = 18083
+host = "emqx.yourdomain.com"
+
+[[config.domains]]
+serviceName = "emqx"
+port = 8083
+host = "broker.yourdomain.com"
diff --git a/blueprints/habitica/docker-compose.yml b/blueprints/habitica/docker-compose.yml
index af226516..3990e571 100644
--- a/blueprints/habitica/docker-compose.yml
+++ b/blueprints/habitica/docker-compose.yml
@@ -1,13 +1,18 @@
-version: "3.8"
-
services:
server:
image: docker.io/awinterstein/habitica-server:latest
restart: unless-stopped
depends_on:
- - mongo
+ mongo:
+ condition: service_healthy
environment:
- - NODE_DB_URI=mongodb://mongo/habitica
+ NODE_DB_URI: "mongodb://${MONGO_HABITICA_USER}:${MONGO_HABITICA_PASSWORD}@mongo/habitica?authSource=habitica"
+ INVITE_ONLY: "${INVITE_ONLY}"
+ EMAIL_SERVER_URL: "${EMAIL_SERVER_URL}"
+ EMAIL_SERVER_PORT: "${EMAIL_SERVER_PORT}"
+ EMAIL_SERVER_AUTH_USER: "${EMAIL_SERVER_AUTH_USER}"
+ EMAIL_SERVER_AUTH_PASSWORD: "${EMAIL_SERVER_AUTH_PASSWORD}"
+ ADMIN_EMAIL: "${ADMIN_EMAIL}"
client:
image: docker.io/awinterstein/habitica-client:latest
@@ -20,12 +25,64 @@ services:
mongo:
image: docker.io/mongo:latest
restart: unless-stopped
- command: ["--replSet", "rs", "--bind_ip_all", "--port", "27017"]
+ command: >
+ bash -c "
+ echo \"${MONGO_KEYFILE_CONTENT}\" > /etc/mongo-keyfile &&
+ chown 999:999 /etc/mongo-keyfile &&
+ chmod 400 /etc/mongo-keyfile &&
+ exec docker-entrypoint.sh mongod --replSet rs --bind_ip_all --port 27017 --keyFile /etc/mongo-keyfile
+ "
+ environment:
+ MONGO_INITDB_ROOT_USERNAME: ${MONGO_ADMIN_USER}
+ MONGO_INITDB_ROOT_PASSWORD: ${MONGO_ADMIN_PASSWORD}
+ MONGO_KEYFILE_CONTENT: ${MONGO_KEYFILE_CONTENT}
+ MONGO_HABITICA_USER: ${MONGO_HABITICA_USER}
+ MONGO_HABITICA_PASSWORD: ${MONGO_HABITICA_PASSWORD}
+ # ---------------------------------------------------------
+ # SMART HEALTHCHECK: Auto-fixes Hostname Mismatches for replicaSet
+ # ---------------------------------------------------------
healthcheck:
- test: echo "try { rs.status() } catch (err) { rs.initiate() }" | mongosh --port 27017 --quiet
- interval: 10s
- timeout: 30s
- retries: 30
+ test: |
+ mongosh --port 27017 --quiet -u "${MONGO_ADMIN_USER}" -p "${MONGO_ADMIN_PASSWORD}" --authenticationDatabase admin --eval "
+ try {
+ // 1. Hostname Fix
+ const config = rs.conf();
+ const currentHost = require('os').hostname() + ':27017';
+ if (config.members[0].host !== currentHost) {
+ config.members[0].host = currentHost;
+ rs.reconfig(config, { force: true });
+ }
+
+ // 2. User Creation Logic
+ const targetDb = db.getSiblingDB('habitica');
+ const hUser = process.env.MONGO_HABITICA_USER;
+ const hPass = process.env.MONGO_HABITICA_PASSWORD;
+
+ // We can only check/create users if we are Primary
+ if (rs.isMaster().ismaster) {
+ if (!targetDb.getUser(hUser)) {
+ print('Creating missing user ' + hUser + '...');
+ targetDb.createUser({ user: hUser, pwd: hPass, roles: ['readWrite'] });
+ }
+ // SUCCESS: User exists and we are Primary
+ quit(0);
+ } else {
+ // We are not Primary yet (still electing), so we cannot confirm user exists.
+ // Fail the check so the dependent app waits.
+ print('Waiting for Primary state...');
+ quit(1);
+ }
+ } catch (err) {
+ // If not initialized, initiate and FAIL this check so we wait for the next cycle
+ try {
+ rs.initiate({ _id: 'rs', members: [{ _id: 0, host: require('os').hostname() + ':27017' }] });
+ } catch (e) {}
+ quit(1);
+ }
+ "
+ interval: 5s
+ timeout: 10s
+ retries: 20
volumes:
- habitica-mongo-data:/data/db
diff --git a/blueprints/habitica/template.toml b/blueprints/habitica/template.toml
index 3888ae24..a8cb5fc6 100644
--- a/blueprints/habitica/template.toml
+++ b/blueprints/habitica/template.toml
@@ -1,6 +1,9 @@
[variables]
main_domain = "${domain}"
mail_password = "${password:32}"
+mongo_key = "${base64:756}"
+mongo_admin_password = "${password}"
+mongo_habitica_password = "${password}"
[config]
[[config.domains]]
@@ -9,16 +12,21 @@ port = 80
host = "habitica.${main_domain}"
[config.env]
-
-BASE_URL="https://habitica.${main_domain}"
-INVITE_ONLY="false"
-EMAIL_SERVER_URL="mail.example.com"
-EMAIL_SERVER_PORT="587"
-EMAIL_SERVER_AUTH_USER="mail_user"
-EMAIL_SERVER_AUTH_PASSWORD="${mail_password}"
+BASE_URL = "https://habitica.${main_domain}"
+INVITE_ONLY = "false"
+EMAIL_SERVER_URL = "mail.example.com"
+EMAIL_SERVER_PORT = "587"
+EMAIL_SERVER_AUTH_USER = "mail_user"
+EMAIL_SERVER_AUTH_PASSWORD = "${mail_password}"
+MONGO_KEYFILE_CONTENT = "${mongo_key}"
+MONGO_ADMIN_USER = "admin"
+MONGO_ADMIN_PASSWORD = "${mongo_admin_password}"
+MONGO_HABITICA_USER = "habitica"
+MONGO_HABITICA_PASSWORD = "${mongo_habitica_password}"
+ADMIN_EMAIL = "no-reply@${main_domain}"
[[config.mounts]]
serviceName = "mongo"
type = "volume"
source = "habitica-mongo-data"
-target = "/data/db"
\ No newline at end of file
+target = "/data/db"
diff --git a/blueprints/instantdb/docker-compose.yml b/blueprints/instantdb/docker-compose.yml
new file mode 100644
index 00000000..b40e043d
--- /dev/null
+++ b/blueprints/instantdb/docker-compose.yml
@@ -0,0 +1,64 @@
+services:
+ postgres:
+ image: ghcr.io/instantdb/postgresql:postgresql-16-pg-hint-plan
+ restart: unless-stopped
+ environment:
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
+ POSTGRES_USER: ${POSTGRES_USER}
+ POSTGRES_DB: ${POSTGRES_DB}
+ volumes:
+ - backend-db:/var/lib/postgresql/data
+ healthcheck:
+ test: ["CMD", "pg_isready", "-U", "${POSTGRES_USER}"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+ command:
+ - "postgres"
+ - "-c"
+ - "wal_level=logical"
+ - "-c"
+ - "max_replication_slots=4"
+ - "-c"
+ - "max_wal_senders=4"
+ - "-c"
+ - "shared_preload_libraries=pg_hint_plan"
+ - "-c"
+ - "random_page_cost=1.1"
+ server:
+ depends_on:
+ postgres:
+ condition: service_healthy
+ image: hari1367709/instantdb-server:latest
+ restart: unless-stopped
+ working_dir: /app
+ environment:
+ DATABASE_URL: "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}"
+ NREPL_BIND_ADDRESS: "0.0.0.0"
+ PORT: "8888"
+ HOST: "0.0.0.0"
+ # AWS Credentials for KMS (required for InstantDB)
+ AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
+ AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
+ AWS_REGION: ${AWS_REGION:-us-east-1}
+ # Force unbuffered output for logs
+ PYTHONUNBUFFERED: "1"
+ NODE_ENV: "production"
+ command: ["java", "-Djava.awt.headless=true", "-server", "-jar", "target/instant-standalone.jar"]
+ ports:
+ - "8888"
+ - "6005"
+ logging:
+ driver: "json-file"
+ options:
+ max-size: "10m"
+ max-file: "3"
+ healthcheck:
+ test: ["CMD-SHELL", "curl -f http://localhost:8888/health || exit 1"]
+ interval: 30s
+ timeout: 10s
+ retries: 3
+ start_period: 40s
+volumes:
+ backend-db:
+
diff --git a/blueprints/instantdb/instant.svg b/blueprints/instantdb/instant.svg
new file mode 100644
index 00000000..4e2dc24c
--- /dev/null
+++ b/blueprints/instantdb/instant.svg
@@ -0,0 +1,4 @@
+
diff --git a/blueprints/instantdb/template.toml b/blueprints/instantdb/template.toml
new file mode 100644
index 00000000..571e6b7a
--- /dev/null
+++ b/blueprints/instantdb/template.toml
@@ -0,0 +1,29 @@
+[variables]
+main_domain = "${domain}"
+postgres_password = "${password:32}"
+postgres_user = "instant"
+postgres_db = "instant"
+aws_access_key_id = "FILL-YOUR-CREDENTIALS"
+aws_secret_access_key = "FILL-YOUR-CREDENTIALS"
+aws_region = "us-east-1"
+
+[config]
+env = [
+ "POSTGRES_PASSWORD=${postgres_password}",
+ "POSTGRES_USER=${postgres_user}",
+ "POSTGRES_DB=${postgres_db}",
+ "DATABASE_URL=postgresql://${postgres_user}:${postgres_password}@postgres:5432/${postgres_db}",
+ "NREPL_BIND_ADDRESS=0.0.0.0",
+ "PORT=8888",
+ "HOST=0.0.0.0",
+ "AWS_ACCESS_KEY_ID=${aws_access_key_id}",
+ "AWS_SECRET_ACCESS_KEY=${aws_secret_access_key}",
+ "AWS_REGION=${aws_region}",
+]
+mounts = []
+
+[[config.domains]]
+serviceName = "server"
+port = 8888
+host = "${main_domain}"
+
diff --git a/blueprints/invoiceshelf/docker-compose.yml b/blueprints/invoiceshelf/docker-compose.yml
index 8d2c8265..bc4e8ff0 100644
--- a/blueprints/invoiceshelf/docker-compose.yml
+++ b/blueprints/invoiceshelf/docker-compose.yml
@@ -20,8 +20,7 @@ services:
image: invoiceshelf/invoiceshelf:nightly
volumes:
- - invoiceshelf-app-data:/data
- - invoiceshelf-app-conf:/conf
+ - invoiceshelf-storage:/var/www/html/storage
environment:
- PHP_TZ=UTC
- TIMEZONE=UTC
@@ -49,5 +48,4 @@ services:
volumes:
invoiceshelf-postgres-data:
- invoiceshelf-app-data:
- invoiceshelf-app-conf:
\ No newline at end of file
+ invoiceshelf-storage:
diff --git a/blueprints/ipfs/docker-compose.yml b/blueprints/ipfs/docker-compose.yml
new file mode 100644
index 00000000..4275f553
--- /dev/null
+++ b/blueprints/ipfs/docker-compose.yml
@@ -0,0 +1,17 @@
+version: "3.8"
+services:
+ ipfs:
+ image: ipfs/kubo:latest
+ restart: unless-stopped
+ environment:
+ - IPFS_PROFILE=server
+ volumes:
+ - ipfs_data:/data/ipfs
+ - ipfs_staging:/export
+ ports:
+ - 4001
+ - 8080
+ - 5001
+volumes:
+ ipfs_data: {}
+ ipfs_staging: {}
diff --git a/blueprints/ipfs/ipfs.svg b/blueprints/ipfs/ipfs.svg
new file mode 100644
index 00000000..1b90c313
--- /dev/null
+++ b/blueprints/ipfs/ipfs.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/blueprints/ipfs/template.toml b/blueprints/ipfs/template.toml
new file mode 100644
index 00000000..89d4677e
--- /dev/null
+++ b/blueprints/ipfs/template.toml
@@ -0,0 +1,25 @@
+[variables]
+gateway_domain = "${domain}"
+api_domain = "${domain}"
+
+[config]
+env = []
+
+[[config.domains]]
+serviceName = "ipfs"
+port = 8080
+host = "${gateway_domain}"
+
+[[config.domains]]
+serviceName = "ipfs"
+port = 5001
+host = "${api_domain}"
+
+[[config.mounts]]
+filePath = "/container-init.d/001-configure-api.sh"
+content = """
+#!/bin/sh
+ipfs config Addresses.API /ip4/0.0.0.0/tcp/5001
+ipfs config --json API.HTTPHeaders.Access-Control-Allow-Origin '["*"]'
+ipfs config --json API.HTTPHeaders.Access-Control-Allow-Methods '["PUT", "POST", "GET"]'
+"""
diff --git a/blueprints/jenkins/docker-compose.yml b/blueprints/jenkins/docker-compose.yml
new file mode 100644
index 00000000..f2b8ad3c
--- /dev/null
+++ b/blueprints/jenkins/docker-compose.yml
@@ -0,0 +1,13 @@
+version: "3.8"
+
+services:
+ jenkins:
+ image: jenkins/jenkins:latest
+ volumes:
+ - jenkins-home:/var/jenkins_home
+ - /var/run/docker.sock:/var/run/docker.sock
+ ports:
+ - 8080
+
+volumes:
+ jenkins-home: {}
\ No newline at end of file
diff --git a/blueprints/jenkins/jenkins.svg b/blueprints/jenkins/jenkins.svg
new file mode 100644
index 00000000..b511310d
--- /dev/null
+++ b/blueprints/jenkins/jenkins.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/blueprints/jenkins/template.toml b/blueprints/jenkins/template.toml
new file mode 100644
index 00000000..46a84921
--- /dev/null
+++ b/blueprints/jenkins/template.toml
@@ -0,0 +1,12 @@
+[variables]
+main_domain = "${domain}"
+
+[config]
+env = {}
+mounts = []
+
+[[config.domains]]
+serviceName = "jenkins"
+port = 8080
+host = "${main_domain}"
+
diff --git a/blueprints/komari-monitor/docker-compose.yml b/blueprints/komari-monitor/docker-compose.yml
new file mode 100644
index 00000000..149999b0
--- /dev/null
+++ b/blueprints/komari-monitor/docker-compose.yml
@@ -0,0 +1,13 @@
+version: "3.8"
+services:
+ komari:
+ image: ghcr.io/komari-monitor/komari:latest
+ restart: unless-stopped
+ volumes:
+ - komari-data:/app/data
+ environment:
+ - ADMIN_USERNAME
+ - ADMIN_PASSWORD
+
+volumes:
+ komari-data: {}
diff --git a/blueprints/komari-monitor/komari-monitor.ico b/blueprints/komari-monitor/komari-monitor.ico
new file mode 100644
index 00000000..f314b8f2
Binary files /dev/null and b/blueprints/komari-monitor/komari-monitor.ico differ
diff --git a/blueprints/komari-monitor/template.toml b/blueprints/komari-monitor/template.toml
new file mode 100644
index 00000000..20955090
--- /dev/null
+++ b/blueprints/komari-monitor/template.toml
@@ -0,0 +1,15 @@
+[variables]
+main_domain = "${domain}"
+admin_password = "${password:16}"
+
+[config]
+mounts = []
+
+[[config.domains]]
+serviceName = "komari"
+port = 25_774
+host = "${main_domain}"
+
+[config.env]
+ADMIN_USERNAME = "admin"
+ADMIN_PASSWORD = "${admin_password}"
diff --git a/blueprints/lavalink/docker-compose.yml b/blueprints/lavalink/docker-compose.yml
new file mode 100644
index 00000000..1f4e91cf
--- /dev/null
+++ b/blueprints/lavalink/docker-compose.yml
@@ -0,0 +1,41 @@
+services:
+ fix-perms:
+ image: busybox:1.36
+ command: >
+ sh -c "mkdir -p /opt/Lavalink/plugins &&
+ chmod -R 0777 /opt/Lavalink/plugins || true &&
+ chown -R 1000:1000 /opt/Lavalink/plugins || true &&
+ echo perms-fixed && sleep 1"
+ volumes:
+ - "../files/plugins/:/opt/Lavalink/plugins/"
+ - "../files/application.yml:/opt/Lavalink/application.yml"
+ restart: "no"
+ lavalink:
+ image: ghcr.io/lavalink-devs/lavalink:4
+ depends_on:
+ - fix-perms
+ restart: unless-stopped
+ environment:
+ _JAVA_OPTIONS: "${_JAVA_OPTIONS:--Xmx6G}"
+ LAVALINK_SERVER_PASSWORD: "${LAVALINK_SERVER_PASSWORD:-youshallnotpass}"
+ SERVER_PORT: "${SERVER_PORT:-2333}"
+ volumes:
+ - "../files/application.yml:/opt/Lavalink/application.yml:rw"
+ - "../files/plugins/:/opt/Lavalink/plugins/:rw"
+ ports:
+ - ${SERVER_PORT}
+
+ healthcheck:
+ test: >
+ sh -c 'wget --header="Authorization: ${LAVALINK_SERVER_PASSWORD}" -qO- http://127.0.0.1:${SERVER_PORT}/v4/info >/dev/null 2>&1 || exit 1'
+ interval: 100s
+ timeout: 5s
+ retries: 5
+ start_period: 30s
+
+ entrypoint: >
+ sh -c 'until [ -w /opt/Lavalink/plugins ] ; do
+ echo "waiting for /opt/Lavalink/plugins to be writable";
+ sleep 1;
+ done;
+ exec java -jar /opt/Lavalink/Lavalink.jar'
diff --git a/blueprints/lavalink/lavalink.svg b/blueprints/lavalink/lavalink.svg
new file mode 100644
index 00000000..0ade923f
--- /dev/null
+++ b/blueprints/lavalink/lavalink.svg
@@ -0,0 +1,50 @@
+
+
diff --git a/blueprints/lavalink/template.toml b/blueprints/lavalink/template.toml
new file mode 100644
index 00000000..6c9a92cd
--- /dev/null
+++ b/blueprints/lavalink/template.toml
@@ -0,0 +1,123 @@
+[variables]
+main_domain = "${domain}"
+server_port = "2333"
+lavalink_server_password = "${password}"
+
+[config]
+[[config.mounts]]
+filePath = "./application.yml"
+content = """
+server: # REST and WS server
+ port: 2333
+ address: 0.0.0.0
+ http2:
+ enabled: false
+plugins:
+# name: # Name of the plugin
+# some_key: some_value # Some key-value pair for the plugin
+# another_key: another_value
+lavalink:
+ plugins:
+ # - dependency: "com.github.username.pluginName:pluginName-plugin:x.y.z"
+ # snapshot: false
+ # pluginsDir: "/opt/Lavalink/plugins"
+ # defaultPluginRepository: "https://maven.lavalink.dev/releases"
+ # defaultPluginSnapshotRepository: "https://maven.lavalink.dev/snapshots"
+ server:
+ password: "youshallnotpass"
+ sources:
+ # The default Youtube source is now deprecated and won't receive further updates. Please use https://github.com/lavalink-devs/youtube-source#plugin instead.
+ youtube: true
+ bandcamp: true
+ soundcloud: true
+ twitch: true
+ vimeo: true
+ nico: true
+ http: true
+ local: false
+ filters:
+ volume: true
+ equalizer: true
+ karaoke: true
+ timescale: true
+ tremolo: true
+ vibrato: true
+ distortion: true
+ rotation: true
+ channelMix: true
+ lowPass: true
+ nonAllocatingFrameBuffer: false
+ bufferDurationMs: 400
+ frameBufferDurationMs: 5000
+ opusEncodingQuality: 10
+ resamplingQuality: LOW
+ trackStuckThresholdMs: 10000
+ useSeekGhosting: true
+ youtubePlaylistLoadLimit: 6
+ playerUpdateInterval: 5
+ youtubeSearchEnabled: true
+ soundcloudSearchEnabled: true
+ gc-warnings: true
+ #ratelimit:
+ #ipBlocks: ["1.0.0.0/8", "..."] # list of ip blocks
+ #excludedIps: ["...", "..."] # ips which should be explicit excluded from usage by lavalink
+ #strategy: "RotateOnBan" # RotateOnBan | LoadBalance | NanoSwitch | RotatingNanoSwitch
+ #searchTriggersFail: true # Whether a search 429 should trigger marking the ip as failing
+ #retryLimit: -1 # -1 = use default lavaplayer value | 0 = infinity | >0 = retry will happen this numbers times
+ #youtubeConfig: # Required for avoiding all age restrictions by YouTube, some restricted videos still can be played without.
+ #email: "" # Email of Google account
+ #password: "" # Password of Google account
+ #httpConfig: # Useful for blocking bad-actors from ip-grabbing your music node and attacking it, this way only the http proxy will be attacked
+ #proxyHost: "localhost" # Hostname of the proxy, (ip or domain)
+ #proxyPort: 3128 # Proxy port, 3128 is the default for squidProxy
+ #proxyUser: "" # Optional user for basic authentication fields, leave blank if you don't use basic auth
+ #proxyPassword: "" # Password for basic authentication
+ timeouts:
+ connectTimeoutMs: 3000
+ connectionRequestTimeoutMs: 3000
+ socketTimeoutMs: 3000
+
+metrics:
+ prometheus:
+ enabled: false
+ endpoint: /metrics
+
+sentry:
+ dsn: ""
+ environment: ""
+# tags:
+# some_key: some_value
+# another_key: another_value
+
+logging:
+ file:
+ path: ./logs/
+
+ level:
+ root: INFO
+ lavalink: INFO
+
+ request:
+ enabled: true
+ includeClientInfo: true
+ includeHeaders: false
+ includeQueryString: true
+ includePayload: true
+ maxPayloadLength: 10000
+
+
+ logback:
+ rollingpolicy:
+ max-file-size: 1GB
+ max-history: 30
+"""
+
+[[config.domains]]
+serviceName = "lavalink"
+port = 2_333
+host = "${main_domain}"
+
+[config.env]
+_JAVA_OPTIONS = "-Xmx6G"
+LAVALINK_SERVER_PASSWORD = "${lavalink_server_password}"
+SERVER_PORT = "${server_port}"
diff --git a/blueprints/mautic/docker-compose.yml b/blueprints/mautic/docker-compose.yml
new file mode 100644
index 00000000..223ea7ee
--- /dev/null
+++ b/blueprints/mautic/docker-compose.yml
@@ -0,0 +1,131 @@
+version: "3.8"
+
+services:
+ # -------------------------------------------------------------------------
+ # Service 1: Database
+ # -------------------------------------------------------------------------
+ mysql:
+ image: mysql:8.0
+ command: --default-authentication-plugin=mysql_native_password
+ restart: unless-stopped
+ environment:
+ MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
+ MYSQL_DATABASE: ${MAUTIC_DB_DATABASE}
+ MYSQL_USER: ${MAUTIC_DB_USER}
+ MYSQL_PASSWORD: ${MAUTIC_DB_PASSWORD}
+ volumes:
+ - mysql_data:/var/lib/mysql
+ healthcheck:
+ test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+
+ # -------------------------------------------------------------------------
+ # Service 2: Mautic Web (The Leader)
+ # -------------------------------------------------------------------------
+ mautic:
+ image: mautic/mautic:5.1.1-apache
+ restart: unless-stopped
+ depends_on:
+ mysql:
+ condition: service_healthy
+ ports:
+ - 80
+ environment:
+ - DOCKER_MAUTIC_ROLE=mautic_web
+ - DOCKER_MAUTIC_RUN_MIGRATIONS=true
+ - MAUTIC_DB_HOST=${MAUTIC_DB_HOST}
+ - MAUTIC_DB_PORT=${MAUTIC_DB_PORT}
+ - MAUTIC_DB_DATABASE=${MAUTIC_DB_DATABASE}
+ - MAUTIC_DB_USER=${MAUTIC_DB_USER}
+ - MAUTIC_DB_PASSWORD=${MAUTIC_DB_PASSWORD}
+ - MAUTIC_URL=${MAUTIC_URL}
+ - MAUTIC_TRUSTED_PROXIES=${MAUTIC_TRUSTED_PROXIES}
+ - MAUTIC_MESSENGER_DSN_EMAIL=${MAUTIC_MESSENGER_DSN_EMAIL}
+ - MAUTIC_MESSENGER_DSN_HIT=${MAUTIC_MESSENGER_DSN_HIT}
+ - PHP_INI_DATE_TIMEZONE=${PHP_INI_DATE_TIMEZONE}
+ - PHP_MEMORY_LIMIT=${PHP_MEMORY_LIMIT}
+ volumes:
+ - mautic_data:/var/www/html
+ # AUTOMATION FIX 1: Force permissions to be correct on every start
+ entrypoint: ["/bin/sh", "-c", "chown -R www-data:www-data /var/www/html && /entrypoint.sh apache2-foreground"]
+ # AUTOMATION FIX 2: Check if the CONFIG FILE exists. If not, report 'unhealthy'.
+ # This signals the other containers to keep waiting.
+ healthcheck:
+ test: ["CMD-SHELL", "test -f /var/www/html/config/local.php || exit 1"]
+ interval: 10s
+ timeout: 5s
+ retries: 3
+ start_period: 300s # Give you 5 mins to run the installer before marking failed
+
+ # -------------------------------------------------------------------------
+ # Service 3: Mautic Cron (Waits for Install)
+ # -------------------------------------------------------------------------
+ mautic-cron:
+ image: mautic/mautic:5.1.1-apache
+ restart: unless-stopped
+ depends_on:
+ mautic:
+ condition: service_healthy # AUTOMATION FIX 3: Do not start until config file exists
+ environment:
+ - DOCKER_MAUTIC_ROLE=mautic_cron
+ - MAUTIC_DB_HOST=${MAUTIC_DB_HOST}
+ - MAUTIC_DB_PORT=${MAUTIC_DB_PORT}
+ - MAUTIC_DB_DATABASE=${MAUTIC_DB_DATABASE}
+ - MAUTIC_DB_USER=${MAUTIC_DB_USER}
+ - MAUTIC_DB_PASSWORD=${MAUTIC_DB_PASSWORD}
+ - MAUTIC_URL=${MAUTIC_URL}
+ - PHP_INI_DATE_TIMEZONE=${PHP_INI_DATE_TIMEZONE}
+ volumes:
+ - mautic_data:/var/www/html
+
+ # -------------------------------------------------------------------------
+ # Service 4: Mautic Worker (Waits for Install)
+ # -------------------------------------------------------------------------
+ mautic-worker:
+ image: mautic/mautic:5.1.1-apache
+ restart: unless-stopped
+ depends_on:
+ mautic:
+ condition: service_healthy # AUTOMATION FIX 3: Do not start until config file exists
+ deploy:
+ resources:
+ limits:
+ memory: 512M
+ environment:
+ - DOCKER_MAUTIC_ROLE=mautic_worker
+ - DOCKER_MAUTIC_WORKERS_CONSUME_EMAIL=2
+ - DOCKER_MAUTIC_WORKERS_CONSUME_HIT=2
+ - DOCKER_MAUTIC_WORKERS_CONSUME_FAILED=2
+ - MAUTIC_DB_HOST=${MAUTIC_DB_HOST}
+ - MAUTIC_DB_PORT=${MAUTIC_DB_PORT}
+ - MAUTIC_DB_DATABASE=${MAUTIC_DB_DATABASE}
+ - MAUTIC_DB_USER=${MAUTIC_DB_USER}
+ - MAUTIC_DB_PASSWORD=${MAUTIC_DB_PASSWORD}
+ - MAUTIC_URL=${MAUTIC_URL}
+ - MAUTIC_MESSENGER_DSN_EMAIL=${MAUTIC_MESSENGER_DSN_EMAIL}
+ - MAUTIC_MESSENGER_DSN_HIT=${MAUTIC_MESSENGER_DSN_HIT}
+ - PHP_INI_DATE_TIMEZONE=${PHP_INI_DATE_TIMEZONE}
+ volumes:
+ - mautic_data:/var/www/html
+
+ # -------------------------------------------------------------------------
+ # Service 5: phpMyAdmin
+ # -------------------------------------------------------------------------
+ phpmyadmin:
+ image: phpmyadmin/phpmyadmin
+ restart: unless-stopped
+ depends_on:
+ mysql:
+ condition: service_healthy
+ environment:
+ PMA_HOST: mysql
+ PMA_PORT: 3306
+ UPLOAD_LIMIT: 64M
+ ports:
+ - 80
+
+volumes:
+ mysql_data:
+ mautic_data:
diff --git a/blueprints/mautic/mautic.svg b/blueprints/mautic/mautic.svg
new file mode 100644
index 00000000..3f5229ae
--- /dev/null
+++ b/blueprints/mautic/mautic.svg
@@ -0,0 +1,76 @@
+
+
+
+
diff --git a/blueprints/mautic/template.toml b/blueprints/mautic/template.toml
new file mode 100644
index 00000000..eeb79eef
--- /dev/null
+++ b/blueprints/mautic/template.toml
@@ -0,0 +1,52 @@
+[variables]
+# Domain 1: For the main Mautic Application
+mautic_domain = "${domain}"
+
+# Domain 2: For phpMyAdmin (Database Manager)
+pma_domain = "${domain}"
+
+# Security: Random passwords
+db_password = "${password:32}"
+root_password = "${password:32}"
+
+[config]
+
+# --- Service 1: Mautic Web ---
+[[config.domains]]
+serviceName = "mautic"
+port = 80
+host = "${mautic_domain}"
+path = "/"
+
+# --- Service 2: phpMyAdmin ---
+[[config.domains]]
+serviceName = "phpmyadmin"
+port = 80
+host = "${pma_domain}"
+path = "/"
+
+# --- Shared Environment Variables ---
+[config.env]
+
+# URL Configuration
+MAUTIC_URL = "https://${mautic_domain}"
+
+# Database Connections
+MAUTIC_DB_HOST = "mysql"
+MAUTIC_DB_PORT = "3306"
+MAUTIC_DB_DATABASE = "mautic"
+MAUTIC_DB_USER = "mautic"
+MAUTIC_DB_PASSWORD = "${db_password}"
+MYSQL_ROOT_PASSWORD = "${root_password}"
+
+# Security & Proxy (JSON ARRAY FIXED)
+# We use single quotes '...' so TOML treats the inner [...] as a string
+MAUTIC_TRUSTED_PROXIES = '["0.0.0.0/0"]'
+
+# Queue Settings
+MAUTIC_MESSENGER_DSN_EMAIL = "doctrine://default"
+MAUTIC_MESSENGER_DSN_HIT = "doctrine://default"
+
+# PHP Settings
+PHP_INI_DATE_TIMEZONE = "UTC"
+PHP_MEMORY_LIMIT = "512M"
\ No newline at end of file
diff --git a/blueprints/minepanel/docker-compose.yml b/blueprints/minepanel/docker-compose.yml
new file mode 100644
index 00000000..e69b75f9
--- /dev/null
+++ b/blueprints/minepanel/docker-compose.yml
@@ -0,0 +1,29 @@
+version: "3.8"
+services:
+ backend:
+ image: ketbom/minepanel-backend:1.7.1
+ restart: unless-stopped
+ environment:
+ - NODE_ENV=production
+ - FRONTEND_URL=${FRONTEND_URL}
+ - JWT_SECRET=${JWT_SECRET}
+ - CLIENT_PASSWORD=${CLIENT_PASSWORD}
+ - CLIENT_USERNAME=${CLIENT_USERNAME}
+ - BASE_DIR=${BASE_DIR}
+ volumes:
+ - minepanel-servers:/app/servers
+ - minepanel-data:/app/data
+ - /var/run/docker.sock:/var/run/docker.sock
+
+ frontend:
+ image: ketbom/minepanel-frontend:1.7.1
+ restart: unless-stopped
+ environment:
+ - NEXT_PUBLIC_BACKEND_URL=${NEXT_PUBLIC_BACKEND_URL}
+ - NEXT_PUBLIC_DEFAULT_LANGUAGE=${NEXT_PUBLIC_DEFAULT_LANGUAGE}
+ depends_on:
+ - backend
+
+volumes:
+ minepanel-servers:
+ minepanel-data:
diff --git a/blueprints/minepanel/minepanel.webp b/blueprints/minepanel/minepanel.webp
new file mode 100644
index 00000000..21a6f7a4
Binary files /dev/null and b/blueprints/minepanel/minepanel.webp differ
diff --git a/blueprints/minepanel/template.toml b/blueprints/minepanel/template.toml
new file mode 100644
index 00000000..4f1b0862
--- /dev/null
+++ b/blueprints/minepanel/template.toml
@@ -0,0 +1,28 @@
+[variables]
+main_domain = "${domain}"
+jwt_secret = "${base64:32}"
+client_username = "admin"
+client_password = "${password:16}"
+default_language = "en"
+
+[config]
+mounts = []
+
+[[config.domains]]
+serviceName = "frontend"
+port = 3_000
+host = "${main_domain}"
+
+[[config.domains]]
+serviceName = "backend"
+port = 8_091
+host = "api-${main_domain}"
+
+[config.env]
+JWT_SECRET = "${jwt_secret}"
+CLIENT_USERNAME = "${client_username}"
+CLIENT_PASSWORD = "${client_password}"
+FRONTEND_URL = "http://${main_domain}"
+NEXT_PUBLIC_BACKEND_URL = "http://api-${main_domain}"
+NEXT_PUBLIC_DEFAULT_LANGUAGE = "${default_language}"
+BASE_DIR = "/app"
diff --git a/blueprints/misaka-danmu-server/docker-compose.yml b/blueprints/misaka-danmu-server/docker-compose.yml
new file mode 100644
index 00000000..42252c25
--- /dev/null
+++ b/blueprints/misaka-danmu-server/docker-compose.yml
@@ -0,0 +1,43 @@
+version: "3.8"
+services:
+ postgres:
+ image: postgres:18
+ restart: unless-stopped
+ environment:
+ - POSTGRES_PASSWORD
+ - POSTGRES_USER
+ - POSTGRES_DB
+ - TZ=Asia/Shanghai
+ volumes:
+ - postgres-data:/var/lib/postgresql
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U danmuapi -d danmuapi"]
+ interval: 10s
+ timeout: 5s
+ retries: 10
+ start_period: 60s
+
+ danmu-app:
+ image: l429609201/misaka_danmu_server:latest
+ restart: unless-stopped
+ depends_on:
+ postgres:
+ condition: service_healthy
+ environment:
+ - PUID=1000
+ - PGID=1000
+ - UMASK=0022
+ - TZ=Asia/Shanghai
+ - DANMUAPI_DATABASE__TYPE
+ - DANMUAPI_DATABASE__HOST
+ - DANMUAPI_DATABASE__PORT
+ - DANMUAPI_DATABASE__NAME
+ - DANMUAPI_DATABASE__USER
+ - DANMUAPI_DATABASE__PASSWORD
+ - DANMUAPI_ADMIN__INITIAL_USER
+ volumes:
+ - danmu-config:/app/config
+
+volumes:
+ postgres-data: {}
+ danmu-config: {}
diff --git a/blueprints/misaka-danmu-server/misaka-danmu-server.png b/blueprints/misaka-danmu-server/misaka-danmu-server.png
new file mode 100644
index 00000000..30990611
Binary files /dev/null and b/blueprints/misaka-danmu-server/misaka-danmu-server.png differ
diff --git a/blueprints/misaka-danmu-server/template.toml b/blueprints/misaka-danmu-server/template.toml
new file mode 100644
index 00000000..62e1c268
--- /dev/null
+++ b/blueprints/misaka-danmu-server/template.toml
@@ -0,0 +1,30 @@
+[variables]
+main_domain = "${domain}"
+db_password = "${password:24}"
+db_user = "danmuapi"
+db_name = "danmuapi"
+
+[config]
+mounts = []
+
+[[config.domains]]
+serviceName = "danmu-app"
+port = 7768
+host = "${main_domain}"
+
+[config.env]
+# PostgreSQL
+POSTGRES_PASSWORD = "${db_password}"
+POSTGRES_USER = "${db_user}"
+POSTGRES_DB = "${db_name}"
+
+# Danmu App Database Connection
+DANMUAPI_DATABASE__TYPE = "postgresql"
+DANMUAPI_DATABASE__HOST = "postgres"
+DANMUAPI_DATABASE__PORT = "5432"
+DANMUAPI_DATABASE__NAME = "${db_name}"
+DANMUAPI_DATABASE__USER = "${db_user}"
+DANMUAPI_DATABASE__PASSWORD = "${db_password}"
+
+# Admin
+DANMUAPI_ADMIN__INITIAL_USER = "admin"
diff --git a/blueprints/nextcloud-aio/docker-compose.yml b/blueprints/nextcloud-aio/docker-compose.yml
index 1f4e43e6..f262b157 100644
--- a/blueprints/nextcloud-aio/docker-compose.yml
+++ b/blueprints/nextcloud-aio/docker-compose.yml
@@ -1,6 +1,6 @@
services:
nextcloud:
- image: nextcloud:30.0.2
+ image: nextcloud:32.0.5
restart: always
ports:
diff --git a/blueprints/openclaw/docker-compose.yml b/blueprints/openclaw/docker-compose.yml
new file mode 100644
index 00000000..e6aba49b
--- /dev/null
+++ b/blueprints/openclaw/docker-compose.yml
@@ -0,0 +1,86 @@
+services:
+ openclaw:
+ image: "coollabsio/openclaw:2026.2.6"
+ environment:
+ - AUTH_USERNAME=${AUTH_USERNAME}
+ - AUTH_PASSWORD=${AUTH_PASSWORD}
+ - OPENCLAW_GATEWAY_TOKEN=${OPENCLAW_GATEWAY_TOKEN}
+ - ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
+ - OPENAI_API_KEY=${OPENAI_API_KEY}
+ - OPENROUTER_API_KEY=${OPENROUTER_API_KEY}
+ - GEMINI_API_KEY=${GEMINI_API_KEY}
+ - XAI_API_KEY=${XAI_API_KEY}
+ - GROQ_API_KEY=${GROQ_API_KEY}
+ - MISTRAL_API_KEY=${MISTRAL_API_KEY}
+ - CEREBRAS_API_KEY=${CEREBRAS_API_KEY}
+ - VENICE_API_KEY=${VENICE_API_KEY}
+ - MOONSHOT_API_KEY=${MOONSHOT_API_KEY}
+ - KIMI_API_KEY=${KIMI_API_KEY}
+ - MINIMAX_API_KEY=${MINIMAX_API_KEY}
+ - ZAI_API_KEY=${ZAI_API_KEY}
+ - AI_GATEWAY_API_KEY=${AI_GATEWAY_API_KEY}
+ - OPENCODE_API_KEY=${OPENCODE_API_KEY}
+ - SYNTHETIC_API_KEY=${SYNTHETIC_API_KEY}
+ - COPILOT_GITHUB_TOKEN=${COPILOT_GITHUB_TOKEN}
+ - XIAOMI_API_KEY=${XIAOMI_API_KEY}
+ - OPENCLAW_PRIMARY_MODEL=${OPENCLAW_PRIMARY_MODEL}
+ - DEEPGRAM_API_KEY=${DEEPGRAM_API_KEY}
+ - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
+ - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
+ - AWS_REGION=${AWS_REGION:-us-east-1}
+ - AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
+ - BEDROCK_PROVIDER_FILTER=${BEDROCK_PROVIDER_FILTER:-anthropic}
+ - OLLAMA_BASE_URL=${OLLAMA_BASE_URL}
+ - PORT=8080
+ - OPENCLAW_GATEWAY_PORT=18789
+ - OPENCLAW_GATEWAY_BIND=${OPENCLAW_GATEWAY_BIND:-loopback}
+ - OPENCLAW_STATE_DIR=/data/.openclaw
+ - OPENCLAW_WORKSPACE_DIR=/data/workspace
+ - BROWSER_CDP_URL=http://browser:9223
+ - BROWSER_DEFAULT_PROFILE=${BROWSER_DEFAULT_PROFILE:-openclaw}
+ - BROWSER_EVALUATE_ENABLED=${BROWSER_EVALUATE_ENABLED:-true}
+ - BROWSER_SNAPSHOT_MODE=${BROWSER_SNAPSHOT_MODE:-efficient}
+ - BROWSER_REMOTE_TIMEOUT_MS=${BROWSER_REMOTE_TIMEOUT_MS:-1500}
+ - BROWSER_REMOTE_HANDSHAKE_TIMEOUT_MS=${BROWSER_REMOTE_HANDSHAKE_TIMEOUT_MS:-3000}
+ - HOOKS_ENABLED=${HOOKS_ENABLED:-false}
+ - HOOKS_PATH=${HOOKS_PATH:-/hooks}
+ - MOONSHOT_BASE_URL=${MOONSHOT_BASE_URL:-https://api.moonshot.ai/v1}
+ - KIMI_BASE_URL=${KIMI_BASE_URL:-https://api.moonshot.ai/anthropic}
+ - TELEGRAM_BOT_TOKEN=$TELEGRAM_BOT_TOKEN
+ - DISCORD_BOT_TOKEN=$DISCORD_BOT_TOKEN
+ - SLACK_BOT_TOKEN=$SLACK_BOT_TOKEN
+ - SLACK_APP_TOKEN=$SLACK_APP_TOKEN
+ - WHATSAPP_ENABLED=$WHATSAPP_ENABLED
+ - OPENCLAW_DOCKER_APT_PACKAGES=$OPENCLAW_DOCKER_APT_PACKAGES
+ volumes:
+ - "openclaw-data:/data"
+ depends_on:
+ browser:
+ condition: service_healthy
+ healthcheck:
+ test: ["CMD", "curl", "-sf", "http://127.0.0.1:8080/healthz"]
+ interval: 10s
+ timeout: 10s
+ retries: 5
+
+
+ browser:
+ image: "coollabsio/openclaw-browser:latest"
+ environment:
+ - PUID=1000
+ - PGID=1000
+ - TZ=Etc/UTC
+ - CHROME_CLI=--remote-debugging-port=9222
+ volumes:
+ - "browser-data:/config"
+ shm_size: 2g
+ healthcheck:
+ test: ["CMD-SHELL", "bash -c ':> /dev/tcp/127.0.0.1/9222' || exit 1"]
+ interval: 5s
+ timeout: 5s
+ retries: 10
+
+
+volumes:
+ openclaw-data:
+ browser-data:
diff --git a/blueprints/openclaw/openclaw.svg b/blueprints/openclaw/openclaw.svg
new file mode 100644
index 00000000..6d89f848
--- /dev/null
+++ b/blueprints/openclaw/openclaw.svg
@@ -0,0 +1,60 @@
+
+
\ No newline at end of file
diff --git a/blueprints/openclaw/template.toml b/blueprints/openclaw/template.toml
new file mode 100644
index 00000000..188d1e83
--- /dev/null
+++ b/blueprints/openclaw/template.toml
@@ -0,0 +1,21 @@
+[variables]
+gateway_token = "${password:32}"
+auth_username = "dokploy"
+auth_password = "${password:32}"
+
+[config]
+[[config.domains]]
+serviceName = "openclaw"
+port = 8080
+host = "${domain}"
+
+[config.env]
+OPENCLAW_GATEWAY_TOKEN = "${gateway_token}"
+OPENCLAW_GATEWAY_PORT = 18789
+AUTH_USERNAME="${auth_username}"
+AUTH_PASSWORD="${auth_password}"
+OPENCLAW_BRIDGE_PORT = 18790
+OPENCLAW_GATEWAY_BIND="lan"
+OPENCLAW_PLUGINS="discord,memory-core"
+# Get here https://openrouter.ai/
+OPENROUTER_API_KEY="YOUR-API-KEY"
diff --git a/blueprints/openpanel/docker-compose.yml b/blueprints/openpanel/docker-compose.yml
index f6393543..53c95bd2 100644
--- a/blueprints/openpanel/docker-compose.yml
+++ b/blueprints/openpanel/docker-compose.yml
@@ -54,7 +54,7 @@ services:
retries: 5
op-api:
- image: lindesvard/openpanel-api:2.0.0
+ image: lindesvard/openpanel-api:2
restart: always
command: >
sh -c "
@@ -97,7 +97,7 @@ services:
condition: service_healthy
op-dashboard:
- image: lindesvard/openpanel-dashboard:2.0.0
+ image: lindesvard/openpanel-dashboard:2
restart: always
depends_on:
op-api:
@@ -111,7 +111,7 @@ services:
retries: 5
op-worker:
- image: lindesvard/openpanel-worker:2.0.0
+ image: lindesvard/openpanel-worker:2
restart: always
depends_on:
op-api:
diff --git a/blueprints/postgres-pgdog/docker-compose.yml b/blueprints/postgres-pgdog/docker-compose.yml
new file mode 100644
index 00000000..f5164d9c
--- /dev/null
+++ b/blueprints/postgres-pgdog/docker-compose.yml
@@ -0,0 +1,33 @@
+services:
+ postgres-pgdog:
+ image: ${PGDOG_IMAGE}
+ restart: unless-stopped
+ # Uncomment 'ports' settings below to enable external access
+ # ports:
+ # - "6432:6432"
+ volumes:
+ - ../files/pgdog.toml:/pgdog/pgdog.toml
+ - ../files/users.toml:/pgdog/users.toml
+ environment:
+ - RUST_LOG=${RUST_LOG}
+ depends_on:
+ postgres:
+ condition: service_healthy
+
+ postgres:
+ image: ${POSTGRES_IMAGE}
+ restart: unless-stopped
+ environment:
+ - POSTGRES_USER=${POSTGRES_USER}
+ - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
+ - POSTGRES_DB=${POSTGRES_DB}
+ volumes:
+ - postgres-data:/var/lib/postgresql
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
+ interval: 10s
+ timeout: 5s
+ retries: 5
+
+volumes:
+ postgres-data:
diff --git a/blueprints/postgres-pgdog/postgres-pgdog.png b/blueprints/postgres-pgdog/postgres-pgdog.png
new file mode 100644
index 00000000..bbc4aae7
Binary files /dev/null and b/blueprints/postgres-pgdog/postgres-pgdog.png differ
diff --git a/blueprints/postgres-pgdog/template.toml b/blueprints/postgres-pgdog/template.toml
new file mode 100644
index 00000000..2ffc4ec0
--- /dev/null
+++ b/blueprints/postgres-pgdog/template.toml
@@ -0,0 +1,36 @@
+[variables]
+postgres_user = "${username}"
+postgres_password = "${password:32}"
+postgres_db = "postgres"
+pgdog_image = "ghcr.io/pgdogdev/pgdog:v0.1.26"
+postgres_image = "postgres:18-alpine"
+
+[[config.mounts]]
+filePath = "pgdog.toml"
+content = """
+[general]
+host = "0.0.0.0"
+port = 6432
+
+[[databases]]
+name = "${postgres_db}"
+host = "postgres"
+port = 5432
+"""
+
+[[config.mounts]]
+filePath = "users.toml"
+content = """
+[[users]]
+name = "${postgres_user}"
+database = "${postgres_db}"
+password = "${postgres_password}"
+"""
+
+[config.env]
+POSTGRES_USER = "${postgres_user}"
+POSTGRES_PASSWORD = "${postgres_password}"
+POSTGRES_DB = "${postgres_db}"
+PGDOG_IMAGE = "${pgdog_image}"
+POSTGRES_IMAGE = "${postgres_image}"
+RUST_LOG = "info"
diff --git a/blueprints/pulse/docker-compose.yml b/blueprints/pulse/docker-compose.yml
new file mode 100644
index 00000000..074aec07
--- /dev/null
+++ b/blueprints/pulse/docker-compose.yml
@@ -0,0 +1,22 @@
+version: "3.8"
+services:
+ pulse:
+ image: rcourtman/pulse:5.1
+ restart: always
+ expose:
+ - 7655
+ volumes:
+ - pulse_data:/data
+ - /var/run/docker.sock:/var/run/docker.sock
+ environment:
+ - PULSE_AUTH_USER=${PULSE_AUTH_USER}
+ - PULSE_AUTH_PASS=${PULSE_AUTH_PASS}
+ healthcheck:
+ test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:7655/api/health"]
+ interval: 30s
+ timeout: 10s
+ retries: 3
+ start_period: 40s
+
+volumes:
+ pulse_data:
\ No newline at end of file
diff --git a/blueprints/pulse/pulse.svg b/blueprints/pulse/pulse.svg
new file mode 100644
index 00000000..428a6e54
--- /dev/null
+++ b/blueprints/pulse/pulse.svg
@@ -0,0 +1,4 @@
+
\ No newline at end of file
diff --git a/blueprints/pulse/template.toml b/blueprints/pulse/template.toml
new file mode 100644
index 00000000..865990c4
--- /dev/null
+++ b/blueprints/pulse/template.toml
@@ -0,0 +1,13 @@
+[variables]
+main_domain = "${domain}"
+pulse_auth_user = "${username}"
+pulse_auth_pass = "${password:32}"
+
+[config]
+env = ["PULSE_AUTH_USER=${pulse_auth_user}", "PULSE_AUTH_PASS=${pulse_auth_pass}"]
+mounts = []
+
+[[config.domains]]
+serviceName = "pulse"
+port = 7_655
+host = "${main_domain}"
\ No newline at end of file
diff --git a/blueprints/pyrodactyl/docker-compose.yml b/blueprints/pyrodactyl/docker-compose.yml
index ad0e42b7..2fde33d7 100644
--- a/blueprints/pyrodactyl/docker-compose.yml
+++ b/blueprints/pyrodactyl/docker-compose.yml
@@ -1,6 +1,6 @@
services:
database:
- image: mariadb:10.5
+ image: mariadb:11
restart: always
command: --default-authentication-plugin=mysql_native_password
volumes:
@@ -14,7 +14,7 @@ services:
image: redis:alpine
restart: always
panel:
- image: ghcr.io/pyrohost/pyrodactyl:main
+ image: ghcr.io/pyrodactyl-oss/pyrodactyl:latest
restart: always
links:
- database
@@ -35,15 +35,8 @@ services:
DB_HOST:
DB_PORT:
DB_PASSWORD: ${MYSQL_PASSWORD}
- RECAPTCHA_ENABLED:
DB_CONNECTION: "mariadb"
-networks:
- default:
- ipam:
- config:
- - subnet: 172.20.0.0/16
-
volumes:
pterodb:
pterovar:
diff --git a/blueprints/qbitwebui/docker-compose.yml b/blueprints/qbitwebui/docker-compose.yml
new file mode 100644
index 00000000..3e805c3c
--- /dev/null
+++ b/blueprints/qbitwebui/docker-compose.yml
@@ -0,0 +1,39 @@
+version: "3.8"
+
+services:
+ qbitwebui:
+ image: ghcr.io/maciejonos/qbitwebui:latest
+ restart: unless-stopped
+ environment:
+ # Required: Encryption key for storing credentials (min 32 chars)
+ - ENCRYPTION_KEY=${ENCRYPTION_KEY}
+ # Optional: Server port (default: 3000)
+ - PORT=${PORT:-3000}
+ # Optional: Database location (default: ./data/qbitwebui.db)
+ - DATABASE_PATH=${DATABASE_PATH:-/data/qbitwebui.db}
+ # Optional: Salt file location (default: ./data/.salt)
+ - SALT_PATH=${SALT_PATH:-/data/.salt}
+ # Optional: Allow self-signed certificates for qBittorrent instances (default: false)
+ # - ALLOW_SELF_SIGNED_CERTS=${ALLOW_SELF_SIGNED_CERTS:-false}
+ # Optional: Disable authentication/login (single-user mode) (default: false)
+ # - DISABLE_AUTH=${DISABLE_AUTH:-false}
+ # Optional: Disable new registrations, creates default admin account (default: false)
+ # - DISABLE_REGISTRATION=${DISABLE_REGISTRATION:-false}
+ # Optional: Enable file browser by setting downloads path
+ # - DOWNLOADS_PATH=/downloads
+ volumes:
+ - qbitwebui_data:/data
+ # Optional: Mount downloads directory for file browser feature
+ # Read-only mount (browse & download only):
+ # - /path/to/your/downloads:/downloads:ro
+ # Or read-write mount (enables delete/move/copy/rename):
+ # - /path/to/your/downloads:/downloads
+ healthcheck:
+ test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000"]
+ interval: 30s
+ timeout: 5s
+ retries: 3
+ start_period: 10s
+
+volumes:
+ qbitwebui_data:
diff --git a/blueprints/qbitwebui/qbitwebui.png b/blueprints/qbitwebui/qbitwebui.png
new file mode 100644
index 00000000..48052dff
Binary files /dev/null and b/blueprints/qbitwebui/qbitwebui.png differ
diff --git a/blueprints/qbitwebui/template.toml b/blueprints/qbitwebui/template.toml
new file mode 100644
index 00000000..62151ba2
--- /dev/null
+++ b/blueprints/qbitwebui/template.toml
@@ -0,0 +1,16 @@
+[variables]
+main_domain = "${domain}"
+encryption_key = "${password:32}"
+
+[config]
+[[config.domains]]
+serviceName = "qbitwebui"
+port = 3000
+host = "${main_domain}"
+path = "/"
+
+[config.env]
+ENCRYPTION_KEY = "${encryption_key}"
+PORT = "3000"
+DATABASE_PATH = "/data/qbitwebui.db"
+SALT_PATH = "/data/.salt"
diff --git a/blueprints/scrutiny/docker-compose.yml b/blueprints/scrutiny/docker-compose.yml
new file mode 100644
index 00000000..56b27bd2
--- /dev/null
+++ b/blueprints/scrutiny/docker-compose.yml
@@ -0,0 +1,55 @@
+services:
+ scrutiny:
+ restart: unless-stopped
+ container_name: scrutiny
+ image: ghcr.io/analogj/scrutiny:master-omnibus
+ cap_add:
+ - SYS_RAWIO
+ ports:
+ - 8080 # webapp
+ - 8086 # influxDB admin
+ volumes:
+ - /run/udev:/run/udev:ro
+ - ./config:/opt/scrutiny/config
+ - ./influxdb:/opt/scrutiny/influxdb
+ devices:
+ - "/dev/sda"
+ - "/dev/sdb"
+
+# PROXMOX USERS: Proxmox LXCs don't have access to S.M.A.R.T data, while this may be possible on VMs using PCI passthrough,
+# there's another way which is to run the scrutiny collector on proxmox host and have it send data to the scrutiny webapp running in an LXC or VM
+# so basically you can use the following commented docker-compose (web+db) and run the collector directly on the proxmox host (guide: https://github.com/AnalogJ/scrutiny/blob/master/docs/INSTALL_HUB_SPOKE.md#setting-up-a-spoke-without-docker)
+
+# services:
+# influxdb:
+# restart: unless-stopped
+# image: influxdb:2.2
+# ports:
+# - '8086:8086'
+# volumes:
+# - './influxdb:/var/lib/influxdb2'
+# healthcheck:
+# test: ["CMD", "curl", "-f", "http://localhost:8086/health"]
+# interval: 5s
+# timeout: 10s
+# retries: 20
+#
+#
+# web:
+# restart: unless-stopped
+# image: 'ghcr.io/analogj/scrutiny:master-web'
+# ports:
+# - '8080:8080'
+# volumes:
+# - './config:/opt/scrutiny/config'
+# environment:
+# SCRUTINY_WEB_INFLUXDB_HOST: 'influxdb'
+# depends_on:
+# influxdb:
+# condition: service_healthy
+# healthcheck:
+# test: ["CMD", "curl", "-f", "http://localhost:8080/api/health"]
+# interval: 5s
+# timeout: 10s
+# retries: 20
+# start_period: 10s
diff --git a/blueprints/scrutiny/scrutiny.png b/blueprints/scrutiny/scrutiny.png
new file mode 100644
index 00000000..c0812c1b
Binary files /dev/null and b/blueprints/scrutiny/scrutiny.png differ
diff --git a/blueprints/scrutiny/template.toml b/blueprints/scrutiny/template.toml
new file mode 100644
index 00000000..60ff998b
--- /dev/null
+++ b/blueprints/scrutiny/template.toml
@@ -0,0 +1 @@
+[config]
\ No newline at end of file
diff --git a/blueprints/searxng/docker-compose.yml b/blueprints/searxng/docker-compose.yml
index 856490c6..721c077a 100644
--- a/blueprints/searxng/docker-compose.yml
+++ b/blueprints/searxng/docker-compose.yml
@@ -1,20 +1,18 @@
-version: "3.8"
services:
- redis:
+ valkey:
image: valkey/valkey:8-alpine
command: valkey-server --save 30 1 --loglevel warning
restart: unless-stopped
volumes:
- - redis-data:/data
+ - valkey-data:/data
searxng:
image: searxng/searxng:latest
restart: unless-stopped
volumes:
- - searxng-config:/etc/searxng
+ - ../files/searxng:/etc/searxng
- searxng-data:/var/cache/searxng
volumes:
- redis-data: {}
- searxng-config: {}
+ valkey-data: {}
searxng-data: {}
diff --git a/blueprints/searxng/template.toml b/blueprints/searxng/template.toml
index 78f7bc68..092aca39 100644
--- a/blueprints/searxng/template.toml
+++ b/blueprints/searxng/template.toml
@@ -12,11 +12,15 @@ env = [
]
[[config.mounts]]
-filePath = "/etc/searxng/settings.yml"
+filePath = "/searxng/settings.yml"
content = """
use_default_settings: true
+
server:
secret_key: \"${secret_key}\"
limiter: false
image_proxy: false
+
+valkey:
+ url: valkey://valkey:6379/0
"""
\ No newline at end of file
diff --git a/blueprints/seaweedfs/docker-compose.yml b/blueprints/seaweedfs/docker-compose.yml
new file mode 100644
index 00000000..ca4a0968
--- /dev/null
+++ b/blueprints/seaweedfs/docker-compose.yml
@@ -0,0 +1,114 @@
+services:
+ master:
+ image: chrislusf/seaweedfs:4.02
+ command: >
+ -v=0
+ master
+ -volumeSizeLimitMB=10240
+ -ip=master
+ -ip.bind=0.0.0.0
+ -port=9333
+ -mdir=/data/master
+ volumes:
+ - seaweedfs-master:/data/master
+ restart: unless-stopped
+ healthcheck:
+ test: ["CMD", "wget", "-q", "--spider", "http://localhost:9333"]
+ interval: 30s
+ timeout: 10s
+ retries: 3
+ expose:
+ - 9333
+ deploy:
+ resources:
+ limits:
+ memory: 512M
+ reservations:
+ memory: 256M
+
+ volume:
+ image: chrislusf/seaweedfs:4.02
+ command: >
+ -v=0
+ volume
+ -mserver="master:9333"
+ -port=8080
+ -dir=/data/volume
+ -max=100
+ volumes:
+ - seaweedfs-volume:/data/volume
+ depends_on:
+ master:
+ condition: service_healthy
+ restart: unless-stopped
+ expose:
+ - 8080
+ deploy:
+ resources:
+ limits:
+ memory: 1G
+ reservations:
+ memory: 512M
+
+ filer:
+ image: chrislusf/seaweedfs:4.02
+ command: >
+ -v=0
+ filer
+ -defaultReplicaPlacement=000
+ -master="master:9333"
+ -ip=filer
+ -ip.bind=0.0.0.0
+ -port=8888
+ environment:
+ - WEED_MASTER=master:9333
+ volumes:
+ - seaweedfs-filer:/data
+ depends_on:
+ - master
+ - volume
+ restart: unless-stopped
+ # # Secure the GUI with username/password
+ # labels:
+ # # htpasswd -nb admin admin
+ # - "traefik.http.middlewares.basic-auth.basicauth.users=admin:$$apr1$$aLLYxhdC$$ZAW26eJfBRC8qWjCkcZns."
+ # - "traefik.http.routers.service-name.middlewares=basic-auth"
+ healthcheck:
+ test: ["CMD", "wget", "-q", "--spider", "http://localhost:8888"]
+ interval: 30s
+ timeout: 10s
+ retries: 3
+ deploy:
+ resources:
+ limits:
+ memory: 1G
+ reservations:
+ memory: 512M
+ expose:
+ - 8888
+
+ s3:
+ image: chrislusf/seaweedfs:4.02
+ command: >
+ -v=0
+ s3
+ -filer="filer:8888"
+ -ip.bind=0.0.0.0
+ -port=8333
+ environment:
+ - AWS_ACCESS_KEY_ID=${S3_ACCESS_KEY}
+ - AWS_SECRET_ACCESS_KEY=${S3_SECRET_KEY}
+ restart: unless-stopped
+ deploy:
+ resources:
+ limits:
+ memory: 512M
+ reservations:
+ memory: 256M
+ expose:
+ - 8333
+
+volumes:
+ seaweedfs-master:
+ seaweedfs-volume:
+ seaweedfs-filer:
diff --git a/blueprints/seaweedfs/seaweedfs.svg b/blueprints/seaweedfs/seaweedfs.svg
new file mode 100644
index 00000000..61fce568
--- /dev/null
+++ b/blueprints/seaweedfs/seaweedfs.svg
@@ -0,0 +1,317 @@
+
+
+
+
diff --git a/blueprints/seaweedfs/template.toml b/blueprints/seaweedfs/template.toml
new file mode 100644
index 00000000..a72ae280
--- /dev/null
+++ b/blueprints/seaweedfs/template.toml
@@ -0,0 +1,27 @@
+[variables]
+main_domain = "${domain}"
+filer_domain = "filer.${domain}"
+master_domain = "master.${domain}"
+s3_domain = "s3.${domain}"
+
+[config]
+mounts = []
+
+[[config.domains]]
+serviceName = "filer"
+port = 8888
+host = "${filer_domain}"
+
+[[config.domains]]
+serviceName = "master"
+port = 9333
+host = "${master_domain}"
+
+[[config.domains]]
+serviceName = "s3"
+port = 8333
+host = "${s3_domain}"
+
+[config.env]
+S3_ACCESS_KEY = "admin"
+S3_SECRET_KEY = "${password:16}"
diff --git a/blueprints/strapi/docker-compose.yml b/blueprints/strapi/docker-compose.yml
new file mode 100644
index 00000000..6ac724fc
--- /dev/null
+++ b/blueprints/strapi/docker-compose.yml
@@ -0,0 +1,58 @@
+# Self-host guide:
+# - https://strapi.io/blog/how-to-self-host-your-headless-cms-using-docker-compose
+
+services:
+ strapi:
+ image: elestio/strapi-production:v5.33.0
+ environment:
+ # https://docs.strapi.io/cms/configurations/environment
+ NODE_ENV: production
+ STRAPI_TELEMETRY_DISABLED: true
+ STRAPI_PLUGIN_I18N_INIT_LOCALE_CODE: en
+ FAST_REFRESH: true
+ JWT_SECRET: ${JWT_SECRET}
+ ADMIN_JWT_SECRET: ${ADMIN_JWT_SECRET}
+ DATABASE_CLIENT: postgres
+ DATABASE_HOST: strapi_postgres
+ DATABASE_PORT: 5432
+ DATABASE_NAME: strapi
+ DATABASE_USERNAME: strapi
+ DATABASE_PASSWORD: ${POSTGRES_PASSWORD}
+ volumes:
+ - strapi_data:/srv/app
+ expose:
+ - 1337
+ depends_on:
+ - strapi_postgres
+ healthcheck:
+ test:
+ - CMD
+ - wget
+ - "-q"
+ - "--spider"
+ - "http://127.0.0.1:1337"
+ start_period: 3s
+ interval: 30s
+ timeout: 10s
+ retries: 5
+
+ strapi_postgres:
+ image: postgres:18
+ environment:
+ POSTGRES_DB: strapi
+ POSTGRES_USER: strapi
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
+ volumes:
+ - strapi_postgres_data:/var/lib/postgresql
+ healthcheck:
+ test:
+ - CMD-SHELL
+ - "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"
+ start_period: 3s
+ interval: 30s
+ timeout: 10s
+ retries: 5
+
+volumes:
+ strapi_data:
+ strapi_postgres_data:
diff --git a/blueprints/strapi/strapi.svg b/blueprints/strapi/strapi.svg
new file mode 100644
index 00000000..1e4ed993
--- /dev/null
+++ b/blueprints/strapi/strapi.svg
@@ -0,0 +1,23 @@
+
diff --git a/blueprints/strapi/template.toml b/blueprints/strapi/template.toml
new file mode 100644
index 00000000..0acddaf5
--- /dev/null
+++ b/blueprints/strapi/template.toml
@@ -0,0 +1,15 @@
+[variables]
+main_domain = "${domain}"
+postgres_password = "${password:32}"
+jwt_secret = "${password:32}"
+admin_jwt_secret = "${password:32}"
+
+[[config.domains]]
+serviceName = "strapi"
+port = 1337
+host = "${main_domain}"
+
+[config.env]
+POSTGRES_PASSWORD = "${postgres_password}"
+JWT_SECRET = "${jwt_secret}"
+ADMIN_JWT_SECRET = "${admin_jwt_secret}"
diff --git a/blueprints/streamflow/docker-compose.yml b/blueprints/streamflow/docker-compose.yml
new file mode 100644
index 00000000..cbfa8b51
--- /dev/null
+++ b/blueprints/streamflow/docker-compose.yml
@@ -0,0 +1,22 @@
+version: "3.8"
+services:
+ streamflow:
+ build:
+ context: https://github.com/bangtutorial/streamflow.git
+ restart: unless-stopped
+ environment:
+ - PORT=7575
+ - SESSION_SECRET=${SESSION_SECRET}
+ - NODE_ENV=production
+ - TZ=${TIMEZONE}
+ volumes:
+ - streamflow-db:/app/db
+ - streamflow-logs:/app/logs
+ - streamflow-uploads:/app/public/uploads
+ ports:
+ - 7575
+
+volumes:
+ streamflow-db: {}
+ streamflow-logs: {}
+ streamflow-uploads: {}
diff --git a/blueprints/streamflow/streamflow.png b/blueprints/streamflow/streamflow.png
new file mode 100644
index 00000000..ac281760
Binary files /dev/null and b/blueprints/streamflow/streamflow.png differ
diff --git a/blueprints/streamflow/template.toml b/blueprints/streamflow/template.toml
new file mode 100644
index 00000000..3867afaa
--- /dev/null
+++ b/blueprints/streamflow/template.toml
@@ -0,0 +1,15 @@
+[variables]
+main_domain = "${domain}"
+session_secret = "${password:64}"
+
+[config]
+[[config.domains]]
+serviceName = "streamflow"
+port = 7575
+host = "${main_domain}"
+
+[config.env]
+SESSION_SECRET = "${session_secret}"
+TIMEZONE = "Asia/Jakarta"
+
+[[config.mounts]]
diff --git a/blueprints/supabase/docker-compose.yml b/blueprints/supabase/docker-compose.yml
index 7d4dae81..506ddc90 100644
--- a/blueprints/supabase/docker-compose.yml
+++ b/blueprints/supabase/docker-compose.yml
@@ -77,6 +77,7 @@ services:
SUPABASE_SERVICE_KEY: ${SERVICE_ROLE_KEY}
DASHBOARD_USERNAME: ${DASHBOARD_USERNAME}
DASHBOARD_PASSWORD: ${DASHBOARD_PASSWORD}
+ CONTAINER_PREFIX: ${CONTAINER_PREFIX}
# https://unix.stackexchange.com/a/294837
entrypoint: bash -c 'eval "echo \"$$(cat ~/temp.yml)\"" > ~/kong.yml && /docker-entrypoint.sh kong docker-start'
diff --git a/blueprints/supabase/template.toml b/blueprints/supabase/template.toml
index 9f35f79c..f70c93cc 100644
--- a/blueprints/supabase/template.toml
+++ b/blueprints/supabase/template.toml
@@ -309,7 +309,7 @@ services:
## Secure Realtime routes
- name: realtime-v1-ws
_comment: 'Realtime: /realtime/v1/* -> ws://realtime:4000/socket/*'
- url: http://realtime-dev.supabase-realtime:4000/socket
+ url: http://realtime-dev.${CONTAINER_PREFIX}-realtime:4000/socket
protocol: ws
routes:
- name: realtime-v1-ws
@@ -329,7 +329,7 @@ services:
- anon
- name: realtime-v1-rest
_comment: 'Realtime: /realtime/v1/* -> ws://realtime:4000/socket/*'
- url: http://realtime-dev.supabase-realtime:4000/api
+ url: http://realtime-dev.${CONTAINER_PREFIX}-realtime:4000/api
protocol: http
routes:
- name: realtime-v1-rest
@@ -850,7 +850,7 @@ transforms:
kong: '.appname == "supabase-kong"'
auth: '.appname == "supabase-auth"'
rest: '.appname == "supabase-rest"'
- realtime: '.appname == "realtime-dev.supabase-realtime"'
+ realtime: '.appname == "realtime-dev.${CONTAINER_PREFIX}-realtime"'
storage: '.appname == "supabase-storage"'
functions: '.appname == "supabase-edge-functions"'
db: '.appname == "supabase-db"'
diff --git a/blueprints/superset/docker-compose.yml b/blueprints/superset/docker-compose.yml
index 076fe0a8..3a20fd04 100644
--- a/blueprints/superset/docker-compose.yml
+++ b/blueprints/superset/docker-compose.yml
@@ -15,23 +15,14 @@
# ## NETWORK INSTRUCTIONS
#
# If you want to connect superset with other internal databases managed by
-# Dokploy (on dokploy-network) using internal hostnames, you will need to
-# uncomment the `networks` section, both for the superset container and
-# at the very bottom of this docker-compose template.
+# Dokploy using internal hostnames, you will need to connect the `superset`
+# container to those networks.
#
-# Note that the `superset` service name/hostname will not be unique on the
-# global `dokploy-network`. If you plan to:
-#
-# 1. deploy a second instance of superset on dokploy-network, and
-# 2. have other containers on dokploy-network utilise the second instance's
-# Superset API (https://superset.apache.org/docs/api)
-#
-# Please change the service name of the second instance.
services:
superset:
- image: amancevice/superset
- restart: always
+ image: amancevice/superset:6.0.0
+ restart: unless-stopped
#networks:
# - dokploy-network
depends_on:
@@ -52,14 +43,14 @@ services:
REDIS_HOST: superset_redis
superset_postgres:
- image: postgres
- restart: always
+ image: postgres:18
+ restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB}
volumes:
- - superset_postgres_data:/var/lib/postgresql/data
+ - superset_postgres_data:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
interval: 30s
@@ -67,8 +58,8 @@ services:
retries: 3
superset_redis:
- image: redis
- restart: always
+ image: redis:8
+ restart: unless-stopped
volumes:
- superset_redis_data:/data
command: redis-server --requirepass ${REDIS_PASSWORD}
@@ -78,10 +69,6 @@ services:
timeout: 10s
retries: 3
-#networks:
-# dokploy-network:
-# external: true
-
volumes:
superset_postgres_data:
superset_redis_data:
diff --git a/blueprints/superset/template.toml b/blueprints/superset/template.toml
index ec4535fd..7cee12fc 100644
--- a/blueprints/superset/template.toml
+++ b/blueprints/superset/template.toml
@@ -3,7 +3,6 @@ main_domain = "${domain}"
secret_key = "${password:30}"
postgres_password = "${password:30}"
redis_password = "${password:30}"
-mapbox_api_key = ""
[[config.domains]]
serviceName = "superset"
@@ -12,7 +11,7 @@ host = "${main_domain}"
[config.env]
SECRET_KEY = "${secret_key}"
-MAPBOX_API_KEY = "${mapbox_api_key}"
+MAPBOX_API_KEY = ""
POSTGRES_DB = "superset"
POSTGRES_USER = "superset"
POSTGRES_PASSWORD = "${postgres_password}"
diff --git a/blueprints/syncthing/docker-compose.yml b/blueprints/syncthing/docker-compose.yml
new file mode 100644
index 00000000..e6083a7b
--- /dev/null
+++ b/blueprints/syncthing/docker-compose.yml
@@ -0,0 +1,19 @@
+services:
+ syncthing:
+ image: lscr.io/linuxserver/syncthing:latest
+ restart: unless-stopped
+ expose:
+ - 8384
+ - 22000
+ - 21027/udp
+ volumes:
+ - syncthing_config:/config
+ - syncthing_data:/var/syncthing/Sync
+ environment:
+ - PUID=1000
+ - PGID=1000
+ - TZ=${timezone}
+
+volumes:
+ syncthing_config:
+ syncthing_data:
diff --git a/blueprints/syncthing/syncthing.svg b/blueprints/syncthing/syncthing.svg
new file mode 100644
index 00000000..de8850f5
--- /dev/null
+++ b/blueprints/syncthing/syncthing.svg
@@ -0,0 +1,54 @@
+
+
+
diff --git a/blueprints/syncthing/template.toml b/blueprints/syncthing/template.toml
new file mode 100644
index 00000000..eda476e4
--- /dev/null
+++ b/blueprints/syncthing/template.toml
@@ -0,0 +1,9 @@
+[variables]
+main_domain = "${domain}"
+timezone = "America/Sao_Paulo"
+
+[config]
+[[config.domains]]
+serviceName = "syncthing"
+port = 8384
+host = "${main_domain}"
diff --git a/blueprints/tailscale-exitnode/template.toml b/blueprints/tailscale-exitnode/template.toml
index eac3e68e..cc03571f 100644
--- a/blueprints/tailscale-exitnode/template.toml
+++ b/blueprints/tailscale-exitnode/template.toml
@@ -1,4 +1,4 @@
[config.env]
TAILSCALE_HOSTNAME = ""
-TAILSCALE_APIKEY = ""
\ No newline at end of file
+TAILSCALE_AUTHKEY = ""
\ No newline at end of file
diff --git a/blueprints/trilium-next/docker-compose.yml b/blueprints/trilium-next/docker-compose.yml
new file mode 100755
index 00000000..6ffc82a5
--- /dev/null
+++ b/blueprints/trilium-next/docker-compose.yml
@@ -0,0 +1,23 @@
+# Running `docker-compose up` will create/use the "trilium-data" directory in the user home
+services:
+ trilium_next:
+ # Optionally, replace `latest` with a version tag like `v0.110.3`
+ # Using `latest` may cause unintended updates to the container
+ image: triliumnext/trilium:v0.101.3
+ # Restart the container unless it was stopped by the user
+ restart: unless-stopped
+ environment:
+ - TRILIUM_DATA_DIR=/home/node/trilium-data
+ ports:
+ # By default, Trilium will be available at http://localhost:8080
+ # It will also be accessible at http://:8080
+ # You might want to limit this with something like Docker Networks, reverse proxies, or firewall rules,
+ # however be aware that using UFW is known to not work with default Docker installations, see:
+ # https://docs.docker.com/engine/network/packet-filtering-firewalls/#docker-and-ufw
+ - "8080"
+ volumes:
+ # Unless TRILIUM_DATA_DIR is set, the data will be stored in the "trilium-data" directory in the home directory.
+ # This can also be changed with by replacing the line below with `- /path/of/your/choice:/home/node/trilium-data
+ - ${TRILIUM_DATA_DIR:-~/trilium-data}:/home/node/trilium-data
+ - /etc/timezone:/etc/timezone:ro
+ - /etc/localtime:/etc/localtime:ro
diff --git a/blueprints/trilium-next/template.toml b/blueprints/trilium-next/template.toml
new file mode 100755
index 00000000..0292bb68
--- /dev/null
+++ b/blueprints/trilium-next/template.toml
@@ -0,0 +1,13 @@
+[variables]
+main_domain = "${domain}"
+
+[config]
+env = [
+"TRILIUM_DATA_DIR=/root"
+]
+mount = []
+
+[[config.domains]]
+serviceName = "trilium_next"
+port = 8080
+host = "${main_domain}"
diff --git a/blueprints/trilium-next/trilium-next-logo.svg b/blueprints/trilium-next/trilium-next-logo.svg
new file mode 100644
index 00000000..79f47a82
--- /dev/null
+++ b/blueprints/trilium-next/trilium-next-logo.svg
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/blueprints/trmnl-byos-laravel/docker-compose.yml b/blueprints/trmnl-byos-laravel/docker-compose.yml
index f571719d..61674d23 100644
--- a/blueprints/trmnl-byos-laravel/docker-compose.yml
+++ b/blueprints/trmnl-byos-laravel/docker-compose.yml
@@ -1,6 +1,6 @@
services:
trmnl-byos-laravel:
- image: ghcr.io/usetrmnl/byos_laravel:0.21.0
+ image: ghcr.io/usetrmnl/byos_laravel:0.27.0
environment:
- APP_URL=${APP_URL}
- PHP_OPCACHE_ENABLE=${PHP_OPCACHE_ENABLE}
diff --git a/blueprints/umami/docker-compose.yml b/blueprints/umami/docker-compose.yml
index b20524a7..6cd51601 100644
--- a/blueprints/umami/docker-compose.yml
+++ b/blueprints/umami/docker-compose.yml
@@ -1,6 +1,6 @@
services:
umami:
- image: ghcr.io/umami-software/umami:postgresql-v2.19.0
+ image: ghcr.io/umami-software/umami:3.0.3
restart: always
healthcheck:
test: ["CMD-SHELL", "curl http://localhost:3000/api/heartbeat"]
diff --git a/blueprints/uptime-kuma/docker-compose.yml b/blueprints/uptime-kuma/docker-compose.yml
index ca80a8a3..f50c2013 100644
--- a/blueprints/uptime-kuma/docker-compose.yml
+++ b/blueprints/uptime-kuma/docker-compose.yml
@@ -1,7 +1,7 @@
version: "3.8"
services:
uptime-kuma:
- image: louislam/uptime-kuma:1.23.15
+ image: louislam/uptime-kuma:2.1.0
restart: always
volumes:
- uptime-kuma-data:/app/data
diff --git a/blueprints/vikunja/docker-compose.yml b/blueprints/vikunja/docker-compose.yml
index 11b744b0..0d1c7fbe 100644
--- a/blueprints/vikunja/docker-compose.yml
+++ b/blueprints/vikunja/docker-compose.yml
@@ -1,17 +1,17 @@
-version: "3.8"
-
services:
vikunja:
image: vikunja/vikunja
+ user: "0:0"
environment:
- VIKUNJA_SERVICE_PUBLICURL: http://vikunja.local
- VIKUNJA_DATABASE_HOST: db
+ VIKUNJA_SERVICE_PUBLICURL: ${VIKUNJA_SERVICE_PUBLICURL}
+ VIKUNJA_PUBLIC_PORT: ${VIKUNJA_PUBLIC_PORT}
+ VIKUNJA_DATABASE_HOST: ${VIKUNJA_DATABASE_HOST}
VIKUNJA_DATABASE_PASSWORD: ${VIKUNJA_DATABASE_PASSWORD}
- VIKUNJA_DATABASE_TYPE: postgres
- VIKUNJA_DATABASE_USER: vikunja
- VIKUNJA_DATABASE_DATABASE: vikunja
+ VIKUNJA_DATABASE_TYPE: ${VIKUNJA_DATABASE_TYPE}
+ VIKUNJA_DATABASE_USER: ${VIKUNJA_DATABASE_USER}
+ VIKUNJA_DATABASE_DATABASE: ${VIKUNJA_DATABASE_DATABASE}
VIKUNJA_SERVICE_JWTSECRET: ${VIKUNJA_SERVICE_JWTSECRET}
- expose:
+ ports:
- 3456
volumes:
- vikunja-files:/app/vikunja/files
@@ -24,15 +24,16 @@ services:
image: postgres:17
environment:
POSTGRES_PASSWORD: ${VIKUNJA_DATABASE_PASSWORD}
- POSTGRES_USER: vikunja
- POSTGRES_DB: vikunja
+ POSTGRES_USER: ${VIKUNJA_DATABASE_USER}
+ POSTGRES_DB: ${VIKUNJA_DATABASE_DATABASE}
volumes:
- vikunja-db:/var/lib/postgresql/data
restart: unless-stopped
healthcheck:
- test: ["CMD-SHELL", "pg_isready -h localhost -U $$POSTGRES_USER"]
- interval: 2s
- start_period: 30s
+ test: ["CMD-SHELL", "pg_isready", "-U", "${VIKUNJA_DATABASE_USER}", "-d", "${VIKUNJA_DATABASE_DATABASE}"]
+ interval: 10s
+ timeout: 5s
+ retries: 3
volumes:
vikunja-files: {}
diff --git a/blueprints/vikunja/template.toml b/blueprints/vikunja/template.toml
index 0a4e88f9..1740d3e6 100644
--- a/blueprints/vikunja/template.toml
+++ b/blueprints/vikunja/template.toml
@@ -18,10 +18,6 @@ VIKUNJA_DATABASE_USER = "vikunja"
VIKUNJA_DATABASE_DATABASE = "vikunja"
VIKUNJA_SERVICE_JWTSECRET = "${jwt_secret}"
-POSTGRES_PASSWORD = "${db_password}"
-POSTGRES_USER = "vikunja"
-POSTGRES_DB = "vikunja"
-
[[config.mounts]]
serviceName = "vikunja"
volumeName = "vikunja-files"
diff --git a/blueprints/wg-easy/docker-compose.yml b/blueprints/wg-easy/docker-compose.yml
index 1161bb12..0a98f6d9 100644
--- a/blueprints/wg-easy/docker-compose.yml
+++ b/blueprints/wg-easy/docker-compose.yml
@@ -3,24 +3,23 @@ volumes:
services:
wg-easy:
- image: ghcr.io/wg-easy/wg-easy:15
- restart: unless-stopped
environment:
- - WG_HOST=${WIREGUARD_HOST}
- - PASSWORD=${WIREGUARD_PASSWORD}
- - WG_PORT=51820
+ - INIT_ENABLED=1
+ - INIT_HOST=${WIREGUARD_HOST}
+ - INIT_PORT=51820
+ - INIT_USERNAME=admin
+ - INIT_PASSWORD=${WIREGUARD_PASSWORD}
+ - INIT_DNS=1.1.1.1,8.8.8.8
- PORT=51821
- - WG_MTU=1280
- - WG_DEFAULT_DNS=1.1.1.1,8.8.8.8
- - WG_ALLOWED_IPS=0.0.0.0/0
- - WG_POST_UP=iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE; iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT;
- - WG_POST_DOWN=iptables -t nat -D POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE; iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT;
+ image: ghcr.io/wg-easy/wg-easy:15
+ container_name: wg-easy
volumes:
- etc_wireguard:/etc/wireguard
- /lib/modules:/lib/modules:ro
ports:
- "51820:51820/udp"
- "51821:51821/tcp"
+ restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_MODULE
diff --git a/blueprints/wuzapi/docker-compose.yml b/blueprints/wuzapi/docker-compose.yml
new file mode 100644
index 00000000..87b5b8b8
--- /dev/null
+++ b/blueprints/wuzapi/docker-compose.yml
@@ -0,0 +1,36 @@
+version: "3.8"
+services:
+ wuzapi-server:
+ image: asternic/wuzapi:sha-30c1805
+ restart: unless-stopped
+ expose:
+ - 8080
+ environment:
+ - WUZAPI_ADMIN_TOKEN=${WUZAPI_ADMIN_TOKEN}
+ - WUZAPI_GLOBAL_ENCRYPTION_KEY=${WUZAPI_GLOBAL_ENCRYPTION_KEY}
+ - DB_USER=${DB_USER:-wuzapi}
+ - DB_PASSWORD=${DB_PASSWORD:-wuzapi}
+ - DB_NAME=${DB_NAME:-wuzapi}
+ - DB_HOST=db
+ - DB_PORT=5432
+ - TZ=${TZ:-UTC}
+ depends_on:
+ - db
+
+ db:
+ image: postgres:16-alpine
+ restart: always
+ environment:
+ POSTGRES_USER: ${DB_USER:-wuzapi}
+ POSTGRES_PASSWORD: ${DB_PASSWORD:-wuzapi}
+ POSTGRES_DB: ${DB_NAME:-wuzapi}
+ volumes:
+ - db_data:/var/lib/postgresql/data
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U $${DB_USER:-wuzapi}"]
+ interval: 5s
+ timeout: 5s
+ retries: 5
+
+volumes:
+ db_data:
diff --git a/blueprints/wuzapi/template.toml b/blueprints/wuzapi/template.toml
new file mode 100644
index 00000000..71d95c49
--- /dev/null
+++ b/blueprints/wuzapi/template.toml
@@ -0,0 +1,20 @@
+[variables]
+main_domain = "${domain}"
+admin_token = "${password:32}"
+encryption_key = "${password:32}"
+db_user = "wuzapi"
+db_password = "${password:32}"
+db_name = "wuzapi"
+
+[config]
+[[config.domains]]
+serviceName = "wuzapi-server"
+port = 8080
+host = "${main_domain}"
+
+[config.env]
+WUZAPI_ADMIN_TOKEN = "${admin_token}"
+WUZAPI_GLOBAL_ENCRYPTION_KEY = "${encryption_key}"
+DB_USER = "${db_user}"
+DB_PASSWORD = "${db_password}"
+DB_NAME = "${db_name}"
diff --git a/blueprints/wuzapi/wuzapi.png b/blueprints/wuzapi/wuzapi.png
new file mode 100644
index 00000000..f48f5d33
Binary files /dev/null and b/blueprints/wuzapi/wuzapi.png differ
diff --git a/meta.json b/meta.json
index a9f88590..723047d4 100644
--- a/meta.json
+++ b/meta.json
@@ -365,8 +365,8 @@
{
"id": "appwrite",
"name": "Appwrite",
- "version": "1.6.1",
- "description": "Appwrite is an end-to-end backend server for Web, Mobile, Native, or Backend apps. Appwrite abstracts the complexity and repetitiveness required to build a modern backend API from scratch and allows you to build secure apps faster.\nUsing Appwrite, you can easily integrate your app with user authentication and multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, messaging, and more services.",
+ "version": "1.8.0",
+ "description": "Appwrite is an end-to-end platform for building Web, Mobile, Native, or Backend apps, packaged as a set of Docker microservices. It includes both a backend server and a fully integrated hosting solution for deploying static and server-side rendered frontends. Appwrite abstracts the complexity and repetitiveness required to build modern apps from scratch and allows you to build secure, full-stack applications faster.\nUsing Appwrite, you can easily integrate your app with user authentication and multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, messaging, and more services.",
"links": {
"github": "https://github.com/appwrite/appwrite",
"website": "https://appwrite.io/",
@@ -376,7 +376,9 @@
"tags": [
"database",
"firebase",
- "postgres"
+ "mariadb",
+ "hosting",
+ "self-hosted"
]
},
{
@@ -508,8 +510,8 @@
{
"id": "autobase",
"name": "Autobase",
- "version": "2.3.0",
- "description": "Autobase for PostgreSQL® is an open-source alternative to cloud-managed databases (DBaaS) such as Amazon RDS, Google Cloud SQL, Azure Database, and more.",
+ "version": "2.5.2",
+ "description": "Autobase for PostgreSQL® is an open-source alternative to cloud-managed databases (self-hosted DBaaS).",
"links": {
"github": "https://github.com/vitabaks/autobase",
"website": "https://autobase.tech/",
@@ -1297,6 +1299,23 @@
"console"
]
},
+ {
+ "id": "cloudflare-ddns",
+ "name": "Cloudflare DDNS",
+ "version": "1.15.1",
+ "description": "A small, feature-rich, and robust Cloudflare DDNS updater.",
+ "logo": "cloudflare-ddns.svg",
+ "links": {
+ "github": "https://github.com/favonia/cloudflare-ddns",
+ "website": "https://github.com/favonia/cloudflare-ddns",
+ "docs": "https://github.com/favonia/cloudflare-ddns"
+ },
+ "tags": [
+ "cloud",
+ "networking",
+ "ddns"
+ ]
+ },
{
"id": "cloudflared",
"name": "Cloudflared",
@@ -1305,8 +1324,8 @@
"logo": "cloudflared.svg",
"links": {
"github": "https://github.com/cloudflare/cloudflared",
- "website": "https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/",
- "docs": "https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/"
+ "website": "https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/",
+ "docs": "https://developers.cloudflare.com/cloudflare-one/networks/connectors/cloudflare-tunnel/get-started/"
},
"tags": [
"cloud",
@@ -1315,6 +1334,24 @@
"tunnel"
]
},
+ {
+ "id": "cloudreve",
+ "name": "Cloudreve",
+ "version": "4.10.1",
+ "description": "Self-hosted file management and sharing system with multi-cloud storage support. Compatible with local, OneDrive, S3, and various cloud providers.",
+ "logo": "cloudreve.png",
+ "links": {
+ "github": "https://github.com/cloudreve/Cloudreve",
+ "website": "https://cloudreve.org",
+ "docs": "https://docs.cloudreve.org"
+ },
+ "tags": [
+ "storage",
+ "file-sharing",
+ "cloud",
+ "self-hosted"
+ ]
+ },
{
"id": "cockpit",
"name": "Cockpit",
@@ -2101,6 +2138,23 @@
"media system"
]
},
+ {
+ "id": "emqx",
+ "name": "EMQX",
+ "version": "6.0.1",
+ "description": "A scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles",
+ "logo": "emqx.svg",
+ "links": {
+ "github": "https://github.com/emqx/emqx",
+ "website": "https://www.emqx.com",
+ "docs": "https://docs.emqx.com"
+ },
+ "tags": [
+ "broker",
+ "iot",
+ "mqtt"
+ ]
+ },
{
"id": "enshrouded",
"name": "Enshrouded",
@@ -3116,6 +3170,23 @@
"events"
]
},
+ {
+ "id": "instantdb",
+ "name": "InstantDB",
+ "version": "latest",
+ "description": "InstantDB is a real-time database server that provides instant data synchronization and real-time updates for applications.",
+ "logo": "instant.svg",
+ "links": {
+ "github": "https://github.com/instantdb/instant/tree/main/server",
+ "website": "https://github.com/instantdb/instant",
+ "docs": "https://github.com/instantdb/instant"
+ },
+ "tags": [
+ "database",
+ "real-time",
+ "self-hosted"
+ ]
+ },
{
"id": "invoiceshelf",
"name": "InvoiceShelf",
@@ -3133,6 +3204,24 @@
"finance"
]
},
+ {
+ "id": "ipfs",
+ "name": "IPFS (Kubo)",
+ "version": "latest",
+ "description": "IPFS (Kubo) is a decentralized peer-to-peer file sharing and storage network node. Host your own IPFS gateway and API.",
+ "logo": "ipfs.svg",
+ "links": {
+ "github": "https://github.com/ipfs/kubo",
+ "website": "https://ipfs.tech/",
+ "docs": "https://docs.ipfs.tech/"
+ },
+ "tags": [
+ "storage",
+ "decentralized",
+ "p2p",
+ "self-hosted"
+ ]
+ },
{
"id": "it-tools",
"name": "IT Tools",
@@ -3182,6 +3271,25 @@
"media system"
]
},
+ {
+ "id": "jenkins",
+ "name": "jenkins",
+ "version": "latest",
+ "description": "Jenkins is a free, open-source automation server that helps developers build, test, and deploy software by automating repetitive tasks in the software delivery pipeline.",
+ "logo": "jenkins.svg",
+ "links": {
+ "github": "https://github.com/jenkinsci/jenkins",
+ "website": "https://www.jenkins.io/",
+ "docs": "https://www.jenkins.io/doc/"
+ },
+ "tags": [
+ "ci-cd",
+ "devops",
+ "automation",
+ "pipelines",
+ "open-source"
+ ]
+ },
{
"id": "kaneo",
"name": "Kaneo",
@@ -3342,6 +3450,22 @@
"web"
]
},
+ {
+ "id": "komari-monitor",
+ "name": "Komari Monitor",
+ "version": "latest",
+ "description": "A lightweight, self-hosted server monitoring tool for tracking server performance.",
+ "logo": "komari-monitor.ico",
+ "links": {
+ "github": "https://github.com/komari-monitor/komari",
+ "website": "https://github.com/komari-monitor/komari",
+ "docs": "https://github.com/komari-monitor/komari#readme"
+ },
+ "tags": [
+ "monitoring",
+ "self-hosted"
+ ]
+ },
{
"id": "kutt",
"name": "Kutt",
@@ -3373,6 +3497,22 @@
"ai"
]
},
+ {
+ "id": "lavalink",
+ "name": "Lavalink",
+ "version": "4.1.1",
+ "description": "Lavalink is an open source standalone audio sending node based on Lavaplayer.",
+ "logo": "lavalink.svg",
+ "links": {
+ "github": "https://github.com/lavalink-devs/Lavalink",
+ "website": "https://lavalink.dev/",
+ "docs": "https://lavalink.dev/getting-started/index.html"
+ },
+ "tags": [
+ "voice",
+ "discord"
+ ]
+ },
{
"id": "letterfeed",
"name": "Letterfeed",
@@ -3682,6 +3822,24 @@
"self-hosted"
]
},
+ {
+ "id": "mautic",
+ "name": "Mautic",
+ "version": "5.1.1",
+ "description": "Mautic is the world's largest open-source marketing automation project. It allows you to automate the process of finding and nurturing contacts through landing pages and forms, sending email, text messages, web notifications, and tracking your contacts.",
+ "logo": "mautic.svg",
+ "links": {
+ "github": "https://github.com/mautic/mautic",
+ "website": "https://www.mautic.org/",
+ "docs": "https://docs.mautic.org/en"
+ },
+ "tags": [
+ "marketing",
+ "automation",
+ "email",
+ "crm"
+ ]
+ },
{
"id": "maybe",
"name": "Maybe",
@@ -3836,6 +3994,24 @@
"media"
]
},
+ {
+ "id": "minepanel",
+ "name": "Minepanel",
+ "version": "1.7.1",
+ "description": "Web panel for managing Minecraft servers with Docker. Create, configure, start/stop, and monitor multiple instances from a modern UI.",
+ "logo": "minepanel.webp",
+ "links": {
+ "github": "https://github.com/Ketbome/minepanel",
+ "website": "https://minepanel.ketbome.lat",
+ "docs": "https://minepanel.ketbome.lat"
+ },
+ "tags": [
+ "gaming",
+ "minecraft",
+ "server-management",
+ "docker"
+ ]
+ },
{
"id": "minio",
"name": "Minio",
@@ -3851,6 +4027,23 @@
"storage"
]
},
+ {
+ "id": "misaka-danmu-server",
+ "name": "Misaka Danmu Server",
+ "version": "latest",
+ "description": "A self-hosted danmaku (bullet comments) server for live streaming and video platforms.",
+ "logo": "misaka-danmu-server.png",
+ "links": {
+ "github": "https://github.com/l429609201/misaka_danmu_server",
+ "website": "https://github.com/l429609201/misaka_danmu_server",
+ "docs": "https://github.com/l429609201/misaka_danmu_server#readme"
+ },
+ "tags": [
+ "streaming",
+ "danmaku",
+ "live"
+ ]
+ },
{
"id": "mixpost",
"name": "Mixpost",
@@ -4171,8 +4364,8 @@
"description": "Obsidian LiveSync with CouchDB for real-time note synchronization.",
"logo": "obsidian.png",
"links": {
- "github": "https://github.com/apache/couchdb",
- "website": "https://couchdb.apache.org/",
+ "github": "https://github.com/vrtmrz/obsidian-livesync",
+ "website": "https://obsidian.md/sync",
"docs": "https://docs.couchdb.apache.org/"
},
"tags": [
@@ -4362,6 +4555,27 @@
"surrealdb"
]
},
+ {
+ "id": "openclaw",
+ "name": "Openclaw",
+ "version": "2026.1.29",
+ "description": "WhatsApp gateway CLI with Pi RPC agent - self-hosted AI-powered messaging platform",
+ "logo": "openclaw.svg",
+ "links": {
+ "github": "https://github.com/openclaw/openclaw",
+ "website": "https://openclaw.ai/",
+ "docs": "https://docs.openclaw.ai/"
+ },
+ "tags": [
+ "whatsapp",
+ "ai",
+ "messaging",
+ "chatbot",
+ "gateway",
+ "self-hosted",
+ "automation"
+ ]
+ },
{
"id": "opengist",
"name": "OpenGist",
@@ -4910,6 +5124,25 @@
"webmail"
]
},
+ {
+ "id": "postgres-pgdog",
+ "name": "PostgreSQL with PgDog",
+ "version": "0.1.26",
+ "description": "PostgreSQL database with PgDog connection pooler, load balancer, and horizontal scaling proxy. A modern alternative to PgBouncer with multi-threading support.",
+ "logo": "postgres-pgdog.png",
+ "links": {
+ "github": "https://github.com/pgdogdev/pgdog",
+ "website": "https://pgdog.dev",
+ "docs": "https://docs.pgdog.dev"
+ },
+ "tags": [
+ "database",
+ "postgresql",
+ "pooler",
+ "proxy",
+ "load-balancer"
+ ]
+ },
{
"id": "postgresus",
"name": "Postgresus",
@@ -4996,6 +5229,24 @@
"management"
]
},
+ {
+ "id": "pulse",
+ "name": "Pulse",
+ "version": "latest",
+ "description": "A responsive monitoring platform for Proxmox VE, PBS, and Docker with real-time metrics across nodes and containers.",
+ "logo": "pulse.svg",
+ "links": {
+ "github": "https://github.com/rcourtman/Pulse",
+ "website": "https://pulserelay.pro/",
+ "docs": "https://github.com/rcourtman/Pulse/blob/main/docs/README.md"
+ },
+ "tags": [
+ "monitoring",
+ "proxmox",
+ "docker",
+ "metrics"
+ ]
+ },
{
"id": "pyrodactyl",
"name": "Pyrodactyl",
@@ -5030,6 +5281,24 @@
"file-sharing"
]
},
+ {
+ "id": "qbitwebui",
+ "name": "qBittorrent Web UI",
+ "version": "latest",
+ "description": "A modern web interface for managing multiple qBittorrent instances. Built with React, Hono, and Bun.",
+ "logo": "qbitwebui.png",
+ "links": {
+ "github": "https://github.com/Maciejonos/qbitwebui",
+ "website": "https://github.com/Maciejonos/qbitwebui",
+ "docs": "https://github.com/Maciejonos/qbitwebui#readme"
+ },
+ "tags": [
+ "torrent",
+ "download",
+ "media",
+ "qbittorrent"
+ ]
+ },
{
"id": "qdrant",
"name": "Qdrant",
@@ -5288,6 +5557,22 @@
"self-hosted"
]
},
+ {
+ "id": "scrutiny",
+ "name": "Scrutiny",
+ "version": "latest",
+ "description": "Hard Drive S.M.A.R.T Monitoring, Historical Trends & Real World Failure Thresholds",
+ "logo": "scrutiny.png",
+ "links": {
+ "github": "https://github.com/AnalogJ/scrutiny/",
+ "website": "",
+ "docs": ""
+ },
+ "tags": [
+ "monitoring",
+ "NAS"
+ ]
+ },
{
"id": "scrypted",
"name": "Scrypted",
@@ -5342,6 +5627,25 @@
"aggregator"
]
},
+ {
+ "id": "seaweedfs",
+ "name": "SeaweedFS",
+ "version": "latest",
+ "description": "SeaweedFS is a fast distributed storage system for blobs, objects, and files. Features S3-compatible API, POSIX FUSE mount, and WebDAV support.",
+ "logo": "seaweedfs.svg",
+ "links": {
+ "github": "https://github.com/seaweedfs/seaweedfs",
+ "website": "https://seaweedfs.com/",
+ "docs": "https://github.com/seaweedfs/seaweedfs/wiki"
+ },
+ "tags": [
+ "storage",
+ "s3",
+ "distributed",
+ "object-storage",
+ "file-system"
+ ]
+ },
{
"id": "shlink",
"name": "Shlink",
@@ -5554,6 +5858,43 @@
"open-source"
]
},
+ {
+ "id": "streamflow",
+ "name": "StreamFlow",
+ "version": "2.1",
+ "description": "StreamFlow is a multi-platform live streaming web application that enables simultaneous RTMP streaming to YouTube, Facebook, and other platforms with video gallery, scheduled streaming, and real-time monitoring.",
+ "logo": "streamflow.png",
+ "links": {
+ "github": "https://github.com/bangtutorial/streamflow",
+ "website": "https://github.com/bangtutorial/streamflow",
+ "docs": "https://github.com/bangtutorial/streamflow#readme"
+ },
+ "tags": [
+ "streaming",
+ "rtmp",
+ "video",
+ "live-streaming",
+ "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",
@@ -5575,7 +5916,7 @@
{
"id": "superset",
"name": "Superset (Unofficial)",
- "version": "latest",
+ "version": "6.0.0",
"description": "Data visualization and data exploration platform.",
"logo": "superset.svg",
"links": {
@@ -5608,6 +5949,23 @@
"surrealdb"
]
},
+ {
+ "id": "syncthing",
+ "name": "Syncthing",
+ "version": "latest",
+ "description": "Syncthing is a continuous file synchronization program that synchronizes files between two or more computers in real time.",
+ "logo": "syncthing.svg",
+ "links": {
+ "github": "https://github.com/syncthing/syncthing",
+ "website": "https://syncthing.net/",
+ "docs": "https://docs.syncthing.net/"
+ },
+ "tags": [
+ "file-sync",
+ "synchronization",
+ "backup"
+ ]
+ },
{
"id": "tailscale-exitnode",
"name": "Tailscale Exit nodes",
@@ -5762,10 +6120,27 @@
"personal-use"
]
},
+ {
+ "id": "trilium-next",
+ "name": "TriliumNext",
+ "version": "latest",
+ "description": "Is a free and open-source, cross-platform hierarchical note taking application with focus on building large personal knowledge bases.",
+ "logo": "trilium-next-logo.svg",
+ "links": {
+ "github": "https://github.com/TriliumNext/Trilium",
+ "website": "https://triliumnotes.org/",
+ "docs": "https://docs.triliumnotes.org/"
+ },
+ "tags": [
+ "self-hosted",
+ "productivity",
+ "personal-use"
+ ]
+ },
{
"id": "trmnl-byos-laravel",
"name": "TRMNL BYOS Laravel",
- "version": "0.21.0",
+ "version": "0.27.0",
"description": "TRMNL BYOS Laravel is a self-hosted application to manage TRMNL e-ink devices.",
"logo": "byos-laravel.svg",
"links": {
@@ -5846,7 +6221,7 @@
{
"id": "umami",
"name": "Umami",
- "version": "v2.19.0",
+ "version": "v3.0.3",
"description": "Umami is a simple, fast, privacy-focused alternative to Google Analytics.",
"logo": "umami.png",
"links": {
@@ -5895,7 +6270,7 @@
{
"id": "uptime-kuma",
"name": "Uptime Kuma",
- "version": "1.23.15",
+ "version": "2.1.0",
"description": "Uptime Kuma is a free and open source monitoring tool that allows you to monitor your websites and applications.",
"logo": "uptime-kuma.png",
"links": {
@@ -5983,7 +6358,7 @@
"description": "Vikunja is a self-hosted, open-source to-do list application to organize tasks, projects, and notes.",
"logo": "image.png",
"links": {
- "github": "https://kolaente.dev/vikunja/",
+ "github": "https://github.com/go-vikunja/vikunja",
"website": "https://vikunja.io/",
"docs": "https://vikunja.io/docs/"
},
@@ -6132,6 +6507,24 @@
"cms"
]
},
+ {
+ "id": "wuzapi",
+ "name": "WuzAPI",
+ "version": "v1.0.0",
+ "description": "A RESTful API service for WhatsApp with multiple device support and concurrent sessions.",
+ "logo": "wuzapi.png",
+ "links": {
+ "github": "https://github.com/asternic/wuzapi",
+ "website": "https://www.wuzapi.app/",
+ "docs": "https://github.com/asternic/wuzapi/blob/main/README.md"
+ },
+ "tags": [
+ "api",
+ "whatsapp",
+ "messaging",
+ "automation"
+ ]
+ },
{
"id": "xsshunter",
"name": "XSSHunter",