Compare commits
@@ -6,22 +6,36 @@ x-logging: &x-logging
|
||||
max-size: "10m"
|
||||
services:
|
||||
appwrite:
|
||||
image: appwrite/appwrite:2.5.0
|
||||
image: appwrite/appwrite:2.7.0
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
# Dokploy generates the specific routers (console, API, realtime) from the
|
||||
# domains declared in template.toml, naming them
|
||||
# "<appName>-<uniqueConfigKey>-<entrypoint>" and never setting a priority.
|
||||
# Their priority is therefore Traefik's default: the length of the rule.
|
||||
# The wildcard routers below are owned by this template, and a HostRegexp
|
||||
# rule is longer than a Host rule, so without an explicit priority they can
|
||||
# outrank the console/API router whenever the wildcard also matches the
|
||||
# host (for example a Sites/Functions wildcard rooted at the same apex as
|
||||
# the console). Pin every wildcard router to the lowest useful priority so
|
||||
# the specific router always wins; 1 is below any rule-derived priority.
|
||||
- 'traefik.http.routers.appwrite-sites-wildcard.rule=HostRegexp(`^.+\.${_APP_DOMAIN_SITES}$$`)'
|
||||
- traefik.http.routers.appwrite-sites-wildcard.priority=1
|
||||
- traefik.http.routers.appwrite-sites-wildcard.entrypoints=web
|
||||
- traefik.http.routers.appwrite-sites-wildcard.service=appwrite-wildcard
|
||||
- 'traefik.http.routers.appwrite-sites-wildcard-secure.rule=HostRegexp(`^.+\.${_APP_DOMAIN_SITES}$$`)'
|
||||
- traefik.http.routers.appwrite-sites-wildcard-secure.priority=1
|
||||
- traefik.http.routers.appwrite-sites-wildcard-secure.entrypoints=websecure
|
||||
- traefik.http.routers.appwrite-sites-wildcard-secure.tls=true
|
||||
- traefik.http.routers.appwrite-sites-wildcard-secure.service=appwrite-wildcard
|
||||
- 'traefik.http.routers.appwrite-functions-wildcard.rule=HostRegexp(`^.+\.${_APP_DOMAIN_FUNCTIONS}$$`)'
|
||||
- traefik.http.routers.appwrite-functions-wildcard.priority=1
|
||||
- traefik.http.routers.appwrite-functions-wildcard.entrypoints=web
|
||||
- traefik.http.routers.appwrite-functions-wildcard.service=appwrite-wildcard
|
||||
- 'traefik.http.routers.appwrite-functions-wildcard-secure.rule=HostRegexp(`^.+\.${_APP_DOMAIN_FUNCTIONS}$$`)'
|
||||
- traefik.http.routers.appwrite-functions-wildcard-secure.priority=1
|
||||
- traefik.http.routers.appwrite-functions-wildcard-secure.entrypoints=websecure
|
||||
- traefik.http.routers.appwrite-functions-wildcard-secure.tls=true
|
||||
- traefik.http.routers.appwrite-functions-wildcard-secure.service=appwrite-wildcard
|
||||
@@ -29,7 +43,7 @@ services:
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
- 'curl -fsS -o /dev/null -H "Host: $${_APP_DOMAIN:-localhost}" http://localhost/v1/health/version'
|
||||
- 'test -f /tmp/.appwrite-ready && curl -fsS -o /dev/null -H "Host: $${_APP_DOMAIN:-localhost}" http://localhost/v1/health/version'
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 12
|
||||
@@ -52,8 +66,13 @@ services:
|
||||
condition: service_started
|
||||
appwrite-autogravity:
|
||||
condition: service_started
|
||||
appwrite-exiftool:
|
||||
condition: service_started
|
||||
environment:
|
||||
- _APP_DNS_EXTERNAL
|
||||
- _APP_ALLOWED_INTERNAL_ADDRESSES
|
||||
- _APP_ENV
|
||||
- _APP_MEMORY_LIMIT
|
||||
- _APP_EDITION
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_LOCALE
|
||||
@@ -86,7 +105,12 @@ services:
|
||||
- _APP_OPTIONS_ROUTER_FORCE_HTTPS
|
||||
- _APP_ROUTER_AUTO_CERTIFICATES
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_OPENSSL_KEY_V2
|
||||
- _APP_OPENSSL_KEY_CURRENT
|
||||
- _APP_OPENSSL_KEY_OLDEST
|
||||
- _APP_NOTIFICATIONS_TRACKING_SECRET
|
||||
- _APP_NOTIFICATIONS_PUSH_APNS
|
||||
- _APP_NOTIFICATIONS_PUSH_APNS_KEY
|
||||
- _APP_DOMAIN
|
||||
- _APP_CONSOLE_DOMAIN
|
||||
- _APP_CONSOLE_URL
|
||||
@@ -97,6 +121,7 @@ services:
|
||||
- _APP_DOMAIN_TARGET_CAA
|
||||
- _APP_DNS
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_DOMAIN_FUNCTIONS_FALLBACK
|
||||
- _APP_DOMAIN_SITES
|
||||
- _APP_CUSTOM_DOMAIN_DENY_LIST
|
||||
- _APP_TRUSTED_HEADERS
|
||||
@@ -134,6 +159,7 @@ services:
|
||||
- _APP_CONNECTIONS_DATABASE_VECTORSDB
|
||||
- _APP_EMBEDDING
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_ALERTS_USAGE_LAG
|
||||
- _APP_USAGE_PASS
|
||||
- _APP_CONNECTIONS_DB_USAGE
|
||||
- _APP_POOL_SIZE_USAGE
|
||||
@@ -153,6 +179,7 @@ services:
|
||||
- _APP_STORAGE_LIMIT
|
||||
- _APP_STORAGE_PREVIEW_LIMIT
|
||||
- _APP_AUTOGRAVITY_HOST
|
||||
- _APP_EXIFTOOL_HOST
|
||||
- _APP_STORAGE_ANTIVIRUS
|
||||
- _APP_STORAGE_ANTIVIRUS_HOST
|
||||
- _APP_STORAGE_ANTIVIRUS_PORT
|
||||
@@ -162,6 +189,7 @@ services:
|
||||
- _APP_STORAGE_S3_REGION
|
||||
- _APP_STORAGE_S3_BUCKET
|
||||
- _APP_STORAGE_S3_ENDPOINT
|
||||
- _APP_STORAGE_S3_PATH_STYLE
|
||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
||||
- _APP_STORAGE_DO_SPACES_SECRET
|
||||
- _APP_STORAGE_DO_SPACES_REGION
|
||||
@@ -194,6 +222,7 @@ services:
|
||||
- _APP_JOBS_HOST
|
||||
- _APP_JOBS_SECRET
|
||||
- _APP_JOBS_ENDPOINT
|
||||
# - _APP_REVIEWS_SECRET # uncomment with the optional reviews setup
|
||||
- _APP_GEO_SECRET
|
||||
- _APP_GEO_ENDPOINT
|
||||
- _APP_LOGGING_CONFIG
|
||||
@@ -205,6 +234,7 @@ services:
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
|
||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
||||
- _APP_MAINTENANCE_RETENTION_ALERTS
|
||||
- _APP_GRAPHQL_INTROSPECTION
|
||||
- _APP_GRAPHQL_MAX_BATCH_SIZE
|
||||
- _APP_GRAPHQL_MAX_COMPLEXITY
|
||||
@@ -229,6 +259,10 @@ services:
|
||||
- _APP_VCS_BITBUCKET_WEBHOOK_SECRET
|
||||
- _APP_VCS_ORIGIN_CLIENT_ID
|
||||
- _APP_VCS_ORIGIN_PRIVATE_KEY
|
||||
- _APP_VCS_ENTIRE_PLUGIN
|
||||
- _APP_VCS_ENTIRE_PRIVATE_KEY
|
||||
- _APP_VCS_ENTIRE_ISSUER
|
||||
- _APP_VCS_ENTIRE_ENDPOINT
|
||||
- _APP_VCS_WEBHOOK_URL
|
||||
- _APP_MIGRATION_HOST
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
|
||||
@@ -237,16 +271,17 @@ services:
|
||||
- _APP_PWNED_PASSWORDS_DSN
|
||||
|
||||
appwrite-console:
|
||||
image: appwrite/new:1.2.74-self-hosted
|
||||
image: appwrite/new:1.2.138-self-hosted
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- VITE_CONSOLE_PROFILE=self-hosted
|
||||
- VITE_APPWRITE_VERSION=${_APP_VERSION:-2.7.0}
|
||||
- APPWRITE_ENDPOINT_SAME_ORIGIN=true
|
||||
- VITE_GROWTH_ENDPOINT=https://growth.appwrite.io/v1
|
||||
|
||||
appwrite-realtime:
|
||||
image: appwrite/appwrite:2.5.0
|
||||
image: appwrite/appwrite:2.7.0
|
||||
entrypoint: realtime
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
@@ -257,12 +292,19 @@ services:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_MEMORY_LIMIT
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPTIONS_ABUSE
|
||||
- _APP_OPTIONS_ROUTER_PROTECTION
|
||||
- _APP_CONSOLE_HOSTNAMES
|
||||
- _APP_REALTIME_TAIL_RATE
|
||||
- _APP_LIMIT_REALTIME_SUBSCRIPTIONS
|
||||
- _APP_LIMIT_REALTIME_CHANNELS
|
||||
- _APP_LIMIT_REALTIME_QUERIES
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_OPENSSL_KEY_V2
|
||||
- _APP_OPENSSL_KEY_CURRENT
|
||||
- _APP_OPENSSL_KEY_OLDEST
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
@@ -298,7 +340,7 @@ services:
|
||||
- _APP_LOGGING_FORMAT
|
||||
|
||||
appwrite-mqtt:
|
||||
image: appwrite/appwrite:2.5.0
|
||||
image: appwrite/appwrite:2.7.0
|
||||
entrypoint: mqtt
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
@@ -319,11 +361,15 @@ services:
|
||||
start_period: 20s
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_MEMORY_LIMIT
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPTIONS_ABUSE
|
||||
- _APP_OPTIONS_ROUTER_PROTECTION
|
||||
- _APP_REALTIME_TAIL_RATE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_OPENSSL_KEY_V2
|
||||
- _APP_OPENSSL_KEY_CURRENT
|
||||
- _APP_OPENSSL_KEY_OLDEST
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
@@ -348,7 +394,7 @@ services:
|
||||
- _APP_MQTT_MAX_PACKET_SIZE
|
||||
|
||||
appwrite-worker:
|
||||
image: appwrite/appwrite:2.5.0
|
||||
image: appwrite/appwrite:2.7.0
|
||||
entrypoint: worker
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
@@ -369,13 +415,21 @@ services:
|
||||
extra_hosts:
|
||||
- host.docker.internal:host-gateway
|
||||
environment:
|
||||
- _APP_DNS_EXTERNAL
|
||||
- _APP_ALLOWED_INTERNAL_ADDRESSES
|
||||
- _APP_ENV
|
||||
- _APP_MEMORY_LIMIT
|
||||
- _APP_WORKERS_NUM=1
|
||||
# Pool sizing only (sum of per-queue caps). Each queue keeps its own maxCoroutines in PHP; databases stays at 1.
|
||||
- _APP_WORKER_MAX_COROUTINES=78
|
||||
# Pool sizing only (sum of per-queue caps). Each queue keeps its own maxCoroutines in PHP; databases and maintenance stay at 1.
|
||||
- _APP_WORKER_MAX_COROUTINES=83
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_OPENSSL_KEY_V2
|
||||
- _APP_OPENSSL_KEY_CURRENT
|
||||
- _APP_OPENSSL_KEY_OLDEST
|
||||
- _APP_NOTIFICATIONS_TRACKING_SECRET
|
||||
- _APP_NOTIFICATIONS_PUSH_APNS
|
||||
- _APP_NOTIFICATIONS_PUSH_APNS_KEY
|
||||
- _APP_EMAIL_SECURITY
|
||||
- _APP_EMAIL_CERTIFICATES
|
||||
- _APP_REDIS_HOST
|
||||
@@ -408,6 +462,7 @@ services:
|
||||
- _APP_CONNECTIONS_DATABASE_VECTORSDB
|
||||
- _APP_EMBEDDING
|
||||
- _APP_USAGE_STATS
|
||||
- _APP_ALERTS_USAGE_LAG
|
||||
- _APP_USAGE_PASS
|
||||
- _APP_CONNECTIONS_DB_USAGE
|
||||
- _APP_POOL_SIZE_USAGE
|
||||
@@ -416,6 +471,7 @@ services:
|
||||
- _APP_MAINTENANCE_RETENTION_USAGE_TTL
|
||||
- _APP_STATS_USAGE_QUEUE_NAME
|
||||
- _APP_STATS_RESOURCES_QUEUE_NAME
|
||||
- _APP_MAINTENANCE_QUEUE_NAME
|
||||
- _APP_STATS_RESOURCES_INTERVAL
|
||||
- _APP_LOGGING_CONFIG
|
||||
- _APP_LOGGING_FORMAT
|
||||
@@ -440,6 +496,7 @@ services:
|
||||
- _APP_STORAGE_S3_REGION
|
||||
- _APP_STORAGE_S3_BUCKET
|
||||
- _APP_STORAGE_S3_ENDPOINT
|
||||
- _APP_STORAGE_S3_PATH_STYLE
|
||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
||||
- _APP_STORAGE_DO_SPACES_SECRET
|
||||
- _APP_STORAGE_DO_SPACES_REGION
|
||||
@@ -491,6 +548,10 @@ services:
|
||||
- _APP_VCS_BITBUCKET_WEBHOOK_SECRET
|
||||
- _APP_VCS_ORIGIN_CLIENT_ID
|
||||
- _APP_VCS_ORIGIN_PRIVATE_KEY
|
||||
- _APP_VCS_ENTIRE_PLUGIN
|
||||
- _APP_VCS_ENTIRE_PRIVATE_KEY
|
||||
- _APP_VCS_ENTIRE_ISSUER
|
||||
- _APP_VCS_ENTIRE_ENDPOINT
|
||||
- _APP_VCS_WEBHOOK_URL
|
||||
- _APP_SYSTEM_EMAIL_NAME
|
||||
- _APP_SYSTEM_EMAIL_ADDRESS
|
||||
@@ -509,7 +570,7 @@ services:
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
|
||||
|
||||
appwrite-task-scheduler:
|
||||
image: appwrite/appwrite:2.5.0
|
||||
image: appwrite/appwrite:2.7.0
|
||||
entrypoint: schedule
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
@@ -520,11 +581,15 @@ services:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_MEMORY_LIMIT
|
||||
# Combined mode runs functions/executions/messages timers + enqueue coroutines
|
||||
# against shared console/cache pools; floor must cover concurrent ticks.
|
||||
- _APP_WORKER_MAX_COROUTINES=8
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_OPENSSL_KEY_V2
|
||||
- _APP_OPENSSL_KEY_CURRENT
|
||||
- _APP_OPENSSL_KEY_OLDEST
|
||||
- _APP_OPTIONS_FORCE_HTTPS
|
||||
- _APP_DOMAIN
|
||||
- _APP_CONSOLE_DOMAIN
|
||||
@@ -552,12 +617,16 @@ services:
|
||||
- _APP_MAINTENANCE_RETENTION_USAGE_TTL
|
||||
- _APP_STATS_USAGE_QUEUE_NAME
|
||||
- _APP_STATS_RESOURCES_QUEUE_NAME
|
||||
- _APP_MAINTENANCE_QUEUE_NAME
|
||||
- _APP_STATS_RESOURCES_INTERVAL
|
||||
- _APP_FUNCTIONS_SCHEDULE_SPREAD
|
||||
- _APP_MAINTENANCE_INACTIVE_INTERVAL
|
||||
- _APP_MAINTENANCE_INTERVAL
|
||||
- _APP_ALERTS_INTERVAL
|
||||
- _APP_LOGGING_FORMAT
|
||||
|
||||
appwrite-task-maintenance:
|
||||
image: appwrite/appwrite:2.5.0
|
||||
image: appwrite/appwrite:2.7.0
|
||||
entrypoint: maintenance
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
@@ -568,6 +637,7 @@ services:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_MEMORY_LIMIT
|
||||
- _APP_EDITION
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_DOMAIN
|
||||
@@ -579,6 +649,9 @@ services:
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_ROUTER_AUTO_CERTIFICATES
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_OPENSSL_KEY_V2
|
||||
- _APP_OPENSSL_KEY_CURRENT
|
||||
- _APP_OPENSSL_KEY_OLDEST
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
@@ -598,10 +671,11 @@ services:
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
|
||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
||||
- _APP_MAINTENANCE_RETENTION_ALERTS
|
||||
- _APP_LOGGING_FORMAT
|
||||
|
||||
appwrite-task-interval:
|
||||
image: appwrite/appwrite:2.5.0
|
||||
image: appwrite/appwrite:2.7.0
|
||||
entrypoint: interval
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
@@ -612,6 +686,7 @@ services:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
- _APP_ENV
|
||||
- _APP_MEMORY_LIMIT
|
||||
- _APP_WORKER_PER_CORE
|
||||
- _APP_DOMAIN
|
||||
- _APP_DOMAIN_TARGET_CNAME
|
||||
@@ -622,6 +697,9 @@ services:
|
||||
- _APP_DOMAIN_FUNCTIONS
|
||||
- _APP_DOMAIN_SITES
|
||||
- _APP_OPENSSL_KEY_V1
|
||||
- _APP_OPENSSL_KEY_V2
|
||||
- _APP_OPENSSL_KEY_CURRENT
|
||||
- _APP_OPENSSL_KEY_OLDEST
|
||||
- _APP_REDIS_HOST
|
||||
- _APP_REDIS_PORT
|
||||
- _APP_REDIS_USER
|
||||
@@ -638,7 +716,7 @@ services:
|
||||
- _APP_LOGGING_FORMAT
|
||||
|
||||
appwrite-browser:
|
||||
image: appwrite/browser:0.3.6
|
||||
image: appwrite/browser:0.3.10
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
@@ -649,6 +727,35 @@ services:
|
||||
- 1.1.1.1
|
||||
- 8.8.8.8
|
||||
|
||||
# AI code review for GitHub pull requests (optional, shipped off by default).
|
||||
# The Reviews screen is hidden in the self-hosted console profile, so this
|
||||
# worker would run with nowhere to configure it from. To opt in:
|
||||
# 1. uncomment the _APP_REVIEWS_* variables in template.toml (this enables
|
||||
# the /v1/reviews API and generates the shared secret);
|
||||
# 2. uncomment this service;
|
||||
# 3. set _APP_REVIEWS_AI_GATEWAY_KEY, otherwise no review ever runs.
|
||||
# appwrite-hansi:
|
||||
# image: ghcr.io/appwrite/hansi:0.4.2
|
||||
# <<: *x-logging
|
||||
# restart: unless-stopped
|
||||
# # A stopped review is not redelivered for about a day, so a running one gets time to finish.
|
||||
# stop_grace_period: 16m
|
||||
# depends_on:
|
||||
# redis:
|
||||
# condition: service_healthy
|
||||
# appwrite:
|
||||
# condition: service_started
|
||||
# environment:
|
||||
# - HANSI_APPWRITE_ENDPOINT=http://appwrite/v1
|
||||
# - HANSI_APPWRITE_SECRET=${_APP_REVIEWS_SECRET}
|
||||
# - HANSI_QUEUE_URL=redis://${_APP_REDIS_HOST:-redis}:${_APP_REDIS_PORT:-6379}
|
||||
# - HANSI_QUEUE_USER=${_APP_REDIS_USER}
|
||||
# - HANSI_QUEUE_PASSWORD=${_APP_REDIS_PASS}
|
||||
# - HANSI_SHUTDOWN_TIMEOUT=900
|
||||
# - HANSI_REVIEW_MODEL=${_APP_REVIEWS_MODEL}
|
||||
# - HANSI_VERIFY_MODEL=${_APP_REVIEWS_VERIFY_MODEL:-${_APP_REVIEWS_MODEL}}
|
||||
# - AI_GATEWAY_API_KEY=${_APP_REVIEWS_AI_GATEWAY_KEY}
|
||||
|
||||
appwrite-autogravity:
|
||||
image: ghcr.io/appwrite/autogravity:0.0.11
|
||||
<<: *x-logging
|
||||
@@ -656,6 +763,11 @@ services:
|
||||
environment:
|
||||
- MODEL_BACKEND=focalnet
|
||||
|
||||
appwrite-exiftool:
|
||||
image: ghcr.io/appwrite/exiftool:0.1.1
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
|
||||
appwrite-geo:
|
||||
image: appwrite/geo:0.3.2
|
||||
<<: *x-logging
|
||||
@@ -738,7 +850,7 @@ services:
|
||||
start_period: 5s
|
||||
|
||||
orchestrator:
|
||||
image: ghcr.io/open-runtimes/orchestrator/orchestrator:2.2.2
|
||||
image: ghcr.io/open-runtimes/orchestrator/orchestrator:4.0.0
|
||||
hostname: orchestrator
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
@@ -761,6 +873,8 @@ services:
|
||||
image: appwrite/postgres:0.1.0
|
||||
<<: *x-logging
|
||||
restart: unless-stopped
|
||||
init: true
|
||||
shm_size: 1g
|
||||
volumes:
|
||||
- appwrite-postgresql:/var/lib/postgresql:rw
|
||||
environment:
|
||||
@@ -769,6 +883,9 @@ services:
|
||||
- POSTGRES_PASSWORD=${_APP_DB_PASS}
|
||||
command:
|
||||
- postgres
|
||||
# Every HTTP worker and worker coroutine pools its own connections; the default of 100 runs out under load.
|
||||
- -c
|
||||
- max_connections=${_APP_DB_MAX_CONNECTIONS:-500}
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD-SHELL
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "appwrite",
|
||||
"name": "Appwrite",
|
||||
"version": "2.5.0",
|
||||
"version": "2.7.0",
|
||||
"description": "Appwrite is an end-to-end platform for building Web, Mobile, Native, or Backend apps, packaged as a set of Docker microservices. It includes both a backend server and a fully integrated hosting solution for deploying static and server-side rendered frontends. Appwrite abstracts the complexity and repetitiveness required to build modern apps from scratch and allows you to build secure, full-stack applications faster.\nUsing Appwrite, you can easily integrate your app with user authentication and multiple sign-in methods, a database for storing and querying users and team data, storage and file management, image manipulation, Cloud Functions, messaging, and more services.",
|
||||
"links": {
|
||||
"github": "https://github.com/appwrite/appwrite",
|
||||
|
||||
@@ -12,6 +12,9 @@ usage_pw = "${password:32}"
|
||||
executor_secret = "${password:32}"
|
||||
jobs_secret = "${password:32}"
|
||||
geo_secret = "${password:32}"
|
||||
# Optional AI code review of GitHub pull requests. Uncomment together with the
|
||||
# _APP_REVIEWS_* variables and the appwrite-hansi service in docker-compose.yml.
|
||||
# reviews_secret = "${password:32}"
|
||||
console_domain = "console.${main_domain}"
|
||||
|
||||
[config]
|
||||
@@ -20,6 +23,8 @@ console_domain = "console.${main_domain}"
|
||||
isolated = false
|
||||
env = [
|
||||
"_APP_ENV=production",
|
||||
"_APP_VERSION=2.7.0",
|
||||
"_APP_MEMORY_LIMIT=512M",
|
||||
"_APP_EDITION=self-hosted",
|
||||
"_APP_LOCALE=en",
|
||||
"_APP_WORKER_PER_CORE=6",
|
||||
@@ -31,7 +36,12 @@ env = [
|
||||
"_APP_ROUTER_AUTO_CERTIFICATES=enabled",
|
||||
"_APP_LOCKING_ENABLED=enabled",
|
||||
"_APP_OPENSSL_KEY_V1=${openssl_key}",
|
||||
"_APP_OPENSSL_KEY_V2=",
|
||||
"_APP_OPENSSL_KEY_CURRENT=1",
|
||||
"_APP_OPENSSL_KEY_OLDEST=1",
|
||||
"_APP_NOTIFICATIONS_TRACKING_SECRET=${notifications_tracking_secret}",
|
||||
"_APP_NOTIFICATIONS_PUSH_APNS=",
|
||||
"_APP_NOTIFICATIONS_PUSH_APNS_KEY=",
|
||||
"_APP_DOMAIN=${main_domain}",
|
||||
"_APP_CONSOLE_DOMAIN=${console_domain}",
|
||||
"_APP_CONSOLE_URL=https://${console_domain}",
|
||||
@@ -39,17 +49,19 @@ env = [
|
||||
"_APP_CONSOLE_TRUSTED_PROJECTS=",
|
||||
"_APP_CUSTOM_DOMAIN_DENY_LIST=example.com,test.com,app.example.com",
|
||||
"_APP_DOMAIN_FUNCTIONS=${functions_domain}",
|
||||
"_APP_DOMAIN_FUNCTIONS_FALLBACK=",
|
||||
"_APP_DOMAIN_SITES=${sites_domain}",
|
||||
"_APP_DOMAIN_TARGET_CNAME=localhost",
|
||||
"_APP_DOMAIN_TARGET_AAAA=::1",
|
||||
"_APP_DOMAIN_TARGET_A=127.0.0.1",
|
||||
"_APP_DOMAIN_TARGET_CAA=",
|
||||
"_APP_DNS=8.8.8.8",
|
||||
"_APP_DNS_EXTERNAL=",
|
||||
"_APP_ALLOWED_INTERNAL_ADDRESSES=",
|
||||
"_APP_TRUSTED_HEADERS=x-forwarded-for",
|
||||
"_APP_CONSOLE_WHITELIST_ROOT=enabled",
|
||||
"_APP_CONSOLE_WHITELIST_EMAILS=",
|
||||
"_APP_CONSOLE_WHITELIST_IPS=",
|
||||
"_APP_CONSOLE_HOSTNAMES=",
|
||||
"_APP_CONSOLE_SCHEMA=appwriteio",
|
||||
"_APP_CONSOLE_SESSION_ALERTS=disabled",
|
||||
"_APP_CONSOLE_COUNTRIES_DENYLIST=",
|
||||
@@ -113,9 +125,15 @@ env = [
|
||||
"_APP_MAINTENANCE_RETENTION_USAGE_TTL=180",
|
||||
"_APP_STATS_USAGE_QUEUE_NAME=v1-stats-usage",
|
||||
"_APP_STATS_RESOURCES_QUEUE_NAME=v1-stats-resources",
|
||||
"_APP_MAINTENANCE_QUEUE_NAME=v1-maintenance",
|
||||
"_APP_STATS_RESOURCES_INTERVAL=3600",
|
||||
"_APP_ALERTS_INTERVAL=60",
|
||||
"_APP_ALERTS_USAGE_LAG=120",
|
||||
"_APP_MQTT_REPLAY_DEPTH=5",
|
||||
"_APP_MQTT_MAX_PACKET_SIZE=64000",
|
||||
"_APP_LIMIT_REALTIME_SUBSCRIPTIONS=100",
|
||||
"_APP_LIMIT_REALTIME_CHANNELS=100",
|
||||
"_APP_LIMIT_REALTIME_QUERIES=100",
|
||||
"_APP_SMTP_HOST=",
|
||||
"_APP_SMTP_PORT=",
|
||||
"_APP_SMTP_SECURE=",
|
||||
@@ -128,6 +146,7 @@ env = [
|
||||
"_APP_STORAGE_LIMIT=30000000",
|
||||
"_APP_STORAGE_PREVIEW_LIMIT=20000000",
|
||||
"_APP_AUTOGRAVITY_HOST=http://appwrite-autogravity:8080",
|
||||
"_APP_EXIFTOOL_HOST=http://appwrite-exiftool:8080",
|
||||
"_APP_STORAGE_ANTIVIRUS=disabled",
|
||||
"_APP_STORAGE_ANTIVIRUS_HOST=clamav",
|
||||
"_APP_STORAGE_ANTIVIRUS_PORT=3310",
|
||||
@@ -137,6 +156,7 @@ env = [
|
||||
"_APP_STORAGE_S3_REGION=us-east-1",
|
||||
"_APP_STORAGE_S3_BUCKET=",
|
||||
"_APP_STORAGE_S3_ENDPOINT=",
|
||||
"_APP_STORAGE_S3_PATH_STYLE=",
|
||||
"_APP_STORAGE_DO_SPACES_ACCESS_KEY=",
|
||||
"_APP_STORAGE_DO_SPACES_SECRET=",
|
||||
"_APP_STORAGE_DO_SPACES_REGION=us-east-1",
|
||||
@@ -174,11 +194,18 @@ env = [
|
||||
"_APP_JOBS_HOST=http://orchestrator:8080",
|
||||
"_APP_JOBS_SECRET=${jobs_secret}",
|
||||
"_APP_JOBS_ENDPOINT=http://appwrite",
|
||||
# Reviews are opt-in: the shared secret turns the /v1/reviews API on, and the
|
||||
# console hides the screen in the self-hosted profile regardless.
|
||||
# "_APP_REVIEWS_SECRET=${reviews_secret}",
|
||||
# "_APP_REVIEWS_MODEL=anthropic/claude-sonnet-4.5",
|
||||
# "_APP_REVIEWS_VERIFY_MODEL=",
|
||||
# "_APP_REVIEWS_AI_GATEWAY_KEY=",
|
||||
"_APP_BROWSER_HOST=http://appwrite-browser:3000/v1",
|
||||
"_APP_WORKER_SCREENSHOTS_ROUTER=http://appwrite",
|
||||
"_APP_DOCKER_HUB_USERNAME=",
|
||||
"_APP_DOCKER_HUB_PASSWORD=",
|
||||
"_APP_MAINTENANCE_INTERVAL=86400",
|
||||
"_APP_MAINTENANCE_INACTIVE_INTERVAL=604800",
|
||||
"_APP_MAINTENANCE_START_TIME=00:00",
|
||||
"_APP_MAINTENANCE_RETENTION_CACHE=2592000",
|
||||
"_APP_MAINTENANCE_RETENTION_EXECUTION=1209600",
|
||||
@@ -186,6 +213,7 @@ env = [
|
||||
"_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=15778800",
|
||||
"_APP_MAINTENANCE_RETENTION_ABUSE=86400",
|
||||
"_APP_MAINTENANCE_RETENTION_SCHEDULES=86400",
|
||||
"_APP_MAINTENANCE_RETENTION_ALERTS=7776000",
|
||||
"_APP_INTERVAL_DOMAIN_VERIFICATION=120",
|
||||
"_APP_INTERVAL_CLEANUP_STALE_EXECUTIONS=300",
|
||||
"_APP_GRAPHQL_INTROSPECTION=enabled",
|
||||
@@ -213,12 +241,17 @@ env = [
|
||||
"_APP_VCS_BITBUCKET_WEBHOOK_SECRET=",
|
||||
"_APP_VCS_ORIGIN_CLIENT_ID=",
|
||||
"_APP_VCS_ORIGIN_PRIVATE_KEY=",
|
||||
"_APP_VCS_ENTIRE_PLUGIN=",
|
||||
"_APP_VCS_ENTIRE_PRIVATE_KEY=",
|
||||
"_APP_VCS_ENTIRE_ISSUER=",
|
||||
"_APP_VCS_ENTIRE_ENDPOINT=",
|
||||
"_APP_VCS_WEBHOOK_URL=",
|
||||
"_APP_MIGRATION_HOST=appwrite",
|
||||
"_APP_MIGRATIONS_FIREBASE_CLIENT_ID=",
|
||||
"_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET=",
|
||||
"_APP_DB_ROOT_PASS=${db_root_pw}",
|
||||
"_APP_DB_USER_PASS=${db_user_pw}",
|
||||
"_APP_DB_MAX_CONNECTIONS=500",
|
||||
]
|
||||
|
||||
[[config.mounts]]
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
# dokploy: allow-host-ports — WoW clients connect directly over raw TCP (3724 authentication, 8085 world); Traefik cannot route the game protocol.
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
azerothcore-database:
|
||||
image: mysql:8.4.11
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
services:
|
||||
# Web app (public): named after the template, as Dokploy requires.
|
||||
cachkey:
|
||||
image: ghcr.io/joyboy-dy/cachkey-web:0.1.0
|
||||
image: ghcr.io/joyboy-dy/cachkey-web:0.2.0
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- 3000
|
||||
@@ -16,7 +16,7 @@ services:
|
||||
|
||||
# Applies pending database migrations at startup, then serves /api.
|
||||
cachkey-api:
|
||||
image: ghcr.io/joyboy-dy/cachkey-api:0.1.0
|
||||
image: ghcr.io/joyboy-dy/cachkey-api:0.2.0
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- 3001
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "cachkey",
|
||||
"name": "Cachkey",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"description": "Cachkey is an open-source, self-hosted manager for secrets and environment variables: encrypted values, per-environment access for your team, a CLI and a read-only API for servers and CI.",
|
||||
"logo": "cachkey.svg",
|
||||
"links": {
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="230px" height="24.673px" viewBox="0 0 230 24.673" enable-background="new 0 0 230 24.673" xml:space="preserve">
|
||||
<g>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M133.629,15.422c1.175,0,1.926-0.515,1.926-1.304c0-0.619-0.489-0.957-1.343-0.957h-1.849l-0.601,2.261
|
||||
H133.629z M133.161,18.398c1.183,0,1.924-0.498,1.924-1.313c0-0.667-0.629-1.005-1.511-1.005h-1.99l-0.619,2.318H133.161z
|
||||
M131.819,12.495h2.458c1.285,0,2.037,0.601,2.037,1.53c0,0.938-0.714,1.539-1.643,1.726c0.647,0.197,1.163,0.619,1.163,1.361
|
||||
c0,1.135-1.031,1.952-2.759,1.952h-3.021L131.819,12.495z"/>
|
||||
<path fill="#FFFFFF" d="M137.138,17.666c0-0.226,0.058-0.498,0.123-0.751l0.713-2.702h0.723l-0.741,2.749
|
||||
c-0.038,0.16-0.064,0.386-0.064,0.545c0,0.637,0.411,1.013,1.078,1.013c0.751,0,1.511-0.647,1.754-1.577l0.732-2.73h0.723
|
||||
l-1.295,4.851h-0.724l0.217-0.788c-0.441,0.497-0.957,0.892-1.698,0.892C137.749,19.167,137.138,18.585,137.138,17.666"/>
|
||||
</g>
|
||||
<path fill="#FFFFFF" d="M144.419,12.355h0.826l-0.217,0.797h-0.824L144.419,12.355z M143.97,14.212h0.722l-1.305,4.852h-0.722
|
||||
L143.97,14.212z"/>
|
||||
<polygon fill="#FFFFFF" points="147.075,12.214 147.797,12.214 145.958,19.064 145.235,19.064 "/>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M152.339,16.249c0-0.845-0.61-1.501-1.502-1.501c-1.154,0-2.026,1.07-2.026,2.309
|
||||
c0,0.901,0.562,1.482,1.37,1.482C151.26,18.539,152.339,17.441,152.339,16.249 M148.051,17.122c0-1.718,1.304-3.012,2.722-3.012
|
||||
c0.994,0,1.558,0.562,1.819,1.201l0.826-3.097h0.723l-1.83,6.85h-0.723l0.216-0.826c-0.46,0.525-1.051,0.938-1.83,0.938
|
||||
C148.876,19.176,148.051,18.351,148.051,17.122"/>
|
||||
<path fill="#FFFFFF" d="M158.333,14.851h-0.667l0.171-0.638h0.666l0.159-0.582c0.253-0.976,0.825-1.436,1.661-1.436
|
||||
c0.375,0,0.712,0.075,0.966,0.207l-0.17,0.619c-0.28-0.132-0.516-0.197-0.796-0.197c-0.46,0-0.808,0.282-0.977,0.92l-0.123,0.469
|
||||
h1.588l-0.18,0.638h-1.577l-1.134,4.213h-0.724L158.333,14.851z"/>
|
||||
<path fill="#FFFFFF" d="M164.057,17.159l0.093-0.337c-0.421-0.122-0.976-0.216-1.576-0.216c-0.863,0-1.454,0.469-1.454,1.135
|
||||
c0,0.517,0.403,0.863,1.032,0.863C162.968,18.604,163.821,18.013,164.057,17.159 M160.388,17.825c0-1.088,0.909-1.755,2.157-1.755
|
||||
c0.648,0,1.258,0.131,1.727,0.263l0.028-0.112c0.038-0.141,0.066-0.319,0.066-0.45c0-0.629-0.432-0.986-1.313-0.986
|
||||
c-0.518,0-0.939,0.103-1.37,0.253l-0.123-0.601c0.479-0.178,0.976-0.291,1.605-0.291c1.22,0,1.904,0.563,1.904,1.501
|
||||
c0,0.207-0.037,0.441-0.103,0.666l-0.732,2.75h-0.704l0.207-0.76c-0.45,0.516-1.041,0.863-1.812,0.863
|
||||
C161.11,19.167,160.388,18.688,160.388,17.825"/>
|
||||
<path fill="#FFFFFF" d="M165.651,18.323l0.469-0.469c0.525,0.507,1.106,0.713,1.689,0.713c0.553,0,1.069-0.32,1.069-0.807
|
||||
c0-0.319-0.217-0.554-0.921-0.826c-0.872-0.338-1.37-0.657-1.37-1.333c0-0.825,0.714-1.492,1.84-1.492
|
||||
c0.714,0,1.389,0.32,1.792,0.667l-0.422,0.497c-0.403-0.328-0.91-0.563-1.436-0.563c-0.685,0-1.052,0.366-1.052,0.77
|
||||
c0,0.319,0.198,0.525,0.968,0.826c0.873,0.356,1.322,0.704,1.322,1.333c0,0.901-0.825,1.53-1.857,1.53
|
||||
C166.992,19.167,166.214,18.886,165.651,18.323"/>
|
||||
<path fill="#FFFFFF" d="M171.074,18.191c0-0.169,0.027-0.356,0.064-0.507l0.761-2.834h-0.666l0.169-0.638h0.675l0.396-1.464h0.713
|
||||
l-0.395,1.464h1.529l-0.169,0.638h-1.529l-0.751,2.797c-0.019,0.112-0.037,0.253-0.037,0.356c0,0.337,0.253,0.497,0.665,0.497
|
||||
c0.217,0,0.441-0.046,0.705-0.149l-0.179,0.656c-0.254,0.103-0.488,0.141-0.77,0.141C171.562,19.148,171.074,18.82,171.074,18.191
|
||||
"/>
|
||||
<path fill="#FFFFFF" d="M173.794,19.881c0.545-0.141,0.807-0.414,0.882-0.817h-0.348l0.272-0.985h0.855l-0.227,0.845
|
||||
c-0.226,0.816-0.61,1.135-1.36,1.276L173.794,19.881z"/>
|
||||
<path fill="#FFFFFF" d="M184.378,16.118c0-0.713-0.562-1.37-1.492-1.37c-1.032,0-1.998,0.854-1.998,2.018
|
||||
c0,0.863,0.676,1.304,1.416,1.304C183.401,18.069,184.378,17.112,184.378,16.118 M179.489,19.74l0.45-0.507
|
||||
c0.516,0.441,1.173,0.732,1.914,0.732c0.61,0,1.069-0.197,1.36-0.498c0.301-0.291,0.47-0.666,0.61-1.163l0.131-0.488
|
||||
c-0.487,0.497-1.061,0.872-1.857,0.872c-1.013,0-1.971-0.666-1.971-1.83c0-1.614,1.36-2.749,2.722-2.749
|
||||
c1.041,0,1.511,0.582,1.782,1.163l0.282-1.06h0.723l-1.107,4.157c-0.207,0.75-0.441,1.182-0.789,1.53
|
||||
c-0.45,0.45-1.051,0.685-1.877,0.685C180.972,20.584,180.09,20.265,179.489,19.74"/>
|
||||
<path fill="#FFFFFF" d="M187.343,14.212h0.723l-0.33,1.267c0.593-0.845,1.343-1.408,2.31-1.352l-0.207,0.779h-0.047
|
||||
c-1.06,0-2.12,0.779-2.506,2.243l-0.515,1.914h-0.724L187.343,14.212z"/>
|
||||
<path fill="#FFFFFF" d="M194.491,16.305c0-0.985-0.619-1.558-1.52-1.558c-1.117,0-2.075,1.107-2.075,2.234
|
||||
c0,0.985,0.62,1.547,1.521,1.547C193.506,18.529,194.491,17.459,194.491,16.305 M190.166,17c0-1.511,1.303-2.891,2.852-2.891
|
||||
c1.333,0,2.214,0.911,2.214,2.168c0,1.549-1.342,2.9-2.861,2.9C191.038,19.177,190.166,18.257,190.166,17"/>
|
||||
</g>
|
||||
<polygon fill="#FFFFFF" points="196.459,14.212 197.19,14.212 197.444,18.079 199.791,14.194 200.391,14.194 200.663,18.079
|
||||
202.999,14.212 203.75,14.212 200.728,19.102 200.091,19.102 199.809,15.273 197.473,19.102 196.845,19.102 "/>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M206.461,18.323l0.469-0.469c0.525,0.507,1.106,0.713,1.688,0.713c0.554,0,1.07-0.32,1.07-0.807
|
||||
c0-0.319-0.216-0.554-0.92-0.826c-0.873-0.338-1.37-0.657-1.37-1.333c0-0.825,0.713-1.492,1.84-1.492
|
||||
c0.713,0,1.389,0.32,1.791,0.667l-0.422,0.497c-0.403-0.328-0.91-0.563-1.436-0.563c-0.685,0-1.051,0.366-1.051,0.77
|
||||
c0,0.319,0.197,0.525,0.967,0.826c0.873,0.356,1.323,0.704,1.323,1.333c0,0.901-0.826,1.53-1.857,1.53
|
||||
C207.802,19.167,207.022,18.886,206.461,18.323"/>
|
||||
<path fill="#FFFFFF" d="M216.05,16.305c0-0.985-0.619-1.558-1.521-1.558c-1.116,0-2.073,1.107-2.073,2.234
|
||||
c0,0.985,0.619,1.547,1.521,1.547C215.065,18.529,216.05,17.459,216.05,16.305 M211.723,17c0-1.511,1.306-2.891,2.854-2.891
|
||||
c1.333,0,2.216,0.911,2.216,2.168c0,1.549-1.343,2.9-2.862,2.9C212.596,19.177,211.723,18.257,211.723,17"/>
|
||||
</g>
|
||||
<polygon fill="#FFFFFF" points="219.408,12.214 220.131,12.214 218.291,19.064 217.568,19.064 "/>
|
||||
<path fill="#FFFFFF" d="M221.895,12.355h0.826l-0.217,0.797h-0.825L221.895,12.355z M221.443,14.212h0.724l-1.305,4.852h-0.724
|
||||
L221.443,14.212z"/>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M227.243,16.249c0-0.845-0.61-1.501-1.503-1.501c-1.154,0-2.026,1.07-2.026,2.309
|
||||
c0,0.901,0.563,1.482,1.37,1.482C226.163,18.539,227.243,17.441,227.243,16.249 M222.954,17.122c0-1.718,1.304-3.012,2.722-3.012
|
||||
c0.994,0,1.558,0.562,1.821,1.201l0.825-3.097h0.721l-1.829,6.85h-0.723l0.216-0.826c-0.46,0.525-1.051,0.938-1.83,0.938
|
||||
C223.779,19.176,222.954,18.351,222.954,17.122"/>
|
||||
</g>
|
||||
<polygon fill="#FFFFFF" points="229.146,18.079 228.874,19.064 229.738,19.064 230,18.079 "/>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M15.806,9.873l12.366,3.07c2.152-0.84,3.445-1.911,3.445-3.07V4.935C31.617,2.213,24.537,0,15.806,0
|
||||
C7.076,0,0,2.213,0,4.935v4.938c0,2.723,7.076,4.933,15.806,4.933V9.873z"/>
|
||||
<path fill="#FFFFFF" d="M28.171,17.879l-12.366-3.073v4.934l12.366,3.074c2.153-0.844,3.446-1.911,3.446-3.074v-4.934
|
||||
C31.618,15.969,30.324,17.036,28.171,17.879"/>
|
||||
<path fill="#FFFFFF" d="M0,14.806v4.935c0,2.724,7.076,4.933,15.806,4.933v-4.933C7.076,19.741,0,17.53,0,14.806"/>
|
||||
<path fill="#FFFFFF" d="M45.185,19.29c-3.861,0-6.727-2.98-6.727-6.747v-0.036c0-3.728,2.81-6.784,6.838-6.784
|
||||
c2.473,0,3.955,0.826,5.172,2.024l-1.836,2.117c-1.012-0.918-2.043-1.48-3.354-1.48c-2.212,0-3.803,1.836-3.803,4.084v0.039
|
||||
c0,2.248,1.554,4.122,3.803,4.122c1.499,0,2.416-0.599,3.446-1.537l1.836,1.854C49.213,18.39,47.714,19.29,45.185,19.29"/>
|
||||
<path fill="#FFFFFF" d="M58.506,15.017c-0.486-0.227-1.125-0.375-1.817-0.375c-1.218,0-1.969,0.487-1.969,1.387v0.037
|
||||
c0,0.767,0.638,1.217,1.555,1.217c1.33,0,2.231-0.728,2.231-1.761V15.017z M58.448,19.064v-1.086
|
||||
c-0.692,0.768-1.647,1.274-3.035,1.274c-1.891,0-3.447-1.087-3.447-3.073v-0.039c0-2.193,1.667-3.205,4.046-3.205
|
||||
c1.013,0,1.744,0.169,2.457,0.412V13.18c0-1.179-0.731-1.836-2.156-1.836c-1.086,0-1.854,0.207-2.772,0.543l-0.713-2.173
|
||||
c1.106-0.489,2.193-0.806,3.897-0.806c3.111,0,4.48,1.611,4.48,4.33v5.826H58.448z"/>
|
||||
</g>
|
||||
<polygon fill="#FFFFFF" points="70.123,19.064 67.499,14.961 66.505,16.01 66.505,19.064 63.659,19.064 63.659,5.384 66.505,5.384
|
||||
66.505,12.676 69.842,9.021 73.251,9.021 69.429,12.973 73.382,19.064 "/>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M78.757,11.12c-1.18,0-1.95,0.843-2.174,2.135h4.292C80.705,11.98,79.956,11.12,78.757,11.12
|
||||
M83.61,15.037h-6.989c0.28,1.292,1.18,1.966,2.455,1.966c0.956,0,1.648-0.301,2.435-1.031l1.632,1.444
|
||||
c-0.939,1.162-2.288,1.874-4.105,1.874c-3.017,0-5.249-2.117-5.249-5.19v-0.039c0-2.867,2.044-5.228,4.967-5.228
|
||||
c3.354,0,4.891,2.605,4.891,5.454v0.037C83.647,14.605,83.629,14.774,83.61,15.037"/>
|
||||
<path fill="#FFFFFF" d="M93.521,10.538c0-1.292-0.898-1.985-2.342-1.985H88.95v4.012h2.286c1.442,0,2.285-0.865,2.285-1.987
|
||||
V10.538z M91.141,15.129h-2.19v3.935h-2.886V5.947h5.359c3.128,0,5.021,1.855,5.021,4.537v0.036
|
||||
C96.444,13.555,94.083,15.129,91.141,15.129"/>
|
||||
</g>
|
||||
<polygon fill="#FFFFFF" points="106.787,19.064 106.787,13.796 101.465,13.796 101.465,19.064 98.58,19.064 98.58,5.947
|
||||
101.465,5.947 101.465,11.138 106.787,11.138 106.787,5.947 109.672,5.947 109.672,19.064 "/>
|
||||
<g>
|
||||
<path fill="#FFFFFF" d="M120.277,10.538c0-1.292-0.899-1.985-2.342-1.985h-2.23v4.012h2.285c1.444,0,2.287-0.865,2.287-1.987
|
||||
V10.538z M117.899,15.129h-2.194v3.935h-2.886V5.947h5.359c3.128,0,5.022,1.855,5.022,4.537v0.036
|
||||
C123.201,13.555,120.84,15.129,117.899,15.129"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.4 KiB |
@@ -0,0 +1,30 @@
|
||||
services:
|
||||
cakephp:
|
||||
image: ghcr.io/themusicdev/cakephp-hello:1.0.0
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- mariadb
|
||||
environment:
|
||||
# CakePHP skeleton reads its app config from these env vars
|
||||
# (config/app_local.php in the starter repo is env-driven)
|
||||
- DEBUG=${DEBUG}
|
||||
- SECURITY_SALT=${SECURITY_SALT}
|
||||
- DATABASE_URL=mysql://${MARIADB_USER}:${MARIADB_PASSWORD}@mariadb:3306/${MARIADB_DATABASE}?encoding=utf8mb4
|
||||
expose:
|
||||
- 80
|
||||
|
||||
mariadb:
|
||||
image: mariadb:11
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- MARIADB_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD}
|
||||
- MARIADB_DATABASE=${MARIADB_DATABASE}
|
||||
- MARIADB_USER=${MARIADB_USER}
|
||||
- MARIADB_PASSWORD=${MARIADB_PASSWORD}
|
||||
volumes:
|
||||
- mariadb-data:/var/lib/mysql
|
||||
expose:
|
||||
- 3306
|
||||
|
||||
volumes:
|
||||
mariadb-data:
|
||||
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"id": "cakephp",
|
||||
"name": "CakePHP 5",
|
||||
"version": "1.0.0",
|
||||
"description": "CakePHP 5 starter app running on the themusicdev/php-apache 8.5 Apache + PHP runtime image, backed by MariaDB. Fork the starter repo, build your app, and deploy it on Dokploy in a few clicks.",
|
||||
"logo": "cakephp.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/TheMusicDev/cakephp-hello",
|
||||
"website": "https://cakephp.org/",
|
||||
"docs": "https://book.cakephp.org/5/en/index.html"
|
||||
},
|
||||
"tags": [
|
||||
"php",
|
||||
"framework",
|
||||
"cakephp",
|
||||
"website"
|
||||
],
|
||||
"seoTitle": "CakePHP 5 Docker Compose Setup",
|
||||
"seoDescription": "Deploy a CakePHP 5 application with MariaDB on Dokploy in minutes — runs on the themusicdev/php-apache Apache + PHP 8.5 runtime image with Traefik proxy awareness built in.",
|
||||
"newConfig": true
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
root_password = "${password:32}"
|
||||
database_password = "${password:32}"
|
||||
database_username = "${username:8}"
|
||||
database_name = "cakephp"
|
||||
security_salt = "${base64:32}"
|
||||
app_debug = "false"
|
||||
|
||||
[config]
|
||||
mounts = []
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "cakephp"
|
||||
port = 80
|
||||
host = "${main_domain}"
|
||||
|
||||
[config.env]
|
||||
DEBUG = "${app_debug}"
|
||||
SECURITY_SALT = "${security_salt}"
|
||||
MARIADB_ROOT_PASSWORD = "${root_password}"
|
||||
MARIADB_DATABASE = "${database_name}"
|
||||
MARIADB_USER = "${database_username}"
|
||||
MARIADB_PASSWORD = "${database_password}"
|
||||
@@ -1,40 +1,271 @@
|
||||
# If you are on a machine with ARM architecture, please add a "-arm" suffix to the calcom image on line 19.
|
||||
# If you are on a machine with ARM architecture, please add a "-arm" suffix to the calcom image.
|
||||
# For example, `calcom/cal.com:v6.2.0` will become `calcom/cal.com:v6.2.0-arm`
|
||||
|
||||
# If serving the instance on https, change `NEXT_PUBLIC_WEBAPP_URL` (Line 28) and `NEXTAUTH_URL` (Line 30) to https
|
||||
#
|
||||
# If serving the instance over https, change NEXT_PUBLIC_WEBAPP_URL, NEXT_PUBLIC_WEBSITE_URL,
|
||||
# NEXT_PUBLIC_EMBED_LIB_URL and NEXTAUTH_URL in template.toml to use the https scheme.
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:16-alpine
|
||||
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- calcom-data:/var/lib/postgresql/data
|
||||
environment:
|
||||
- POSTGRES_USER=postgres
|
||||
- POSTGRES_PASSWORD=password
|
||||
- POSTGRES_DB=db
|
||||
- DATABASE_URL=postgres://postgres:password@postgres:5432/db
|
||||
- POSTGRES_USER
|
||||
- POSTGRES_PASSWORD
|
||||
- POSTGRES_DB
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
start_period: 30s
|
||||
|
||||
calcom:
|
||||
image: calcom/cal.com:v6.2.0
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- postgres
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
expose:
|
||||
- 3000
|
||||
environment:
|
||||
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
|
||||
- CALENDSO_ENCRYPTION_KEY=${CALENDSO_ENCRYPTION_KEY}
|
||||
- DATABASE_URL=postgres://postgres:password@postgres:5432/db
|
||||
- DATABASE_DIRECT_URL=postgres://postgres:password@postgres:5432/db
|
||||
- DATABASE_HOST=postgres:5432
|
||||
- NEXT_PUBLIC_WEBAPP_URL=http://${CALCOM_HOST}
|
||||
- ALLOWED_HOSTNAMES="${CALCOM_HOST}"
|
||||
- NEXTAUTH_URL=http://${CALCOM_HOST}/api/auth
|
||||
- NEXT_PUBLIC_DISABLE_SIGNUP=${DISABLE_SIGNUP}
|
||||
- EMAIL_SERVER_HOST=${SMTP_SERVER}
|
||||
- EMAIL_SERVER_PORT=${SMTP_PORT}
|
||||
- EMAIL_SERVER_USER=${EMAIL_SERVER_USER}
|
||||
- EMAIL_SERVER_PASSWORD=${SMTP_PASSWORD}
|
||||
- EMAIL_FROM=${EMAIL_FROM}
|
||||
# --- DATABASE ---------------------------------------------------------------------------
|
||||
- DATABASE_URL
|
||||
- DATABASE_DIRECT_URL
|
||||
- INSIGHTS_DATABASE_URL
|
||||
|
||||
# --- SHARED -----------------------------------------------------------------------------
|
||||
- NEXT_PUBLIC_WEBAPP_URL
|
||||
- NEXT_PUBLIC_WEBSITE_URL
|
||||
- NEXT_PUBLIC_EMBED_LIB_URL
|
||||
- 'ALLOWED_HOSTNAMES="${ALLOWED_HOSTNAMES}"'
|
||||
- 'RESERVED_SUBDOMAINS="app","auth","docs","design","console","go","status","api","saml","www","matrix","developer","cal","my","team","support","security","blog","learn","admin"'
|
||||
- SAML_DATABASE_URL
|
||||
- SAML_ADMINS
|
||||
- NEXT_PUBLIC_HOSTED_CAL_FEATURES
|
||||
- PGSSLMODE
|
||||
|
||||
# --- NEXTAUTH ---------------------------------------------------------------------------
|
||||
- NEXTAUTH_URL
|
||||
- NEXTAUTH_SECRET
|
||||
- NEXTAUTH_COOKIE_DOMAIN
|
||||
|
||||
- CALCOM_TELEMETRY_DISABLED
|
||||
- CRON_API_KEY
|
||||
- CRON_ENABLE_APP_SYNC
|
||||
- CALENDSO_ENCRYPTION_KEY
|
||||
|
||||
# --- SUPPORT / ANALYTICS WIDGETS --------------------------------------------------------
|
||||
- NEXT_PUBLIC_INTERCOM_APP_ID
|
||||
- INTERCOM_SECRET
|
||||
- INTERCOM_API_TOKEN
|
||||
- NEXT_PUBLIC_POSTHOG_KEY
|
||||
- NEXT_PUBLIC_POSTHOG_HOST
|
||||
- NEXT_PUBLIC_ZENDESK_KEY
|
||||
- NEXT_PUBLIC_HELPSCOUT_KEY
|
||||
- NEXT_PUBLIC_FRESHCHAT_TOKEN
|
||||
- NEXT_PUBLIC_FRESHCHAT_HOST
|
||||
|
||||
# --- URL SHORTENERS ---------------------------------------------------------------------
|
||||
- DUB_API_KEY
|
||||
- NEXT_PUBLIC_DUB_PROGRAM_ID
|
||||
- DUB_SMS_DOMAIN
|
||||
- DUB_SMS_FOLDER_ID
|
||||
- SINK_API_URL
|
||||
- SINK_API_KEY
|
||||
|
||||
# --- OAUTH / CALENDAR INTEGRATIONS ------------------------------------------------------
|
||||
- OUTLOOK_LOGIN_ENABLED
|
||||
- GOOGLE_CALENDAR_API_KEY
|
||||
- GOOGLE_LOGIN_ENABLED
|
||||
- GOOGLE_API_CREDENTIALS
|
||||
- GOOGLE_WEBHOOK_TOKEN
|
||||
- GOOGLE_WEBHOOK_URL
|
||||
- MICROSOFT_WEBHOOK_TOKEN
|
||||
- MICROSOFT_WEBHOOK_URL
|
||||
|
||||
# --- FEEDBACK / TRANSACTIONAL PROVIDERS -------------------------------------------------
|
||||
- SEND_FEEDBACK_EMAIL
|
||||
- SENDGRID_API_KEY
|
||||
- SENDGRID_EMAIL
|
||||
- NEXT_PUBLIC_SENDGRID_SENDER_NAME
|
||||
- SENDGRID_SYNC_API_KEY
|
||||
- RESEND_API_KEY
|
||||
|
||||
# --- SENTRY -----------------------------------------------------------------------------
|
||||
- SENTRY_ORG
|
||||
- SENTRY_PROJECT
|
||||
- SENTRY_AUTH_TOKEN
|
||||
- NEXT_PUBLIC_SENTRY_DSN
|
||||
- NEXT_PUBLIC_SENTRY_DSN_CLIENT
|
||||
- SENTRY_DEBUG
|
||||
- SENTRY_MAX_SPANS
|
||||
- SENTRY_SAMPLE_RATE
|
||||
- SENTRY_TRACES_SAMPLE_RATE
|
||||
- SENTRY_REPLAYS_SESSION_SAMPLE_RATE
|
||||
- SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE
|
||||
|
||||
# --- FORMBRICKS -------------------------------------------------------------------------
|
||||
- NEXT_PUBLIC_FORMBRICKS_HOST_URL
|
||||
- NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID
|
||||
- FORMBRICKS_FEEDBACK_SURVEY_ID
|
||||
|
||||
# --- AVATARAPI --------------------------------------------------------------------------
|
||||
- AVATARAPI_USERNAME
|
||||
- AVATARAPI_PASSWORD
|
||||
|
||||
# --- TWILIO -----------------------------------------------------------------------------
|
||||
- NEXT_PUBLIC_SENDER_ID
|
||||
- TWILIO_VERIFY_SID
|
||||
- TWILIO_OPT_OUT_ENABLED
|
||||
|
||||
# --- STRIPE -----------------------------------------------------------------------------
|
||||
- NEXT_PUBLIC_STRIPE_PRO_PLAN_PRICE
|
||||
- NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE
|
||||
- NEXT_PUBLIC_IS_PREMIUM_NEW_PLAN
|
||||
- NEXT_PUBLIC_STRIPE_PREMIUM_NEW_PLAN_PRICE
|
||||
- STRIPE_TEAM_MONTHLY_PRICE_ID
|
||||
- STRIPE_TEAM_ANNUAL_PRICE_ID
|
||||
- NEXT_PUBLIC_STRIPE_CREDITS_PRICE_ID
|
||||
- ORG_MONTHLY_CREDITS
|
||||
- STRIPE_TEAM_PRODUCT_ID
|
||||
- STRIPE_ORG_MONTHLY_PRICE_ID
|
||||
- STRIPE_ORG_ANNUAL_PRICE_ID
|
||||
- STRIPE_ORG_PRODUCT_ID
|
||||
- STRIPE_ORG_TRIAL_DAYS
|
||||
- STRIPE_WEBHOOK_SECRET
|
||||
- STRIPE_WEBHOOK_SECRET_APPS
|
||||
- STRIPE_WEBHOOK_SECRET_BILLING
|
||||
- STRIPE_PRIVATE_KEY
|
||||
- STRIPE_CLIENT_ID
|
||||
- API_KEY_PREFIX
|
||||
|
||||
# --- E-MAIL SETTINGS --------------------------------------------------------------------
|
||||
- EMAIL_FROM
|
||||
- EMAIL_FROM_NAME
|
||||
- EMAIL_SERVER_HOST
|
||||
- EMAIL_SERVER_PORT
|
||||
- EMAIL_SERVER_USER
|
||||
- EMAIL_SERVER_PASSWORD
|
||||
- AWAITING_PAYMENT_EMAIL_DELAY_MINUTES
|
||||
|
||||
# --- BOT PROTECTION ---------------------------------------------------------------------
|
||||
- NEXT_PUBLIC_CLOUDFLARE_SITEKEY
|
||||
- NEXT_PUBLIC_CLOUDFLARE_USE_TURNSTILE_IN_BOOKER
|
||||
- CLOUDFLARE_TURNSTILE_SECRET
|
||||
- NEXT_PUBLIC_VERCEL_USE_BOTID_IN_BOOKER
|
||||
|
||||
# --- CLOSE.COM INTERNAL CRM -------------------------------------------------------------
|
||||
- CLOSECOM_CLIENT_ID
|
||||
- CLOSECOM_CLIENT_SECRET
|
||||
|
||||
# --- BRANDING ---------------------------------------------------------------------------
|
||||
- NEXT_PUBLIC_APP_NAME
|
||||
- NEXT_PUBLIC_SUPPORT_MAIL_ADDRESS
|
||||
- NEXT_PUBLIC_COMPANY_NAME
|
||||
- NEXT_PUBLIC_DISABLE_SIGNUP
|
||||
- NEXT_PUBLIC_WEBSITE_PRIVACY_POLICY_URL
|
||||
- NEXT_PUBLIC_WEBSITE_TERMS_URL
|
||||
- NEXT_PUBLIC_HEAD_SCRIPTS
|
||||
- NEXT_PUBLIC_BODY_SCRIPTS
|
||||
- CSP_POLICY
|
||||
- EDGE_CONFIG
|
||||
|
||||
# --- BOOKER BEHAVIOUR -------------------------------------------------------------------
|
||||
- NEXT_PUBLIC_MINUTES_TO_BOOK
|
||||
- NEXT_PUBLIC_BOOKER_NUMBER_OF_DAYS_TO_LOAD
|
||||
- NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL
|
||||
- NEXT_PUBLIC_QUERY_RESERVATION_INTERVAL_SECONDS
|
||||
- NEXT_PUBLIC_QUERY_RESERVATION_STALE_TIME_SECONDS
|
||||
- NEXT_PUBLIC_QUERY_AVAILABLE_SLOTS_INTERVAL_SECONDS
|
||||
- NEXT_PUBLIC_INVALIDATE_AVAILABLE_SLOTS_ON_BOOKING_FORM
|
||||
- NEXT_PUBLIC_QUICK_AVAILABILITY_ROLLOUT
|
||||
- BLACKLISTED_GUEST_EMAILS
|
||||
|
||||
# --- ORGANIZATIONS ----------------------------------------------------------------------
|
||||
- ORGANIZATIONS_ENABLED
|
||||
- NEXT_PUBLIC_ORGANIZATIONS_MIN_SELF_SERVE_SEATS
|
||||
- NEXT_PUBLIC_ORGANIZATIONS_SELF_SERVE_PRICE_NEW
|
||||
- ORGANIZATIONS_AUTOLINK
|
||||
- NEXT_PUBLIC_SINGLE_ORG_SLUG
|
||||
- PROJECT_ID_VERCEL
|
||||
- TEAM_ID_VERCEL
|
||||
- AUTH_BEARER_TOKEN_VERCEL
|
||||
- LOCAL_TESTING_DOMAIN_VERCEL
|
||||
- CLOUDFLARE_DNS
|
||||
- AUTH_BEARER_TOKEN_CLOUDFLARE
|
||||
- CLOUDFLARE_ZONE_ID
|
||||
- CLOUDFLARE_VERCEL_CNAME
|
||||
|
||||
# --- APP CREDENTIAL SYNC ----------------------------------------------------------------
|
||||
- CALCOM_CREDENTIAL_SYNC_SECRET
|
||||
- CALCOM_CREDENTIAL_SYNC_HEADER_NAME
|
||||
- CALCOM_CREDENTIAL_SYNC_ENDPOINT
|
||||
- CALCOM_APP_CREDENTIAL_ENCRYPTION_KEY
|
||||
- CALCOM_SERVICE_ACCOUNT_ENCRYPTION_KEY
|
||||
|
||||
# --- API V2 -----------------------------------------------------------------------------
|
||||
- NEXT_PUBLIC_API_V2_URL
|
||||
|
||||
# --- TASKER / BACKGROUND JOBS -----------------------------------------------------------
|
||||
- TASKER_ENABLE_WEBHOOKS
|
||||
- TASKER_ENABLE_EMAILS
|
||||
- ENABLE_ASYNC_TASKER
|
||||
- TRIGGER_SECRET_KEY
|
||||
- TRIGGER_API_URL
|
||||
- TRIGGER_DEV_PROJECT_REF
|
||||
|
||||
# --- RATE LIMITING ----------------------------------------------------------------------
|
||||
- UNKEY_ROOT_KEY
|
||||
|
||||
# --- CAL.AI VOICE AGENTS ----------------------------------------------------------------
|
||||
- RETELL_AI_KEY
|
||||
- RETELL_AI_TEST_MODE
|
||||
- RETELL_AI_TEST_EVENT_TYPE_MAP
|
||||
- RETELL_AI_TEST_CAL_API_KEY
|
||||
- STRIPE_PHONE_NUMBER_MONTHLY_PRICE_ID
|
||||
- CAL_AI_CALL_RATE_PER_MINUTE
|
||||
- NEXT_PUBLIC_CAL_AI_PHONE_NUMBER_MONTHLY_PRICE
|
||||
|
||||
# --- VIDEO ------------------------------------------------------------------------------
|
||||
- HUDDLE01_API_TOKEN
|
||||
- CAL_VIDEO_BUCKET_NAME
|
||||
- CAL_VIDEO_BUCKET_REGION
|
||||
- CAL_VIDEO_ASSUME_ROLE_ARN
|
||||
- CAL_VIDEO_MEETING_LINK_FOR_TESTING
|
||||
- CAL_VIDEO_RECORDING_TOKEN_SECRET
|
||||
|
||||
# --- WEB PUSH NOTIFICATIONS -------------------------------------------------------------
|
||||
- NEXT_PUBLIC_VAPID_PUBLIC_KEY
|
||||
- VAPID_PRIVATE_KEY
|
||||
|
||||
# --- MISC -------------------------------------------------------------------------------
|
||||
- LINGO_DOT_DEV_API_KEY
|
||||
- IFFY_API_KEY
|
||||
- DIRECTORY_IDS_TO_LOG
|
||||
- NEXT_PUBLIC_LOGGER_LEVEL
|
||||
- DATABASE_CHUNK_SIZE
|
||||
- SALESFORCE_GRAPHQL_DELAY_MS
|
||||
- SALESFORCE_GRAPHQL_MAX_DELAY_MS
|
||||
- SALESFORCE_GRAPHQL_MAX_RETRIES
|
||||
- TZ
|
||||
- GOOGLE_ADS_ENABLED
|
||||
- LINKEDIN_ADS_ENABLED
|
||||
|
||||
# --- DEVELOPMENT / E2E ONLY -------------------------------------------------------------
|
||||
- NEXT_PUBLIC_IS_E2E
|
||||
- E2E_TEST_MAILHOG_ENABLED
|
||||
- E2E_TEST_APPLE_CALENDAR_EMAIL
|
||||
- E2E_TEST_APPLE_CALENDAR_PASSWORD
|
||||
- E2E_TEST_CALCOM_QA_EMAIL
|
||||
- E2E_TEST_CALCOM_QA_PASSWORD
|
||||
- E2E_TEST_CALCOM_QA_GCAL_CREDENTIALS
|
||||
- E2E_TEST_CALCOM_GCAL_KEYS
|
||||
- SEED_PLATFORM_OAUTH_CLIENT_ID
|
||||
- SEED_PLATFORM_OAUTH_CLIENT_SECRET
|
||||
- SEED_OAUTH2_CLIENT_ID
|
||||
- SEED_OAUTH2_CLIENT_SECRET_HASHED
|
||||
|
||||
volumes:
|
||||
calcom-data:
|
||||
|
||||
@@ -1,19 +1,303 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
calcom_encryption_key = "${base64:32}"
|
||||
postgres_password = "${password:32}"
|
||||
database_url = "postgresql://calcom:${postgres_password}@postgres:5432/calendso"
|
||||
nextauth_secret = "${base64:32}"
|
||||
calendso_encryption_key = "${base64:24}"
|
||||
calcom_credential_sync_secret = "${base64:32}"
|
||||
calcom_app_credential_encryption_key = "${base64:24}"
|
||||
calcom_service_account_encryption_key = "${base64:24}"
|
||||
cal_video_recording_token_secret = "${base64:32}"
|
||||
cron_api_key = "${hash:32}"
|
||||
|
||||
[config]
|
||||
env = [
|
||||
"CALCOM_HOST=${main_domain}",
|
||||
# --- POSTGRES (consumed by the `postgres` service) -----------------------------------------
|
||||
"POSTGRES_USER=calcom",
|
||||
"POSTGRES_PASSWORD=${postgres_password}",
|
||||
"POSTGRES_DB=calendso",
|
||||
|
||||
# --- DATABASE ------------------------------------------------------------------------------
|
||||
"DATABASE_URL=${database_url}",
|
||||
"DATABASE_DIRECT_URL=${database_url}",
|
||||
# Optional read replica for the Insights dashboard. Falls back to DATABASE_URL when empty.
|
||||
"INSIGHTS_DATABASE_URL=",
|
||||
|
||||
# --- SHARED --------------------------------------------------------------------------------
|
||||
"NEXT_PUBLIC_WEBAPP_URL=http://${main_domain}",
|
||||
"NEXT_PUBLIC_WEBSITE_URL=http://${main_domain}",
|
||||
"NEXT_PUBLIC_EMBED_LIB_URL=http://${main_domain}/embed/embed.js",
|
||||
"ALLOWED_HOSTNAMES=${main_domain}",
|
||||
|
||||
# SAML login needs a separate database and is Enterprise Edition only.
|
||||
"SAML_DATABASE_URL=",
|
||||
"SAML_ADMINS=",
|
||||
"NEXT_PUBLIC_HOSTED_CAL_FEATURES=",
|
||||
# Set to no-verify only when your Postgres uses a self-signed certificate.
|
||||
"PGSSLMODE=",
|
||||
|
||||
# - NEXTAUTH
|
||||
"NEXTAUTH_URL=http://${main_domain}",
|
||||
"NEXTAUTH_SECRET=${nextauth_secret}",
|
||||
"CALENDSO_ENCRYPTION_KEY=${calcom_encryption_key}",
|
||||
"DISABLE_SIGNUP=true",
|
||||
"SMTP_SERVER=",
|
||||
"SMTP_PORT=",
|
||||
"SMTP_PASSWORD=",
|
||||
"NEXTAUTH_COOKIE_DOMAIN=",
|
||||
|
||||
# 1 disables anonymous usage collection.
|
||||
"CALCOM_TELEMETRY_DISABLED=1",
|
||||
|
||||
"CRON_API_KEY=${cron_api_key}",
|
||||
"CRON_ENABLE_APP_SYNC=false",
|
||||
"CALENDSO_ENCRYPTION_KEY=${calendso_encryption_key}",
|
||||
|
||||
# --- SUPPORT / ANALYTICS WIDGETS -----------------------------------------------------------
|
||||
"NEXT_PUBLIC_INTERCOM_APP_ID=",
|
||||
"INTERCOM_SECRET=",
|
||||
"INTERCOM_API_TOKEN=",
|
||||
"NEXT_PUBLIC_POSTHOG_KEY=",
|
||||
"NEXT_PUBLIC_POSTHOG_HOST=",
|
||||
"NEXT_PUBLIC_ZENDESK_KEY=",
|
||||
"NEXT_PUBLIC_HELPSCOUT_KEY=",
|
||||
"NEXT_PUBLIC_FRESHCHAT_TOKEN=",
|
||||
"NEXT_PUBLIC_FRESHCHAT_HOST=",
|
||||
|
||||
# --- URL SHORTENERS (SMS workflow links) ---------------------------------------------------
|
||||
"DUB_API_KEY=",
|
||||
"NEXT_PUBLIC_DUB_PROGRAM_ID=",
|
||||
"DUB_SMS_DOMAIN=",
|
||||
"DUB_SMS_FOLDER_ID=",
|
||||
"SINK_API_URL=",
|
||||
"SINK_API_KEY=",
|
||||
|
||||
# --- OAUTH / CALENDAR INTEGRATIONS ---------------------------------------------------------
|
||||
"OUTLOOK_LOGIN_ENABLED=false",
|
||||
"GOOGLE_CALENDAR_API_KEY=",
|
||||
"GOOGLE_LOGIN_ENABLED=false",
|
||||
"GOOGLE_API_CREDENTIALS=",
|
||||
"GOOGLE_WEBHOOK_TOKEN=",
|
||||
# Defaults to NEXT_PUBLIC_WEBAPP_URL when empty.
|
||||
"GOOGLE_WEBHOOK_URL=",
|
||||
"MICROSOFT_WEBHOOK_TOKEN=",
|
||||
"MICROSOFT_WEBHOOK_URL=",
|
||||
|
||||
# --- FEEDBACK / TRANSACTIONAL PROVIDERS ----------------------------------------------------
|
||||
"SEND_FEEDBACK_EMAIL=",
|
||||
"SENDGRID_API_KEY=",
|
||||
"SENDGRID_EMAIL=",
|
||||
"NEXT_PUBLIC_SENDGRID_SENDER_NAME=",
|
||||
"SENDGRID_SYNC_API_KEY=",
|
||||
"RESEND_API_KEY=",
|
||||
|
||||
# --- SENTRY --------------------------------------------------------------------------------
|
||||
"SENTRY_ORG=",
|
||||
"SENTRY_PROJECT=",
|
||||
"SENTRY_AUTH_TOKEN=",
|
||||
"NEXT_PUBLIC_SENTRY_DSN=",
|
||||
"NEXT_PUBLIC_SENTRY_DSN_CLIENT=",
|
||||
"SENTRY_DEBUG=",
|
||||
"SENTRY_MAX_SPANS=",
|
||||
"SENTRY_SAMPLE_RATE=",
|
||||
"SENTRY_TRACES_SAMPLE_RATE=",
|
||||
"SENTRY_REPLAYS_SESSION_SAMPLE_RATE=",
|
||||
"SENTRY_REPLAYS_ON_ERROR_SAMPLE_RATE=",
|
||||
|
||||
# --- FORMBRICKS ----------------------------------------------------------------------------
|
||||
"NEXT_PUBLIC_FORMBRICKS_HOST_URL=https://app.formbricks.com",
|
||||
"NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID=",
|
||||
"FORMBRICKS_FEEDBACK_SURVEY_ID=",
|
||||
|
||||
# --- AVATARAPI (pre-fills avatars during signup) -------------------------------------------
|
||||
"AVATARAPI_USERNAME=",
|
||||
"AVATARAPI_PASSWORD=",
|
||||
|
||||
# --- TWILIO (SMS workflows) ----------------------------------------------------------------
|
||||
# NEXT_PUBLIC_SENDER_ID: letters, numbers and spaces only, max 11 characters.
|
||||
"NEXT_PUBLIC_SENDER_ID=",
|
||||
"TWILIO_VERIFY_SID=",
|
||||
"TWILIO_OPT_OUT_ENABLED=",
|
||||
|
||||
# --- STRIPE (internal billing, teams and organizations) ------------------------------------
|
||||
"NEXT_PUBLIC_STRIPE_PRO_PLAN_PRICE=",
|
||||
"NEXT_PUBLIC_STRIPE_PREMIUM_PLAN_PRICE=",
|
||||
"NEXT_PUBLIC_IS_PREMIUM_NEW_PLAN=0",
|
||||
"NEXT_PUBLIC_STRIPE_PREMIUM_NEW_PLAN_PRICE=",
|
||||
"STRIPE_TEAM_MONTHLY_PRICE_ID=",
|
||||
"STRIPE_TEAM_ANNUAL_PRICE_ID=",
|
||||
"NEXT_PUBLIC_STRIPE_CREDITS_PRICE_ID=",
|
||||
"ORG_MONTHLY_CREDITS=",
|
||||
"STRIPE_TEAM_PRODUCT_ID=",
|
||||
# A price ID belonging to the product in STRIPE_ORG_PRODUCT_ID.
|
||||
"STRIPE_ORG_MONTHLY_PRICE_ID=",
|
||||
"STRIPE_ORG_ANNUAL_PRICE_ID=",
|
||||
"STRIPE_ORG_PRODUCT_ID=",
|
||||
# Trial days passed to the Stripe checkout session for organizations.
|
||||
"STRIPE_ORG_TRIAL_DAYS=",
|
||||
"STRIPE_WEBHOOK_SECRET=",
|
||||
"STRIPE_WEBHOOK_SECRET_APPS=",
|
||||
"STRIPE_WEBHOOK_SECRET_BILLING=",
|
||||
"STRIPE_PRIVATE_KEY=",
|
||||
"STRIPE_CLIENT_ID=",
|
||||
|
||||
# Prefix for public API keys.
|
||||
"API_KEY_PREFIX=cal_",
|
||||
|
||||
# --- E-MAIL SETTINGS -----------------------------------------------------------------------
|
||||
"EMAIL_FROM=notifications@${main_domain}",
|
||||
"EMAIL_FROM_NAME=Cal.com",
|
||||
"EMAIL_SERVER_HOST=",
|
||||
"EMAIL_SERVER_PORT=587",
|
||||
"EMAIL_SERVER_USER=",
|
||||
"EMAIL_FROM=",
|
||||
"EMAIL_SERVER_PASSWORD=",
|
||||
"AWAITING_PAYMENT_EMAIL_DELAY_MINUTES=",
|
||||
|
||||
# --- BOT PROTECTION ------------------------------------------------------------------------
|
||||
"NEXT_PUBLIC_CLOUDFLARE_SITEKEY=",
|
||||
"NEXT_PUBLIC_CLOUDFLARE_USE_TURNSTILE_IN_BOOKER=",
|
||||
"CLOUDFLARE_TURNSTILE_SECRET=",
|
||||
"NEXT_PUBLIC_VERCEL_USE_BOTID_IN_BOOKER=0",
|
||||
|
||||
# --- CLOSE.COM INTERNAL CRM ----------------------------------------------------------------
|
||||
"CLOSECOM_CLIENT_ID=",
|
||||
"CLOSECOM_CLIENT_SECRET=",
|
||||
|
||||
# --- BRANDING ------------------------------------------------------------------------------
|
||||
"NEXT_PUBLIC_APP_NAME=Cal.com",
|
||||
"NEXT_PUBLIC_SUPPORT_MAIL_ADDRESS=help@cal.com",
|
||||
"NEXT_PUBLIC_COMPANY_NAME=Cal.com, Inc.",
|
||||
"NEXT_PUBLIC_DISABLE_SIGNUP=false",
|
||||
"NEXT_PUBLIC_WEBSITE_PRIVACY_POLICY_URL=",
|
||||
"NEXT_PUBLIC_WEBSITE_TERMS_URL=",
|
||||
# Deprecated: NEXT_PUBLIC_HEAD_SCRIPTS is injected into the body only, use BODY_SCRIPTS.
|
||||
"NEXT_PUBLIC_HEAD_SCRIPTS=",
|
||||
"NEXT_PUBLIC_BODY_SCRIPTS=",
|
||||
|
||||
# Set to non-strict to enable a Content Security Policy for support pages.
|
||||
"CSP_POLICY=",
|
||||
# Vercel Edge Config, unused outside Vercel.
|
||||
"EDGE_CONFIG=",
|
||||
|
||||
# --- BOOKER BEHAVIOUR ----------------------------------------------------------------------
|
||||
"NEXT_PUBLIC_MINUTES_TO_BOOK=5",
|
||||
# Override the booker to only load X days worth of data. 0 = no override.
|
||||
"NEXT_PUBLIC_BOOKER_NUMBER_OF_DAYS_TO_LOAD=0",
|
||||
"NEXT_PUBLIC_AVAILABILITY_SCHEDULE_INTERVAL=",
|
||||
# Retry interval for stale slot-reservation checks.
|
||||
"NEXT_PUBLIC_QUERY_RESERVATION_INTERVAL_SECONDS=",
|
||||
# Must be lower than NEXT_PUBLIC_QUERY_RESERVATION_INTERVAL_SECONDS.
|
||||
"NEXT_PUBLIC_QUERY_RESERVATION_STALE_TIME_SECONDS=",
|
||||
# Keep high (minutes) — low values put significant load on the instance.
|
||||
"NEXT_PUBLIC_QUERY_AVAILABLE_SLOTS_INTERVAL_SECONDS=",
|
||||
"NEXT_PUBLIC_INVALIDATE_AVAILABLE_SLOTS_ON_BOOKING_FORM=0",
|
||||
# Percentage of visitors that get quick availability checks.
|
||||
"NEXT_PUBLIC_QUICK_AVAILABILITY_ROLLOUT=10",
|
||||
# Emails that may never be added as booking guests.
|
||||
"BLACKLISTED_GUEST_EMAILS=",
|
||||
|
||||
# --- ORGANIZATIONS -------------------------------------------------------------------------
|
||||
# Organizations need a full domain pointing at the app and must also be enabled at build
|
||||
# time, so setting this on a prebuilt image is not enough on its own.
|
||||
"ORGANIZATIONS_ENABLED=",
|
||||
"NEXT_PUBLIC_ORGANIZATIONS_MIN_SELF_SERVE_SEATS=30",
|
||||
# $37.00 per seat
|
||||
"NEXT_PUBLIC_ORGANIZATIONS_SELF_SERVE_PRICE_NEW=37",
|
||||
# Autolink external provider sign-ups to existing orgs by email domain.
|
||||
"ORGANIZATIONS_AUTOLINK=",
|
||||
# Serve only one organization's booking pages. Baked in at build time.
|
||||
"NEXT_PUBLIC_SINGLE_ORG_SLUG=",
|
||||
|
||||
# Vercel/Cloudflare subdomain management for organizations. Only relevant on Vercel.
|
||||
"PROJECT_ID_VERCEL=",
|
||||
"TEAM_ID_VERCEL=",
|
||||
"AUTH_BEARER_TOKEN_VERCEL=",
|
||||
"LOCAL_TESTING_DOMAIN_VERCEL=",
|
||||
"CLOUDFLARE_DNS=",
|
||||
"AUTH_BEARER_TOKEN_CLOUDFLARE=",
|
||||
"CLOUDFLARE_ZONE_ID=",
|
||||
"CLOUDFLARE_VERCEL_CNAME=",
|
||||
|
||||
# --- APP CREDENTIAL SYNC -------------------------------------------------------------------
|
||||
# For self-hosters embedding Cal into an app that already holds the integration secrets.
|
||||
"CALCOM_CREDENTIAL_SYNC_SECRET=${calcom_credential_sync_secret}",
|
||||
# Header used to verify the webhook secret. Must be lowercase.
|
||||
"CALCOM_CREDENTIAL_SYNC_HEADER_NAME=calcom-credential-sync-secret",
|
||||
"CALCOM_CREDENTIAL_SYNC_ENDPOINT=",
|
||||
# Must match the key configured in your application.
|
||||
"CALCOM_APP_CREDENTIAL_ENCRYPTION_KEY=${calcom_app_credential_encryption_key}",
|
||||
"CALCOM_SERVICE_ACCOUNT_ENCRYPTION_KEY=${calcom_service_account_encryption_key}",
|
||||
|
||||
# --- API V2 --------------------------------------------------------------------------------
|
||||
# This blueprint does not ship the API v2 service (upstream builds it from source and has no
|
||||
# published image). Point this at your own deployment to enable the v2 API.
|
||||
"NEXT_PUBLIC_API_V2_URL=",
|
||||
|
||||
# --- TASKER / BACKGROUND JOBS --------------------------------------------------------------
|
||||
"TASKER_ENABLE_WEBHOOKS=0",
|
||||
"TASKER_ENABLE_EMAILS=0",
|
||||
"ENABLE_ASYNC_TASKER=false",
|
||||
"TRIGGER_SECRET_KEY=",
|
||||
"TRIGGER_API_URL=https://api.trigger.dev",
|
||||
"TRIGGER_DEV_PROJECT_REF=",
|
||||
|
||||
# --- RATE LIMITING (Unkey) -----------------------------------------------------------------
|
||||
# Optional. Not needed for self-hosting unless you want rate limiting.
|
||||
"UNKEY_ROOT_KEY=",
|
||||
|
||||
# --- CAL.AI VOICE AGENTS (Retell AI) -------------------------------------------------------
|
||||
"RETELL_AI_KEY=",
|
||||
"RETELL_AI_TEST_MODE=false",
|
||||
# JSON map of local to production event type IDs.
|
||||
"RETELL_AI_TEST_EVENT_TYPE_MAP=",
|
||||
"RETELL_AI_TEST_CAL_API_KEY=",
|
||||
"STRIPE_PHONE_NUMBER_MONTHLY_PRICE_ID=",
|
||||
"CAL_AI_CALL_RATE_PER_MINUTE=0.29",
|
||||
# Price for buying a phone number for the Cal.ai voice agent (default 5).
|
||||
"NEXT_PUBLIC_CAL_AI_PHONE_NUMBER_MONTHLY_PRICE=",
|
||||
|
||||
# --- VIDEO ---------------------------------------------------------------------------------
|
||||
"HUDDLE01_API_TOKEN=",
|
||||
# S3 storage for Daily Video recordings.
|
||||
"CAL_VIDEO_BUCKET_NAME=",
|
||||
"CAL_VIDEO_BUCKET_REGION=",
|
||||
"CAL_VIDEO_ASSUME_ROLE_ARN=",
|
||||
"CAL_VIDEO_MEETING_LINK_FOR_TESTING=",
|
||||
"CAL_VIDEO_RECORDING_TOKEN_SECRET=${cal_video_recording_token_secret}",
|
||||
|
||||
# --- WEB PUSH NOTIFICATIONS ----------------------------------------------------------------
|
||||
# Generate a pair with: npx web-push generate-vapid-keys
|
||||
"NEXT_PUBLIC_VAPID_PUBLIC_KEY=",
|
||||
"VAPID_PRIVATE_KEY=",
|
||||
|
||||
# --- MISC ----------------------------------------------------------------------------------
|
||||
# Real-time AI localization via lingo.dev.
|
||||
"LINGO_DOT_DEV_API_KEY=",
|
||||
# Content moderation.
|
||||
"IFFY_API_KEY=",
|
||||
# Comma-separated DSyncData.directoryId values to log SCIM requests for (debugging only).
|
||||
"DIRECTORY_IDS_TO_LOG=",
|
||||
# 0: silly, 1: trace, 2: debug, 3: info, 4: warn, 5: error/fatal, 6: fatal
|
||||
"NEXT_PUBLIC_LOGGER_LEVEL=",
|
||||
"DATABASE_CHUNK_SIZE=",
|
||||
"SALESFORCE_GRAPHQL_DELAY_MS=500",
|
||||
"SALESFORCE_GRAPHQL_MAX_DELAY_MS=2000",
|
||||
"SALESFORCE_GRAPHQL_MAX_RETRIES=3",
|
||||
# Force Node.js to use UTC as the process timezone.
|
||||
"TZ=UTC",
|
||||
# Ad click tracking (gclid / li_fat_id). Off by default for self-hosted instances.
|
||||
"GOOGLE_ADS_ENABLED=0",
|
||||
"LINKEDIN_ADS_ENABLED=0",
|
||||
|
||||
# --- DEVELOPMENT / E2E ONLY ----------------------------------------------------------------
|
||||
# Leave empty on a real deployment.
|
||||
"NEXT_PUBLIC_IS_E2E=",
|
||||
"E2E_TEST_MAILHOG_ENABLED=",
|
||||
"E2E_TEST_APPLE_CALENDAR_EMAIL=",
|
||||
"E2E_TEST_APPLE_CALENDAR_PASSWORD=",
|
||||
"E2E_TEST_CALCOM_QA_EMAIL=",
|
||||
"E2E_TEST_CALCOM_QA_PASSWORD=",
|
||||
"E2E_TEST_CALCOM_QA_GCAL_CREDENTIALS=",
|
||||
"E2E_TEST_CALCOM_GCAL_KEYS=",
|
||||
"SEED_PLATFORM_OAUTH_CLIENT_ID=",
|
||||
"SEED_PLATFORM_OAUTH_CLIENT_SECRET=",
|
||||
"SEED_OAUTH2_CLIENT_ID=",
|
||||
"SEED_OAUTH2_CLIENT_SECRET_HASHED=",
|
||||
]
|
||||
mounts = []
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 27 31">
|
||||
<path fill="#60a5fa" d="m 3.043653,30.614292 c -1.04707,-0.32444 -1.94939,-1.09611 -2.51053002,-2.14706 l -0.28493,-0.53364 -0.0338,-10.26902 c -0.0333,-10.1001 -0.0296,-10.28026 0.22157,-10.95165 C 0.93698298,5.3738426 2.254043,4.3160626 3.592343,4.1779326 l 0.66734,-0.069 0.0442,1.54722 c 0.0411,1.4322294 0.069,1.5846294 0.37758,2.0507194 0.43775,0.66128 1.06374,1.03377 1.8697695,1.11256 0.83411,0.0815 1.60889,-0.30288 2.1454309,-1.06449 0.35775,-0.50781 0.37448,-0.59108 0.41656,-2.0715194 l 0.0439,-1.54245 h 4.3226446 4.32263 l 0.0491,1.45985 c 0.0578,1.7152194 0.26715,2.2526994 1.10313,2.8320394 0.44147,0.30594 0.6462,0.36331 1.30282,0.36509 0.6673,0.002 0.85479,-0.0513 1.30717,-0.3706 0.83953,-0.59252 1.03808,-1.10942 1.09117,-2.8410394 l 0.0452,-1.47436 0.61114,0.0588 c 0.88513,0.085 1.92322,0.66148 2.52855,1.40407 0.98071,1.2030494 0.9433,0.7026404 0.90509,12.1120594 l -0.0339,10.12241 -0.34547,0.70339 c -0.37943,0.77247 -1.03179,1.43013 -1.85424,1.86928 l -0.53363,0.28492 -10.31215,0.0218 c -5.6716955,0.0121 -10.451945,-0.0215 -10.622765,-0.0745 z M 5.994413,7.609932 C 5.466163,7.302262 5.404273,6.907952 5.404273,3.8497926 v -2.91273 l 0.36045,-0.38587 c 0.39686,-0.42484 0.9678395,-0.51125 1.5687795,-0.23743 0.6263,0.28536 0.67987,0.58051 0.67987,3.7459 V 6.972402 l -0.36047,0.38586 c -0.29807,0.31911 -0.45393,0.38521 -0.90075,0.3821 -0.29716,-0.002 -0.6381595,-0.0608 -0.7577395,-0.13043 z m 13.312785,-0.25167 -0.36045,-0.38586 V 4.0596626 c 0,-3.08584 0.0628,-3.47128 0.61433,-3.76641 0.31968,-0.17109 0.91477,-0.16181 1.3149,0.0204 0.62629,0.28536 0.67987,0.58051 0.67987,3.74591 V 6.972292 l -0.36046,0.38587 c -0.30429,0.32575 -0.45138,0.38587 -0.9441,0.38587 -0.4927,0 -0.6398,-0.0601 -0.94409,-0.38587 z"/>
|
||||
<path fill="#ffffff" d="M 13.529898,23.489202 c 0.41676,-0.42858 2.30921,-2.34577 4.20548,-4.26044 3.89443,-3.93222 3.79896,-3.77881 2.93494,-4.71617 -0.86333,-0.9366 -0.70987,-1.03489 -4.7574,3.04728 -2.01816,2.03542 -3.63135,3.56753 -3.70704,3.52074 -0.0737,-0.0455 -0.86549,-0.83379 -1.759495,-1.7516 -1.7365396,-1.78282 -2.1646795,-2.10404 -2.5380305,-1.90423 -0.40259,0.21546 -1.13741,1.12099 -1.13741,1.40162 0,0.18848 0.79327,1.06899 2.5741409,2.85723 3.0861346,3.09893 2.9741146,3.05059 4.1848146,1.80557 z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,47 @@
|
||||
|
||||
services:
|
||||
calnode:
|
||||
image: ghcr.io/calnode/calnode:0.12.0
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
- calnode_data:/data
|
||||
|
||||
expose:
|
||||
- "3000"
|
||||
|
||||
environment:
|
||||
PORT: ${PORT}
|
||||
BASE_URL: ${BASE_URL}
|
||||
PUBLIC_BASE_URL: ${PUBLIC_BASE_URL}
|
||||
DATABASE_URL: ${DATABASE_URL}
|
||||
CALNODE_ENCRYPTION_KEY: ${CALNODE_ENCRYPTION_KEY}
|
||||
CALNODE_RECOVERY_SECRET: ${CALNODE_RECOVERY_SECRET}
|
||||
GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
|
||||
GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET}
|
||||
MICROSOFT_CLIENT_ID: ${MICROSOFT_CLIENT_ID}
|
||||
MICROSOFT_CLIENT_SECRET: ${MICROSOFT_CLIENT_SECRET}
|
||||
MICROSOFT_TENANT: ${MICROSOFT_TENANT}
|
||||
EMAIL_SMTP_HOST: ${EMAIL_SMTP_HOST}
|
||||
EMAIL_SMTP_PORT : ${EMAIL_SMTP_PORT}
|
||||
EMAIL_SMTP_CONNECT_HOST: ${EMAIL_SMTP_CONNECT_HOST}
|
||||
EMAIL_SMTP_CONNECT_PORT: ${EMAIL_SMTP_CONNECT_PORT}
|
||||
EMAIL_SMTP_USER: ${EMAIL_SMTP_USER}
|
||||
EMAIL_SMTP_PASS : ${EMAIL_SMTP_PASS}
|
||||
EMAIL_FROM_ADDRESS: ${EMAIL_FROM_ADDRESS}
|
||||
EMAIL_FROM_NAME: ${EMAIL_FROM_NAME}
|
||||
EMAIL_SMTP_TLS: ${EMAIL_SMTP_TLS}
|
||||
EMAIL_SMTP_STARTTLS: ${EMAIL_SMTP_STARTTLS}
|
||||
LITESTREAM_REPLICA_URL: ${LITESTREAM_REPLICA_URL}
|
||||
LITESTREAM_ACCESS_KEY_ID: ${LITESTREAM_ACCESS_KEY_ID}
|
||||
LITESTREAM_SECRET_ACCESS_KEY: ${LITESTREAM_SECRET_ACCESS_KEY}
|
||||
LITESTREAM_ENDPOINT: ${LITESTREAM_ENDPOINT}
|
||||
LITESTREAM_REGION: ${LITESTREAM_REGION}
|
||||
COOKIE_SECURE: ${COOKIE_SECURE}
|
||||
TRUSTED_PROXY_CIDRS: ${TRUSTED_PROXY_CIDRS}
|
||||
FRAME_ANCESTORS: ${FRAME_ANCESTORS}
|
||||
LOG_LEVEL: ${LOG_LEVEL}
|
||||
|
||||
|
||||
volumes:
|
||||
calnode_data:
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"id": "calnode",
|
||||
"name": "Calnode",
|
||||
"version": "v0.12.0",
|
||||
"description": "Calnode is a Calendly-style booking app — with first-party video meetings, recording, and AI notetaking built in. It's API-first, webhook-native, and built for a world where agents do the booking. Nothing is paywalled.",
|
||||
"links": {
|
||||
"github": "https://github.com/Calnode/calnode",
|
||||
"website": "https://calnode.com/",
|
||||
"docs": "https://github.com/Calnode/calnode/tree/main/docs"
|
||||
},
|
||||
"logo": "calnode.svg",
|
||||
"tags": [
|
||||
"scheduling",
|
||||
"booking",
|
||||
"calendar",
|
||||
"meetings"
|
||||
],
|
||||
"seoTitle": "Self-Host Calnode in minutes",
|
||||
"seoDescription": "Scheduling and booking tool, an alternative to Calendly. Self-host Calnode on Dokploy in minutes – no manual setup needed."
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
calnode_encryption_key = "${base64:32}"
|
||||
|
||||
[config]
|
||||
env = [
|
||||
"PORT=3000",
|
||||
"BASE_URL=http:${main_domain}",
|
||||
"PUBLIC_BASE_URL=",
|
||||
"DATABASE_URL=sqlite://./data/calnode.db",
|
||||
"COOKIE_SECURE=",
|
||||
|
||||
"CALNODE_ENCRYPTION_KEY=${calnode_encryption_key}",
|
||||
"CALNODE_RECOVERY_SECRET=",
|
||||
|
||||
# Redirect URIs to add:
|
||||
# http://<domain>/v1/auth/callback
|
||||
# http://<domain>/v1/calendar/callback
|
||||
"GOOGLE_CLIENT_ID=",
|
||||
"GOOGLE_CLIENT_SECRET=",
|
||||
|
||||
# Add a Web platform with these redirect URIs:
|
||||
# http://<domain>/v1/auth/microsoft/callback
|
||||
# http://<domain>/v1/calendar/callback
|
||||
"MICROSOFT_CLIENT_ID=",
|
||||
"MICROSOFT_CLIENT_SECRET=",
|
||||
"MICROSOFT_TENANT=common",
|
||||
|
||||
"EMAIL_SMTP_HOST=",
|
||||
"EMAIL_SMTP_PORT=587",
|
||||
"EMAIL_SMTP_CONNECT_HOST=",
|
||||
"EMAIL_SMTP_CONNECT_PORT=",
|
||||
"EMAIL_SMTP_USER=",
|
||||
"EMAIL_SMTP_PASS=",
|
||||
"EMAIL_FROM_ADDRESS=",
|
||||
"EMAIL_FROM_NAME=Calnode",
|
||||
"EMAIL_SMTP_TLS=",
|
||||
"EMAIL_SMTP_STARTTLS=",
|
||||
|
||||
# Object storage (Litestream) — optional, but required for two things: continuous
|
||||
# SQLite backups, and meeting recordings (Settings → Storage; the "Record" button
|
||||
# only appears once this is configured AND recordings are turned on there). Both
|
||||
# share one S3-compatible bucket. No in-app form for this — set as environment
|
||||
# variables/secrets with your hosting provider and redeploy.
|
||||
|
||||
"LITESTREAM_REPLICA_URL=",
|
||||
"LITESTREAM_ACCESS_KEY_ID=",
|
||||
"LITESTREAM_SECRET_ACCESS_KEY=",
|
||||
# LITESTREAM_ENDPOINT is required for any provider other than AWS S3 (Cloudflare
|
||||
# R2, Backblaze B2, MinIO, etc.) — set it to that provider's S3-compatible endpoint.
|
||||
"LITESTREAM_ENDPOINT=",
|
||||
# LITESTREAM_REGION is optional — only some providers need it.
|
||||
"LITESTREAM_REGION=",
|
||||
|
||||
"TRUSTED_PROXY_CIDRS=",
|
||||
"FRAME_ANCESTORS=",
|
||||
"LOG_LEVEL=",
|
||||
]
|
||||
mounts = []
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "calnode"
|
||||
port = 3_000
|
||||
host = "${main_domain}"
|
||||
@@ -0,0 +1,21 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="512" height="512">
|
||||
<rect width="512" height="512" rx="96" fill="#0b1220"/>
|
||||
<g stroke="#1e2a44" stroke-width="2" opacity="0.7">
|
||||
<path d="M96 128h320M96 192h320M96 256h320M96 320h320M96 384h320"/>
|
||||
<path d="M128 96v320M192 96v320M256 96v320M320 96v320M384 96v320"/>
|
||||
</g>
|
||||
<g fill="#1f6feb" opacity="0.9">
|
||||
<rect x="136" y="288" width="40" height="96" rx="6"/>
|
||||
<rect x="200" y="240" width="40" height="144" rx="6"/>
|
||||
<rect x="264" y="176" width="40" height="208" rx="6"/>
|
||||
<rect x="328" y="216" width="40" height="168" rx="6"/>
|
||||
</g>
|
||||
<path d="M120 352l64-80 56 24 72-96 80 48" fill="none" stroke="#3fb950" stroke-width="12" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<g fill="#3fb950">
|
||||
<circle cx="120" cy="352" r="12"/>
|
||||
<circle cx="184" cy="272" r="12"/>
|
||||
<circle cx="240" cy="296" r="12"/>
|
||||
<circle cx="312" cy="200" r="12"/>
|
||||
<circle cx="392" cy="248" r="12"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 999 B |
@@ -0,0 +1,57 @@
|
||||
services:
|
||||
cadvisor:
|
||||
image: gcr.io/cadvisor/cadvisor:v0.55.1
|
||||
restart: unless-stopped
|
||||
privileged: true
|
||||
devices:
|
||||
- /dev/kmsg
|
||||
volumes:
|
||||
- /:/rootfs:ro
|
||||
- /var/run:/var/run:ro
|
||||
- /sys:/sys:ro
|
||||
- /var/lib/docker/:/var/lib/docker:ro
|
||||
- /dev/disk/:/dev/disk:ro
|
||||
command:
|
||||
- --housekeeping_interval=15s
|
||||
- --docker_only=true
|
||||
|
||||
node-exporter:
|
||||
image: prom/node-exporter:v1.12.1
|
||||
restart: unless-stopped
|
||||
pid: host
|
||||
volumes:
|
||||
- /:/host:ro,rslave
|
||||
command:
|
||||
- --path.rootfs=/host
|
||||
|
||||
prometheus:
|
||||
image: prom/prometheus:v3.15.1
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ../files/prometheus.yml:/etc/prometheus/prometheus.yml:ro
|
||||
- prometheus-data:/prometheus
|
||||
command:
|
||||
- --config.file=/etc/prometheus/prometheus.yml
|
||||
- --storage.tsdb.path=/prometheus
|
||||
- --storage.tsdb.retention.time=30d
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana:13.2.4
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
GF_SECURITY_ADMIN_USER: admin
|
||||
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_ADMIN_PASSWORD}
|
||||
GF_USERS_ALLOW_SIGN_UP: "false"
|
||||
GF_AUTH_ANONYMOUS_ENABLED: "false"
|
||||
volumes:
|
||||
- grafana-data:/var/lib/grafana
|
||||
- ../files/grafana/datasources.yml:/etc/grafana/provisioning/datasources/prometheus.yml:ro
|
||||
- ../files/grafana/dashboards.yml:/etc/grafana/provisioning/dashboards/provider.yml:ro
|
||||
- ../files/grafana/cluster-overview.json:/etc/grafana/provisioning/dashboards/cluster-overview.json:ro
|
||||
- ../files/grafana/container-detail.json:/etc/grafana/provisioning/dashboards/container-detail.json:ro
|
||||
depends_on:
|
||||
- prometheus
|
||||
|
||||
volumes:
|
||||
prometheus-data: {}
|
||||
grafana-data: {}
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"id": "container-monitoring",
|
||||
"name": "Container Monitoring",
|
||||
"version": "13.2.4",
|
||||
"description": "Per-container and host monitoring with cAdvisor, node-exporter, Prometheus and Grafana. Ships two ready dashboards: a cluster overview and a container detail view with project/container filters.",
|
||||
"logo": "container-monitoring.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/google/cadvisor",
|
||||
"website": "https://prometheus.io/",
|
||||
"docs": "https://prometheus.io/docs/introduction/overview/"
|
||||
},
|
||||
"tags": [
|
||||
"monitoring",
|
||||
"observability",
|
||||
"metrics",
|
||||
"prometheus",
|
||||
"grafana",
|
||||
"docker"
|
||||
],
|
||||
"seoTitle": "Container Monitoring with Prometheus and Grafana",
|
||||
"seoDescription": "Self-host cAdvisor, node-exporter, Prometheus and Grafana with Docker Compose on Dokploy. Includes per-container CPU, memory and network dashboards.",
|
||||
"newConfig": true
|
||||
}
|
||||
@@ -0,0 +1,543 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
grafana_admin_password = "${password:24}"
|
||||
|
||||
[config.env]
|
||||
GRAFANA_ADMIN_PASSWORD = "${grafana_admin_password}"
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "grafana"
|
||||
port = 3000
|
||||
host = "${main_domain}"
|
||||
|
||||
[[config.mounts]]
|
||||
filePath = "/prometheus.yml"
|
||||
content = '''
|
||||
global:
|
||||
scrape_interval: 15s
|
||||
evaluation_interval: 15s
|
||||
|
||||
scrape_configs:
|
||||
- job_name: cadvisor
|
||||
static_configs:
|
||||
- targets: ["cadvisor:8080"]
|
||||
- job_name: node
|
||||
static_configs:
|
||||
- targets: ["node-exporter:9100"]
|
||||
'''
|
||||
|
||||
[[config.mounts]]
|
||||
filePath = "/grafana/datasources.yml"
|
||||
content = '''
|
||||
apiVersion: 1
|
||||
|
||||
datasources:
|
||||
- name: Prometheus
|
||||
uid: prometheus
|
||||
type: prometheus
|
||||
access: proxy
|
||||
url: http://prometheus:9090
|
||||
isDefault: true
|
||||
editable: true
|
||||
'''
|
||||
|
||||
[[config.mounts]]
|
||||
filePath = "/grafana/dashboards.yml"
|
||||
content = '''
|
||||
apiVersion: 1
|
||||
|
||||
providers:
|
||||
- name: containers
|
||||
orgId: 1
|
||||
folder: ""
|
||||
type: file
|
||||
disableDeletion: false
|
||||
updateIntervalSeconds: 30
|
||||
allowUiUpdates: true
|
||||
options:
|
||||
path: /etc/grafana/provisioning/dashboards
|
||||
'''
|
||||
|
||||
[[config.mounts]]
|
||||
filePath = "/grafana/cluster-overview.json"
|
||||
content = '''
|
||||
{
|
||||
"annotations": { "list": [] },
|
||||
"editable": true,
|
||||
"graphTooltip": 1,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "stat",
|
||||
"title": "CPU used",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 5, "w": 4, "x": 0, "y": 0 },
|
||||
"options": {
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"textMode": "auto",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"unit": "percent",
|
||||
"decimals": 1,
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }, { "color": "yellow", "value": 70 }, { "color": "red", "value": 90 }] }
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "100 - (avg(rate(node_cpu_seconds_total{mode=\"idle\"}[$__rate_interval])) * 100)" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "stat",
|
||||
"title": "RAM used",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 5, "w": 4, "x": 4, "y": 0 },
|
||||
"options": {
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"textMode": "auto",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"unit": "bytes",
|
||||
"decimals": 1,
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }, { "color": "yellow", "value": 70 }, { "color": "red", "value": 90 }] }
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "stat",
|
||||
"title": "RAM used %",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 5, "w": 4, "x": 8, "y": 0 },
|
||||
"options": {
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"textMode": "auto",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"unit": "percent",
|
||||
"decimals": 1,
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }, { "color": "yellow", "value": 70 }, { "color": "red", "value": 90 }] }
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "100 * (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"type": "stat",
|
||||
"title": "RAM available",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 5, "w": 4, "x": 12, "y": 0 },
|
||||
"options": {
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"textMode": "auto",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"fieldConfig": { "defaults": { "unit": "bytes", "decimals": 1 }, "overrides": [] },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "node_memory_MemAvailable_bytes" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"type": "stat",
|
||||
"title": "Containers",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 5, "w": 4, "x": 16, "y": 0 },
|
||||
"options": {
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"textMode": "auto",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"fieldConfig": { "defaults": { "unit": "none", "decimals": 0 }, "overrides": [] },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "count(count by (name) (container_last_seen{name!=\"\"}))" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"type": "stat",
|
||||
"title": "Disk / used",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 5, "w": 4, "x": 20, "y": 0 },
|
||||
"options": {
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"textMode": "auto",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"unit": "percent",
|
||||
"decimals": 1,
|
||||
"thresholds": { "mode": "absolute", "steps": [{ "color": "green", "value": null }, { "color": "yellow", "value": 75 }, { "color": "red", "value": 90 }] }
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "100 - (node_filesystem_avail_bytes{mountpoint=\"/\",fstype!~\"tmpfs|overlay\"} / node_filesystem_size_bytes{mountpoint=\"/\",fstype!~\"tmpfs|overlay\"} * 100)" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"type": "timeseries",
|
||||
"title": "Host CPU by mode",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 5 },
|
||||
"fieldConfig": { "defaults": { "unit": "percent", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
|
||||
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "avg by (mode) (rate(node_cpu_seconds_total{mode!=\"idle\"}[$__rate_interval])) * 100", "legendFormat": "{{mode}}" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"type": "timeseries",
|
||||
"title": "Host memory",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 5 },
|
||||
"fieldConfig": { "defaults": { "unit": "bytes", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
|
||||
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes", "legendFormat": "used" },
|
||||
{ "refId": "B", "expr": "node_memory_MemAvailable_bytes", "legendFormat": "available" },
|
||||
{ "refId": "C", "expr": "node_memory_MemTotal_bytes", "legendFormat": "total" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"type": "timeseries",
|
||||
"title": "Container CPU (all)",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 13 },
|
||||
"fieldConfig": { "defaults": { "unit": "percent", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
|
||||
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "sum(rate(container_cpu_usage_seconds_total{name!=\"\", cpu=\"total\"}[$__rate_interval])) * 100", "legendFormat": "all containers" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"type": "timeseries",
|
||||
"title": "Container memory (all)",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 13 },
|
||||
"fieldConfig": { "defaults": { "unit": "bytes", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
|
||||
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "sum(container_memory_working_set_bytes{name!=\"\"})", "legendFormat": "all containers" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"type": "timeseries",
|
||||
"title": "Container network (all)",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 7, "w": 24, "x": 0, "y": 21 },
|
||||
"fieldConfig": { "defaults": { "unit": "Bps", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
|
||||
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "sum(rate(container_network_receive_bytes_total{name!=\"\"}[$__rate_interval]))", "legendFormat": "RX" },
|
||||
{ "refId": "B", "expr": "sum(rate(container_network_transmit_bytes_total{name!=\"\"}[$__rate_interval]))", "legendFormat": "TX" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"type": "table",
|
||||
"title": "Top containers by memory",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 9, "w": 24, "x": 0, "y": 28 },
|
||||
"fieldConfig": { "defaults": { "unit": "bytes", "custom": { "align": "auto" } }, "overrides": [] },
|
||||
"options": { "showHeader": true, "sortBy": [{ "displayName": "Value", "desc": true }] },
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"expr": "topk(10, sum by (name, container_label_com_docker_compose_project) (container_memory_working_set_bytes{name!=\"\"}))",
|
||||
"instant": true,
|
||||
"format": "table"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"refresh": "30s",
|
||||
"schemaVersion": 39,
|
||||
"tags": ["cluster"],
|
||||
"templating": { "list": [] },
|
||||
"time": { "from": "now-6h", "to": "now" },
|
||||
"timezone": "browser",
|
||||
"title": "Cluster Overview",
|
||||
"uid": "cluster-overview",
|
||||
"version": 1
|
||||
}
|
||||
'''
|
||||
|
||||
[[config.mounts]]
|
||||
filePath = "/grafana/container-detail.json"
|
||||
content = '''
|
||||
{
|
||||
"annotations": { "list": [] },
|
||||
"editable": true,
|
||||
"graphTooltip": 1,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"id": 1,
|
||||
"type": "stat",
|
||||
"title": "CPU",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 5, "w": 4, "x": 0, "y": 0 },
|
||||
"options": {
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"textMode": "auto",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"fieldConfig": { "defaults": { "unit": "percent", "decimals": 1, "min": 0 }, "overrides": [] },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "sum(rate(container_cpu_usage_seconds_total{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\", cpu=\"total\"}[$__rate_interval])) by (name) * 100", "legendFormat": "{{name}}" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"type": "stat",
|
||||
"title": "Memory",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 5, "w": 4, "x": 4, "y": 0 },
|
||||
"options": {
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"textMode": "auto",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"fieldConfig": { "defaults": { "unit": "bytes", "decimals": 1, "min": 0 }, "overrides": [] },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "sum(container_memory_working_set_bytes{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}) by (name)", "legendFormat": "{{name}}" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"type": "stat",
|
||||
"title": "RAM % of host",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 5, "w": 4, "x": 8, "y": 0 },
|
||||
"options": {
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"textMode": "auto",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"fieldConfig": { "defaults": { "unit": "percent", "decimals": 2, "min": 0 }, "overrides": [] },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "100 * sum(container_memory_working_set_bytes{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}) by (name) / scalar(node_memory_MemTotal_bytes)", "legendFormat": "{{name}}" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"type": "stat",
|
||||
"title": "Network RX",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 5, "w": 4, "x": 12, "y": 0 },
|
||||
"options": {
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"textMode": "auto",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"fieldConfig": { "defaults": { "unit": "Bps", "decimals": 1, "min": 0 }, "overrides": [] },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "sum(rate(container_network_receive_bytes_total{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}[$__rate_interval])) by (name)", "legendFormat": "{{name}}" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 5,
|
||||
"type": "stat",
|
||||
"title": "Network TX",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 5, "w": 4, "x": 16, "y": 0 },
|
||||
"options": {
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"colorMode": "value",
|
||||
"graphMode": "area",
|
||||
"justifyMode": "auto",
|
||||
"textMode": "auto",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"fieldConfig": { "defaults": { "unit": "Bps", "decimals": 1, "min": 0 }, "overrides": [] },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "sum(rate(container_network_transmit_bytes_total{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}[$__rate_interval])) by (name)", "legendFormat": "{{name}}" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 6,
|
||||
"type": "stat",
|
||||
"title": "Uptime",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 5, "w": 4, "x": 20, "y": 0 },
|
||||
"options": {
|
||||
"reduceOptions": { "calcs": ["lastNotNull"], "fields": "", "values": false },
|
||||
"colorMode": "value",
|
||||
"graphMode": "none",
|
||||
"justifyMode": "auto",
|
||||
"textMode": "auto",
|
||||
"orientation": "auto"
|
||||
},
|
||||
"fieldConfig": { "defaults": { "unit": "s", "decimals": 0, "min": 0 }, "overrides": [] },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "time() - container_start_time_seconds{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}", "legendFormat": "{{name}}" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"type": "timeseries",
|
||||
"title": "CPU",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 5 },
|
||||
"fieldConfig": { "defaults": { "unit": "percent", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
|
||||
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "sum(rate(container_cpu_usage_seconds_total{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\", cpu=\"total\"}[$__rate_interval])) by (name) * 100", "legendFormat": "{{name}}" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"type": "timeseries",
|
||||
"title": "Memory working set",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 5 },
|
||||
"fieldConfig": { "defaults": { "unit": "bytes", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
|
||||
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "sum(container_memory_working_set_bytes{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}) by (name)", "legendFormat": "{{name}}" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 9,
|
||||
"type": "timeseries",
|
||||
"title": "Network RX / TX",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 8, "w": 24, "x": 0, "y": 13 },
|
||||
"fieldConfig": { "defaults": { "unit": "Bps", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
|
||||
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "sum(rate(container_network_receive_bytes_total{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}[$__rate_interval])) by (name)", "legendFormat": "RX {{name}}" },
|
||||
{ "refId": "B", "expr": "sum(rate(container_network_transmit_bytes_total{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}[$__rate_interval])) by (name)", "legendFormat": "TX {{name}}" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"type": "timeseries",
|
||||
"title": "Block I/O",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 21 },
|
||||
"fieldConfig": { "defaults": { "unit": "Bps", "min": 0, "custom": { "drawStyle": "line", "lineWidth": 1, "fillOpacity": 10, "showPoints": "never" } }, "overrides": [] },
|
||||
"options": { "legend": { "displayMode": "table", "placement": "bottom", "calcs": ["lastNotNull", "max"] }, "tooltip": { "mode": "multi", "sort": "desc" } },
|
||||
"targets": [
|
||||
{ "refId": "A", "expr": "sum(rate(container_fs_reads_bytes_total{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}[$__rate_interval])) by (name)", "legendFormat": "read {{name}}" },
|
||||
{ "refId": "B", "expr": "sum(rate(container_fs_writes_bytes_total{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"}[$__rate_interval])) by (name)", "legendFormat": "write {{name}}" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 11,
|
||||
"type": "table",
|
||||
"title": "Containers",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"gridPos": { "h": 8, "w": 12, "x": 12, "y": 21 },
|
||||
"fieldConfig": { "defaults": { "unit": "bytes", "custom": { "align": "auto" } }, "overrides": [] },
|
||||
"options": { "showHeader": true },
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"expr": "sum by (name, image, container_label_com_docker_compose_project) (container_memory_working_set_bytes{name=~\"$container\", container_label_com_docker_compose_project=~\"$project\"})",
|
||||
"instant": true,
|
||||
"format": "table"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"refresh": "30s",
|
||||
"schemaVersion": 39,
|
||||
"tags": ["containers"],
|
||||
"templating": {
|
||||
"list": [
|
||||
{
|
||||
"name": "project",
|
||||
"label": "Project",
|
||||
"type": "query",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"definition": "label_values(container_last_seen{container_label_com_docker_compose_project!=\"\"}, container_label_com_docker_compose_project)",
|
||||
"query": {
|
||||
"query": "label_values(container_last_seen{container_label_com_docker_compose_project!=\"\"}, container_label_com_docker_compose_project)",
|
||||
"refId": "StandardVariableQuery"
|
||||
},
|
||||
"refresh": 2,
|
||||
"multi": true,
|
||||
"includeAll": true,
|
||||
"allValue": ".*",
|
||||
"current": { "selected": true, "text": ["All"], "value": ["$__all"] },
|
||||
"options": []
|
||||
},
|
||||
{
|
||||
"name": "container",
|
||||
"label": "Container",
|
||||
"type": "query",
|
||||
"datasource": { "type": "prometheus", "uid": "prometheus" },
|
||||
"definition": "label_values(container_last_seen{container_label_com_docker_compose_project=~\"$project\", name!=\"\"}, name)",
|
||||
"query": {
|
||||
"query": "label_values(container_last_seen{container_label_com_docker_compose_project=~\"$project\", name!=\"\"}, name)",
|
||||
"refId": "StandardVariableQuery"
|
||||
},
|
||||
"refresh": 2,
|
||||
"multi": false,
|
||||
"includeAll": false,
|
||||
"current": {},
|
||||
"options": [],
|
||||
"sort": 1
|
||||
}
|
||||
]
|
||||
},
|
||||
"time": { "from": "now-6h", "to": "now" },
|
||||
"timezone": "browser",
|
||||
"title": "Container Detail",
|
||||
"uid": "container-detail",
|
||||
"version": 1
|
||||
}
|
||||
'''
|
||||
@@ -0,0 +1,13 @@
|
||||
<svg width="256" height="256" viewBox="0 0 256 256" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_10269_2435)">
|
||||
<path d="M206.222 0H49.7778C22.2863 0 0 22.2863 0 49.7778V206.222C0 233.714 22.2863 256 49.7778 256H206.222C233.714 256 256 233.714 256 206.222V49.7778C256 22.2863 233.714 0 206.222 0Z" fill="white"/>
|
||||
<path d="M201.697 178.505L175.67 168.424C169.43 166.007 162.039 168.153 156.544 171.971C149.591 176.802 137.646 182.809 118.247 186.566C81.5296 193.677 60.3846 153.139 60.3846 153.139C60.3846 153.139 64.84 196.282 114.909 210.505C164.978 224.727 201.697 178.505 201.697 178.505Z" fill="black"/>
|
||||
<path d="M161.754 53.5827C161.754 53.5827 98.2194 61.1686 91.5434 110.946C84.8675 160.724 134.937 178.502 134.937 178.502C134.937 178.502 115.366 188.683 95.3394 181.576C75.3116 174.468 64.8398 153.61 64.8398 153.61C64.8398 153.61 41.4738 114.502 74.8537 75.3907C108.233 36.2797 161.754 53.5827 161.754 53.5827Z" fill="black"/>
|
||||
<path d="M201.672 86.0414L181.054 96.11C172.525 100.275 159.267 88.6796 150.153 86.0293C147.272 85.1916 143.526 84.9392 138.683 85.555C110.719 89.1106 96.0384 103.819 96.0384 103.819C96.0384 103.819 100.233 77.3772 142.179 61.3915C184.124 45.4054 201.672 86.0414 201.672 86.0414Z" fill="black"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_10269_2435">
|
||||
<rect width="256" height="256" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,38 @@
|
||||
services:
|
||||
customermates:
|
||||
image: ghcr.io/customermates/customermates:sha-4f4d61c
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
customermates-postgres:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
APP_MODE: self-hosted
|
||||
NODE_ENV: production
|
||||
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@customermates-postgres:5432/${POSTGRES_DB}
|
||||
WORKFLOW_TARGET_WORLD: "@workflow/world-postgres"
|
||||
WORKFLOW_POSTGRES_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@customermates-postgres:5432/${POSTGRES_DB}
|
||||
BASE_URL: ${BASE_URL}
|
||||
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
|
||||
CRON_SECRET: ${CRON_SECRET}
|
||||
RESEND_API_KEY: ${RESEND_API_KEY}
|
||||
RESEND_OPERATOR_EMAIL: ${RESEND_OPERATOR_EMAIL}
|
||||
expose:
|
||||
- 4000
|
||||
|
||||
customermates-postgres:
|
||||
image: postgres:16.15-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
POSTGRES_DB: ${POSTGRES_DB}
|
||||
volumes:
|
||||
- customermates-postgres-data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
volumes:
|
||||
customermates-postgres-data: {}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"id": "customermates",
|
||||
"name": "Customermates",
|
||||
"version": "sha-4f4d61c",
|
||||
"description": "Customermates is an open-source CRM for contacts, organizations, deals, services and tasks, with a REST API, webhooks and an MCP endpoint for external AI clients. Self-hosted, it runs on PostgreSQL 16 and uses the Starter feature set.",
|
||||
"logo": "customermates.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/customermates/customermates",
|
||||
"website": "https://customermates.com",
|
||||
"docs": "https://customermates.com/docs/self-hosting"
|
||||
},
|
||||
"tags": [
|
||||
"crm",
|
||||
"sales",
|
||||
"business"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
postgres_password = "${hash:16}"
|
||||
auth_secret = "${hash:32}"
|
||||
cron_secret = "${hash:32}"
|
||||
|
||||
[config]
|
||||
mounts = []
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "customermates"
|
||||
port = 4000
|
||||
host = "${main_domain}"
|
||||
|
||||
[config.env]
|
||||
BASE_URL = "http://${main_domain}"
|
||||
BETTER_AUTH_SECRET = "${auth_secret}"
|
||||
CRON_SECRET = "${cron_secret}"
|
||||
POSTGRES_USER = "customermates"
|
||||
POSTGRES_PASSWORD = "${postgres_password}"
|
||||
POSTGRES_DB = "customermates"
|
||||
RESEND_API_KEY = ""
|
||||
RESEND_OPERATOR_EMAIL = "mail@your-company.com"
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
services:
|
||||
dagu:
|
||||
image: ghcr.io/dagucloud/dagu:2.10.7
|
||||
image: ghcr.io/dagucloud/dagu:2.25.4
|
||||
command: dagu start-all
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "dagu",
|
||||
"name": "Dagu",
|
||||
"version": "2.10.7",
|
||||
"version": "2.25.4",
|
||||
"description": "Dagu is a self-contained workflow engine with a Web UI. Schedule and orchestrate jobs as DAGs defined in declarative YAML, with no DBMS required.",
|
||||
"logo": "logo.png",
|
||||
"links": {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
docktail:
|
||||
image: ghcr.io/marvinvr/docktail:1.6.0
|
||||
|
||||
@@ -11,9 +11,9 @@ services:
|
||||
- DATABASE_URL=postgresql://${POSTGRES_USER:-docuseal}:${POSTGRES_PASSWORD}@docu-postgres:5432/${POSTGRES_DB:-docuseal}
|
||||
|
||||
docu-postgres:
|
||||
image: postgres:latest
|
||||
image: postgres:18
|
||||
volumes:
|
||||
- docuseal-db:/var/lib/postgresql/data
|
||||
- docuseal-db:/var/lib/postgresql
|
||||
environment:
|
||||
- POSTGRES_USER=${POSTGRES_USER}
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
@@ -24,6 +24,7 @@ services:
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
|
||||
docu-redis:
|
||||
image: redis:alpine
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
services:
|
||||
dokploy-actions-runner:
|
||||
# Maintained upstream runner, Ubuntu 24.04; multi-architecture index digest.
|
||||
image: ghcr.io/myoung34/docker-github-actions-runner:2.338.0-ubuntu-noble@sha256:2112bde2ee92b7480babfbe3043d0461e322b97ca01e6ac94698895f3dc1f528
|
||||
image: ghcr.io/myoung34/docker-github-actions-runner:2.338.2-ubuntu-noble@sha256:23e3a4a1da30de5b462ad0ae13d901288e803a688075c3b9b5bb79b7148c07fa
|
||||
restart: unless-stopped
|
||||
user: runner
|
||||
cap_drop:
|
||||
@@ -19,6 +19,9 @@ services:
|
||||
RUNNER_NAME: ${RUNNER_NAME:?Set a unique RUNNER_NAME for each deployment}
|
||||
LABELS: ${LABELS:?Set comma-separated runner LABELS}
|
||||
RUNNER_GROUP: ${RUNNER_GROUP:-Default}
|
||||
# Use the maintained embedded Node24 for shell steps as well as JS actions.
|
||||
# Keep upstream runtime slots intact; this is not a Node20 binary replacement.
|
||||
PATH: /actions-runner/externals/node24/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
RUN_AS_ROOT: "false"
|
||||
START_DOCKER_SERVICE: "false"
|
||||
DISABLE_AUTOMATIC_DEREGISTRATION: "false"
|
||||
@@ -26,7 +29,7 @@ services:
|
||||
# Keep the PAT in the entrypoint shell for shutdown deregistration.
|
||||
# Upstream un-exports it before starting the listener. See the linked project security guide.
|
||||
UNSET_CONFIG_VARS: "false"
|
||||
# Only validates configuration, then execs the upstream lifecycle handler.
|
||||
# Validates configuration and the runtime floor, then execs upstream lifecycle.
|
||||
# Inline so Dokploy imports need no custom image or repository file mounts.
|
||||
# Double dollars defer expansion to the container, not Compose/Dokploy.
|
||||
entrypoint:
|
||||
@@ -55,6 +58,14 @@ services:
|
||||
;;
|
||||
*) fail 'RUNNER_SCOPE must be exactly repo or org' ;;
|
||||
esac
|
||||
# Runtime gate: refuse fallback to distro Node after a runner self-update.
|
||||
node_binary=/actions-runner/externals/node24/bin/node
|
||||
[[ -x "$${node_binary}" ]] || fail 'The maintained Node24 runtime is missing; update the image'
|
||||
[[ "$$(command -v node)" == "$${node_binary}" ]] || fail 'Default node must use the maintained Node24 runtime'
|
||||
node_version="$$("$${node_binary}" --version)"
|
||||
[[ "$${node_version}" =~ ^v24\.([0-9]+)\.([0-9]+)$$ ]] || fail 'The maintained Node24 runtime is required'
|
||||
(( 10#$${BASH_REMATCH[1]} > 22 || (10#$${BASH_REMATCH[1]} == 22 && 10#$${BASH_REMATCH[2]} >= 1) )) || fail 'Node24 is below the security baseline; update the image'
|
||||
# End runtime gate.
|
||||
exec /entrypoint.sh ./bin/Runner.Listener run --startuptype service
|
||||
# Local listener liveness only; does not prove GitHub connectivity/readiness.
|
||||
healthcheck:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "dokploy-actions-runner",
|
||||
"name": "GitHub Actions Runner",
|
||||
"version": "2.338.0-ubuntu-noble",
|
||||
"version": "2.338.2-ubuntu-noble",
|
||||
"description": "Self-hosted GitHub Actions runner for repositories or organizations, with independent names, labels and runner groups. Runs without privileged mode or Docker socket access.",
|
||||
"logo": "logo.svg",
|
||||
"links": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
dossier:
|
||||
image: ghcr.io/aientech/dossier:v1.5.0
|
||||
image: ghcr.io/aientech/dossier:v1.9.0
|
||||
restart: unless-stopped
|
||||
env_file:
|
||||
- path: .env
|
||||
@@ -14,6 +14,7 @@ services:
|
||||
DOSSIER_SECRET: "${DOSSIER_SECRET:?Keep the generated DOSSIER_SECRET}"
|
||||
DOSSIER_DATA_DIR: /data
|
||||
DOSSIER_TELEMETRY: "${DOSSIER_TELEMETRY:-off}"
|
||||
DOSSIER_JOBS_ARBEITSAGENTUR: "${DOSSIER_JOBS_ARBEITSAGENTUR:-off}"
|
||||
DOSSIER_BACKUP_RETENTION_DAYS: "${DOSSIER_BACKUP_RETENTION_DAYS:-14}"
|
||||
TZ: "${TZ:-UTC}"
|
||||
command:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "dossier",
|
||||
"name": "Dossier",
|
||||
"version": "v1.5.0",
|
||||
"version": "v1.9.0",
|
||||
"description": "Dossier is a personal job search app with a career profile, resume and cover letter drafting, PDF export, and an application tracking board. It supports local and hosted AI providers.",
|
||||
"logo": "dossier.svg",
|
||||
"links": {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
version: "3.8"
|
||||
services:
|
||||
emaki-video-starter:
|
||||
image: san8888/emaki-video-starter:1.0.0
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
heyo-docs:
|
||||
build:
|
||||
|
||||
@@ -0,0 +1,182 @@
|
||||
# Dokploy template for the Community edition of It's a Plan.
|
||||
# Dokploy routes the api and web services through its proxy, so this file uses
|
||||
# expose instead of publishing host ports.
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:17-alpine
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER:-itsaplan}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in Dokploy}
|
||||
POSTGRES_DB: ${POSTGRES_DB:-itsaplan}
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD-SHELL",
|
||||
"pg_isready -U ${POSTGRES_USER:-itsaplan} -d ${POSTGRES_DB:-itsaplan}",
|
||||
]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
minio:
|
||||
image: rustfs/rustfs:1.0.0
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
RUSTFS_ACCESS_KEY: ${S3_ACCESS_KEY_ID:?set S3_ACCESS_KEY_ID in Dokploy}
|
||||
RUSTFS_SECRET_KEY: ${S3_SECRET_ACCESS_KEY:?set S3_SECRET_ACCESS_KEY in Dokploy}
|
||||
volumes:
|
||||
- minio-data:/data
|
||||
healthcheck:
|
||||
test:
|
||||
[
|
||||
"CMD",
|
||||
"curl",
|
||||
"-fsS",
|
||||
"-o",
|
||||
"/dev/null",
|
||||
"http://127.0.0.1:9000/health",
|
||||
]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
|
||||
minio-init:
|
||||
image: rustfs/rustfs:1.0.0
|
||||
restart: "no"
|
||||
depends_on:
|
||||
minio:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID}
|
||||
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY}
|
||||
S3_BUCKET: ${S3_BUCKET:-planner-attachments}
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- >-
|
||||
curl -fsS -X PUT --aws-sigv4 aws:amz:us-east-1:s3
|
||||
--user "$$S3_ACCESS_KEY_ID:$$S3_SECRET_ACCESS_KEY"
|
||||
"http://minio:9000/$$S3_BUCKET" &&
|
||||
echo "bucket ready: $$S3_BUCKET"
|
||||
|
||||
migrate:
|
||||
image: ghcr.io/croffasia/itsaplan-api:1.9.0
|
||||
restart: "no"
|
||||
command: ["bun", "run", "packages/db/src/migrate.ts"]
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
DATABASE_URL: postgres://${POSTGRES_USER:-itsaplan}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-itsaplan}
|
||||
BACKUP_RETENTION_DAYS: ${BACKUP_RETENTION_DAYS:-30}
|
||||
SKIP_PRE_MIGRATION_BACKUP: ${SKIP_PRE_MIGRATION_BACKUP:-}
|
||||
volumes:
|
||||
- db-backups:/backups
|
||||
|
||||
api:
|
||||
image: ghcr.io/croffasia/itsaplan-api:1.9.0
|
||||
restart: unless-stopped
|
||||
command: ["bun", "run", "apps/api/src/index.ts"]
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
minio-init:
|
||||
condition: service_completed_successfully
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
API_PORT: 3000
|
||||
DATABASE_URL: postgres://${POSTGRES_USER:-itsaplan}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-itsaplan}
|
||||
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET:?set BETTER_AUTH_SECRET in Dokploy}
|
||||
APP_ENCRYPTION_KEY: ${APP_ENCRYPTION_KEY:?set APP_ENCRYPTION_KEY in Dokploy}
|
||||
API_URL: ${API_URL:?set API_URL in Dokploy}
|
||||
APP_URL: ${APP_URL:?set APP_URL in Dokploy}
|
||||
COOKIE_DOMAIN: ${COOKIE_DOMAIN:-}
|
||||
CLIENT_IP_HEADER: ${CLIENT_IP_HEADER:-}
|
||||
TRUSTED_PROXIES: ${TRUSTED_PROXIES:-}
|
||||
GIT_WEBHOOK_BASE_URL: ${GIT_WEBHOOK_BASE_URL:-}
|
||||
S3_ENDPOINT: http://minio:9000
|
||||
S3_BUCKET: ${S3_BUCKET:-planner-attachments}
|
||||
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:?set S3_ACCESS_KEY_ID in Dokploy}
|
||||
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:?set S3_SECRET_ACCESS_KEY in Dokploy}
|
||||
S3_REGION: ${S3_REGION:-us-east-1}
|
||||
S3_FORCE_PATH_STYLE: ${S3_FORCE_PATH_STYLE:-true}
|
||||
SSRF_ALLOWED_HOSTS: ${SSRF_ALLOWED_HOSTS:-}
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:3000/"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
expose:
|
||||
- "3000"
|
||||
|
||||
worker:
|
||||
image: ghcr.io/croffasia/itsaplan-worker:1.9.0
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
DATABASE_URL: postgres://${POSTGRES_USER:-itsaplan}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-itsaplan}
|
||||
APP_ENCRYPTION_KEY: ${APP_ENCRYPTION_KEY:?set APP_ENCRYPTION_KEY in Dokploy}
|
||||
TELEMETRY_DISABLED: ${TELEMETRY_DISABLED:-}
|
||||
DO_NOT_TRACK: ${DO_NOT_TRACK:-}
|
||||
TELEMETRY_DEBUG: ${TELEMETRY_DEBUG:-}
|
||||
SSRF_ALLOWED_HOSTS: ${SSRF_ALLOWED_HOSTS:-}
|
||||
S3_ENDPOINT: http://minio:9000
|
||||
S3_BUCKET: ${S3_BUCKET:-planner-attachments}
|
||||
S3_ACCESS_KEY_ID: ${S3_ACCESS_KEY_ID:?set S3_ACCESS_KEY_ID in Dokploy}
|
||||
S3_SECRET_ACCESS_KEY: ${S3_SECRET_ACCESS_KEY:?set S3_SECRET_ACCESS_KEY in Dokploy}
|
||||
S3_REGION: ${S3_REGION:-us-east-1}
|
||||
S3_FORCE_PATH_STYLE: ${S3_FORCE_PATH_STYLE:-true}
|
||||
|
||||
bot:
|
||||
image: ghcr.io/croffasia/itsaplan-bot:1.9.0
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
DATABASE_URL: postgres://${POSTGRES_USER:-itsaplan}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB:-itsaplan}
|
||||
APP_ENCRYPTION_KEY: ${APP_ENCRYPTION_KEY:?set APP_ENCRYPTION_KEY in Dokploy}
|
||||
|
||||
web:
|
||||
image: ghcr.io/croffasia/itsaplan-web:1.9.0
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- api
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
PORT: 3001
|
||||
HOSTNAME: 0.0.0.0
|
||||
API_URL: ${API_URL:?set API_URL in Dokploy}
|
||||
SERVICE_URL_API: http://api:3000
|
||||
PRIVACY_URL: ${PRIVACY_URL:-}
|
||||
TERMS_URL: ${TERMS_URL:-}
|
||||
healthcheck:
|
||||
test:
|
||||
["CMD", "wget", "-q", "-O", "/dev/null", "http://127.0.0.1:3001/login"]
|
||||
interval: 15s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
expose:
|
||||
- "3001"
|
||||
|
||||
volumes:
|
||||
postgres-data: {}
|
||||
minio-data: {}
|
||||
db-backups: {}
|
||||
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 32 32">
|
||||
<rect width="32" height="32" rx="7" fill="#08090a"/>
|
||||
<g transform="translate(4 4) scale(0.75)" fill="none">
|
||||
<rect x="13" y="14.3" width="6" height="3.4" rx="1.7" fill="#fbfbfa" opacity="0.4"/>
|
||||
<circle cx="9.5" cy="16" r="6" fill="#fbfbfa"/>
|
||||
<rect x="17" y="10.5" width="11" height="11" rx="3.4" stroke="#fbfbfa" stroke-width="3"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 447 B |
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"id": "itsaplan",
|
||||
"name": "It's a Plan",
|
||||
"version": "1.9.0",
|
||||
"description": "It's a Plan is an open-source project management and issue tracking platform where people and AI agents work together.",
|
||||
"logo": "itsaplan.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/croffasia/itsaplan",
|
||||
"website": "https://itsaplan.dev",
|
||||
"docs": "https://github.com/croffasia/itsaplan/blob/main/docs/self-hosting.md"
|
||||
},
|
||||
"tags": ["project-management", "issue-tracking", "ai"],
|
||||
"seoTitle": "Self-host It's a Plan with Dokploy",
|
||||
"seoDescription": "Deploy the open-source project management and issue tracking platform It's a Plan with Dokploy."
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
api_domain = "api.${main_domain}"
|
||||
postgres_password = "${password:32}"
|
||||
auth_secret = "${base64:32}"
|
||||
encryption_key = "${base64:32}"
|
||||
s3_access_key = "${username}"
|
||||
s3_secret_key = "${password:32}"
|
||||
|
||||
[config]
|
||||
env = [
|
||||
"POSTGRES_USER=itsaplan",
|
||||
"POSTGRES_PASSWORD=${postgres_password}",
|
||||
"POSTGRES_DB=itsaplan",
|
||||
"BETTER_AUTH_SECRET=${auth_secret}",
|
||||
"APP_ENCRYPTION_KEY=${encryption_key}",
|
||||
"API_URL=https://${api_domain}",
|
||||
"APP_URL=https://${main_domain}",
|
||||
"S3_BUCKET=planner-attachments",
|
||||
"S3_ACCESS_KEY_ID=${s3_access_key}",
|
||||
"S3_SECRET_ACCESS_KEY=${s3_secret_key}",
|
||||
"S3_REGION=us-east-1",
|
||||
"S3_FORCE_PATH_STYLE=true",
|
||||
"BACKUP_RETENTION_DAYS=30",
|
||||
]
|
||||
mounts = []
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "api"
|
||||
port = 3000
|
||||
host = "${api_domain}"
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "web"
|
||||
port = 3001
|
||||
host = "${main_domain}"
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
junctio:
|
||||
image: ghcr.io/k2so-dev/junctio:0.2.1
|
||||
image: ghcr.io/k2so-dev/junctio:0.2.6
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- 3000
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"id": "junctio",
|
||||
"name": "Junctio",
|
||||
"version": "0.2.1",
|
||||
"version": "0.2.6",
|
||||
"description": "Self-hosted MCP gateway that puts stdio, Docker and remote MCP servers behind one endpoint per client, with API key or OAuth downstream auth and upstream tokens refreshed before they expire.",
|
||||
"logo": "logo.png",
|
||||
"links": {
|
||||
"github": "https://github.com/k2so-dev/junctio",
|
||||
"website": "https://junctio.pages.dev",
|
||||
"docs": "https://junctio.pages.dev/docs/"
|
||||
"website": "https://junctio.org",
|
||||
"docs": "https://junctio.org/docs/"
|
||||
},
|
||||
"tags": [
|
||||
"ai",
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Kortix Setup Instructions
|
||||
|
||||
## Deploy
|
||||
|
||||
1. Create the service from the **Kortix** template. Dokploy generates the database password, JWT secret and secret seed, and three domains (app, API, Supabase gateway).
|
||||
2. In the service's **Environment** tab, replace each `REPLACE_ME`:
|
||||
- `PLATINUM_API_KEY`: Platinum API key. Kortix agents run in Platinum cloud sandboxes; get a key at https://platinum.dev.
|
||||
- `KORTIX_ADMIN_EMAIL`: Email of the first admin. Sign up with this address right after the deploy finishes.
|
||||
3. In the **Domains** tab, edit each of the three domains (frontend, api, kong), turn on **HTTPS** and choose **Let's Encrypt**. The template's addresses use `https://`; if you swap in your own domains, update `PUBLIC_URL`, `API_PUBLIC_URL` and `SUPABASE_PUBLIC_URL` to match.
|
||||
4. Deploy and wait until every container is healthy. The first deploy takes a few minutes while the images download and Postgres initializes.
|
||||
|
||||
## After the first deploy
|
||||
|
||||
1. Open the Kortix app's address and **sign up with the admin email** right away.
|
||||
2. Signed in as the admin, open **`/admin/git`** and connect GitHub. Install the GitHub App on an organization so Kortix can create project repos. On a personal account, create each repo on GitHub first, then import it.
|
||||
3. Add your model key in **Settings → Model**.
|
||||
4. Create a project and give an agent its first task.
|
||||
5. To stop others from signing up, set `DISABLE_SIGNUP=true` and redeploy.
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg width="30" height="25" viewBox="0 0 30 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M25.5614 24.916H29.8268C29.8268 19.6306 26.9378 15.0039 22.6171 12.4587C26.9377 9.91355 29.8267 5.28685 29.8267 0.00146484H25.5613C25.5613 5.00287 21.8906 9.18692 17.0654 10.1679V0.00146484H12.8005V10.1679C7.9526 9.20401 4.3046 5.0186 4.3046 0.00146484H0.0391572C0.0391572 5.28685 2.92822 9.91355 7.24884 12.4587C2.92818 15.0039 0.0390625 19.6306 0.0390625 24.916H4.30451C4.30451 19.8989 7.95259 15.7135 12.8005 14.7496V24.9206H17.0654V14.7496C21.9133 15.7134 25.5614 19.8989 25.5614 24.916Z" fill="black"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 620 B |
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"id": "kortix",
|
||||
"name": "Kortix",
|
||||
"version": "0.14.19",
|
||||
"description": "Kortix is an open source AI Operating System: AI agents that do real work for your team, with your own models and tools. Self-host it on your own server with Dokploy in a few clicks.",
|
||||
"logo": "kortix.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/kortix-ai/suna",
|
||||
"website": "https://kortix.com",
|
||||
"docs": "https://kortix.com/docs/developers#self-hosting"
|
||||
},
|
||||
"tags": [
|
||||
"ai",
|
||||
"agents",
|
||||
"automation",
|
||||
"self-hosted"
|
||||
],
|
||||
"seoTitle": "Kortix: Self-Hosted AI Agents & Docker Compose",
|
||||
"seoDescription": "Open source AI agents for your team. Self-host Kortix via Docker Compose on Dokploy: your data, your model keys."
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
api_domain = "${domain}"
|
||||
supabase_domain = "${domain}"
|
||||
postgres_password = "${password:64}"
|
||||
jwt_secret = "${password:128}"
|
||||
kortix_secret_seed = "${password:64}"
|
||||
|
||||
[config]
|
||||
env = [
|
||||
"POSTGRES_PASSWORD=${postgres_password}",
|
||||
"JWT_SECRET=${jwt_secret}",
|
||||
"KORTIX_SECRET_SEED=${kortix_secret_seed}",
|
||||
"PUBLIC_URL=https://${main_domain}",
|
||||
"API_PUBLIC_URL=https://${api_domain}",
|
||||
"SUPABASE_PUBLIC_URL=https://${supabase_domain}",
|
||||
"PLATINUM_API_KEY=REPLACE_ME",
|
||||
"KORTIX_ADMIN_EMAIL=REPLACE_ME",
|
||||
"DISABLE_SIGNUP=false",
|
||||
"EMAIL_URL=",
|
||||
"EMAIL_FROM=",
|
||||
"COMPOSIO_API_KEY=",
|
||||
]
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "frontend"
|
||||
port = 3000
|
||||
host = "${main_domain}"
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "api"
|
||||
port = 8008
|
||||
host = "${api_domain}"
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "kong"
|
||||
port = 8000
|
||||
host = "${supabase_domain}"
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
legejo:
|
||||
image: slurvdjur/legejo:1.23.1
|
||||
image: slurvdjur/legejo:1.33.0
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- "3000"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "legejo",
|
||||
"name": "Legejo",
|
||||
"version": "1.23.1",
|
||||
"version": "1.33.0",
|
||||
"description": "Legejo is a self-hosted library for your EPUB books, with a web reader, Kobo sync, OPDS for reading apps, KOReader progress sync, shared shelves and audiobooks. Runs on SQLite with no other services needed.",
|
||||
"logo": "legejo.svg",
|
||||
"links": {
|
||||
|
||||
@@ -13,19 +13,23 @@ host = "${main_domain}"
|
||||
# An empty value counts as unset.
|
||||
[config.env]
|
||||
# The first admin account, created on the first start; sign in with these.
|
||||
# (Left empty, the first visitor would create it in the browser instead.)
|
||||
LEGEJO_ADMIN_USER = "admin"
|
||||
LEGEJO_ADMIN_PASSWORD = "${admin_password}"
|
||||
# Change to https:// once the domain has a certificate: session cookies are
|
||||
# then marked Secure, and federation and mailed links use it.
|
||||
LEGEJO_PUBLIC_URL = "http://${main_domain}"
|
||||
# Mail, for self-registration, invitations and password reset.
|
||||
# Mail, for self-registration, invitations and password reset. Empty: it can
|
||||
# be set up on Legejo's Admin page instead, with a test mail.
|
||||
LEGEJO_SMTP_HOST = ""
|
||||
LEGEJO_SMTP_PORT = "587"
|
||||
LEGEJO_SMTP_USER = ""
|
||||
LEGEJO_SMTP_PASSWORD = ""
|
||||
LEGEJO_MAIL_FROM = ""
|
||||
# Searching inside the books; keeps the text of the EPUBs in the database.
|
||||
LEGEJO_FULLTEXT = "false"
|
||||
# Empty: switched on and off on Legejo's Admin page. "true" or "false" here
|
||||
# fixes it, and the Admin page shows it as set by the environment.
|
||||
LEGEJO_FULLTEXT = ""
|
||||
# Read-only MCP server for AI assistants at /api/mcp.
|
||||
LEGEJO_MCP = "false"
|
||||
# The librarian: book suggestions from an OpenAI-compatible language model.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
libredb-studio:
|
||||
image: ghcr.io/libredb/libredb-studio:1.0.0
|
||||
image: ghcr.io/libredb/libredb-studio:1.2.0
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
# Since 0.18.0 ADMIN_PASSWORD and USER_PASSWORD seed the account table only
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"id": "libredb-studio",
|
||||
"name": "LibreDB Studio",
|
||||
"version": "1.0.0",
|
||||
"description": "The open-source SQL IDE you host yourself. Query PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Redis, ClickHouse, Cassandra and more from your browser, twenty-seven drivers reaching fifty-four named engines.",
|
||||
"version": "1.2.0",
|
||||
"description": "The open-source SQL IDE you host yourself. Query PostgreSQL, MySQL, Oracle, SQL Server, MongoDB, Redis, ClickHouse, Cassandra and more from your browser, forty-two drivers reaching sixty-nine named engines.",
|
||||
"logo": "libredb-studio.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/libredb/libredb-studio",
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
services:
|
||||
maintenant:
|
||||
image: nginxinc/nginx-unprivileged:1.29-alpine
|
||||
restart: unless-stopped
|
||||
read_only: true
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
tmpfs:
|
||||
- /tmp:noexec,nosuid,size=16m
|
||||
entrypoint:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- printf '%s:{PLAIN}%s\n' "$$AUTH_USER" "$$AUTH_PASSWORD" > /tmp/htpasswd && exec nginx -g 'daemon off;'
|
||||
environment:
|
||||
AUTH_USER: ${AUTH_USER}
|
||||
AUTH_PASSWORD: ${AUTH_PASSWORD}
|
||||
volumes:
|
||||
- ../files/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
expose:
|
||||
- 8080
|
||||
depends_on:
|
||||
- maintenant-app
|
||||
|
||||
maintenant-app:
|
||||
image: ghcr.io/kolapsis/maintenant:1.10.1
|
||||
restart: unless-stopped
|
||||
read_only: true
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
||||
tmpfs:
|
||||
- /tmp:noexec,nosuid,size=64m
|
||||
volumes:
|
||||
- maintenant-data:/data
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- /proc:/host/proc:ro
|
||||
- /etc/os-release:/host/etc/os-release:ro
|
||||
environment:
|
||||
MAINTENANT_ADDR: 0.0.0.0:8080
|
||||
MAINTENANT_DB: /data/maintenant.db
|
||||
MAINTENANT_BASE_URL: ${MAINTENANT_BASE_URL}
|
||||
MAINTENANT_TRUSTED_PROXIES: 10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
|
||||
|
||||
volumes:
|
||||
maintenant-data: {}
|
||||
@@ -0,0 +1,17 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32">
|
||||
<defs>
|
||||
<linearGradient id="sig" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||
<stop offset="0%" style="stop-color:#3ECF8E;stop-opacity:0.5"/>
|
||||
<stop offset="60%" style="stop-color:#3ECF8E"/>
|
||||
<stop offset="100%" style="stop-color:#22D3EE;stop-opacity:0.7"/>
|
||||
</linearGradient>
|
||||
<filter id="gl">
|
||||
<feGaussianBlur stdDeviation="1.2" result="b"/>
|
||||
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
|
||||
</filter>
|
||||
</defs>
|
||||
<rect width="32" height="32" rx="7" fill="#12151C"/>
|
||||
<polyline points="6,25 6,7 16,20 26,7 26,25" fill="none" stroke="url(#sig)" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" filter="url(#gl)"/>
|
||||
<line x1="26" y1="25" x2="28.5" y2="25" stroke="#3ECF8E" stroke-width="2" stroke-linecap="round" opacity="0.3"/>
|
||||
<circle cx="30" cy="25" r="1.5" fill="#3ECF8E"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 944 B |
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"id": "maintenant",
|
||||
"name": "maintenant",
|
||||
"version": "1.10.1",
|
||||
"description": "Self-hosted monitoring for Docker, Swarm and Kubernetes in a single Go binary that uses about 100 MB of RAM. maintenant has no login of its own, so this template puts an nginx basic-auth proxy in front of it: the user is admin and the password is the AUTH_PASSWORD variable in the Environment tab. Heartbeat pings and the public status page stay reachable without auth.",
|
||||
"logo": "logo.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/kolapsis/maintenant",
|
||||
"website": "https://maintenant.dev",
|
||||
"docs": "https://docs.maintenant.dev/"
|
||||
},
|
||||
"tags": [
|
||||
"monitoring",
|
||||
"docker",
|
||||
"alerts"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
auth_password = "${password:32}"
|
||||
|
||||
[config]
|
||||
[[config.domains]]
|
||||
serviceName = "maintenant"
|
||||
port = 8080
|
||||
host = "${main_domain}"
|
||||
|
||||
[config.env]
|
||||
AUTH_USER = "admin"
|
||||
AUTH_PASSWORD = "${auth_password}"
|
||||
MAINTENANT_BASE_URL = "https://${main_domain}"
|
||||
|
||||
[[config.mounts]]
|
||||
filePath = "/default.conf"
|
||||
content = """
|
||||
server {
|
||||
listen 8080;
|
||||
server_name _;
|
||||
|
||||
auth_basic "maintenant";
|
||||
auth_basic_user_file /tmp/htpasswd;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
|
||||
|
||||
location ~ ^/((ping|status|assets|screenshots)(/|$)|workbox-|favicon|icon|(sw|registerSW)[.]js$|manifest[.]webmanifest$|apple-touch-icon[.]png$|logo[.]svg$) {
|
||||
auth_basic off;
|
||||
proxy_pass http://maintenant-app:8080;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://maintenant-app:8080;
|
||||
}
|
||||
}
|
||||
"""
|
||||
@@ -0,0 +1,60 @@
|
||||
services:
|
||||
db:
|
||||
image: timescale/timescaledb:2.30.1-pg17
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: mcpspan
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
POSTGRES_DB: mcpspan
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -h 127.0.0.1 -U mcpspan -d mcpspan"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
migrate:
|
||||
image: ghcr.io/mcpspan/core-api:0.13.0
|
||||
restart: "no"
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
DATABASE_URL: postgres://mcpspan:${POSTGRES_PASSWORD}@db:5432/mcpspan
|
||||
command: ["./node_modules/.bin/node-pg-migrate", "up"]
|
||||
|
||||
api:
|
||||
image: ghcr.io/mcpspan/core-api:0.13.0
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
environment:
|
||||
DATABASE_URL: postgres://mcpspan:${POSTGRES_PASSWORD}@db:5432/mcpspan
|
||||
PORT: 6271
|
||||
API_KEY_SECRET: ${API_KEY_SECRET}
|
||||
MCPSPAN_DASHBOARD_URL: ${MCPSPAN_DASHBOARD_URL}
|
||||
expose:
|
||||
- 6271
|
||||
healthcheck:
|
||||
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:6271/health').then(r=>process.exit(r.ok?0:1),()=>process.exit(1))"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
|
||||
dashboard:
|
||||
image: ghcr.io/mcpspan/core-dashboard:0.13.0
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
api:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
CORE_API_URL: http://api:6271
|
||||
MCPSPAN_INGEST_URL: ${MCPSPAN_INGEST_URL}
|
||||
expose:
|
||||
- 6270
|
||||
|
||||
volumes:
|
||||
db-data: {}
|
||||
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||
<rect width="64" height="64" rx="14" fill="#23262b"/>
|
||||
<path d="M17 23.5Q19.5 29.5 25.5 32Q19.5 34.5 17 40.5Q14.5 34.5 8.5 32Q14.5 29.5 17 23.5Z" fill="#fff" stroke="#fff" stroke-width="2.5" stroke-linejoin="round"/>
|
||||
<rect x="30" y="16" width="22" height="7" rx="3.5" fill="#8a9099"/>
|
||||
<rect x="30" y="28.5" width="16" height="7" rx="3.5" fill="#2a78d6"/>
|
||||
<rect x="30" y="41" width="26" height="7" rx="3.5" fill="#8a9099"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 500 B |
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"id": "mcpspan",
|
||||
"name": "mcpspan",
|
||||
"version": "0.13.0",
|
||||
"description": "mcpspan is open-source analytics for MCP servers: which tools agents call, how often they fail and why, which clients call them, and how fast they answer. Add one line with an SDK in any of eight languages, or none at all behind its proxy, and see it in the dashboard. Parameter values never leave your server.",
|
||||
"logo": "mcpspan.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/mcpspan/mcpspan",
|
||||
"website": "https://mcpspan.com",
|
||||
"docs": "https://mcpspan.com/docs/self-hosting/"
|
||||
},
|
||||
"tags": [
|
||||
"analytics",
|
||||
"monitoring",
|
||||
"mcp"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
api_domain = "${domain}"
|
||||
|
||||
[config]
|
||||
mounts = []
|
||||
|
||||
# The dashboard, where you sign in.
|
||||
[[config.domains]]
|
||||
serviceName = "dashboard"
|
||||
port = 6270
|
||||
host = "${main_domain}"
|
||||
|
||||
# Where your MCP servers send their calls, with the API key from the dashboard.
|
||||
[[config.domains]]
|
||||
serviceName = "api"
|
||||
port = 6271
|
||||
host = "${api_domain}"
|
||||
|
||||
[config.env]
|
||||
POSTGRES_PASSWORD = "${password:32}"
|
||||
# Signs API keys; changing it later invalidates every key issued.
|
||||
API_KEY_SECRET = "${base64:48}"
|
||||
# The address the dashboard's setup snippet tells MCP servers to send to.
|
||||
MCPSPAN_INGEST_URL = "http://${api_domain}"
|
||||
# Where MCP clients that sign in to the API's /mcp (claude.ai, Claude Code...) send people to allow them.
|
||||
MCPSPAN_DASHBOARD_URL = "http://${main_domain}"
|
||||
@@ -1,16 +1,9 @@
|
||||
services:
|
||||
navi-music:
|
||||
# 4.1.0 is the newest release that can boot without a YouTube OAuth2 refresh
|
||||
# token; 4.1.1+ throws at startup ("YouTube OAuth token is mandatory") unless
|
||||
# a valid token obtained via an interactive device-code flow is provided, so
|
||||
# newer tags can never boot with template defaults.
|
||||
image: anvian/navi-music:4.1.0
|
||||
image: ghcr.io/andre-carbajal/navimusic:4.3.0
|
||||
restart: unless-stopped
|
||||
# NaviMusic logs (rather than throws) when DISCORD_TOKEN is empty or invalid,
|
||||
# then exits 0 because no JDA threads keep the JVM alive. Keep the container
|
||||
# running in that case so first-time users see the instructions in the logs
|
||||
# instead of a restart loop; real crashes (non-zero exits) still propagate to
|
||||
# the restart policy.
|
||||
depends_on:
|
||||
- yt-cipher
|
||||
entrypoint:
|
||||
- sh
|
||||
- -c
|
||||
@@ -18,7 +11,7 @@ services:
|
||||
java $$JAVA_OPTS -jar /app/NaviMusic.jar nogui --spring.profiles.active=prod;
|
||||
code=$$?;
|
||||
if [ "$$code" -eq 0 ]; then
|
||||
echo "NaviMusic is idle. Set DISCORD_TOKEN (and optionally Spotify/YouTube credentials) in the Environment tab, then redeploy.";
|
||||
echo "NaviMusic is idle. Set DISCORD_TOKEN and required YouTube credentials in the Environment tab, then redeploy.";
|
||||
tail -f /dev/null;
|
||||
fi;
|
||||
exit $$code
|
||||
@@ -29,3 +22,12 @@ services:
|
||||
YOUTUBE_POTOKEN: ${YOUTUBE_POTOKEN}
|
||||
YOUTUBE_VISITOR: ${YOUTUBE_VISITOR}
|
||||
YOUTUBE_OAUTH2: ${YOUTUBE_OAUTH2}
|
||||
YOUTUBE_CIPHER_URL: http://yt-cipher:8001
|
||||
YOUTUBE_CIPHER_PASSWORD: ${YOUTUBE_CIPHER_PASSWORD}
|
||||
|
||||
yt-cipher:
|
||||
image: ghcr.io/kikkia/yt-cipher:master@sha256:4c5ec381ff57336cfc24822d2b526a5ad7cd0171f61065a1bbc87bb736842449
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
OVERRIDE_PLAYER_VARIANT: IAS
|
||||
API_TOKEN: ${YOUTUBE_CIPHER_PASSWORD}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "navi-music",
|
||||
"name": "NaviMusic",
|
||||
"version": "4.1.0",
|
||||
"version": "4.3.0",
|
||||
"description": "A Discord music bot that plays YouTube and Spotify tracks and playlists in voice channels.",
|
||||
"logo": "navi-music.png",
|
||||
"links": {
|
||||
|
||||
@@ -5,8 +5,11 @@ env = [
|
||||
# Optional but recommended for Spotify links: https://developer.spotify.com/dashboard
|
||||
"SPOTIFY_CLIENT_ID=",
|
||||
"SPOTIFY_CLIENT_SECRET=",
|
||||
# Optional YouTube tweaks (leave empty to use the default anonymous clients).
|
||||
# YouTube OAuth2 refresh token is required by current NaviMusic versions.
|
||||
"YOUTUBE_OAUTH2=",
|
||||
# Optional YouTube tweaks.
|
||||
"YOUTUBE_POTOKEN=",
|
||||
"YOUTUBE_VISITOR=",
|
||||
"YOUTUBE_OAUTH2=",
|
||||
# Shared secret for the internal yt-cipher service.
|
||||
"YOUTUBE_CIPHER_PASSWORD=${password:32}",
|
||||
]
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# dokploy: allow-host-ports
|
||||
# LiveKit requires public TCP/UDP media ports 7881 and 7882 for WebRTC.
|
||||
# Dokploy owns routing and the isolated network.
|
||||
version: "3.8"
|
||||
services:
|
||||
frontend:
|
||||
build:
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
opendots:
|
||||
build:
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
services:
|
||||
opentodo:
|
||||
image: ghcr.io/opentodoapp/opentodo:0.19.0
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- 8080
|
||||
environment:
|
||||
- OPENTODO_BASE_URL=${OPENTODO_BASE_URL:-}
|
||||
- OPENTODO_SETUP_TOKEN=${OPENTODO_SETUP_TOKEN:-}
|
||||
- OPENTODO_ALLOW_SIGNUP=${OPENTODO_ALLOW_SIGNUP:-false}
|
||||
- OPENTODO_TRUSTED_PROXIES=${OPENTODO_TRUSTED_PROXIES:-}
|
||||
volumes:
|
||||
- opentodo-data:/data
|
||||
healthcheck:
|
||||
test: ["CMD", "/opentodo", "healthcheck"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 10s
|
||||
|
||||
volumes:
|
||||
opentodo-data:
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"id": "opentodo",
|
||||
"name": "OpenTodo",
|
||||
"version": "0.19.0",
|
||||
"description": "Open-source, local-first task manager. Works offline and syncs every device from one small container.",
|
||||
"logo": "opentodo.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/OpenTodoApp/OpenTodo",
|
||||
"website": "https://open-todo.app",
|
||||
"docs": "https://open-todo.app/docs/self-hosting/dokploy/"
|
||||
},
|
||||
"tags": [
|
||||
"productivity",
|
||||
"tasks",
|
||||
"todo",
|
||||
"self-hosted"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img"><title>OpenTodo</title><!-- OpenTodo brand mark. Part of OpenTodo, AGPL-3.0 (see LICENSE). --><rect width="64" height="64" rx="14" fill="#0f172a"/><g transform="translate(8 6) scale(2)" fill="none" stroke-width="2.6" stroke-linecap="round" stroke-linejoin="round"><path d="M19.73 10.93A8 8 0 1 1 12.7 5.03" stroke="#34d399"/><path d="M8 13l3 3" stroke="#ffffff"/><path d="M11 16l9-9" stroke="#34d399"/></g></svg>
|
||||
|
After Width: | Height: | Size: 484 B |
@@ -0,0 +1,20 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
setup_token = "${password:32}"
|
||||
|
||||
[config]
|
||||
mounts = []
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "opentodo"
|
||||
port = 8080
|
||||
host = "${main_domain}"
|
||||
|
||||
[config.env]
|
||||
# Empty while the domain is plain http (an https value there breaks sign-in).
|
||||
# Once the domain has HTTPS, set https://<your domain> and redeploy.
|
||||
OPENTODO_BASE_URL = ""
|
||||
# Asked for when you create the owner account on the first visit.
|
||||
OPENTODO_SETUP_TOKEN = "${setup_token}"
|
||||
OPENTODO_ALLOW_SIGNUP = "false"
|
||||
OPENTODO_TRUSTED_PROXIES = ""
|
||||
@@ -1,7 +1,10 @@
|
||||
services:
|
||||
openwa:
|
||||
image: ghcr.io/rmyndharis/openwa:0.24.0
|
||||
image: ghcr.io/rmyndharis/openwa:0.25.0
|
||||
restart: unless-stopped
|
||||
# Bounded teardown: drain + engines + webhook flush + queue closes can take up to
|
||||
# 63s in the worst case; the process force-exits after 67s.
|
||||
stop_grace_period: 75s
|
||||
# Hardened runtime matching the upstream production defaults: Chromium (used by the
|
||||
# whatsapp-web.js engine) launches with --no-sandbox, so the container is the confinement
|
||||
# boundary. The caps that remain are only what the entrypoint needs to fix named-volume
|
||||
@@ -37,6 +40,11 @@ services:
|
||||
# Off by default so the template works over HTTP or HTTPS; set "true" when you only ever reach
|
||||
# it through a TLS-terminating proxy.
|
||||
- CSP_UPGRADE_INSECURE_REQUESTS=${CSP_UPGRADE_INSECURE_REQUESTS}
|
||||
# MCP server at POST /mcp. Read-only unless MCP_READONLY is explicitly "false".
|
||||
- MCP_ENABLED=${MCP_ENABLED}
|
||||
- MCP_READONLY=${MCP_READONLY}
|
||||
# Swagger UI at /api/docs; enabled here despite the production default.
|
||||
- ENABLE_SWAGGER=${ENABLE_SWAGGER}
|
||||
expose:
|
||||
- "2785"
|
||||
volumes:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "openwa",
|
||||
"name": "OpenWA",
|
||||
"version": "0.24.0",
|
||||
"version": "0.25.0",
|
||||
"description": "OpenWA is a free, self-hosted WhatsApp API gateway with a REST API, webhooks, multi-session support, and a bundled web dashboard.",
|
||||
"logo": "openwa.svg",
|
||||
"links": {
|
||||
|
||||
@@ -6,6 +6,13 @@ timezone = "UTC"
|
||||
# Set to "true" only when the dashboard is reached exclusively through a TLS-terminating proxy.
|
||||
# Left "false" so the bundled SPA loads over plain HTTP (see comments in docker-compose.yml).
|
||||
csp_upgrade_insecure_requests = "false"
|
||||
# The MCP server is opt-in upstream. Enabled here so the template exposes POST /mcp by default.
|
||||
# Read-only is the upstream-recommended default; set to "false" to mount the write tools too.
|
||||
mcp_enabled = "true"
|
||||
mcp_readonly = "true"
|
||||
# Swagger UI at /api/docs. Upstream disables it under NODE_ENV=production by default.
|
||||
# Note: the docs mount is not behind the API-key guard, so it exposes the schema publicly.
|
||||
enable_swagger = "true"
|
||||
|
||||
[config]
|
||||
env = [
|
||||
@@ -15,6 +22,9 @@ env = [
|
||||
"AUTO_START_SESSIONS=${auto_start_sessions}",
|
||||
"TZ=${timezone}",
|
||||
"CSP_UPGRADE_INSECURE_REQUESTS=${csp_upgrade_insecure_requests}",
|
||||
"MCP_ENABLED=${mcp_enabled}",
|
||||
"MCP_READONLY=${mcp_readonly}",
|
||||
"ENABLE_SWAGGER=${enable_swagger}",
|
||||
]
|
||||
mounts = []
|
||||
|
||||
|
||||
@@ -227,4 +227,3 @@ volumes:
|
||||
postgres: null
|
||||
redis: null
|
||||
storage: null
|
||||
version: '3.8'
|
||||
|
||||
@@ -11,7 +11,7 @@ services:
|
||||
|
||||
|
||||
phpmyadmin:
|
||||
image: phpmyadmin/phpmyadmin:5.2.1
|
||||
image: phpmyadmin:5.2.3
|
||||
environment:
|
||||
PMA_HOST: db
|
||||
PMA_USER: ${MYSQL_USER}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "phpmyadmin",
|
||||
"name": "Phpmyadmin",
|
||||
"version": "5.2.1",
|
||||
"version": "5.2.3",
|
||||
"description": "phpMyAdmin is an open-source web interface for managing MySQL and MariaDB databases. Self-host it on your own server with Dokploy, which deploys phpMyAdmin as a Docker Compose service in a few clicks.",
|
||||
"logo": "phpmyadmin.png",
|
||||
"links": {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
services:
|
||||
ponos:
|
||||
image: ghcr.io/salvadorcardona/ponos:0.1.0
|
||||
image: ghcr.io/hermez-agency/ponos:0.2.0
|
||||
restart: unless-stopped
|
||||
# The image's own user, said again so that nothing runs it as root: Claude
|
||||
# Code refuses bypassPermissions to root.
|
||||
user: ponos
|
||||
expose:
|
||||
- "8787"
|
||||
environment:
|
||||
@@ -9,10 +12,14 @@ services:
|
||||
PONOS_WEB_PASSWORD: ${PONOS_WEB_PASSWORD}
|
||||
PONOS_WEB_TOKEN: ${PONOS_WEB_TOKEN}
|
||||
PONOS_LANGUAGE: ${PONOS_LANGUAGE}
|
||||
TZ: ${TZ}
|
||||
CLAUDE_CODE_OAUTH_TOKEN: ${CLAUDE_CODE_OAUTH_TOKEN}
|
||||
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
|
||||
OPENROUTER_API_KEY: ${OPENROUTER_API_KEY}
|
||||
GH_TOKEN: ${GH_TOKEN}
|
||||
PONOS_NOTION_TOKEN: ${PONOS_NOTION_TOKEN}
|
||||
PONOS_TELEGRAM_TOKEN: ${PONOS_TELEGRAM_TOKEN}
|
||||
PONOS_SLACK_TOKEN: ${PONOS_SLACK_TOKEN}
|
||||
volumes:
|
||||
- ponos-data:/data
|
||||
- ponos-workspace:/workspace
|
||||
@@ -24,6 +31,14 @@ services:
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 60s
|
||||
# A ceiling, not a reservation: a Claude Code session is a Node process of
|
||||
# a few hundred megabytes, and a build or a test suite it runs adds its own.
|
||||
# Four gigabytes hold the two runner.max_concurrent allows by default; raise
|
||||
# it with that number.
|
||||
deploy:
|
||||
resources:
|
||||
limits:
|
||||
memory: 4g
|
||||
|
||||
volumes:
|
||||
ponos-data:
|
||||
|
||||
@@ -1,17 +1,21 @@
|
||||
{
|
||||
"id": "ponos",
|
||||
"name": "Ponos",
|
||||
"version": "0.1.0",
|
||||
"description": "Ponos runs your tickets with Claude Code: a ticket set to Ready becomes a session on a throwaway git worktree, and comes back as a pull request. Board in Notion or in Markdown files, with a web console.",
|
||||
"version": "0.2.0",
|
||||
"description": "A harness around Claude Code that runs your tasks — code or not — from Notion or its own board: a ticket comes back as a pull request on GitHub, a text, an action carried out or a post, and nothing ships until you say yes. Web console, Telegram and Slack.",
|
||||
"logo": "ponos.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/SalvadorCardona/ponos",
|
||||
"github": "https://github.com/hermez-agency/ponos",
|
||||
"website": "https://the-ponos.app/",
|
||||
"docs": "https://github.com/SalvadorCardona/ponos#install-with-dokploy"
|
||||
"docs": "https://github.com/hermez-agency/ponos/blob/main/guide/server.md#install-with-dokploy"
|
||||
},
|
||||
"tags": [
|
||||
"ai",
|
||||
"ai-agent",
|
||||
"automation",
|
||||
"developer-tools"
|
||||
"claude",
|
||||
"developer-tools",
|
||||
"notion",
|
||||
"github"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,244 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128" data-state="idle" data-theme="auto" role="img">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120" role="img">
|
||||
<title>Ponos</title>
|
||||
<style>
|
||||
svg { --robot-body: #78a0ff; --robot-body-shade: #5079e6; --robot-screen: #1c2547; --robot-eye: #b4f1ff; --robot-accent: #ffcf5c; --robot-flame: #f59a3c; --robot-flame-core: #fbd35a; --robot-gold: #f2c65a; --robot-gold-deep: #b8861f; --robot-tunic: #f3ecdc; --robot-sash: #c4553a; --robot-pink: #ff8fb0; --robot-glint: #ffffff; --robot-alert: #ff6b86; --robot-ink: #46599a; --robot-shadow: rgba(36, 52, 110, .16); }
|
||||
svg[data-theme="dark"] { --robot-body: #82a8ff; --robot-body-shade: #5c84ee; --robot-screen: #141b36; --robot-eye: #b4f1ff; --robot-accent: #ffd36b; --robot-flame: #f59a3c; --robot-flame-core: #fbd35a; --robot-gold: #f2c65a; --robot-gold-deep: #b8861f; --robot-tunic: #f3ecdc; --robot-sash: #c4553a; --robot-pink: #ff8fb0; --robot-glint: #ffffff; --robot-alert: #ff7d93; --robot-ink: #a9bdf2; --robot-shadow: rgba(130, 168, 255, .16); }
|
||||
@media (prefers-color-scheme: dark) { svg:not([data-theme="light"]) { --robot-body: #82a8ff; --robot-body-shade: #5c84ee; --robot-screen: #141b36; --robot-eye: #b4f1ff; --robot-accent: #ffd36b; --robot-flame: #f59a3c; --robot-flame-core: #fbd35a; --robot-gold: #f2c65a; --robot-gold-deep: #b8861f; --robot-tunic: #f3ecdc; --robot-sash: #c4553a; --robot-pink: #ff8fb0; --robot-glint: #ffffff; --robot-alert: #ff7d93; --robot-ink: #a9bdf2; --robot-shadow: rgba(130, 168, 255, .16); } }
|
||||
svg { display: block; width: 100%; height: auto; overflow: visible; }
|
||||
[data-layer] { transform-box: view-box; }
|
||||
[data-layer="frame"] { transform-origin: 64px 44px; }
|
||||
[data-layer="base"] { transform-origin: 64px 119px; }
|
||||
[data-layer="rig"] { transform-origin: 64px 119px; }
|
||||
[data-layer="head"] { transform-origin: 64px 86px; }
|
||||
[data-layer="flame"] { transform-origin: 64px 22px; }
|
||||
[data-layer="fire"] { transform-origin: 64px 21px; }
|
||||
[data-layer="arm-left"] { transform-origin: 45px 89px; }
|
||||
[data-layer="arm-right"] { transform-origin: 83px 89px; }
|
||||
[data-layer="forearm-left"] { transform-origin: 38.5px 96px; }
|
||||
[data-layer="forearm-right"] { transform-origin: 89.5px 96px; }
|
||||
[data-layer="leg-left"] { transform-origin: 54px 104px; }
|
||||
[data-layer="leg-right"] { transform-origin: 74px 104px; }
|
||||
[data-layer="lid-left"] { transform-origin: 50px 42px; }
|
||||
[data-layer="lid-right"] { transform-origin: 78px 42px; }
|
||||
[data-layer="mouth"] { transform-origin: 64px 68px; }
|
||||
[data-layer="tear"] { transform-origin: 88px 60px; }
|
||||
[data-layer="z1"] { transform-origin: 97px 23px; }
|
||||
[data-layer="z2"] { transform-origin: 106px 13px; }
|
||||
[data-layer="z3"] { transform-origin: 115px 4px; }
|
||||
.shadow { fill: var(--robot-shadow); }
|
||||
.shell { fill: var(--robot-body); }
|
||||
.ear, .hand, .foot, .limb-fill { fill: var(--robot-body-shade); }
|
||||
.limb { fill: none; stroke: var(--robot-body-shade); stroke-width: 8; stroke-linecap: round; }
|
||||
.sheen { fill: none; stroke: var(--robot-glint); stroke-width: 3.6; stroke-linecap: round; opacity: .55; }
|
||||
.tunic { fill: var(--robot-tunic); }
|
||||
.sash { fill: var(--robot-sash); }
|
||||
.brooch, .socket { fill: var(--robot-gold); }
|
||||
.brooch-pin { fill: var(--robot-gold-deep); }
|
||||
.fire { fill: var(--robot-flame); stroke: var(--robot-flame); stroke-width: 0; stroke-linejoin: round; }
|
||||
.fire-core { fill: var(--robot-flame-core); }
|
||||
.screen, .lid { fill: var(--robot-screen); }
|
||||
.eye, .mouth-fill { fill: var(--robot-eye); }
|
||||
.glint { fill: var(--robot-glint); }
|
||||
.eye .glint, .eye-open .glint { opacity: .95; }
|
||||
.eye-line, .mouth-line { fill: none; stroke: var(--robot-eye); stroke-width: 4.2; stroke-linecap: round; stroke-linejoin: round; }
|
||||
.mouth-line { stroke-width: 2.6; }
|
||||
.eye-joy, .eye-closed, .mouth-alt { opacity: 0; }
|
||||
.tongue { fill: var(--robot-pink); }
|
||||
.tear { fill: var(--robot-eye); opacity: 0; }
|
||||
.lid { transform: scaleY(0); transition: transform .07s ease-in; }
|
||||
.z { fill: none; stroke: var(--robot-body-shade); stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
|
||||
.star { fill: var(--robot-accent); }
|
||||
.heart { fill: var(--robot-pink); }
|
||||
.dot { fill: var(--robot-body-shade); }
|
||||
.fx-zzz, .fx-stars, .fx-dots { opacity: 0; }
|
||||
svg.blinking[data-state] [data-layer^="lid-"] { transform: scaleY(1); }
|
||||
svg[data-state="thinking"] [data-layer="head"] { transform: rotate(4deg); }
|
||||
svg[data-state="thinking"] [data-layer="eyes"] { transform: translate(4px, -4px); }
|
||||
svg[data-state="thinking"] [data-layer="mouth-smile"] { opacity: 0; }
|
||||
svg[data-state="thinking"] [data-layer="mouth-flat"] { opacity: 1; }
|
||||
svg[data-state="thinking"] [data-layer="arm-right"] { transform: rotate(-128deg); }
|
||||
svg[data-state="thinking"] [data-layer="forearm-right"] { transform: rotate(-40deg); }
|
||||
svg[data-state="working"] [data-layer="lid-left"] { transform: scaleY(.3); }
|
||||
svg[data-state="working"] [data-layer="lid-right"] { transform: scaleY(.3); }
|
||||
svg[data-state="working"] [data-layer="mouth-smile"] { opacity: 0; }
|
||||
svg[data-state="working"] [data-layer="mouth-flat"] { opacity: 1; }
|
||||
svg[data-state="working"] [data-layer="arm-left"] { transform: rotate(40deg); }
|
||||
svg[data-state="working"] [data-layer="arm-right"] { transform: rotate(-40deg); }
|
||||
svg[data-state="working"] [data-layer="forearm-left"] { transform: rotate(-50deg); }
|
||||
svg[data-state="working"] [data-layer="forearm-right"] { transform: rotate(50deg); }
|
||||
svg[data-state="working"] [data-layer="fire"] { transform: scale(1.15, 1.3); }
|
||||
svg[data-state="success"] [data-layer="eye-open-left"] { opacity: 0; }
|
||||
svg[data-state="success"] [data-layer="eye-open-right"] { opacity: 0; }
|
||||
svg[data-state="success"] [data-layer="eye-joy-left"] { opacity: 1; }
|
||||
svg[data-state="success"] [data-layer="eye-joy-right"] { opacity: 1; }
|
||||
svg[data-state="success"] [data-layer="mouth-smile"] { opacity: 0; }
|
||||
svg[data-state="success"] [data-layer="mouth-open"] { opacity: 1; }
|
||||
svg[data-state="success"] [data-layer="arm-left"] { transform: rotate(100deg); }
|
||||
svg[data-state="success"] [data-layer="arm-right"] { transform: rotate(-100deg); }
|
||||
svg[data-state="success"] [data-layer="forearm-left"] { transform: rotate(30deg); }
|
||||
svg[data-state="success"] [data-layer="forearm-right"] { transform: rotate(-30deg); }
|
||||
svg[data-state="success"] [data-layer="fx-stars"] { opacity: 1; }
|
||||
svg[data-state="success"] .star { transform-box: fill-box; transform-origin: center; }
|
||||
svg[data-state="success"] .heart { transform-box: fill-box; transform-origin: center; }
|
||||
svg[data-state="error"] [data-layer="rig"] { transform: translateY(2px); }
|
||||
svg[data-state="error"] [data-layer="head"] { transform: rotate(-5deg); }
|
||||
svg[data-state="error"] [data-layer="lid-left"] { transform: rotate(-14deg) scaleY(.32); }
|
||||
svg[data-state="error"] [data-layer="lid-right"] { transform: rotate(14deg) scaleY(.32); }
|
||||
svg[data-state="error"] [data-layer="eyes"] { transform: translateY(2px); }
|
||||
svg[data-state="error"] [data-layer="mouth-smile"] { opacity: 0; }
|
||||
svg[data-state="error"] [data-layer="mouth-frown"] { opacity: 1; }
|
||||
svg[data-state="error"] [data-layer="arm-left"] { transform: rotate(-14deg); }
|
||||
svg[data-state="error"] [data-layer="arm-right"] { transform: rotate(14deg); }
|
||||
svg[data-state="error"] [data-layer="flame"] { transform: rotate(-22deg); }
|
||||
svg[data-state="error"] .fire { fill: var(--robot-alert); stroke: var(--robot-alert); }
|
||||
svg[data-state="error"] [data-layer="tear"] { opacity: 1; }
|
||||
svg[data-state="sleep"] [data-layer="rig"] { transform: translateY(1px); }
|
||||
svg[data-state="sleep"] [data-layer="head"] { transform: rotate(-7deg); }
|
||||
svg[data-state="sleep"] [data-layer="flame"] { transform: rotate(-12deg); }
|
||||
svg[data-state="sleep"] [data-layer="eye-open-left"] { opacity: 0; }
|
||||
svg[data-state="sleep"] [data-layer="eye-open-right"] { opacity: 0; }
|
||||
svg[data-state="sleep"] [data-layer="eye-closed-left"] { opacity: 1; }
|
||||
svg[data-state="sleep"] [data-layer="eye-closed-right"] { opacity: 1; }
|
||||
svg[data-state="sleep"] [data-layer="mouth-smile"] { opacity: 0; }
|
||||
svg[data-state="sleep"] [data-layer="mouth-o"] { opacity: 1; }
|
||||
svg[data-state="sleep"] [data-layer="fire"] { transform: scale(.45); opacity: .5; }
|
||||
svg[data-state="sleep"] .fire-core { opacity: 0; }
|
||||
svg[data-state="sleep"] [data-layer="fx-zzz"] { opacity: 1; }
|
||||
svg[data-state="waiting"] [data-layer="head"] { transform: rotate(-6deg); }
|
||||
svg[data-state="waiting"] [data-layer="eyes"] { transform: translate(5px, -4px); }
|
||||
svg[data-state="waiting"] [data-layer="mouth-smile"] { opacity: 0; }
|
||||
svg[data-state="waiting"] [data-layer="mouth-o"] { opacity: 1; }
|
||||
svg[data-state="waiting"] [data-layer="fx-dots"] { opacity: 1; }svg.small [data-layer="frame"] { transform: translateY(20px) scale(1.4); }svg.small [data-layer="base"], svg.small [data-layer="body"], svg.small [data-layer="arm-left"], svg.small [data-layer="arm-right"], svg.small [data-layer="accessories"], svg.small [data-layer="fx"], svg.small .ear, svg.small .sheen, svg.small .glint-small, svg.small .tear, svg.small .fire-core, svg.small .socket { display: none; }svg.small .fire { stroke-width: 4.5; }svg.small .eye-line { stroke-width: 6; }svg.small .mouth-line { stroke-width: 4; }
|
||||
@media (max-width: 40px) { svg [data-layer="frame"] { transform: translateY(20px) scale(1.4); }svg [data-layer="base"], svg [data-layer="body"], svg [data-layer="arm-left"], svg [data-layer="arm-right"], svg [data-layer="accessories"], svg [data-layer="fx"], svg .ear, svg .sheen, svg .glint-small, svg .tear, svg .fire-core, svg .socket { display: none; }svg .fire { stroke-width: 4.5; }svg .eye-line { stroke-width: 6; }svg .mouth-line { stroke-width: 4; }
|
||||
}
|
||||
@container (max-width: 40px) { svg [data-layer="frame"] { transform: translateY(20px) scale(1.4); }svg [data-layer="base"], svg [data-layer="body"], svg [data-layer="arm-left"], svg [data-layer="arm-right"], svg [data-layer="accessories"], svg [data-layer="fx"], svg .ear, svg .sheen, svg .glint-small, svg .tear, svg .fire-core, svg .socket { display: none; }svg .fire { stroke-width: 4.5; }svg .eye-line { stroke-width: 6; }svg .mouth-line { stroke-width: 4; }
|
||||
}</style>
|
||||
<defs>
|
||||
<linearGradient id="trr-shade" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset=".4" stop-color="#0b1330" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#0b1330" stop-opacity=".2"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="trr-sheen" cx=".32" cy=".18" r=".75">
|
||||
<stop offset="0" stop-color="#fff" stop-opacity=".38"/>
|
||||
<stop offset=".6" stop-color="#fff" stop-opacity="0"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="trr-glow" cx=".5" cy=".35" r=".7">
|
||||
<stop offset="0" stop-color="#fff" stop-opacity=".1"/>
|
||||
<stop offset="1" stop-color="#fff" stop-opacity="0"/>
|
||||
</radialGradient>
|
||||
<clipPath id="trr-torso"><rect x="42" y="78" width="44" height="30" rx="15"/></clipPath>
|
||||
</defs>
|
||||
<g data-layer="frame">
|
||||
<g data-layer="base">
|
||||
<ellipse class="shadow" cx="64" cy="119" rx="27" ry="4.6"/>
|
||||
<ellipse class="shadow" cx="64" cy="119" rx="17" ry="3"/>
|
||||
</g>
|
||||
<g data-layer="rig">
|
||||
<g data-layer="body">
|
||||
<g data-layer="leg-left">
|
||||
<rect class="limb-fill" x="48" y="99" width="12" height="14" rx="6"/>
|
||||
<ellipse class="foot" cx="53" cy="114.5" rx="8" ry="4.5"/>
|
||||
</g>
|
||||
<g data-layer="leg-right">
|
||||
<rect class="limb-fill" x="68" y="99" width="12" height="14" rx="6"/>
|
||||
<ellipse class="foot" cx="75" cy="114.5" rx="8" ry="4.5"/>
|
||||
</g>
|
||||
<rect class="shell" x="42" y="78" width="44" height="30" rx="15"/>
|
||||
<g data-layer="dress" clip-path="url(#trr-torso)">
|
||||
<path class="tunic" d="M42 92 Q64 89 86 92 V108 H42 Z"/>
|
||||
<path class="sash" d="M42 86 L54 81.5 L86 100 L86 108 Z"/>
|
||||
</g>
|
||||
<rect x="42" y="78" width="44" height="30" rx="15" fill="url(#trr-shade)"/>
|
||||
<g data-layer="brooch">
|
||||
<circle class="brooch" cx="51" cy="89" r="3.4"/>
|
||||
<circle class="brooch-pin" cx="51" cy="89" r="1.5"/>
|
||||
<circle class="glint" cx="50" cy="88" r=".8"/>
|
||||
</g>
|
||||
</g>
|
||||
<g data-layer="head">
|
||||
<g data-layer="flame">
|
||||
<g data-layer="fire">
|
||||
<path class="fire" d="M64 4.6 C68.8 10.6 70.6 15.4 67.6 20.2 C66.4 22 61.6 22 60.4 20.2 C57.4 15.4 59.2 10.6 64 4.6 Z"/>
|
||||
<path class="fire-core" d="M64 10.6 C66.4 14.2 67 17.2 65.2 19.6 C64.6 20.2 63.4 20.2 62.8 19.6 C61 17.2 61.6 14.2 64 10.6 Z"/>
|
||||
</g>
|
||||
<rect class="socket" x="59.2" y="19.6" width="9.6" height="3.6" rx="1.2"/>
|
||||
</g>
|
||||
<circle class="ear" cx="19.5" cy="56" r="7.5"/>
|
||||
<circle class="ear" cx="108.5" cy="56" r="7.5"/>
|
||||
<rect class="shell" x="20" y="22" width="88" height="64" rx="30"/>
|
||||
<rect x="20" y="22" width="88" height="64" rx="30" fill="url(#trr-shade)"/>
|
||||
<rect x="20" y="22" width="88" height="64" rx="30" fill="url(#trr-sheen)"/>
|
||||
<path class="sheen" d="M33 38 Q38 29 50 26.5"/>
|
||||
<rect class="screen" x="30" y="33" width="68" height="44" rx="20"/>
|
||||
<g data-layer="eyes">
|
||||
<g data-layer="eye-left">
|
||||
<g data-layer="eye-open-left" class="eye-open">
|
||||
<rect class="eye" x="42.5" y="44" width="15" height="18" rx="7.5"/>
|
||||
<circle class="glint" cx="47" cy="49" r="3"/>
|
||||
<circle class="glint glint-small" cx="53" cy="57.5" r="1.4"/>
|
||||
</g>
|
||||
<path data-layer="eye-joy-left" class="eye-line eye-joy" d="M43.5 55 Q50 45.5 56.5 55"/>
|
||||
<path data-layer="eye-closed-left" class="eye-line eye-closed" d="M43.5 53 Q50 58.5 56.5 53"/>
|
||||
</g>
|
||||
<g data-layer="eye-right">
|
||||
<g data-layer="eye-open-right" class="eye-open">
|
||||
<rect class="eye" x="70.5" y="44" width="15" height="18" rx="7.5"/>
|
||||
<circle class="glint" cx="75" cy="49" r="3"/>
|
||||
<circle class="glint glint-small" cx="81" cy="57.5" r="1.4"/>
|
||||
</g>
|
||||
<path data-layer="eye-joy-right" class="eye-line eye-joy" d="M71.5 55 Q78 45.5 84.5 55"/>
|
||||
<path data-layer="eye-closed-right" class="eye-line eye-closed" d="M71.5 53 Q78 58.5 84.5 53"/>
|
||||
</g>
|
||||
</g>
|
||||
<g data-layer="eyelids">
|
||||
<rect data-layer="lid-left" class="lid" x="40" y="42" width="20" height="22"/>
|
||||
<rect data-layer="lid-right" class="lid" x="68" y="42" width="20" height="22"/>
|
||||
</g>
|
||||
<rect x="30" y="33" width="68" height="44" rx="20" fill="url(#trr-glow)"/>
|
||||
<g data-layer="mouth">
|
||||
<path data-layer="mouth-smile" class="mouth-line" d="M59.5 66 Q64 70.5 68.5 66"/>
|
||||
<g data-layer="mouth-open" class="mouth-alt">
|
||||
<path class="mouth-fill" d="M58.5 65 Q64 66 69.5 65 Q69 73 64 73 Q59 73 58.5 65 Z"/>
|
||||
<path class="tongue" d="M60.8 70.6 Q64 68.4 67.2 70.6 Q64 73 60.8 70.6 Z"/>
|
||||
</g>
|
||||
<path data-layer="mouth-frown" class="mouth-line mouth-alt" d="M59.5 70 Q64 65.5 68.5 70"/>
|
||||
<ellipse data-layer="mouth-o" class="mouth-line mouth-alt" cx="64" cy="68" rx="2.4" ry="2.8"/>
|
||||
<path data-layer="mouth-flat" class="mouth-line mouth-alt" d="M60.5 67.5 Q62.5 66.2 64.5 67.5 Q66.5 68.8 68 67.2"/>
|
||||
</g>
|
||||
<path data-layer="tear" class="tear" d="M88 60 C85.6 64 85.6 66.6 88 66.6 C90.4 66.6 90.4 64 88 60 Z"/>
|
||||
</g>
|
||||
<g data-layer="arm-left">
|
||||
<path class="limb" d="M45 89 L38.5 96"/>
|
||||
<g data-layer="forearm-left">
|
||||
<path class="limb" d="M38.5 96 L37 99.5"/>
|
||||
<circle class="hand" cx="37" cy="100.5" r="5.5"/>
|
||||
</g>
|
||||
</g>
|
||||
<g data-layer="arm-right">
|
||||
<path class="limb" d="M83 89 L89.5 96"/>
|
||||
<g data-layer="forearm-right">
|
||||
<path class="limb" d="M89.5 96 L91 99.5"/>
|
||||
<circle class="hand" cx="91" cy="100.5" r="5.5"/>
|
||||
</g>
|
||||
</g>
|
||||
<g data-layer="accessories"></g>
|
||||
</g>
|
||||
<g data-layer="fx">
|
||||
<g data-layer="fx-zzz" class="fx-zzz">
|
||||
<path data-layer="z1" class="z" d="M94 20 h6 l-6 7 h6"/>
|
||||
<path data-layer="z2" class="z" d="M104 10 h5 l-5 6 h5"/>
|
||||
<path data-layer="z3" class="z" d="M113 2 h4 l-4 5 h4"/>
|
||||
</g>
|
||||
<g data-layer="fx-dots" class="fx-dots">
|
||||
<circle data-layer="dot1" class="dot" cx="98" cy="15" r="2.8"/>
|
||||
<circle data-layer="dot2" class="dot" cx="106.5" cy="15" r="2.8"/>
|
||||
<circle data-layer="dot3" class="dot" cx="115" cy="15" r="2.8"/>
|
||||
</g>
|
||||
<g data-layer="fx-stars" class="fx-stars">
|
||||
<path class="star" d="M14 24 l2 4.4 l4.4 2 l-4.4 2 l-2 4.4 l-2 -4.4 l-4.4 -2 l4.4 -2 z"/>
|
||||
<path class="star" d="M114 30 l1.5 3.3 l3.3 1.5 l-3.3 1.5 l-1.5 3.3 l-1.5 -3.3 l-3.3 -1.5 l3.3 -1.5 z"/>
|
||||
<path class="heart" d="M104 8.5 c-1.6 -3 -6 -2 -5 1.6 c.6 2.2 5 5 5 5 s4.4 -2.8 5 -5 c1 -3.6 -3.4 -4.6 -5 -1.6 z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<style>.ground { fill: #FFFFFF; } .screen { fill: #1c1917; }</style>
|
||||
<rect x="4" y="4" width="112" height="112" rx="26" class="ground" stroke="#E8611A" stroke-width="8"/>
|
||||
<path d="M60 20C67 27 69 32 66 36C64 39 56 39 54 36C51 32 53 27 60 20Z" fill="#E8611A"/>
|
||||
<rect x="28" y="44" width="64" height="50" rx="16" class="screen"/>
|
||||
<circle cx="48" cy="69" r="7" fill="#FFE1CC"/>
|
||||
<circle cx="72" cy="69" r="7" fill="#FFE1CC"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 524 B |
@@ -6,24 +6,53 @@ api_token = "${password:48}"
|
||||
[config]
|
||||
mounts = []
|
||||
env = [
|
||||
# Generated: the console's sign-in, and the token scripts carry. Change the email
|
||||
# to yours if you like; the password is in this tab whenever you need it.
|
||||
# -- Generated -------------------------------------------------------------
|
||||
# The console's sign-in: both set, it is claimed before anybody opens it. The
|
||||
# email is only a login, never written to — change it to yours if you like;
|
||||
# the password is in this tab whenever you need it.
|
||||
"PONOS_WEB_EMAIL=admin@${main_domain}",
|
||||
"PONOS_WEB_PASSWORD=${admin_password}",
|
||||
# What a script carries in `Authorization: Bearer`.
|
||||
"PONOS_WEB_TOKEN=${api_token}",
|
||||
|
||||
# -- Who answers the sessions: one of these is required --------------------
|
||||
# Your Claude subscription: run `claude setup-token` on a machine with a
|
||||
# browser and paste what it prints...
|
||||
"CLAUDE_CODE_OAUTH_TOKEN=",
|
||||
# ...or an Anthropic API key, billed by the token (console.anthropic.com).
|
||||
# Given without the token above, the sessions are billed to it from the start.
|
||||
"ANTHROPIC_API_KEY=",
|
||||
# Optional: an OpenRouter key (openrouter.ai/keys), in every session's
|
||||
# environment for the other models a ticket may call. The sessions only run
|
||||
# there once Settings › OpenRouter says so.
|
||||
"OPENROUTER_API_KEY=",
|
||||
|
||||
# -- GitHub, optional ------------------------------------------------------
|
||||
# A token (repo scope, or a fine-grained one with Contents and Pull requests
|
||||
# on read and write), so Ponos clones, pushes and opens pull requests as that
|
||||
# account. Leave it empty to create a GitHub App from the console instead:
|
||||
# Settings › GitHub › Connect GitHub. Writing tickets need neither.
|
||||
"GH_TOKEN=",
|
||||
|
||||
# -- The board, optional ---------------------------------------------------
|
||||
# A Notion integration token. Without one the board is kept in Markdown files
|
||||
# on the ponos-data volume, and the console is all you need.
|
||||
"PONOS_NOTION_TOKEN=",
|
||||
|
||||
# -- Your phone, optional --------------------------------------------------
|
||||
# A Telegram bot token, from @BotFather (/newbot). Say anything to the bot,
|
||||
# then `ponos notify --pair` in Dokploy's Terminal finds your chat.
|
||||
"PONOS_TELEGRAM_TOKEN=",
|
||||
# A Slack bot token (xoxb-…, chat:write and channels:history); the channel's
|
||||
# ID goes in the console's Settings › Slack.
|
||||
"PONOS_SLACK_TOKEN=",
|
||||
|
||||
# -- Where and in what words -----------------------------------------------
|
||||
# en or fr: the reports Ponos writes, and the console until you pick another.
|
||||
"PONOS_LANGUAGE=en",
|
||||
# Required, one of the two. Your Claude subscription: run `claude setup-token`
|
||||
# on a machine with a browser and paste what it prints...
|
||||
"CLAUDE_CODE_OAUTH_TOKEN=",
|
||||
# ...or an Anthropic API key, billed by the token (https://console.anthropic.com).
|
||||
"ANTHROPIC_API_KEY=",
|
||||
# Optional: a GitHub token (repo scope), so Ponos clones, pushes and opens pull
|
||||
# requests. The console's GitHub step says what is missing without it.
|
||||
"GH_TOKEN=",
|
||||
# Optional: a Notion integration token. Without one the board is kept in Markdown
|
||||
# files on the ponos-data volume, and the console is all you need.
|
||||
"PONOS_NOTION_TOKEN=",
|
||||
# The zone a schedule's hours are read in: 09:00 is nine there. An IANA name,
|
||||
# Europe/Paris for instance.
|
||||
"TZ=UTC",
|
||||
]
|
||||
|
||||
# The console: sign in with PONOS_WEB_EMAIL and PONOS_WEB_PASSWORD above.
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
services:
|
||||
postgres-extensor:
|
||||
image: ruxwez/postgres:18-v1.1.0
|
||||
restart: unless-stopped
|
||||
# Libraries loaded at startup. pg_cron and the other "preload" extensions
|
||||
# need to be listed here before CREATE EXTENSION works.
|
||||
command:
|
||||
- postgres
|
||||
- -c
|
||||
- shared_preload_libraries=${SHARED_PRELOAD_LIBRARIES}
|
||||
- -c
|
||||
- cron.database_name=${POSTGRES_DB}
|
||||
- -c
|
||||
- max_worker_processes=32
|
||||
# Uncomment 'ports' settings below to enable external access
|
||||
# ports:
|
||||
# - "5432:5432"
|
||||
environment:
|
||||
- POSTGRES_USER=${POSTGRES_USER}
|
||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
|
||||
- POSTGRES_DB=${POSTGRES_DB}
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 20s
|
||||
|
||||
volumes:
|
||||
postgres-data:
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"id": "postgres-extensor",
|
||||
"name": "PostgreSQL with 80+ Extensions",
|
||||
"version": "18-v1.1.0",
|
||||
"description": "The official PostgreSQL 18 image with 80+ tested extensions preinstalled: pgvector, PostGIS, TimescaleDB, pgmq, pg_cron, pg_duckdb, Apache AGE, pg_graphql and more. Multi-arch (amd64, arm64).",
|
||||
"logo": "postgres-extensor.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/ruxwez/postgres",
|
||||
"website": "https://hub.docker.com/r/ruxwez/postgres",
|
||||
"docs": "https://github.com/ruxwez/postgres/blob/main/.docs/included-extensions.md"
|
||||
},
|
||||
"tags": ["database", "postgres", "postgresql", "vector", "pgvector", "postgis", "timescaledb", "ai"]
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="576.095" height="593.844" viewBox="0 0 432.071 445.383"><g style="fill-rule:nonzero;clip-rule:nonzero;fill:none;stroke:#fff;stroke-width:12.4651;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4"><path d="M323.205 324.227c2.833-23.601 1.984-27.062 19.563-23.239l4.463.392c13.517.615 31.199-2.174 41.587-7 22.362-10.376 35.622-27.7 13.572-23.148-50.297 10.376-53.755-6.655-53.755-6.655 53.111-78.803 75.313-178.836 56.149-203.322-52.27-66.789-142.748-35.206-144.262-34.386l-.482.089c-9.938-2.062-21.06-3.294-33.554-3.496-22.761-.374-40.032 5.967-53.133 15.904 0 0-161.408-66.498-153.899 83.628 1.597 31.936 45.777 241.655 98.47 178.31 19.259-23.163 37.871-42.748 37.871-42.748 9.242 6.14 20.307 9.272 31.912 8.147l.897-.765c-.281 2.876-.157 5.689.359 9.019-13.572 15.167-9.584 17.83-36.723 23.416-27.457 5.659-11.326 15.734-.797 18.367 12.768 3.193 42.305 7.716 62.268-20.224l-.795 3.188c5.325 4.26 4.965 30.619 5.72 49.452.756 18.834 2.017 36.409 5.856 46.771 3.839 10.36 8.369 37.05 44.036 29.406 29.809-6.388 52.6-15.582 54.677-101.107" style="fill:#000;stroke:#000;stroke-width:37.3953;stroke-linecap:butt;stroke-linejoin:miter"/><path stroke="none" d="M402.395 271.23c-50.302 10.376-53.76-6.655-53.76-6.655 53.111-78.808 75.313-178.843 56.153-203.326-52.27-66.785-142.752-35.2-144.262-34.38l-.486.087c-9.938-2.063-21.06-3.292-33.56-3.496-22.761-.373-40.026 5.967-53.127 15.902 0 0-161.411-66.495-153.904 83.63 1.597 31.938 45.776 241.657 98.471 178.312 19.26-23.163 37.869-42.748 37.869-42.748 9.243 6.14 20.308 9.272 31.908 8.147l.901-.765c-.28 2.876-.152 5.689.361 9.019-13.575 15.167-9.586 17.83-36.723 23.416-27.459 5.659-11.328 15.734-.796 18.367 12.768 3.193 42.307 7.716 62.266-20.224l-.796 3.188c5.319 4.26 9.054 27.711 8.428 48.969s-1.044 35.854 3.147 47.254 8.368 37.05 44.042 29.406c29.809-6.388 45.256-22.942 47.405-50.555 1.525-19.631 4.976-16.729 5.194-34.28l2.768-8.309c3.192-26.611.507-35.196 18.872-31.203l4.463.392c13.517.615 31.208-2.174 41.591-7 22.358-10.376 35.618-27.7 13.573-23.148z" style="fill:#336791;stroke:none"/><path d="M215.866 286.484c-1.385 49.516.348 99.377 5.193 111.495 4.848 12.118 15.223 35.688 50.9 28.045 29.806-6.39 40.651-18.756 45.357-46.051 3.466-20.082 10.148-75.854 11.005-87.281M173.104 38.256S11.583-27.76 19.092 122.365c1.597 31.938 45.779 241.664 98.473 178.316 19.256-23.166 36.671-41.335 36.671-41.335M260.349 26.207c-5.591 1.753 89.848-34.889 144.087 34.417 19.159 24.484-3.043 124.519-56.153 203.329"/><path d="M348.282 263.953s3.461 17.036 53.764 6.653c22.04-4.552 8.776 12.774-13.577 23.155-18.345 8.514-59.474 10.696-60.146-1.069-1.729-30.355 21.647-21.133 19.96-28.739-1.525-6.85-11.979-13.573-18.894-30.338-6.037-14.633-82.796-126.849 21.287-110.183 3.813-.789-27.146-99.002-124.553-100.599-97.385-1.597-94.19 119.762-94.19 119.762" style="stroke-linejoin:bevel"/><path d="M188.604 274.334c-13.577 15.166-9.584 17.829-36.723 23.417-27.459 5.66-11.326 15.733-.797 18.365 12.768 3.195 42.307 7.718 62.266-20.229 6.078-8.509-.036-22.086-8.385-25.547-4.034-1.671-9.428-3.765-16.361 3.994"/><path d="M187.715 274.069c-1.368-8.917 2.93-19.528 7.536-31.942 6.922-18.626 22.893-37.255 10.117-96.339-9.523-44.029-73.396-9.163-73.436-3.193-.039 5.968 2.889 30.26-1.067 58.548-5.162 36.913 23.488 68.132 56.479 64.938"/><path d="M172.517 141.7c-.288 2.039 3.733 7.48 8.976 8.207 5.234.73 9.714-3.522 9.998-5.559.284-2.039-3.732-4.285-8.977-5.015-5.237-.731-9.719.333-9.996 2.367z" style="fill:#fff;stroke-width:4.155;stroke-linecap:butt;stroke-linejoin:miter"/><path d="M331.941 137.543c.284 2.039-3.732 7.48-8.976 8.207-5.238.73-9.718-3.522-10.005-5.559-.277-2.039 3.74-4.285 8.979-5.015s9.718.333 10.002 2.368z" style="fill:#fff;stroke-width:2.0775;stroke-linecap:butt;stroke-linejoin:miter"/><path d="M350.676 123.432c.863 15.994-3.445 26.888-3.988 43.914-.804 24.748 11.799 53.074-7.191 81.435"/></g></svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
@@ -0,0 +1,11 @@
|
||||
[variables]
|
||||
postgres_user = "${username}"
|
||||
postgres_password = "${password:32}"
|
||||
postgres_db = "postgres"
|
||||
|
||||
[config.env]
|
||||
POSTGRES_USER = "${postgres_user}"
|
||||
POSTGRES_PASSWORD = "${postgres_password}"
|
||||
POSTGRES_DB = "${postgres_db}"
|
||||
# Add more preload extensions here, comma-separated (e.g. timescaledb, pg_duckdb).
|
||||
SHARED_PRELOAD_LIBRARIES = "pg_stat_statements,pg_cron"
|
||||
@@ -0,0 +1,19 @@
|
||||
services:
|
||||
privatepaste:
|
||||
image: ghcr.io/dynamicsninja/privatepaste:0.5.0
|
||||
restart: unless-stopped
|
||||
stop_grace_period: 15s
|
||||
environment:
|
||||
PP_DB_KEY: ${PP_DB_KEY}
|
||||
PP_PASSWORD: ${PP_PASSWORD}
|
||||
PP_MAX_IMAGE_MB: ${PP_MAX_IMAGE_MB}
|
||||
PP_MAX_FILE_MB: ${PP_MAX_FILE_MB}
|
||||
PP_MAX_TEXT_KB: ${PP_MAX_TEXT_KB}
|
||||
PP_TRUST_CLOUDFLARE: ${PP_TRUST_CLOUDFLARE}
|
||||
volumes:
|
||||
- privatepaste-data:/data
|
||||
expose:
|
||||
- 8080
|
||||
|
||||
volumes:
|
||||
privatepaste-data:
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"id": "privatepaste",
|
||||
"name": "PrivatePaste",
|
||||
"version": "0.5.0",
|
||||
"description": "Self-hosted clipboard sync: copy on one device, paste on your others, with an encrypted, searchable history and apps for Windows, macOS, Linux and Android.",
|
||||
"logo": "privatepaste.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/DynamicsNinja/privatepaste",
|
||||
"website": "https://github.com/DynamicsNinja/privatepaste",
|
||||
"docs": "https://github.com/DynamicsNinja/privatepaste/blob/main/docs/self-hosting.md"
|
||||
},
|
||||
"tags": [
|
||||
"productivity",
|
||||
"clipboard",
|
||||
"sync"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" role="img" aria-label="PrivatePaste">
|
||||
<rect x="2" y="2" width="60" height="60" rx="18" fill="#221D40"/>
|
||||
<rect x="2.75" y="2.75" width="58.5" height="58.5" rx="17.25" fill="none" stroke="#B7A5FF" stroke-opacity=".35" stroke-width="1.5"/>
|
||||
<circle cx="32" cy="26" r="9" fill="#B7A5FF"/>
|
||||
<path d="M27.5 31.5h9l3 17.5h-15z" fill="#B7A5FF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 411 B |
@@ -0,0 +1,22 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
# 32 random bytes, base64: the encryption key for the database and images. Back it up: without it the data is lost.
|
||||
db_key = "${base64:32}"
|
||||
login_password = "${password:24}"
|
||||
|
||||
[config]
|
||||
mounts = []
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "privatepaste"
|
||||
port = 8080
|
||||
host = "${main_domain}"
|
||||
|
||||
[config.env]
|
||||
PP_DB_KEY = "${db_key}"
|
||||
PP_PASSWORD = "${login_password}"
|
||||
PP_MAX_IMAGE_MB = "20"
|
||||
PP_MAX_FILE_MB = "25"
|
||||
PP_MAX_TEXT_KB = "1024"
|
||||
# Set to "true" only if the server is reachable exclusively through a Cloudflare tunnel.
|
||||
PP_TRUST_CLOUDFLARE = "false"
|
||||
@@ -0,0 +1,179 @@
|
||||
# dokploy: allow-container-names
|
||||
x-puppetflow-environment: &puppetflow-environment
|
||||
APP_ENV: production
|
||||
LOG_STACK: single,stderr
|
||||
LANG: ${LANG}
|
||||
LANGUAGE: ${LANGUAGE}
|
||||
CONNECTION_TIMEOUT_MS: ${CONNECTION_TIMEOUT_MS}
|
||||
APP_URL: ${APP_URL}
|
||||
APP_KEY: ${APP_KEY}
|
||||
APP_QUEUES_COUNTER: "2"
|
||||
DB_CONNECTION: pgsql
|
||||
DB_HOST: postgres
|
||||
DB_PORT: "5432"
|
||||
DB_DATABASE: ${POSTGRES_DB}
|
||||
DB_USERNAME: ${POSTGRES_USER}
|
||||
DB_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
REDIS_HOST: redis
|
||||
REDIS_PORT: "6379"
|
||||
PINOKIO_HOST: pinokio
|
||||
PINOKIO_PORT: "3000"
|
||||
PINOKIO_TOKEN: ${PINOKIO_TOKEN}
|
||||
RUNNER_API_INTERNAL_URL: http://puppetflow:8000/api/internal/runner
|
||||
BROWSER_STREAM_INTERNAL_URL: http://stream-server:6080
|
||||
BROWSER_STREAM_PUBLIC_URL: ${BROWSER_STREAM_PUBLIC_URL}
|
||||
BROWSER_STREAM_ALLOWED_ORIGINS: ${APP_URL}
|
||||
BROWSER_STREAM_SECRET: ${BROWSER_STREAM_SECRET}
|
||||
|
||||
services:
|
||||
puppetflow:
|
||||
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- 8000
|
||||
volumes:
|
||||
- puppetflow-framework:/app/storage
|
||||
- puppetflow-execution:/app/data/execution
|
||||
- puppetflow-uploads:/app/data/storage
|
||||
environment: *puppetflow-environment
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-fsS", "http://localhost:8000/up"]
|
||||
interval: 30s
|
||||
timeout: 5s
|
||||
retries: 3
|
||||
start_period: 15s
|
||||
depends_on:
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
pinokio:
|
||||
condition: service_started
|
||||
stream-server:
|
||||
condition: service_started
|
||||
|
||||
migrate:
|
||||
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
|
||||
command: ["php", "artisan", "migrate", "--force"]
|
||||
restart: "no"
|
||||
volumes:
|
||||
- puppetflow-framework:/app/storage
|
||||
environment: *puppetflow-environment
|
||||
depends_on:
|
||||
init-volumes:
|
||||
condition: service_completed_successfully
|
||||
postgres:
|
||||
condition: service_healthy
|
||||
|
||||
queue-1:
|
||||
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
|
||||
command: ["php", "artisan", "queue:work", "--queue=1", "--tries=1", "--timeout=630", "--sleep=3", "--max-jobs=500", "--max-time=3600"]
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- puppetflow-framework:/app/storage
|
||||
- puppetflow-execution:/app/data/execution
|
||||
- puppetflow-uploads:/app/data/storage
|
||||
environment: *puppetflow-environment
|
||||
depends_on:
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
stream-server:
|
||||
condition: service_started
|
||||
|
||||
queue-2:
|
||||
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
|
||||
command: ["php", "artisan", "queue:work", "--queue=2", "--tries=1", "--timeout=630", "--sleep=3", "--max-jobs=500", "--max-time=3600"]
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- puppetflow-framework:/app/storage
|
||||
- puppetflow-execution:/app/data/execution
|
||||
- puppetflow-uploads:/app/data/storage
|
||||
environment: *puppetflow-environment
|
||||
depends_on:
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
stream-server:
|
||||
condition: service_started
|
||||
|
||||
scheduler:
|
||||
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
|
||||
command: ["php", "artisan", "schedule:work"]
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- puppetflow-framework:/app/storage
|
||||
- puppetflow-execution:/app/data/execution
|
||||
- puppetflow-uploads:/app/data/storage
|
||||
environment: *puppetflow-environment
|
||||
depends_on:
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
|
||||
stream-server:
|
||||
image: ghcr.io/puppetflow/puppetflow-stream-server:v2026.11.7
|
||||
restart: unless-stopped
|
||||
stop_grace_period: 30s
|
||||
expose:
|
||||
- 6080
|
||||
environment: *puppetflow-environment
|
||||
depends_on:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
|
||||
init-volumes:
|
||||
image: busybox:1.37.0
|
||||
command: ["sh", "-c", "chown -R 33:33 /framework /execution /uploads /browsers"]
|
||||
restart: "no"
|
||||
volumes:
|
||||
- puppetflow-framework:/framework
|
||||
- puppetflow-execution:/execution
|
||||
- puppetflow-uploads:/uploads
|
||||
- pinokio-downloads:/browsers
|
||||
|
||||
pinokio:
|
||||
image: ghcr.io/puppetflow/pinokio:v2026.11.1
|
||||
restart: unless-stopped
|
||||
user: "33:33"
|
||||
shm_size: "1gb"
|
||||
volumes:
|
||||
- puppetflow-execution:/app/data/execution
|
||||
- pinokio-downloads:/opt/browsers
|
||||
environment:
|
||||
TOKEN: ${PINOKIO_TOKEN}
|
||||
HOME: /tmp
|
||||
XDG_CONFIG_HOME: /tmp/.config
|
||||
XDG_CACHE_HOME: /tmp/.cache
|
||||
LANG: ${LANG}
|
||||
LANGUAGE: ${LANGUAGE}
|
||||
depends_on:
|
||||
init-volumes:
|
||||
condition: service_completed_successfully
|
||||
|
||||
postgres:
|
||||
image: postgres:17-alpine
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- puppetflow-db:/var/lib/postgresql/data
|
||||
environment:
|
||||
POSTGRES_DB: ${POSTGRES_DB}
|
||||
POSTGRES_USER: ${POSTGRES_USER}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U \"$${POSTGRES_USER}\" -d \"$${POSTGRES_DB}\""]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
|
||||
redis:
|
||||
image: redis:8.2.1-alpine
|
||||
command: ["redis-server", "--save", "", "--appendonly", "no"]
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 5
|
||||
|
||||
volumes:
|
||||
puppetflow-framework:
|
||||
puppetflow-uploads:
|
||||
puppetflow-execution:
|
||||
puppetflow-db:
|
||||
pinokio-downloads:
|
||||
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"id": "puppetflow-postgres",
|
||||
"name": "Puppetflow with Postgres",
|
||||
"version": "v2026.11.7",
|
||||
"description": "A self-hosted browser automation platform for building, running, and monitoring JavaScript workflows powered by Puppeteer and PostgreSQL.",
|
||||
"logo": "puppetflow.png",
|
||||
"links": {
|
||||
"github": "https://github.com/puppetflow/puppetflow",
|
||||
"website": "https://puppetflow.com/",
|
||||
"docs": "https://docs.puppetflow.com/"
|
||||
},
|
||||
"tags": [
|
||||
"automation",
|
||||
"browser",
|
||||
"workflow",
|
||||
"postgres"
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 182 KiB |
@@ -0,0 +1,36 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
stream_domain = "${domain}"
|
||||
app_key = "${base64:32}"
|
||||
browser_stream_secret = "${hash:32}"
|
||||
pinokio_token = "${hash:32}"
|
||||
postgres_user = "${username}"
|
||||
postgres_password = "${password:32}"
|
||||
postgres_database = "puppetflow"
|
||||
instance_id = "${hash:8}"
|
||||
|
||||
[config]
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "puppetflow"
|
||||
port = 8000
|
||||
host = "${main_domain}"
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "stream-server"
|
||||
port = 6080
|
||||
host = "${stream_domain}"
|
||||
|
||||
[config.env]
|
||||
LANG = "C.UTF-8"
|
||||
LANGUAGE = "en-US"
|
||||
CONNECTION_TIMEOUT_MS = "60000000"
|
||||
APP_URL = "http://${main_domain}"
|
||||
APP_KEY = "base64:${app_key}"
|
||||
BROWSER_STREAM_PUBLIC_URL = "http://${stream_domain}"
|
||||
BROWSER_STREAM_SECRET = "${browser_stream_secret}"
|
||||
PINOKIO_TOKEN = "${pinokio_token}"
|
||||
POSTGRES_USER = "${postgres_user}"
|
||||
POSTGRES_PASSWORD = "${postgres_password}"
|
||||
POSTGRES_DB = "${postgres_database}"
|
||||
PUPPETFLOW_INSTANCE_ID = "${instance_id}"
|
||||
@@ -1,10 +1,13 @@
|
||||
version: "3.8"
|
||||
|
||||
# dokploy: allow-container-names
|
||||
x-puppetflow-environment: &puppetflow-environment
|
||||
APP_ENV: production
|
||||
LOG_STACK: single,stderr
|
||||
LANG: ${LANG}
|
||||
LANGUAGE: ${LANGUAGE}
|
||||
CONNECTION_TIMEOUT_MS: ${CONNECTION_TIMEOUT_MS}
|
||||
APP_URL: ${APP_URL}
|
||||
APP_KEY: ${APP_KEY}
|
||||
APP_QUEUES_COUNTER: "1"
|
||||
APP_QUEUES_COUNTER: "2"
|
||||
DB_CONNECTION: sqlite
|
||||
DB_DATABASE: /app/storage/database.sqlite
|
||||
REDIS_HOST: redis
|
||||
@@ -20,7 +23,7 @@ x-puppetflow-environment: &puppetflow-environment
|
||||
|
||||
services:
|
||||
puppetflow:
|
||||
image: ghcr.io/puppetflow/puppetflow:v2026.10.20
|
||||
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- 8000
|
||||
@@ -44,7 +47,7 @@ services:
|
||||
condition: service_started
|
||||
|
||||
migrate:
|
||||
image: ghcr.io/puppetflow/puppetflow:v2026.10.20
|
||||
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
|
||||
command: ["php", "artisan", "migrate", "--force"]
|
||||
restart: "no"
|
||||
volumes:
|
||||
@@ -54,8 +57,8 @@ services:
|
||||
init-volumes:
|
||||
condition: service_completed_successfully
|
||||
|
||||
queue:
|
||||
image: ghcr.io/puppetflow/puppetflow:v2026.10.20
|
||||
queue-1:
|
||||
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
|
||||
command: ["php", "artisan", "queue:work", "--queue=1", "--tries=1", "--timeout=630", "--sleep=3", "--max-jobs=500", "--max-time=3600"]
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
@@ -69,8 +72,23 @@ services:
|
||||
stream-server:
|
||||
condition: service_started
|
||||
|
||||
queue-2:
|
||||
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
|
||||
command: ["php", "artisan", "queue:work", "--queue=2", "--tries=1", "--timeout=630", "--sleep=3", "--max-jobs=500", "--max-time=3600"]
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- puppetflow-framework:/app/storage
|
||||
- puppetflow-execution:/app/data/execution
|
||||
- puppetflow-uploads:/app/data/storage
|
||||
environment: *puppetflow-environment
|
||||
depends_on:
|
||||
migrate:
|
||||
condition: service_completed_successfully
|
||||
stream-server:
|
||||
condition: service_started
|
||||
|
||||
scheduler:
|
||||
image: ghcr.io/puppetflow/puppetflow:v2026.10.20
|
||||
image: ghcr.io/puppetflow/puppetflow:v2026.11.7
|
||||
command: ["php", "artisan", "schedule:work"]
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
@@ -83,7 +101,7 @@ services:
|
||||
condition: service_completed_successfully
|
||||
|
||||
stream-server:
|
||||
image: ghcr.io/puppetflow/puppetflow-stream-server:v2026.10.20
|
||||
image: ghcr.io/puppetflow/puppetflow-stream-server:v2026.11.7
|
||||
restart: unless-stopped
|
||||
stop_grace_period: 30s
|
||||
expose:
|
||||
@@ -95,22 +113,29 @@ services:
|
||||
|
||||
init-volumes:
|
||||
image: busybox:1.37.0
|
||||
command: ["sh", "-c", "touch /framework/database.sqlite && chown -R 33:33 /framework /execution /uploads"]
|
||||
command: ["sh", "-c", "touch /framework/database.sqlite && chown -R 33:33 /framework /execution /uploads /browsers"]
|
||||
restart: "no"
|
||||
volumes:
|
||||
- puppetflow-framework:/framework
|
||||
- puppetflow-execution:/execution
|
||||
- puppetflow-uploads:/uploads
|
||||
- pinokio-downloads:/browsers
|
||||
|
||||
pinokio:
|
||||
image: ghcr.io/puppetflow/pinokio:v2026.9.6
|
||||
image: ghcr.io/puppetflow/pinokio:v2026.11.1
|
||||
restart: unless-stopped
|
||||
user: "33:33"
|
||||
shm_size: "1gb"
|
||||
volumes:
|
||||
- puppetflow-execution:/app/data/execution
|
||||
- pinokio-downloads:/opt/browsers
|
||||
environment:
|
||||
TOKEN: ${PINOKIO_TOKEN}
|
||||
HOME: /tmp
|
||||
XDG_CONFIG_HOME: /tmp/.config
|
||||
XDG_CACHE_HOME: /tmp/.cache
|
||||
LANG: ${LANG}
|
||||
LANGUAGE: ${LANGUAGE}
|
||||
depends_on:
|
||||
init-volumes:
|
||||
condition: service_completed_successfully
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"id": "puppetflow",
|
||||
"name": "Puppetflow",
|
||||
"version": "v2026.10.20",
|
||||
"version": "v2026.11.7",
|
||||
"description": "A self-hosted browser automation platform for building, running, and monitoring JavaScript workflows powered by Puppeteer.",
|
||||
"logo": "puppetflow.png",
|
||||
"links": {
|
||||
|
||||
@@ -4,6 +4,7 @@ stream_domain = "${domain}"
|
||||
app_key = "${base64:32}"
|
||||
browser_stream_secret = "${hash:32}"
|
||||
pinokio_token = "${hash:32}"
|
||||
instance_id = "${hash:8}"
|
||||
|
||||
[config]
|
||||
|
||||
@@ -11,17 +12,19 @@ pinokio_token = "${hash:32}"
|
||||
serviceName = "puppetflow"
|
||||
port = 8000
|
||||
host = "${main_domain}"
|
||||
https = true
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "stream-server"
|
||||
port = 6080
|
||||
host = "${stream_domain}"
|
||||
https = true
|
||||
|
||||
[config.env]
|
||||
APP_URL = "https://${main_domain}"
|
||||
LANG = "C.UTF-8"
|
||||
LANGUAGE = "en-US"
|
||||
CONNECTION_TIMEOUT_MS = "60000000"
|
||||
APP_URL = "http://${main_domain}"
|
||||
APP_KEY = "base64:${app_key}"
|
||||
BROWSER_STREAM_PUBLIC_URL = "https://${stream_domain}"
|
||||
BROWSER_STREAM_PUBLIC_URL = "http://${stream_domain}"
|
||||
BROWSER_STREAM_SECRET = "${browser_stream_secret}"
|
||||
PINOKIO_TOKEN = "${pinokio_token}"
|
||||
PUPPETFLOW_INSTANCE_ID = "${instance_id}"
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
services:
|
||||
reelsaw:
|
||||
image: ghcr.io/osbytes/reelsaw:0.18.2
|
||||
restart: always
|
||||
# a deploy waits for running renders instead of killing them (SHUTDOWN_GRACE_SECONDS=300)
|
||||
stop_grace_period: 330s
|
||||
expose:
|
||||
- 3000
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-fsS", "http://127.0.0.1:3000/api/health"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 12
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
environment:
|
||||
PORT: "3000"
|
||||
DATA_DIR: /data
|
||||
LOG_FILE: /data/logs/reelsaw.log
|
||||
RUN_HTTP: "true"
|
||||
RUN_WORKERS: "true"
|
||||
TRUST_PROXY: "true"
|
||||
DATABASE_URL: postgres://reelsaw:${DB_PASSWORD}@db:5432/reelsaw
|
||||
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
|
||||
APP_URL: ${APP_URL}
|
||||
SIGNUP_MODE: ${SIGNUP_MODE}
|
||||
AI_MODEL: ${AI_MODEL}
|
||||
TRANSCRIPTION_MODEL: ${TRANSCRIPTION_MODEL}
|
||||
OPENAI_API_KEY: ${OPENAI_API_KEY}
|
||||
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
|
||||
GOOGLE_GENERATIVE_AI_API_KEY: ${GOOGLE_GENERATIVE_AI_API_KEY}
|
||||
GROQ_API_KEY: ${GROQ_API_KEY}
|
||||
DEEPGRAM_API_KEY: ${DEEPGRAM_API_KEY}
|
||||
volumes:
|
||||
- data:/data
|
||||
|
||||
db:
|
||||
image: postgres:17-alpine
|
||||
restart: always
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 20
|
||||
environment:
|
||||
POSTGRES_USER: reelsaw
|
||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
||||
POSTGRES_DB: reelsaw
|
||||
volumes:
|
||||
- pgdata:/var/lib/postgresql/data
|
||||
|
||||
volumes:
|
||||
data:
|
||||
pgdata:
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"id": "reelsaw",
|
||||
"name": "Reelsaw",
|
||||
"version": "v0.18.2",
|
||||
"description": "Reelsaw is a self-hosted, AI-powered video clipper: paste a YouTube link or upload a video and it transcribes it, asks a language model for the most clippable moments, reframes the speaker into vertical 9:16 with face tracking, cuts fillers and burns in word-highlight captions. Open source (AGPL-3.0), any model provider (OpenAI, Anthropic, Google, Groq, Deepgram, or a local Ollama and Whisper), and an MCP server so agents can drive it. Deploy it on Dokploy with Docker Compose and a Postgres database in a few clicks.",
|
||||
"logo": "reelsaw.png",
|
||||
"links": {
|
||||
"github": "https://github.com/osbytes/reelsaw",
|
||||
"website": "https://reelsaw.com",
|
||||
"docs": "https://github.com/osbytes/reelsaw#readme"
|
||||
},
|
||||
"tags": [
|
||||
"video",
|
||||
"ai",
|
||||
"self-hosted"
|
||||
],
|
||||
"seoTitle": "Reelsaw Docker Compose Setup",
|
||||
"seoDescription": "Self-hosted AI video clipper: long videos to vertical shorts with face-tracked reframing and word-highlight captions. Deploy Reelsaw with Docker Compose on Dokploy in minutes – free, open source, any AI provider.",
|
||||
"newConfig": true
|
||||
}
|
||||
|
After Width: | Height: | Size: 9.8 KiB |
@@ -0,0 +1,26 @@
|
||||
[variables]
|
||||
main_domain = "${domain}"
|
||||
|
||||
[config]
|
||||
mounts = []
|
||||
|
||||
[[config.domains]]
|
||||
serviceName = "reelsaw"
|
||||
port = 3_000
|
||||
host = "${main_domain}"
|
||||
|
||||
[config.env]
|
||||
APP_URL = "https://${main_domain}"
|
||||
BETTER_AUTH_SECRET = "${base64:48}"
|
||||
DB_PASSWORD = "${password:32}"
|
||||
# open: anyone may sign up; the first account becomes the admin. Switch to approval or closed afterwards.
|
||||
SIGNUP_MODE = "open"
|
||||
# One model provider key is required before first boot (Reelsaw exits with a readable reason otherwise).
|
||||
# Defaults use OpenAI for both models; any provider works, see https://github.com/osbytes/reelsaw#model-configuration
|
||||
AI_MODEL = "openai:gpt-4o-mini"
|
||||
TRANSCRIPTION_MODEL = "openai:whisper-1"
|
||||
OPENAI_API_KEY = ""
|
||||
ANTHROPIC_API_KEY = ""
|
||||
GOOGLE_GENERATIVE_AI_API_KEY = ""
|
||||
GROQ_API_KEY = ""
|
||||
DEEPGRAM_API_KEY = ""
|
||||
@@ -1,4 +1,4 @@
|
||||
# https://manual.seafile.com/latest/setup/setup_ce_by_docker/
|
||||
# https://manual.seafile.com/14.0/setup/setup_ce_by_docker/
|
||||
#
|
||||
# This Dokploy template for seafile sets the default credentials to:
|
||||
# USERNAME: admin@example.com
|
||||
@@ -10,6 +10,10 @@
|
||||
#
|
||||
# If you have already deployed once, changes to some environment
|
||||
# variables may not take effect. For example, initial passwords.
|
||||
#
|
||||
# Upgrading an existing Seafile 13 instance requires a backup and migration
|
||||
# of any customised settings stored in its persistent volume. See:
|
||||
# https://manual.seafile.com/14.0/upgrade/upgrade_docker_14.0/
|
||||
|
||||
services:
|
||||
seafile-db:
|
||||
@@ -46,7 +50,7 @@ services:
|
||||
- REDIS_PASSWORD=${REDIS_PASSWORD:?Variable is not set or empty}
|
||||
|
||||
seafile:
|
||||
image: seafileltd/seafile-mc:13.0-latest
|
||||
image: seafileltd/seafile-mc:14.0.9
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- seafile-data:/shared
|
||||
@@ -69,6 +73,8 @@ services:
|
||||
- JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
|
||||
- SEAFILE_LOG_TO_STDOUT=${SEAFILE_LOG_TO_STDOUT:-false}
|
||||
- ENABLE_GO_FILESERVER=${ENABLE_GO_FILESERVER:-true}
|
||||
- ENABLE_SEAFDAV=${ENABLE_SEAFDAV:-false}
|
||||
- SEAFDAV_WORKERS=${SEAFDAV_WORKERS:-5}
|
||||
- ENABLE_SEADOC=${ENABLE_SEADOC:-true}
|
||||
- SEADOC_SERVER_URL=${SEADOC_SERVER_URL:?Variable is not set or empty}
|
||||
- CACHE_PROVIDER=${CACHE_PROVIDER:-redis}
|
||||
@@ -101,7 +107,7 @@ services:
|
||||
condition: service_started
|
||||
|
||||
seadoc:
|
||||
image: seafileltd/sdoc-server:2.0-latest
|
||||
image: seafileltd/sdoc-server:2.0.11
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- seadoc-data:/shared
|
||||
@@ -110,7 +116,7 @@ services:
|
||||
- DB_PORT=${SEAFILE_MYSQL_DB_PORT:-3306}
|
||||
- DB_USER=${SEAFILE_MYSQL_DB_USER:-seafile}
|
||||
- DB_PASSWORD=${SEAFILE_MYSQL_DB_PASSWORD:?Variable is not set or empty}
|
||||
- DB_NAME=${SEADOC_MYSQL_DB_NAME:-seahub_db}
|
||||
- DB_NAME=${SEADOC_MYSQL_DB_NAME:-${SEAFILE_MYSQL_DB_SEAHUB_DB_NAME:-seahub_db}}
|
||||
- TIME_ZONE=${TIME_ZONE:-Etc/UTC}
|
||||
- JWT_PRIVATE_KEY=${JWT_PRIVATE_KEY:?Variable is not set or empty}
|
||||
- NON_ROOT=${NON_ROOT:-false}
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
{
|
||||
"id": "seafile",
|
||||
"name": "Seafile",
|
||||
"version": "13.0-latest",
|
||||
"version": "14.0.9",
|
||||
"description": "Seafile is an open-source file sync and sharing platform. Self-host it on your own server with Dokploy, which deploys Seafile as a Docker Compose service in a few clicks.",
|
||||
"logo": "seafile.svg",
|
||||
"links": {
|
||||
"github": "https://github.com/haiwen/seafile",
|
||||
"website": "https://seafile.com",
|
||||
"docs": "https://manual.seafile.com/13.0"
|
||||
"docs": "https://manual.seafile.com/14.0"
|
||||
},
|
||||
"tags": [
|
||||
"file-manager",
|
||||
"file-sharing",
|
||||
"storage"
|
||||
],
|
||||
"tags": ["file-manager", "file-sharing", "storage"],
|
||||
"seoTitle": "Self-Host Seafile in minutes",
|
||||
"seoDescription": "Cloud storage for file sync and sharing. Self-host Seafile on Dokploy in minutes – no manual setup needed."
|
||||
}
|
||||
|
||||
@@ -30,5 +30,7 @@ INIT_SEAFILE_ADMIN_EMAIL = "admin@example.com"
|
||||
INIT_SEAFILE_ADMIN_PASSWORD = "${admin_password}"
|
||||
|
||||
ENABLE_GO_FILESERVER = "true"
|
||||
ENABLE_SEAFDAV = "false"
|
||||
SEAFDAV_WORKERS = "5"
|
||||
ENABLE_SEADOC = "true"
|
||||
SEADOC_SERVER_URL = "https://${main_domain}/sdoc-server"
|
||||
SEADOC_SERVER_URL = "https://${main_domain}/sdoc-server"
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
# Dokploy template: the Dokploy Compose file minus the optional CJ Dropshipping app.
|
||||
# Variables come from template.toml. Keep the rest in sync with ../docker-compose.dokploy.yml.
|
||||
services:
|
||||
db:
|
||||
image: postgres:17
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
POSTGRES_USER: shopnex
|
||||
POSTGRES_PASSWORD: shopnex
|
||||
POSTGRES_DB: shopnex
|
||||
volumes:
|
||||
- db:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: ['CMD-SHELL', 'pg_isready -U shopnex']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
shopnex:
|
||||
image: ghcr.io/shopnex-ai/shopnex:${SHOPNEX_VERSION:-v0.13.1}
|
||||
pull_policy: always
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
db: { condition: service_healthy }
|
||||
volumes:
|
||||
- shopnex_data:/data
|
||||
environment:
|
||||
DATABASE_URL: postgres://shopnex:shopnex@db:5432/shopnex
|
||||
APP_URL: ${APP_URL:-http://localhost:3000}
|
||||
BETTER_AUTH_URL: ${APP_URL:-http://localhost:3000}
|
||||
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET:-}
|
||||
SHOPNEX_SECRET: ${SHOPNEX_SECRET:-}
|
||||
TENANCY_MODE: single
|
||||
DEFAULT_SHOP_NAME: ${DEFAULT_SHOP_NAME:-My Shop}
|
||||
# Look for the bundled apps (stripe, cj-dropshipping) at their service names on this network
|
||||
SHOPNEX_BUNDLED_APPS: docker
|
||||
|
||||
stripe:
|
||||
image: ghcr.io/shopnex-ai/shopnex-stripe:${SHOPNEX_VERSION:-v0.13.1}
|
||||
pull_policy: always
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- stripe_data:/data
|
||||
environment:
|
||||
STRIPE_APP_URL: ${STRIPE_APP_URL:-http://localhost:4600}
|
||||
SHOPNEX_INTERNAL_URL: http://shopnex:3000
|
||||
DATA_DIR: /data
|
||||
|
||||
volumes:
|
||||
db:
|
||||
shopnex_data:
|
||||
stripe_data:
|
||||