Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a0b5bb0c2a | |||
| 128651d310 | |||
| 6f07307229 | |||
| f32d48a271 | |||
| c6b41076ea | |||
| 854efbcff0 | |||
| ee335fa22e | |||
| fa0b9127f1 | |||
| e0e7cbeeef | |||
| 405fd49534 | |||
| f57b86d84f | |||
| 5fac760f2a | |||
| aa05d8edec | |||
| 9c2502c8d8 | |||
| e9a2778e17 | |||
| e466f70643 | |||
| bce0268b02 | |||
| 3da4af5431 | |||
| 0b3cb0b5d3 | |||
| 9d7cf80691 | |||
| fec2d9955c | |||
| b16791dd7a | |||
| c82da10738 | |||
| f0fd148d95 | |||
| 334f94878b | |||
| e6ca3d4c99 | |||
| e75da89239 | |||
| 2466ad1785 | |||
| 662394d56d |
@@ -1 +1,2 @@
|
|||||||
repo
|
repo
|
||||||
|
node_modules
|
||||||
|
|||||||
@@ -3,17 +3,26 @@ _APP_LOCALE=en
|
|||||||
_APP_OPTIONS_ABUSE=enabled
|
_APP_OPTIONS_ABUSE=enabled
|
||||||
_APP_OPTIONS_FORCE_HTTPS=disabled
|
_APP_OPTIONS_FORCE_HTTPS=disabled
|
||||||
_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=disabled
|
_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=disabled
|
||||||
|
_APP_OPTIONS_ROUTER_FORCE_HTTPS=disabled
|
||||||
_APP_OPTIONS_ROUTER_PROTECTION=disabled
|
_APP_OPTIONS_ROUTER_PROTECTION=disabled
|
||||||
_APP_OPENSSL_KEY_V1=your-secret-key
|
_APP_OPENSSL_KEY_V1=your-secret-key
|
||||||
_APP_DOMAIN=localhost
|
_APP_DOMAIN=$(PRIMARY_DOMAIN)
|
||||||
|
_APP_CUSTOM_DOMAIN_DENY_LIST=example.com,test.com,app.example.com
|
||||||
_APP_DOMAIN_FUNCTIONS=functions.localhost
|
_APP_DOMAIN_FUNCTIONS=functions.localhost
|
||||||
|
_APP_DOMAIN_SITES=sites.localhost
|
||||||
_APP_DOMAIN_TARGET=localhost
|
_APP_DOMAIN_TARGET=localhost
|
||||||
|
_APP_DOMAIN_TARGET_CNAME=localhost
|
||||||
|
_APP_DOMAIN_TARGET_AAAA=::1
|
||||||
|
_APP_DOMAIN_TARGET_A=127.0.0.1
|
||||||
|
_APP_DOMAIN_TARGET_CAA=
|
||||||
|
_APP_DNS=8.8.8.8
|
||||||
_APP_CONSOLE_WHITELIST_ROOT=enabled
|
_APP_CONSOLE_WHITELIST_ROOT=enabled
|
||||||
_APP_CONSOLE_WHITELIST_EMAILS=
|
_APP_CONSOLE_WHITELIST_EMAILS=
|
||||||
_APP_CONSOLE_WHITELIST_IPS=
|
_APP_CONSOLE_WHITELIST_IPS=
|
||||||
_APP_CONSOLE_HOSTNAMES=
|
_APP_CONSOLE_HOSTNAMES=
|
||||||
_APP_SYSTEM_EMAIL_NAME=Appwrite
|
_APP_SYSTEM_EMAIL_NAME=Appwrite
|
||||||
_APP_SYSTEM_EMAIL_ADDRESS=team@appwrite.io
|
_APP_SYSTEM_EMAIL_ADDRESS=noreply@appwrite.io
|
||||||
|
_APP_SYSTEM_TEAM_EMAIL=team@appwrite.io
|
||||||
_APP_SYSTEM_RESPONSE_FORMAT=
|
_APP_SYSTEM_RESPONSE_FORMAT=
|
||||||
_APP_SYSTEM_SECURITY_EMAIL_ADDRESS=certs@appwrite.io
|
_APP_SYSTEM_SECURITY_EMAIL_ADDRESS=certs@appwrite.io
|
||||||
_APP_EMAIL_SECURITY=
|
_APP_EMAIL_SECURITY=
|
||||||
@@ -25,6 +34,9 @@ _APP_USAGE_AGGREGATION_INTERVAL=30
|
|||||||
_APP_USAGE_TIMESERIES_INTERVAL=30
|
_APP_USAGE_TIMESERIES_INTERVAL=30
|
||||||
_APP_USAGE_DATABASE_INTERVAL=900
|
_APP_USAGE_DATABASE_INTERVAL=900
|
||||||
_APP_WORKER_PER_CORE=6
|
_APP_WORKER_PER_CORE=6
|
||||||
|
_APP_CONSOLE_SESSION_ALERTS=disabled
|
||||||
|
_APP_COMPRESSION_ENABLED=enabled
|
||||||
|
_APP_COMPRESSION_MIN_SIZE_BYTES=1024
|
||||||
_APP_REDIS_HOST=redis
|
_APP_REDIS_HOST=redis
|
||||||
_APP_REDIS_PORT=6379
|
_APP_REDIS_PORT=6379
|
||||||
_APP_REDIS_USER=
|
_APP_REDIS_USER=
|
||||||
@@ -56,6 +68,7 @@ _APP_STORAGE_S3_ACCESS_KEY=
|
|||||||
_APP_STORAGE_S3_SECRET=
|
_APP_STORAGE_S3_SECRET=
|
||||||
_APP_STORAGE_S3_REGION=us-east-1
|
_APP_STORAGE_S3_REGION=us-east-1
|
||||||
_APP_STORAGE_S3_BUCKET=
|
_APP_STORAGE_S3_BUCKET=
|
||||||
|
_APP_STORAGE_S3_ENDPOINT=
|
||||||
_APP_STORAGE_DO_SPACES_ACCESS_KEY=
|
_APP_STORAGE_DO_SPACES_ACCESS_KEY=
|
||||||
_APP_STORAGE_DO_SPACES_SECRET=
|
_APP_STORAGE_DO_SPACES_SECRET=
|
||||||
_APP_STORAGE_DO_SPACES_REGION=us-east-1
|
_APP_STORAGE_DO_SPACES_REGION=us-east-1
|
||||||
@@ -73,11 +86,16 @@ _APP_STORAGE_WASABI_SECRET=
|
|||||||
_APP_STORAGE_WASABI_REGION=eu-central-1
|
_APP_STORAGE_WASABI_REGION=eu-central-1
|
||||||
_APP_STORAGE_WASABI_BUCKET=
|
_APP_STORAGE_WASABI_BUCKET=
|
||||||
_APP_FUNCTIONS_SIZE_LIMIT=30000000
|
_APP_FUNCTIONS_SIZE_LIMIT=30000000
|
||||||
|
_APP_COMPUTE_SIZE_LIMIT=30000000
|
||||||
|
_APP_FUNCTIONS_BUILD_SIZE_LIMIT=2000000000
|
||||||
_APP_FUNCTIONS_TIMEOUT=900
|
_APP_FUNCTIONS_TIMEOUT=900
|
||||||
_APP_FUNCTIONS_BUILD_TIMEOUT=900
|
_APP_FUNCTIONS_BUILD_TIMEOUT=900
|
||||||
|
_APP_COMPUTE_BUILD_TIMEOUT=900
|
||||||
_APP_FUNCTIONS_CONTAINERS=10
|
_APP_FUNCTIONS_CONTAINERS=10
|
||||||
_APP_FUNCTIONS_CPUS=0
|
_APP_FUNCTIONS_CPUS=0
|
||||||
|
_APP_COMPUTE_CPUS=0
|
||||||
_APP_FUNCTIONS_MEMORY=0
|
_APP_FUNCTIONS_MEMORY=0
|
||||||
|
_APP_COMPUTE_MEMORY=0
|
||||||
_APP_FUNCTIONS_MEMORY_SWAP=0
|
_APP_FUNCTIONS_MEMORY_SWAP=0
|
||||||
_APP_FUNCTIONS_RUNTIMES=node-16.0,php-8.0,python-3.9,ruby-3.0
|
_APP_FUNCTIONS_RUNTIMES=node-16.0,php-8.0,python-3.9,ruby-3.0
|
||||||
_APP_EXECUTOR_SECRET=your-secret-key
|
_APP_EXECUTOR_SECRET=your-secret-key
|
||||||
@@ -85,14 +103,19 @@ _APP_EXECUTOR_HOST=http://exc1/v1
|
|||||||
_APP_EXECUTOR_RUNTIME_NETWORK=appwrite_runtimes
|
_APP_EXECUTOR_RUNTIME_NETWORK=appwrite_runtimes
|
||||||
_APP_FUNCTIONS_ENVS=node-16.0,php-7.4,python-3.9,ruby-3.0
|
_APP_FUNCTIONS_ENVS=node-16.0,php-7.4,python-3.9,ruby-3.0
|
||||||
_APP_FUNCTIONS_INACTIVE_THRESHOLD=60
|
_APP_FUNCTIONS_INACTIVE_THRESHOLD=60
|
||||||
|
_APP_COMPUTE_INACTIVE_THRESHOLD=60
|
||||||
DOCKERHUB_PULL_USERNAME=
|
DOCKERHUB_PULL_USERNAME=
|
||||||
DOCKERHUB_PULL_PASSWORD=
|
DOCKERHUB_PULL_PASSWORD=
|
||||||
DOCKERHUB_PULL_EMAIL=
|
DOCKERHUB_PULL_EMAIL=
|
||||||
OPEN_RUNTIMES_NETWORK=appwrite_runtimes
|
OPEN_RUNTIMES_NETWORK=appwrite_runtimes
|
||||||
_APP_FUNCTIONS_RUNTIMES_NETWORK=runtimes
|
_APP_FUNCTIONS_RUNTIMES_NETWORK=runtimes
|
||||||
|
_APP_COMPUTE_RUNTIMES_NETWORK=runtimes
|
||||||
_APP_DOCKER_HUB_USERNAME=
|
_APP_DOCKER_HUB_USERNAME=
|
||||||
_APP_DOCKER_HUB_PASSWORD=
|
_APP_DOCKER_HUB_PASSWORD=
|
||||||
_APP_FUNCTIONS_MAINTENANCE_INTERVAL=3600
|
_APP_FUNCTIONS_MAINTENANCE_INTERVAL=3600
|
||||||
|
_APP_COMPUTE_MAINTENANCE_INTERVAL=3600
|
||||||
|
_APP_SITES_TIMEOUT=900
|
||||||
|
_APP_SITES_RUNTIMES=static-1,node-22,flutter-3.29
|
||||||
_APP_VCS_GITHUB_APP_NAME=
|
_APP_VCS_GITHUB_APP_NAME=
|
||||||
_APP_VCS_GITHUB_PRIVATE_KEY=
|
_APP_VCS_GITHUB_PRIVATE_KEY=
|
||||||
_APP_VCS_GITHUB_APP_ID=
|
_APP_VCS_GITHUB_APP_ID=
|
||||||
@@ -101,9 +124,11 @@ _APP_VCS_GITHUB_CLIENT_SECRET=
|
|||||||
_APP_VCS_GITHUB_WEBHOOK_SECRET=
|
_APP_VCS_GITHUB_WEBHOOK_SECRET=
|
||||||
_APP_MAINTENANCE_INTERVAL=86400
|
_APP_MAINTENANCE_INTERVAL=86400
|
||||||
_APP_MAINTENANCE_DELAY=0
|
_APP_MAINTENANCE_DELAY=0
|
||||||
|
_APP_MAINTENANCE_START_TIME=00:00
|
||||||
_APP_MAINTENANCE_RETENTION_CACHE=2592000
|
_APP_MAINTENANCE_RETENTION_CACHE=2592000
|
||||||
_APP_MAINTENANCE_RETENTION_EXECUTION=1209600
|
_APP_MAINTENANCE_RETENTION_EXECUTION=1209600
|
||||||
_APP_MAINTENANCE_RETENTION_AUDIT=1209600
|
_APP_MAINTENANCE_RETENTION_AUDIT=1209600
|
||||||
|
_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=15778800
|
||||||
_APP_MAINTENANCE_RETENTION_ABUSE=86400
|
_APP_MAINTENANCE_RETENTION_ABUSE=86400
|
||||||
_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000
|
_APP_MAINTENANCE_RETENTION_USAGE_HOURLY=8640000
|
||||||
_APP_MAINTENANCE_RETENTION_SCHEDULES=86400
|
_APP_MAINTENANCE_RETENTION_SCHEDULES=86400
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
x-logging: &x-logging
|
x-logging: &x-logging
|
||||||
logging:
|
logging:
|
||||||
driver: "json-file"
|
driver: 'json-file'
|
||||||
options:
|
options:
|
||||||
max-file: "5"
|
max-file: '5'
|
||||||
max-size: "10m"
|
max-size: '10m'
|
||||||
services:
|
services:
|
||||||
traefik:
|
traefik:
|
||||||
image: traefik:2.11
|
image: traefik:2.11
|
||||||
@@ -28,7 +28,7 @@ services:
|
|||||||
- appwrite
|
- appwrite
|
||||||
|
|
||||||
appwrite:
|
appwrite:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
@@ -49,10 +49,13 @@ services:
|
|||||||
- traefik.http.routers.appwrite_api_https.tls=true
|
- traefik.http.routers.appwrite_api_https.tls=true
|
||||||
volumes:
|
volumes:
|
||||||
- appwrite-uploads:/storage/uploads:rw
|
- appwrite-uploads:/storage/uploads:rw
|
||||||
|
- appwrite-imports:/storage/imports:rw
|
||||||
- appwrite-cache:/storage/cache:rw
|
- appwrite-cache:/storage/cache:rw
|
||||||
- appwrite-config:/storage/config:rw
|
- appwrite-config:/storage/config:rw
|
||||||
- appwrite-certificates:/storage/certificates:rw
|
- appwrite-certificates:/storage/certificates:rw
|
||||||
- appwrite-functions:/storage/functions:rw
|
- appwrite-functions:/storage/functions:rw
|
||||||
|
- appwrite-sites:/storage/sites:rw
|
||||||
|
- appwrite-builds:/storage/builds:rw
|
||||||
depends_on:
|
depends_on:
|
||||||
- mariadb
|
- mariadb
|
||||||
- redis
|
- redis
|
||||||
@@ -61,8 +64,10 @@ services:
|
|||||||
- _APP_ENV
|
- _APP_ENV
|
||||||
- _APP_WORKER_PER_CORE
|
- _APP_WORKER_PER_CORE
|
||||||
- _APP_LOCALE
|
- _APP_LOCALE
|
||||||
|
- _APP_COMPRESSION_MIN_SIZE_BYTES
|
||||||
- _APP_CONSOLE_WHITELIST_ROOT
|
- _APP_CONSOLE_WHITELIST_ROOT
|
||||||
- _APP_CONSOLE_WHITELIST_EMAILS
|
- _APP_CONSOLE_WHITELIST_EMAILS
|
||||||
|
- _APP_CONSOLE_SESSION_ALERTS
|
||||||
- _APP_CONSOLE_WHITELIST_IPS
|
- _APP_CONSOLE_WHITELIST_IPS
|
||||||
- _APP_CONSOLE_HOSTNAMES
|
- _APP_CONSOLE_HOSTNAMES
|
||||||
- _APP_SYSTEM_EMAIL_NAME
|
- _APP_SYSTEM_EMAIL_NAME
|
||||||
@@ -72,10 +77,14 @@ services:
|
|||||||
- _APP_OPTIONS_ABUSE
|
- _APP_OPTIONS_ABUSE
|
||||||
- _APP_OPTIONS_ROUTER_PROTECTION
|
- _APP_OPTIONS_ROUTER_PROTECTION
|
||||||
- _APP_OPTIONS_FORCE_HTTPS
|
- _APP_OPTIONS_FORCE_HTTPS
|
||||||
- _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS
|
- _APP_OPTIONS_ROUTER_FORCE_HTTPS
|
||||||
- _APP_OPENSSL_KEY_V1
|
- _APP_OPENSSL_KEY_V1
|
||||||
- _APP_DOMAIN
|
- _APP_DOMAIN
|
||||||
- _APP_DOMAIN_TARGET
|
- _APP_DOMAIN_TARGET_CNAME
|
||||||
|
- _APP_DOMAIN_TARGET_AAAA
|
||||||
|
- _APP_DOMAIN_TARGET_A
|
||||||
|
- _APP_DOMAIN_TARGET_CAA
|
||||||
|
- _APP_DNS
|
||||||
- _APP_DOMAIN_FUNCTIONS
|
- _APP_DOMAIN_FUNCTIONS
|
||||||
- _APP_REDIS_HOST
|
- _APP_REDIS_HOST
|
||||||
- _APP_REDIS_PORT
|
- _APP_REDIS_PORT
|
||||||
@@ -102,6 +111,7 @@ services:
|
|||||||
- _APP_STORAGE_S3_SECRET
|
- _APP_STORAGE_S3_SECRET
|
||||||
- _APP_STORAGE_S3_REGION
|
- _APP_STORAGE_S3_REGION
|
||||||
- _APP_STORAGE_S3_BUCKET
|
- _APP_STORAGE_S3_BUCKET
|
||||||
|
- _APP_STORAGE_S3_ENDPOINT
|
||||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
||||||
- _APP_STORAGE_DO_SPACES_SECRET
|
- _APP_STORAGE_DO_SPACES_SECRET
|
||||||
- _APP_STORAGE_DO_SPACES_REGION
|
- _APP_STORAGE_DO_SPACES_REGION
|
||||||
@@ -118,22 +128,26 @@ services:
|
|||||||
- _APP_STORAGE_WASABI_SECRET
|
- _APP_STORAGE_WASABI_SECRET
|
||||||
- _APP_STORAGE_WASABI_REGION
|
- _APP_STORAGE_WASABI_REGION
|
||||||
- _APP_STORAGE_WASABI_BUCKET
|
- _APP_STORAGE_WASABI_BUCKET
|
||||||
- _APP_FUNCTIONS_SIZE_LIMIT
|
- _APP_COMPUTE_SIZE_LIMIT
|
||||||
- _APP_FUNCTIONS_TIMEOUT
|
- _APP_FUNCTIONS_TIMEOUT
|
||||||
- _APP_FUNCTIONS_BUILD_TIMEOUT
|
- _APP_SITES_TIMEOUT
|
||||||
- _APP_FUNCTIONS_CPUS
|
- _APP_COMPUTE_BUILD_TIMEOUT
|
||||||
- _APP_FUNCTIONS_MEMORY
|
- _APP_COMPUTE_CPUS
|
||||||
|
- _APP_COMPUTE_MEMORY
|
||||||
- _APP_FUNCTIONS_RUNTIMES
|
- _APP_FUNCTIONS_RUNTIMES
|
||||||
|
- _APP_SITES_RUNTIMES
|
||||||
|
- _APP_DOMAIN_SITES
|
||||||
- _APP_EXECUTOR_SECRET
|
- _APP_EXECUTOR_SECRET
|
||||||
- _APP_EXECUTOR_HOST
|
- _APP_EXECUTOR_HOST
|
||||||
- _APP_LOGGING_PROVIDER
|
|
||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
- _APP_MAINTENANCE_INTERVAL
|
- _APP_MAINTENANCE_INTERVAL
|
||||||
- _APP_MAINTENANCE_DELAY
|
- _APP_MAINTENANCE_DELAY
|
||||||
|
- _APP_MAINTENANCE_START_TIME
|
||||||
- _APP_MAINTENANCE_RETENTION_EXECUTION
|
- _APP_MAINTENANCE_RETENTION_EXECUTION
|
||||||
- _APP_MAINTENANCE_RETENTION_CACHE
|
- _APP_MAINTENANCE_RETENTION_CACHE
|
||||||
- _APP_MAINTENANCE_RETENTION_ABUSE
|
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||||
|
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
|
||||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
|
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
|
||||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
||||||
- _APP_SMS_PROVIDER
|
- _APP_SMS_PROVIDER
|
||||||
@@ -150,9 +164,29 @@ services:
|
|||||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
|
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
|
||||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
|
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
|
||||||
- _APP_ASSISTANT_OPENAI_API_KEY
|
- _APP_ASSISTANT_OPENAI_API_KEY
|
||||||
|
appwrite-console:
|
||||||
|
<<: *x-logging
|
||||||
|
image: appwrite/console:7.4.7
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- appwrite
|
||||||
|
labels:
|
||||||
|
- "traefik.enable=true"
|
||||||
|
- "traefik.constraint-label-stack=appwrite"
|
||||||
|
- "traefik.docker.network=appwrite"
|
||||||
|
- "traefik.http.services.appwrite_console.loadbalancer.server.port=80"
|
||||||
|
#ws
|
||||||
|
- traefik.http.routers.appwrite_console_http.entrypoints=appwrite_web
|
||||||
|
- traefik.http.routers.appwrite_console_http.rule=PathPrefix(`/console`)
|
||||||
|
- traefik.http.routers.appwrite_console_http.service=appwrite_console
|
||||||
|
# wss
|
||||||
|
- traefik.http.routers.appwrite_console_https.entrypoints=appwrite_websecure
|
||||||
|
- traefik.http.routers.appwrite_console_https.rule=PathPrefix(`/console`)
|
||||||
|
- traefik.http.routers.appwrite_console_https.service=appwrite_console
|
||||||
|
- traefik.http.routers.appwrite_console_https.tls=true
|
||||||
|
|
||||||
appwrite-realtime:
|
appwrite-realtime:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
entrypoint: realtime
|
entrypoint: realtime
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -191,11 +225,10 @@ services:
|
|||||||
- _APP_DB_USER
|
- _APP_DB_USER
|
||||||
- _APP_DB_PASS
|
- _APP_DB_PASS
|
||||||
- _APP_USAGE_STATS
|
- _APP_USAGE_STATS
|
||||||
- _APP_LOGGING_PROVIDER
|
|
||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
|
|
||||||
appwrite-worker-audits:
|
appwrite-worker-audits:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
entrypoint: worker-audits
|
entrypoint: worker-audits
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -217,11 +250,10 @@ services:
|
|||||||
- _APP_DB_SCHEMA
|
- _APP_DB_SCHEMA
|
||||||
- _APP_DB_USER
|
- _APP_DB_USER
|
||||||
- _APP_DB_PASS
|
- _APP_DB_PASS
|
||||||
- _APP_LOGGING_PROVIDER
|
|
||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
|
|
||||||
appwrite-worker-webhooks:
|
appwrite-worker-webhooks:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
entrypoint: worker-webhooks
|
entrypoint: worker-webhooks
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -245,11 +277,10 @@ services:
|
|||||||
- _APP_REDIS_PORT
|
- _APP_REDIS_PORT
|
||||||
- _APP_REDIS_USER
|
- _APP_REDIS_USER
|
||||||
- _APP_REDIS_PASS
|
- _APP_REDIS_PASS
|
||||||
- _APP_LOGGING_PROVIDER
|
|
||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
|
|
||||||
appwrite-worker-deletes:
|
appwrite-worker-deletes:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
entrypoint: worker-deletes
|
entrypoint: worker-deletes
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -262,6 +293,7 @@ services:
|
|||||||
- appwrite-uploads:/storage/uploads:rw
|
- appwrite-uploads:/storage/uploads:rw
|
||||||
- appwrite-cache:/storage/cache:rw
|
- appwrite-cache:/storage/cache:rw
|
||||||
- appwrite-functions:/storage/functions:rw
|
- appwrite-functions:/storage/functions:rw
|
||||||
|
- appwrite-sites:/storage/sites:rw
|
||||||
- appwrite-builds:/storage/builds:rw
|
- appwrite-builds:/storage/builds:rw
|
||||||
- appwrite-certificates:/storage/certificates:rw
|
- appwrite-certificates:/storage/certificates:rw
|
||||||
environment:
|
environment:
|
||||||
@@ -282,6 +314,7 @@ services:
|
|||||||
- _APP_STORAGE_S3_SECRET
|
- _APP_STORAGE_S3_SECRET
|
||||||
- _APP_STORAGE_S3_REGION
|
- _APP_STORAGE_S3_REGION
|
||||||
- _APP_STORAGE_S3_BUCKET
|
- _APP_STORAGE_S3_BUCKET
|
||||||
|
- _APP_STORAGE_S3_ENDPOINT
|
||||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
||||||
- _APP_STORAGE_DO_SPACES_SECRET
|
- _APP_STORAGE_DO_SPACES_SECRET
|
||||||
- _APP_STORAGE_DO_SPACES_REGION
|
- _APP_STORAGE_DO_SPACES_REGION
|
||||||
@@ -298,13 +331,18 @@ services:
|
|||||||
- _APP_STORAGE_WASABI_SECRET
|
- _APP_STORAGE_WASABI_SECRET
|
||||||
- _APP_STORAGE_WASABI_REGION
|
- _APP_STORAGE_WASABI_REGION
|
||||||
- _APP_STORAGE_WASABI_BUCKET
|
- _APP_STORAGE_WASABI_BUCKET
|
||||||
- _APP_LOGGING_PROVIDER
|
|
||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
- _APP_EXECUTOR_SECRET
|
- _APP_EXECUTOR_SECRET
|
||||||
- _APP_EXECUTOR_HOST
|
- _APP_EXECUTOR_HOST
|
||||||
|
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||||
|
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||||
|
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
|
||||||
|
- _APP_MAINTENANCE_RETENTION_EXECUTION
|
||||||
|
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS
|
||||||
|
- _APP_EMAIL_CERTIFICATES
|
||||||
|
|
||||||
appwrite-worker-databases:
|
appwrite-worker-databases:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
entrypoint: worker-databases
|
entrypoint: worker-databases
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -326,11 +364,10 @@ services:
|
|||||||
- _APP_DB_SCHEMA
|
- _APP_DB_SCHEMA
|
||||||
- _APP_DB_USER
|
- _APP_DB_USER
|
||||||
- _APP_DB_PASS
|
- _APP_DB_PASS
|
||||||
- _APP_LOGGING_PROVIDER
|
|
||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
|
|
||||||
appwrite-worker-builds:
|
appwrite-worker-builds:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
entrypoint: worker-builds
|
entrypoint: worker-builds
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -341,7 +378,9 @@ services:
|
|||||||
- mariadb
|
- mariadb
|
||||||
volumes:
|
volumes:
|
||||||
- appwrite-functions:/storage/functions:rw
|
- appwrite-functions:/storage/functions:rw
|
||||||
|
- appwrite-sites:/storage/sites:rw
|
||||||
- appwrite-builds:/storage/builds:rw
|
- appwrite-builds:/storage/builds:rw
|
||||||
|
- appwrite-uploads:/storage/uploads:rw
|
||||||
environment:
|
environment:
|
||||||
- _APP_ENV
|
- _APP_ENV
|
||||||
- _APP_WORKER_PER_CORE
|
- _APP_WORKER_PER_CORE
|
||||||
@@ -357,24 +396,25 @@ services:
|
|||||||
- _APP_DB_SCHEMA
|
- _APP_DB_SCHEMA
|
||||||
- _APP_DB_USER
|
- _APP_DB_USER
|
||||||
- _APP_DB_PASS
|
- _APP_DB_PASS
|
||||||
- _APP_LOGGING_PROVIDER
|
|
||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
- _APP_VCS_GITHUB_APP_NAME
|
- _APP_VCS_GITHUB_APP_NAME
|
||||||
- _APP_VCS_GITHUB_PRIVATE_KEY
|
- _APP_VCS_GITHUB_PRIVATE_KEY
|
||||||
- _APP_VCS_GITHUB_APP_ID
|
- _APP_VCS_GITHUB_APP_ID
|
||||||
- _APP_FUNCTIONS_TIMEOUT
|
- _APP_FUNCTIONS_TIMEOUT
|
||||||
- _APP_FUNCTIONS_BUILD_TIMEOUT
|
- _APP_SITES_TIMEOUT
|
||||||
- _APP_FUNCTIONS_CPUS
|
- _APP_COMPUTE_BUILD_TIMEOUT
|
||||||
- _APP_FUNCTIONS_MEMORY
|
- _APP_COMPUTE_CPUS
|
||||||
- _APP_FUNCTIONS_SIZE_LIMIT
|
- _APP_COMPUTE_MEMORY
|
||||||
|
- _APP_COMPUTE_SIZE_LIMIT
|
||||||
- _APP_OPTIONS_FORCE_HTTPS
|
- _APP_OPTIONS_FORCE_HTTPS
|
||||||
- _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS
|
- _APP_OPTIONS_ROUTER_FORCE_HTTPS
|
||||||
- _APP_DOMAIN
|
- _APP_DOMAIN
|
||||||
- _APP_STORAGE_DEVICE
|
- _APP_STORAGE_DEVICE
|
||||||
- _APP_STORAGE_S3_ACCESS_KEY
|
- _APP_STORAGE_S3_ACCESS_KEY
|
||||||
- _APP_STORAGE_S3_SECRET
|
- _APP_STORAGE_S3_SECRET
|
||||||
- _APP_STORAGE_S3_REGION
|
- _APP_STORAGE_S3_REGION
|
||||||
- _APP_STORAGE_S3_BUCKET
|
- _APP_STORAGE_S3_BUCKET
|
||||||
|
- _APP_STORAGE_S3_ENDPOINT
|
||||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
||||||
- _APP_STORAGE_DO_SPACES_SECRET
|
- _APP_STORAGE_DO_SPACES_SECRET
|
||||||
- _APP_STORAGE_DO_SPACES_REGION
|
- _APP_STORAGE_DO_SPACES_REGION
|
||||||
@@ -391,9 +431,10 @@ services:
|
|||||||
- _APP_STORAGE_WASABI_SECRET
|
- _APP_STORAGE_WASABI_SECRET
|
||||||
- _APP_STORAGE_WASABI_REGION
|
- _APP_STORAGE_WASABI_REGION
|
||||||
- _APP_STORAGE_WASABI_BUCKET
|
- _APP_STORAGE_WASABI_BUCKET
|
||||||
|
- _APP_DOMAIN_SITES
|
||||||
|
|
||||||
appwrite-worker-certificates:
|
appwrite-worker-certificates:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
entrypoint: worker-certificates
|
entrypoint: worker-certificates
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -410,7 +451,11 @@ services:
|
|||||||
- _APP_WORKER_PER_CORE
|
- _APP_WORKER_PER_CORE
|
||||||
- _APP_OPENSSL_KEY_V1
|
- _APP_OPENSSL_KEY_V1
|
||||||
- _APP_DOMAIN
|
- _APP_DOMAIN
|
||||||
- _APP_DOMAIN_TARGET
|
- _APP_DOMAIN_TARGET_CNAME
|
||||||
|
- _APP_DOMAIN_TARGET_AAAA
|
||||||
|
- _APP_DOMAIN_TARGET_A
|
||||||
|
- _APP_DOMAIN_TARGET_CAA
|
||||||
|
- _APP_DNS
|
||||||
- _APP_DOMAIN_FUNCTIONS
|
- _APP_DOMAIN_FUNCTIONS
|
||||||
- _APP_EMAIL_CERTIFICATES
|
- _APP_EMAIL_CERTIFICATES
|
||||||
- _APP_REDIS_HOST
|
- _APP_REDIS_HOST
|
||||||
@@ -422,11 +467,10 @@ services:
|
|||||||
- _APP_DB_SCHEMA
|
- _APP_DB_SCHEMA
|
||||||
- _APP_DB_USER
|
- _APP_DB_USER
|
||||||
- _APP_DB_PASS
|
- _APP_DB_PASS
|
||||||
- _APP_LOGGING_PROVIDER
|
|
||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
|
|
||||||
appwrite-worker-functions:
|
appwrite-worker-functions:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
entrypoint: worker-functions
|
entrypoint: worker-functions
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -440,6 +484,8 @@ services:
|
|||||||
- _APP_ENV
|
- _APP_ENV
|
||||||
- _APP_WORKER_PER_CORE
|
- _APP_WORKER_PER_CORE
|
||||||
- _APP_OPENSSL_KEY_V1
|
- _APP_OPENSSL_KEY_V1
|
||||||
|
- _APP_DOMAIN
|
||||||
|
- _APP_OPTIONS_FORCE_HTTPS
|
||||||
- _APP_REDIS_HOST
|
- _APP_REDIS_HOST
|
||||||
- _APP_REDIS_PORT
|
- _APP_REDIS_PORT
|
||||||
- _APP_REDIS_USER
|
- _APP_REDIS_USER
|
||||||
@@ -450,19 +496,19 @@ services:
|
|||||||
- _APP_DB_USER
|
- _APP_DB_USER
|
||||||
- _APP_DB_PASS
|
- _APP_DB_PASS
|
||||||
- _APP_FUNCTIONS_TIMEOUT
|
- _APP_FUNCTIONS_TIMEOUT
|
||||||
- _APP_FUNCTIONS_BUILD_TIMEOUT
|
- _APP_SITES_TIMEOUT
|
||||||
- _APP_FUNCTIONS_CPUS
|
- _APP_COMPUTE_BUILD_TIMEOUT
|
||||||
- _APP_FUNCTIONS_MEMORY
|
- _APP_COMPUTE_CPUS
|
||||||
|
- _APP_COMPUTE_MEMORY
|
||||||
- _APP_EXECUTOR_SECRET
|
- _APP_EXECUTOR_SECRET
|
||||||
- _APP_EXECUTOR_HOST
|
- _APP_EXECUTOR_HOST
|
||||||
- _APP_USAGE_STATS
|
- _APP_USAGE_STATS
|
||||||
- _APP_DOCKER_HUB_USERNAME
|
- _APP_DOCKER_HUB_USERNAME
|
||||||
- _APP_DOCKER_HUB_PASSWORD
|
- _APP_DOCKER_HUB_PASSWORD
|
||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
- _APP_LOGGING_PROVIDER
|
|
||||||
|
|
||||||
appwrite-worker-mails:
|
appwrite-worker-mails:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
entrypoint: worker-mails
|
entrypoint: worker-mails
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -490,11 +536,12 @@ services:
|
|||||||
- _APP_SMTP_SECURE
|
- _APP_SMTP_SECURE
|
||||||
- _APP_SMTP_USERNAME
|
- _APP_SMTP_USERNAME
|
||||||
- _APP_SMTP_PASSWORD
|
- _APP_SMTP_PASSWORD
|
||||||
- _APP_LOGGING_PROVIDER
|
|
||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
|
- _APP_DOMAIN
|
||||||
|
- _APP_OPTIONS_FORCE_HTTPS
|
||||||
|
|
||||||
appwrite-worker-messaging:
|
appwrite-worker-messaging:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
entrypoint: worker-messaging
|
entrypoint: worker-messaging
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -517,7 +564,6 @@ services:
|
|||||||
- _APP_DB_SCHEMA
|
- _APP_DB_SCHEMA
|
||||||
- _APP_DB_USER
|
- _APP_DB_USER
|
||||||
- _APP_DB_PASS
|
- _APP_DB_PASS
|
||||||
- _APP_LOGGING_PROVIDER
|
|
||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
- _APP_SMS_FROM
|
- _APP_SMS_FROM
|
||||||
- _APP_SMS_PROVIDER
|
- _APP_SMS_PROVIDER
|
||||||
@@ -526,6 +572,7 @@ services:
|
|||||||
- _APP_STORAGE_S3_SECRET
|
- _APP_STORAGE_S3_SECRET
|
||||||
- _APP_STORAGE_S3_REGION
|
- _APP_STORAGE_S3_REGION
|
||||||
- _APP_STORAGE_S3_BUCKET
|
- _APP_STORAGE_S3_BUCKET
|
||||||
|
- _APP_STORAGE_S3_ENDPOINT
|
||||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
- _APP_STORAGE_DO_SPACES_ACCESS_KEY
|
||||||
- _APP_STORAGE_DO_SPACES_SECRET
|
- _APP_STORAGE_DO_SPACES_SECRET
|
||||||
- _APP_STORAGE_DO_SPACES_REGION
|
- _APP_STORAGE_DO_SPACES_REGION
|
||||||
@@ -544,12 +591,14 @@ services:
|
|||||||
- _APP_STORAGE_WASABI_BUCKET
|
- _APP_STORAGE_WASABI_BUCKET
|
||||||
|
|
||||||
appwrite-worker-migrations:
|
appwrite-worker-migrations:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
entrypoint: worker-migrations
|
entrypoint: worker-migrations
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
- appwrite
|
- appwrite
|
||||||
|
volumes:
|
||||||
|
- appwrite-imports:/storage/imports:rw
|
||||||
depends_on:
|
depends_on:
|
||||||
- mariadb
|
- mariadb
|
||||||
environment:
|
environment:
|
||||||
@@ -557,7 +606,11 @@ services:
|
|||||||
- _APP_WORKER_PER_CORE
|
- _APP_WORKER_PER_CORE
|
||||||
- _APP_OPENSSL_KEY_V1
|
- _APP_OPENSSL_KEY_V1
|
||||||
- _APP_DOMAIN
|
- _APP_DOMAIN
|
||||||
- _APP_DOMAIN_TARGET
|
- _APP_DOMAIN_TARGET_CNAME
|
||||||
|
- _APP_DOMAIN_TARGET_AAAA
|
||||||
|
- _APP_DOMAIN_TARGET_A
|
||||||
|
- _APP_DOMAIN_TARGET_CAA
|
||||||
|
- _APP_DNS
|
||||||
- _APP_EMAIL_SECURITY
|
- _APP_EMAIL_SECURITY
|
||||||
- _APP_REDIS_HOST
|
- _APP_REDIS_HOST
|
||||||
- _APP_REDIS_PORT
|
- _APP_REDIS_PORT
|
||||||
@@ -568,13 +621,12 @@ services:
|
|||||||
- _APP_DB_SCHEMA
|
- _APP_DB_SCHEMA
|
||||||
- _APP_DB_USER
|
- _APP_DB_USER
|
||||||
- _APP_DB_PASS
|
- _APP_DB_PASS
|
||||||
- _APP_LOGGING_PROVIDER
|
|
||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
|
- _APP_MIGRATIONS_FIREBASE_CLIENT_ID
|
||||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
|
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET
|
||||||
|
|
||||||
appwrite-task-maintenance:
|
appwrite-task-maintenance:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
entrypoint: maintenance
|
entrypoint: maintenance
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -586,7 +638,11 @@ services:
|
|||||||
- _APP_ENV
|
- _APP_ENV
|
||||||
- _APP_WORKER_PER_CORE
|
- _APP_WORKER_PER_CORE
|
||||||
- _APP_DOMAIN
|
- _APP_DOMAIN
|
||||||
- _APP_DOMAIN_TARGET
|
- _APP_DOMAIN_TARGET_CNAME
|
||||||
|
- _APP_DOMAIN_TARGET_AAAA
|
||||||
|
- _APP_DOMAIN_TARGET_A
|
||||||
|
- _APP_DOMAIN_TARGET_CAA
|
||||||
|
- _APP_DNS
|
||||||
- _APP_DOMAIN_FUNCTIONS
|
- _APP_DOMAIN_FUNCTIONS
|
||||||
- _APP_OPENSSL_KEY_V1
|
- _APP_OPENSSL_KEY_V1
|
||||||
- _APP_REDIS_HOST
|
- _APP_REDIS_HOST
|
||||||
@@ -603,12 +659,13 @@ services:
|
|||||||
- _APP_MAINTENANCE_RETENTION_CACHE
|
- _APP_MAINTENANCE_RETENTION_CACHE
|
||||||
- _APP_MAINTENANCE_RETENTION_ABUSE
|
- _APP_MAINTENANCE_RETENTION_ABUSE
|
||||||
- _APP_MAINTENANCE_RETENTION_AUDIT
|
- _APP_MAINTENANCE_RETENTION_AUDIT
|
||||||
|
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE
|
||||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
|
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY
|
||||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
- _APP_MAINTENANCE_RETENTION_SCHEDULES
|
||||||
|
|
||||||
appwrite-worker-usage:
|
appwrite-task-stats-resources:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
entrypoint: worker-usage
|
entrypoint: stats-resources
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
@@ -630,14 +687,42 @@ services:
|
|||||||
- _APP_REDIS_USER
|
- _APP_REDIS_USER
|
||||||
- _APP_REDIS_PASS
|
- _APP_REDIS_PASS
|
||||||
- _APP_USAGE_STATS
|
- _APP_USAGE_STATS
|
||||||
- _APP_LOGGING_PROVIDER
|
|
||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
- _APP_USAGE_AGGREGATION_INTERVAL
|
- _APP_DATABASE_SHARED_TABLES
|
||||||
|
- _APP_STATS_RESOURCES_INTERVAL
|
||||||
|
|
||||||
appwrite-worker-usage-dump:
|
appwrite-worker-stats-resources:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
entrypoint: worker-usage-dump
|
entrypoint: worker-stats-resources
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- appwrite
|
||||||
|
depends_on:
|
||||||
|
- redis
|
||||||
|
- mariadb
|
||||||
|
environment:
|
||||||
|
- _APP_ENV
|
||||||
|
- _APP_WORKER_PER_CORE
|
||||||
|
- _APP_OPENSSL_KEY_V1
|
||||||
|
- _APP_DB_HOST
|
||||||
|
- _APP_DB_PORT
|
||||||
|
- _APP_DB_SCHEMA
|
||||||
|
- _APP_DB_USER
|
||||||
|
- _APP_DB_PASS
|
||||||
|
- _APP_REDIS_HOST
|
||||||
|
- _APP_REDIS_PORT
|
||||||
|
- _APP_REDIS_USER
|
||||||
|
- _APP_REDIS_PASS
|
||||||
|
- _APP_USAGE_STATS
|
||||||
|
- _APP_LOGGING_CONFIG
|
||||||
|
- _APP_STATS_RESOURCES_INTERVAL
|
||||||
|
|
||||||
|
appwrite-worker-stats-usage:
|
||||||
|
image: appwrite/appwrite:1.8.0
|
||||||
|
entrypoint: worker-stats-usage
|
||||||
|
<<: *x-logging
|
||||||
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
- appwrite
|
- appwrite
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -657,12 +742,11 @@ services:
|
|||||||
- _APP_REDIS_USER
|
- _APP_REDIS_USER
|
||||||
- _APP_REDIS_PASS
|
- _APP_REDIS_PASS
|
||||||
- _APP_USAGE_STATS
|
- _APP_USAGE_STATS
|
||||||
- _APP_LOGGING_PROVIDER
|
|
||||||
- _APP_LOGGING_CONFIG
|
- _APP_LOGGING_CONFIG
|
||||||
- _APP_USAGE_AGGREGATION_INTERVAL
|
- _APP_USAGE_AGGREGATION_INTERVAL
|
||||||
|
|
||||||
appwrite-task-scheduler-functions:
|
appwrite-task-scheduler-functions:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
entrypoint: schedule-functions
|
entrypoint: schedule-functions
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -685,8 +769,32 @@ services:
|
|||||||
- _APP_DB_USER
|
- _APP_DB_USER
|
||||||
- _APP_DB_PASS
|
- _APP_DB_PASS
|
||||||
|
|
||||||
|
appwrite-task-scheduler-executions:
|
||||||
|
image: appwrite/appwrite:1.8.0
|
||||||
|
entrypoint: schedule-executions
|
||||||
|
<<: *x-logging
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- appwrite
|
||||||
|
depends_on:
|
||||||
|
- mariadb
|
||||||
|
- redis
|
||||||
|
environment:
|
||||||
|
- _APP_ENV
|
||||||
|
- _APP_WORKER_PER_CORE
|
||||||
|
- _APP_OPENSSL_KEY_V1
|
||||||
|
- _APP_REDIS_HOST
|
||||||
|
- _APP_REDIS_PORT
|
||||||
|
- _APP_REDIS_USER
|
||||||
|
- _APP_REDIS_PASS
|
||||||
|
- _APP_DB_HOST
|
||||||
|
- _APP_DB_PORT
|
||||||
|
- _APP_DB_SCHEMA
|
||||||
|
- _APP_DB_USER
|
||||||
|
- _APP_DB_PASS
|
||||||
|
|
||||||
appwrite-task-scheduler-messages:
|
appwrite-task-scheduler-messages:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.8.0
|
||||||
entrypoint: schedule-messages
|
entrypoint: schedule-messages
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -710,7 +818,7 @@ services:
|
|||||||
- _APP_DB_PASS
|
- _APP_DB_PASS
|
||||||
|
|
||||||
appwrite-assistant:
|
appwrite-assistant:
|
||||||
image: appwrite/assistant:0.4.0
|
image: appwrite/assistant:0.8.3
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
@@ -718,12 +826,19 @@ services:
|
|||||||
environment:
|
environment:
|
||||||
- _APP_ASSISTANT_OPENAI_API_KEY
|
- _APP_ASSISTANT_OPENAI_API_KEY
|
||||||
|
|
||||||
|
appwrite-browser:
|
||||||
|
image: appwrite/browser:0.2.4
|
||||||
|
<<: *x-logging
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- appwrite
|
||||||
|
|
||||||
openruntimes-executor:
|
openruntimes-executor:
|
||||||
hostname: exc1
|
hostname: exc1
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
stop_signal: SIGINT
|
stop_signal: SIGINT
|
||||||
image: openruntimes/executor:0.5.7
|
image: openruntimes/executor:0.7.22
|
||||||
networks:
|
networks:
|
||||||
- appwrite
|
- appwrite
|
||||||
- runtimes
|
- runtimes
|
||||||
@@ -731,25 +846,27 @@ services:
|
|||||||
- /var/run/docker.sock:/var/run/docker.sock
|
- /var/run/docker.sock:/var/run/docker.sock
|
||||||
- appwrite-builds:/storage/builds:rw
|
- appwrite-builds:/storage/builds:rw
|
||||||
- appwrite-functions:/storage/functions:rw
|
- appwrite-functions:/storage/functions:rw
|
||||||
|
- appwrite-sites:/storage/sites:rw
|
||||||
# Host mount nessessary to share files between executor and runtimes.
|
# Host mount nessessary to share files between executor and runtimes.
|
||||||
# It's not possible to share mount file between 2 containers without host mount (copying is too slow)
|
# It's not possible to share mount file between 2 containers without host mount (copying is too slow)
|
||||||
- /tmp:/tmp:rw
|
- /tmp:/tmp:rw
|
||||||
environment:
|
environment:
|
||||||
- OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_FUNCTIONS_INACTIVE_THRESHOLD
|
- OPR_EXECUTOR_INACTIVE_TRESHOLD=$_APP_COMPUTE_INACTIVE_THRESHOLD
|
||||||
- OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_FUNCTIONS_MAINTENANCE_INTERVAL
|
- OPR_EXECUTOR_MAINTENANCE_INTERVAL=$_APP_COMPUTE_MAINTENANCE_INTERVAL
|
||||||
- OPR_EXECUTOR_NETWORK=$_APP_FUNCTIONS_RUNTIMES_NETWORK
|
- OPR_EXECUTOR_NETWORK=$_APP_COMPUTE_RUNTIMES_NETWORK
|
||||||
- OPR_EXECUTOR_DOCKER_HUB_USERNAME=$_APP_DOCKER_HUB_USERNAME
|
- OPR_EXECUTOR_DOCKER_HUB_USERNAME=$_APP_DOCKER_HUB_USERNAME
|
||||||
- OPR_EXECUTOR_DOCKER_HUB_PASSWORD=$_APP_DOCKER_HUB_PASSWORD
|
- OPR_EXECUTOR_DOCKER_HUB_PASSWORD=$_APP_DOCKER_HUB_PASSWORD
|
||||||
- OPR_EXECUTOR_ENV=$_APP_ENV
|
- OPR_EXECUTOR_ENV=$_APP_ENV
|
||||||
- OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES
|
- OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES,$_APP_SITES_RUNTIMES
|
||||||
- OPR_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET
|
- OPR_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET
|
||||||
- OPR_EXECUTOR_LOGGING_PROVIDER=$_APP_LOGGING_PROVIDER
|
- OPR_EXECUTOR_RUNTIME_VERSIONS=v5
|
||||||
- OPR_EXECUTOR_LOGGING_CONFIG=$_APP_LOGGING_CONFIG
|
- OPR_EXECUTOR_LOGGING_CONFIG=$_APP_LOGGING_CONFIG
|
||||||
- OPR_EXECUTOR_STORAGE_DEVICE=$_APP_STORAGE_DEVICE
|
- OPR_EXECUTOR_STORAGE_DEVICE=$_APP_STORAGE_DEVICE
|
||||||
- OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=$_APP_STORAGE_S3_ACCESS_KEY
|
- OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=$_APP_STORAGE_S3_ACCESS_KEY
|
||||||
- OPR_EXECUTOR_STORAGE_S3_SECRET=$_APP_STORAGE_S3_SECRET
|
- OPR_EXECUTOR_STORAGE_S3_SECRET=$_APP_STORAGE_S3_SECRET
|
||||||
- OPR_EXECUTOR_STORAGE_S3_REGION=$_APP_STORAGE_S3_REGION
|
- OPR_EXECUTOR_STORAGE_S3_REGION=$_APP_STORAGE_S3_REGION
|
||||||
- OPR_EXECUTOR_STORAGE_S3_BUCKET=$_APP_STORAGE_S3_BUCKET
|
- OPR_EXECUTOR_STORAGE_S3_BUCKET=$_APP_STORAGE_S3_BUCKET
|
||||||
|
- OPR_EXECUTOR_STORAGE_S3_ENDPOINT=$_APP_STORAGE_S3_ENDPOINT
|
||||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_ACCESS_KEY=$_APP_STORAGE_DO_SPACES_ACCESS_KEY
|
- OPR_EXECUTOR_STORAGE_DO_SPACES_ACCESS_KEY=$_APP_STORAGE_DO_SPACES_ACCESS_KEY
|
||||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_SECRET=$_APP_STORAGE_DO_SPACES_SECRET
|
- OPR_EXECUTOR_STORAGE_DO_SPACES_SECRET=$_APP_STORAGE_DO_SPACES_SECRET
|
||||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_REGION=$_APP_STORAGE_DO_SPACES_REGION
|
- OPR_EXECUTOR_STORAGE_DO_SPACES_REGION=$_APP_STORAGE_DO_SPACES_REGION
|
||||||
@@ -781,22 +898,19 @@ services:
|
|||||||
- MYSQL_USER=${_APP_DB_USER}
|
- MYSQL_USER=${_APP_DB_USER}
|
||||||
- MYSQL_PASSWORD=${_APP_DB_PASS}
|
- MYSQL_PASSWORD=${_APP_DB_PASS}
|
||||||
- MARIADB_AUTO_UPGRADE=1
|
- MARIADB_AUTO_UPGRADE=1
|
||||||
command: "mysqld --innodb-flush-method=fsync"
|
command: 'mysqld --innodb-flush-method=fsync'
|
||||||
|
|
||||||
redis:
|
redis:
|
||||||
image: redis:7.2.4-alpine
|
image: redis:7.2.4-alpine
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: >
|
command: >
|
||||||
redis-server
|
redis-server --maxmemory 512mb
|
||||||
--maxmemory 512mb
|
--maxmemory-policy allkeys-lru --maxmemory-samples 5
|
||||||
--maxmemory-policy allkeys-lru
|
|
||||||
--maxmemory-samples 5
|
|
||||||
networks:
|
networks:
|
||||||
- appwrite
|
- appwrite
|
||||||
volumes:
|
volumes:
|
||||||
- appwrite-redis:/data:rw
|
- appwrite-redis:/data:rw
|
||||||
|
|
||||||
# clamav:
|
# clamav:
|
||||||
# image: appwrite/clamav:1.2.0
|
# image: appwrite/clamav:1.2.0
|
||||||
# container_name: appwrite-clamav
|
# container_name: appwrite-clamav
|
||||||
@@ -819,7 +933,9 @@ volumes:
|
|||||||
appwrite-redis:
|
appwrite-redis:
|
||||||
appwrite-cache:
|
appwrite-cache:
|
||||||
appwrite-uploads:
|
appwrite-uploads:
|
||||||
|
appwrite-imports:
|
||||||
appwrite-certificates:
|
appwrite-certificates:
|
||||||
appwrite-functions:
|
appwrite-functions:
|
||||||
|
appwrite-sites:
|
||||||
appwrite-builds:
|
appwrite-builds:
|
||||||
appwrite-config:
|
appwrite-config:
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
import utils from "../utils.js";
|
||||||
|
|
||||||
|
await utils.downloadFile(
|
||||||
|
"https://appwrite.io/install/compose",
|
||||||
|
"./code/docker-compose.yml"
|
||||||
|
);
|
||||||
|
await utils.downloadFile(
|
||||||
|
"https://appwrite.io/install/env",
|
||||||
|
"./code/.env.example"
|
||||||
|
);
|
||||||
|
|
||||||
|
await utils.removeContainerNames("./code/docker-compose.yml");
|
||||||
|
await utils.removePorts("./code/docker-compose.yml");
|
||||||
|
|
||||||
|
await utils.searchReplace(
|
||||||
|
"./code/.env.example",
|
||||||
|
"_APP_DOMAIN=localhost",
|
||||||
|
"_APP_DOMAIN=$(PRIMARY_DOMAIN)"
|
||||||
|
);
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [ ! -d "./repo" ]; then
|
|
||||||
git clone --depth 1 --branch main --single-branch https://github.com/appwrite/appwrite.git repo
|
|
||||||
else
|
|
||||||
cd repo
|
|
||||||
git pull
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
|
|
||||||
curl -s https://appwrite.io/install/compose > ./code/docker-compose.yml
|
|
||||||
curl -s https://appwrite.io/install/env > ./code/.env.example
|
|
||||||
|
|
||||||
|
|
||||||
@@ -4,7 +4,7 @@ Welcome to the new `docker` directory for deploying Dify using Docker Compose. T
|
|||||||
|
|
||||||
### What's Updated
|
### What's Updated
|
||||||
|
|
||||||
- **Certbot Container**: `docker-compose.yaml` now contains `certbot` for managing SSL certificates. This container automatically renews certificates and ensures secure HTTPS connections.
|
- **Certbot Container**: `docker-compose.yaml` now contains `certbot` for managing SSL certificates. This container automatically renews certificates and ensures secure HTTPS connections.\
|
||||||
For more information, refer `docker/certbot/README.md`.
|
For more information, refer `docker/certbot/README.md`.
|
||||||
|
|
||||||
- **Persistent Environment Variables**: Environment variables are now managed through a `.env` file, ensuring that your configurations persist across deployments.
|
- **Persistent Environment Variables**: Environment variables are now managed through a `.env` file, ensuring that your configurations persist across deployments.
|
||||||
@@ -13,21 +13,28 @@ Welcome to the new `docker` directory for deploying Dify using Docker Compose. T
|
|||||||
> The `.env` file is a crucial component in Docker and Docker Compose environments, serving as a centralized configuration file where you can define environment variables that are accessible to the containers at runtime. This file simplifies the management of environment settings across different stages of development, testing, and production, providing consistency and ease of configuration to deployments.
|
> The `.env` file is a crucial component in Docker and Docker Compose environments, serving as a centralized configuration file where you can define environment variables that are accessible to the containers at runtime. This file simplifies the management of environment settings across different stages of development, testing, and production, providing consistency and ease of configuration to deployments.
|
||||||
|
|
||||||
- **Unified Vector Database Services**: All vector database services are now managed from a single Docker Compose file `docker-compose.yaml`. You can switch between different vector databases by setting the `VECTOR_STORE` environment variable in your `.env` file.
|
- **Unified Vector Database Services**: All vector database services are now managed from a single Docker Compose file `docker-compose.yaml`. You can switch between different vector databases by setting the `VECTOR_STORE` environment variable in your `.env` file.
|
||||||
|
|
||||||
- **Mandatory .env File**: A `.env` file is now required to run `docker compose up`. This file is crucial for configuring your deployment and for any custom settings to persist through upgrades.
|
- **Mandatory .env File**: A `.env` file is now required to run `docker compose up`. This file is crucial for configuring your deployment and for any custom settings to persist through upgrades.
|
||||||
- **Legacy Support**: Previous deployment files are now located in the `docker-legacy` directory and will no longer be maintained.
|
|
||||||
|
|
||||||
### How to Deploy Dify with `docker-compose.yaml`
|
### How to Deploy Dify with `docker-compose.yaml`
|
||||||
|
|
||||||
1. **Prerequisites**: Ensure Docker and Docker Compose are installed on your system.
|
1. **Prerequisites**: Ensure Docker and Docker Compose are installed on your system.
|
||||||
2. **Environment Setup**:
|
1. **Environment Setup**:
|
||||||
- Navigate to the `docker` directory.
|
- Navigate to the `docker` directory.
|
||||||
- Copy the `.env.example` file to a new file named `.env` by running `cp .env.example .env`.
|
- Copy the `.env.example` file to a new file named `.env` by running `cp .env.example .env`.
|
||||||
- Customize the `.env` file as needed. Refer to the `.env.example` file for detailed configuration options.
|
- Customize the `.env` file as needed. Refer to the `.env.example` file for detailed configuration options.
|
||||||
3. **Running the Services**:
|
- **Optional (Recommended for upgrades)**:
|
||||||
|
You may use the environment synchronization tool to help keep your `.env` file aligned with the latest `.env.example` updates, while preserving your custom settings.
|
||||||
|
This is especially useful when upgrading Dify or managing a large, customized `.env` file.
|
||||||
|
See the [Environment Variables Synchronization](#environment-variables-synchronization) section below.
|
||||||
|
1. **Running the Services**:
|
||||||
- Execute `docker compose up` from the `docker` directory to start the services.
|
- Execute `docker compose up` from the `docker` directory to start the services.
|
||||||
- To specify a vector database, set the `VECTOR_STORE` variable in your `.env` file to your desired vector database service, such as `milvus`, `weaviate`, or `opensearch`.
|
- To specify a vector database, set the `VECTOR_STORE` variable in your `.env` file to your desired vector database service, such as `milvus`, `weaviate`, or `opensearch`.
|
||||||
4. **SSL Certificate Setup**:
|
1. **SSL Certificate Setup**:
|
||||||
- Rrefer `docker/certbot/README.md` to set up SSL certificates using Certbot.
|
- Refer `docker/certbot/README.md` to set up SSL certificates using Certbot.
|
||||||
|
1. **OpenTelemetry Collector Setup**:
|
||||||
|
- Change `ENABLE_OTEL` to `true` in `.env`.
|
||||||
|
- Configure `OTLP_BASE_ENDPOINT` properly.
|
||||||
|
|
||||||
### How to Deploy Middleware for Developing Dify
|
### How to Deploy Middleware for Developing Dify
|
||||||
|
|
||||||
@@ -35,17 +42,20 @@ Welcome to the new `docker` directory for deploying Dify using Docker Compose. T
|
|||||||
- Use the `docker-compose.middleware.yaml` for setting up essential middleware services like databases and caches.
|
- Use the `docker-compose.middleware.yaml` for setting up essential middleware services like databases and caches.
|
||||||
- Navigate to the `docker` directory.
|
- Navigate to the `docker` directory.
|
||||||
- Ensure the `middleware.env` file is created by running `cp middleware.env.example middleware.env` (refer to the `middleware.env.example` file).
|
- Ensure the `middleware.env` file is created by running `cp middleware.env.example middleware.env` (refer to the `middleware.env.example` file).
|
||||||
2. **Running Middleware Services**:
|
1. **Running Middleware Services**:
|
||||||
- Execute `docker-compose -f docker-compose.middleware.yaml up -d` to start the middleware services.
|
- Navigate to the `docker` directory.
|
||||||
|
- Execute `docker compose --env-file middleware.env -f docker-compose.middleware.yaml -p dify up -d` to start PostgreSQL/MySQL (per `DB_TYPE`) plus the bundled Weaviate instance.
|
||||||
|
|
||||||
|
> Compose automatically loads `COMPOSE_PROFILES=${DB_TYPE:-postgresql},weaviate` from `middleware.env`, so no extra `--profile` flags are needed. Adjust variables in `middleware.env` if you want a different combination of services.
|
||||||
|
|
||||||
### Migration for Existing Users
|
### Migration for Existing Users
|
||||||
|
|
||||||
For users migrating from the `docker-legacy` setup:
|
For users migrating from the `docker-legacy` setup:
|
||||||
|
|
||||||
1. **Review Changes**: Familiarize yourself with the new `.env` configuration and Docker Compose setup.
|
1. **Review Changes**: Familiarize yourself with the new `.env` configuration and Docker Compose setup.
|
||||||
2. **Transfer Customizations**:
|
1. **Transfer Customizations**:
|
||||||
- If you have customized configurations such as `docker-compose.yaml`, `ssrf_proxy/squid.conf`, or `nginx/conf.d/default.conf`, you will need to reflect these changes in the `.env` file you create.
|
- If you have customized configurations such as `docker-compose.yaml`, `ssrf_proxy/squid.conf`, or `nginx/conf.d/default.conf`, you will need to reflect these changes in the `.env` file you create.
|
||||||
3. **Data Migration**:
|
1. **Data Migration**:
|
||||||
- Ensure that data from services like databases and caches is backed up and migrated appropriately to the new structure if necessary.
|
- Ensure that data from services like databases and caches is backed up and migrated appropriately to the new structure if necessary.
|
||||||
|
|
||||||
### Overview of `.env`
|
### Overview of `.env`
|
||||||
@@ -54,43 +64,98 @@ For users migrating from the `docker-legacy` setup:
|
|||||||
|
|
||||||
- **Vector Database Services**: Depending on the type of vector database used (`VECTOR_STORE`), users can set specific endpoints, ports, and authentication details.
|
- **Vector Database Services**: Depending on the type of vector database used (`VECTOR_STORE`), users can set specific endpoints, ports, and authentication details.
|
||||||
- **Storage Services**: Depending on the storage type (`STORAGE_TYPE`), users can configure specific settings for S3, Azure Blob, Google Storage, etc.
|
- **Storage Services**: Depending on the storage type (`STORAGE_TYPE`), users can configure specific settings for S3, Azure Blob, Google Storage, etc.
|
||||||
- **API and Web Services**: Users can define URLs and other settings that affect how the API and web frontends operate.
|
- **API and Web Services**: Users can define URLs and other settings that affect how the API and web frontend operate.
|
||||||
|
|
||||||
#### Other notable variables
|
#### Other notable variables
|
||||||
|
|
||||||
The `.env.example` file provided in the Docker setup is extensive and covers a wide range of configuration options. It is structured into several sections, each pertaining to different aspects of the application and its services. Here are some of the key sections and variables:
|
The `.env.example` file provided in the Docker setup is extensive and covers a wide range of configuration options. It is structured into several sections, each pertaining to different aspects of the application and its services. Here are some of the key sections and variables:
|
||||||
|
|
||||||
1. **Common Variables**:
|
1. **Common Variables**:
|
||||||
|
|
||||||
- `CONSOLE_API_URL`, `SERVICE_API_URL`: URLs for different API services.
|
- `CONSOLE_API_URL`, `SERVICE_API_URL`: URLs for different API services.
|
||||||
- `APP_WEB_URL`: Frontend application URL.
|
- `APP_WEB_URL`: Frontend application URL.
|
||||||
- `FILES_URL`: Base URL for file downloads and previews.
|
- `FILES_URL`: Base URL for file downloads and previews.
|
||||||
|
|
||||||
2. **Server Configuration**:
|
1. **Server Configuration**:
|
||||||
|
|
||||||
- `LOG_LEVEL`, `DEBUG`, `FLASK_DEBUG`: Logging and debug settings.
|
- `LOG_LEVEL`, `DEBUG`, `FLASK_DEBUG`: Logging and debug settings.
|
||||||
- `SECRET_KEY`: A key for encrypting session cookies and other sensitive data.
|
- `SECRET_KEY`: A key for encrypting session cookies and other sensitive data.
|
||||||
|
|
||||||
3. **Database Configuration**:
|
1. **Database Configuration**:
|
||||||
|
|
||||||
- `DB_USERNAME`, `DB_PASSWORD`, `DB_HOST`, `DB_PORT`, `DB_DATABASE`: PostgreSQL database credentials and connection details.
|
- `DB_USERNAME`, `DB_PASSWORD`, `DB_HOST`, `DB_PORT`, `DB_DATABASE`: PostgreSQL database credentials and connection details.
|
||||||
|
|
||||||
4. **Redis Configuration**:
|
1. **Redis Configuration**:
|
||||||
|
|
||||||
- `REDIS_HOST`, `REDIS_PORT`, `REDIS_PASSWORD`: Redis server connection settings.
|
- `REDIS_HOST`, `REDIS_PORT`, `REDIS_PASSWORD`: Redis server connection settings.
|
||||||
|
|
||||||
5. **Celery Configuration**:
|
1. **Celery Configuration**:
|
||||||
|
|
||||||
- `CELERY_BROKER_URL`: Configuration for Celery message broker.
|
- `CELERY_BROKER_URL`: Configuration for Celery message broker.
|
||||||
|
|
||||||
6. **Storage Configuration**:
|
1. **Storage Configuration**:
|
||||||
|
|
||||||
- `STORAGE_TYPE`, `S3_BUCKET_NAME`, `AZURE_BLOB_ACCOUNT_NAME`: Settings for file storage options like local, S3, Azure Blob, etc.
|
- `STORAGE_TYPE`, `S3_BUCKET_NAME`, `AZURE_BLOB_ACCOUNT_NAME`: Settings for file storage options like local, S3, Azure Blob, etc.
|
||||||
|
|
||||||
7. **Vector Database Configuration**:
|
1. **Vector Database Configuration**:
|
||||||
- `VECTOR_STORE`: Type of vector database (e.g., `weaviate`, `milvus`).
|
|
||||||
- Specific settings for each vector store like `WEAVIATE_ENDPOINT`, `MILVUS_HOST`.
|
- `VECTOR_STORE`: Type of vector database (e.g., `weaviate`, `milvus`).
|
||||||
|
- Specific settings for each vector store like `WEAVIATE_ENDPOINT`, `MILVUS_URI`.
|
||||||
|
|
||||||
|
1. **CORS Configuration**:
|
||||||
|
|
||||||
8. **CORS Configuration**:
|
|
||||||
- `WEB_API_CORS_ALLOW_ORIGINS`, `CONSOLE_CORS_ALLOW_ORIGINS`: Settings for cross-origin resource sharing.
|
- `WEB_API_CORS_ALLOW_ORIGINS`, `CONSOLE_CORS_ALLOW_ORIGINS`: Settings for cross-origin resource sharing.
|
||||||
|
|
||||||
9. **Other Service-Specific Environment Variables**:
|
1. **OpenTelemetry Configuration**:
|
||||||
|
|
||||||
|
- `ENABLE_OTEL`: Enable OpenTelemetry collector in api.
|
||||||
|
- `OTLP_BASE_ENDPOINT`: Endpoint for your OTLP exporter.
|
||||||
|
|
||||||
|
1. **Other Service-Specific Environment Variables**:
|
||||||
|
|
||||||
- Each service like `nginx`, `redis`, `db`, and vector databases have specific environment variables that are directly referenced in the `docker-compose.yaml`.
|
- Each service like `nginx`, `redis`, `db`, and vector databases have specific environment variables that are directly referenced in the `docker-compose.yaml`.
|
||||||
|
|
||||||
|
### Environment Variables Synchronization
|
||||||
|
|
||||||
|
When upgrading Dify or pulling the latest changes, new environment variables may be introduced in `.env.example`.
|
||||||
|
|
||||||
|
To help keep your existing `.env` file up to date **without losing your custom values**, an optional environment variables synchronization tool is provided.
|
||||||
|
|
||||||
|
> This tool performs a **one-way synchronization** from `.env.example` to `.env`.
|
||||||
|
> Existing values in `.env` are never overwritten automatically.
|
||||||
|
|
||||||
|
#### `dify-env-sync.sh` (Optional)
|
||||||
|
|
||||||
|
This script compares your current `.env` file with the latest `.env.example` template and helps safely apply new or updated environment variables.
|
||||||
|
|
||||||
|
**What it does**
|
||||||
|
|
||||||
|
- Creates a backup of the current `.env` file before making any changes
|
||||||
|
- Synchronizes newly added environment variables from `.env.example`
|
||||||
|
- Preserves all existing custom values in `.env`
|
||||||
|
- Displays differences and variables removed from `.env.example` for review
|
||||||
|
|
||||||
|
**Backup behavior**
|
||||||
|
|
||||||
|
Before synchronization, the current `.env` file is saved to the `env-backup/` directory with a timestamped filename
|
||||||
|
(e.g. `env-backup/.env.backup_20231218_143022`).
|
||||||
|
|
||||||
|
**When to use**
|
||||||
|
|
||||||
|
- After upgrading Dify to a newer version
|
||||||
|
- When `.env.example` has been updated with new environment variables
|
||||||
|
- When managing a large or heavily customized `.env` file
|
||||||
|
|
||||||
|
**Usage**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Grant execution permission (first time only)
|
||||||
|
chmod +x dify-env-sync.sh
|
||||||
|
|
||||||
|
# Run the synchronization
|
||||||
|
./dify-env-sync.sh
|
||||||
|
```
|
||||||
|
|
||||||
### Additional Information
|
### Additional Information
|
||||||
|
|
||||||
- **Continuous Improvement Phase**: We are actively seeking feedback from the community to refine and enhance the deployment process. As more users adopt this new method, we will continue to make improvements based on your experiences and suggestions.
|
- **Continuous Improvement Phase**: We are actively seeking feedback from the community to refine and enhance the deployment process. As more users adopt this new method, we will continue to make improvements based on your experiences and suggestions.
|
||||||
|
|||||||
@@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
## Short description
|
## Short description
|
||||||
|
|
||||||
Docker-compose certbot configurations with Backward compatibility (without certbot container).
|
docker compose certbot configurations with Backward compatibility (without certbot container).\
|
||||||
Use `docker-compose --profile certbot up` to use this features.
|
Use `docker compose --profile certbot up` to use this features.
|
||||||
|
|
||||||
## The simplest way for launching new servers with SSL certificates
|
## The simplest way for launching new servers with SSL certificates
|
||||||
|
|
||||||
1. Get letsencrypt certs
|
1. Get letsencrypt certs\
|
||||||
set `.env` values
|
set `.env` values
|
||||||
```properties
|
```properties
|
||||||
NGINX_SSL_CERT_FILENAME=fullchain.pem
|
NGINX_SSL_CERT_FILENAME=fullchain.pem
|
||||||
@@ -18,23 +18,23 @@ Use `docker-compose --profile certbot up` to use this features.
|
|||||||
```
|
```
|
||||||
execute command:
|
execute command:
|
||||||
```shell
|
```shell
|
||||||
sudo docker network prune
|
docker network prune
|
||||||
sudo docker-compose --profile certbot up --force-recreate -d
|
docker compose --profile certbot up --force-recreate -d
|
||||||
```
|
```
|
||||||
then after the containers launched:
|
then after the containers launched:
|
||||||
```shell
|
```shell
|
||||||
sudo docker-compose exec -it certbot /bin/sh /update-cert.sh
|
docker compose exec -it certbot /bin/sh /update-cert.sh
|
||||||
```
|
```
|
||||||
2. Edit `.env` file and `sudo docker-compose --profile certbot up` again.
|
1. Edit `.env` file and `docker compose --profile certbot up` again.\
|
||||||
set `.env` value additionally
|
set `.env` value additionally
|
||||||
```properties
|
```properties
|
||||||
NGINX_HTTPS_ENABLED=true
|
NGINX_HTTPS_ENABLED=true
|
||||||
```
|
```
|
||||||
execute command:
|
execute command:
|
||||||
```shell
|
```shell
|
||||||
sudo docker-compose --profile certbot up -d --no-deps --force-recreate nginx
|
docker compose --profile certbot up -d --no-deps --force-recreate nginx
|
||||||
```
|
```
|
||||||
Then you can access your serve with HTTPS.
|
Then you can access your serve with HTTPS.\
|
||||||
[https://your_domain.com](https://your_domain.com)
|
[https://your_domain.com](https://your_domain.com)
|
||||||
|
|
||||||
## SSL certificates renewal
|
## SSL certificates renewal
|
||||||
@@ -42,8 +42,8 @@ Use `docker-compose --profile certbot up` to use this features.
|
|||||||
For SSL certificates renewal, execute commands below:
|
For SSL certificates renewal, execute commands below:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo docker-compose exec -it certbot /bin/sh /update-cert.sh
|
docker compose exec -it certbot /bin/sh /update-cert.sh
|
||||||
sudo docker-compose exec nginx nginx -s reload
|
docker compose exec nginx nginx -s reload
|
||||||
```
|
```
|
||||||
|
|
||||||
## Options for certbot
|
## Options for certbot
|
||||||
@@ -57,14 +57,14 @@ CERTBOT_OPTIONS=--dry-run
|
|||||||
To apply changes to `CERTBOT_OPTIONS`, regenerate the certbot container before updating the certificates.
|
To apply changes to `CERTBOT_OPTIONS`, regenerate the certbot container before updating the certificates.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo docker-compose --profile certbot up -d --no-deps --force-recreate certbot
|
docker compose --profile certbot up -d --no-deps --force-recreate certbot
|
||||||
sudo docker-compose exec -it certbot /bin/sh /update-cert.sh
|
docker compose exec -it certbot /bin/sh /update-cert.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, reload the nginx container if necessary.
|
Then, reload the nginx container if necessary.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo docker-compose exec nginx nginx -s reload
|
docker compose exec nginx nginx -s reload
|
||||||
```
|
```
|
||||||
|
|
||||||
## For legacy servers
|
## For legacy servers
|
||||||
@@ -72,5 +72,5 @@ sudo docker-compose exec nginx nginx -s reload
|
|||||||
To use cert files dir `nginx/ssl` as before, simply launch containers WITHOUT `--profile certbot` option.
|
To use cert files dir `nginx/ssl` as before, simply launch containers WITHOUT `--profile certbot` option.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
sudo docker-compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
FROM couchbase/server:latest AS stage_base
|
||||||
|
# FROM couchbase:latest AS stage_base
|
||||||
|
COPY init-cbserver.sh /opt/couchbase/init/
|
||||||
|
RUN chmod +x /opt/couchbase/init/init-cbserver.sh
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# used to start couchbase server - can't get around this as docker compose only allows you to start one command - so we have to start couchbase like the standard couchbase Dockerfile would
|
||||||
|
# https://github.com/couchbase/docker/blob/master/enterprise/couchbase-server/7.2.0/Dockerfile#L88
|
||||||
|
|
||||||
|
/entrypoint.sh couchbase-server &
|
||||||
|
|
||||||
|
# track if setup is complete so we don't try to setup again
|
||||||
|
FILE=/opt/couchbase/init/setupComplete.txt
|
||||||
|
|
||||||
|
if ! [ -f "$FILE" ]; then
|
||||||
|
# used to automatically create the cluster based on environment variables
|
||||||
|
# https://docs.couchbase.com/server/current/cli/cbcli/couchbase-cli-cluster-init.html
|
||||||
|
|
||||||
|
echo $COUCHBASE_ADMINISTRATOR_USERNAME ":" $COUCHBASE_ADMINISTRATOR_PASSWORD
|
||||||
|
|
||||||
|
sleep 20s
|
||||||
|
/opt/couchbase/bin/couchbase-cli cluster-init -c 127.0.0.1 \
|
||||||
|
--cluster-username $COUCHBASE_ADMINISTRATOR_USERNAME \
|
||||||
|
--cluster-password $COUCHBASE_ADMINISTRATOR_PASSWORD \
|
||||||
|
--services data,index,query,fts \
|
||||||
|
--cluster-ramsize $COUCHBASE_RAM_SIZE \
|
||||||
|
--cluster-index-ramsize $COUCHBASE_INDEX_RAM_SIZE \
|
||||||
|
--cluster-eventing-ramsize $COUCHBASE_EVENTING_RAM_SIZE \
|
||||||
|
--cluster-fts-ramsize $COUCHBASE_FTS_RAM_SIZE \
|
||||||
|
--index-storage-setting default
|
||||||
|
|
||||||
|
sleep 2s
|
||||||
|
|
||||||
|
# used to auto create the bucket based on environment variables
|
||||||
|
# https://docs.couchbase.com/server/current/cli/cbcli/couchbase-cli-bucket-create.html
|
||||||
|
|
||||||
|
/opt/couchbase/bin/couchbase-cli bucket-create -c localhost:8091 \
|
||||||
|
--username $COUCHBASE_ADMINISTRATOR_USERNAME \
|
||||||
|
--password $COUCHBASE_ADMINISTRATOR_PASSWORD \
|
||||||
|
--bucket $COUCHBASE_BUCKET \
|
||||||
|
--bucket-ramsize $COUCHBASE_BUCKET_RAMSIZE \
|
||||||
|
--bucket-type couchbase
|
||||||
|
|
||||||
|
# create file so we know that the cluster is setup and don't run the setup again
|
||||||
|
touch $FILE
|
||||||
|
fi
|
||||||
|
# docker compose will stop the container from running unless we do this
|
||||||
|
# known issue and workaround
|
||||||
|
tail -f /dev/null
|
||||||
@@ -0,0 +1,465 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# ================================================================
|
||||||
|
# Dify Environment Variables Synchronization Script
|
||||||
|
#
|
||||||
|
# Features:
|
||||||
|
# - Synchronize latest settings from .env.example to .env
|
||||||
|
# - Preserve custom settings in existing .env
|
||||||
|
# - Add new environment variables
|
||||||
|
# - Detect removed environment variables
|
||||||
|
# - Create backup files
|
||||||
|
# ================================================================
|
||||||
|
|
||||||
|
set -eo pipefail # Exit on error and pipe failures (safer for complex variable handling)
|
||||||
|
|
||||||
|
# Error handling function
|
||||||
|
# Arguments:
|
||||||
|
# $1 - Line number where error occurred
|
||||||
|
# $2 - Error code
|
||||||
|
handle_error() {
|
||||||
|
local line_no=$1
|
||||||
|
local error_code=$2
|
||||||
|
echo -e "\033[0;31m[ERROR]\033[0m Script error: line $line_no with error code $error_code" >&2
|
||||||
|
echo -e "\033[0;31m[ERROR]\033[0m Debug info: current working directory $(pwd)" >&2
|
||||||
|
exit $error_code
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set error trap
|
||||||
|
trap 'handle_error ${LINENO} $?' ERR
|
||||||
|
|
||||||
|
# Color settings for output
|
||||||
|
readonly RED='\033[0;31m'
|
||||||
|
readonly GREEN='\033[0;32m'
|
||||||
|
readonly YELLOW='\033[1;33m'
|
||||||
|
readonly BLUE='\033[0;34m'
|
||||||
|
readonly NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Logging functions
|
||||||
|
# Print informational message in blue
|
||||||
|
# Arguments: $1 - Message to print
|
||||||
|
log_info() {
|
||||||
|
echo -e "${BLUE}[INFO]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print success message in green
|
||||||
|
# Arguments: $1 - Message to print
|
||||||
|
log_success() {
|
||||||
|
echo -e "${GREEN}[SUCCESS]${NC} $1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print warning message in yellow
|
||||||
|
# Arguments: $1 - Message to print
|
||||||
|
log_warning() {
|
||||||
|
echo -e "${YELLOW}[WARNING]${NC} $1" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
# Print error message in red to stderr
|
||||||
|
# Arguments: $1 - Message to print
|
||||||
|
log_error() {
|
||||||
|
echo -e "${RED}[ERROR]${NC} $1" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for required files and create .env if missing
|
||||||
|
# Verifies that .env.example exists and creates .env from template if needed
|
||||||
|
check_files() {
|
||||||
|
log_info "Checking required files..."
|
||||||
|
|
||||||
|
if [[ ! -f ".env.example" ]]; then
|
||||||
|
log_error ".env.example file not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f ".env" ]]; then
|
||||||
|
log_warning ".env file does not exist. Creating from .env.example."
|
||||||
|
cp ".env.example" ".env"
|
||||||
|
log_success ".env file created"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_success "Required files verified"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create timestamped backup of .env file
|
||||||
|
# Creates env-backup directory if needed and backs up current .env file
|
||||||
|
create_backup() {
|
||||||
|
local timestamp=$(date +"%Y%m%d_%H%M%S")
|
||||||
|
local backup_dir="env-backup"
|
||||||
|
|
||||||
|
# Create backup directory if it doesn't exist
|
||||||
|
if [[ ! -d "$backup_dir" ]]; then
|
||||||
|
mkdir -p "$backup_dir"
|
||||||
|
log_info "Created backup directory: $backup_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f ".env" ]]; then
|
||||||
|
local backup_file="${backup_dir}/.env.backup_${timestamp}"
|
||||||
|
cp ".env" "$backup_file"
|
||||||
|
log_success "Backed up existing .env to $backup_file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Detect differences between .env and .env.example (optimized for large files)
|
||||||
|
detect_differences() {
|
||||||
|
log_info "Detecting differences between .env and .env.example..."
|
||||||
|
|
||||||
|
# Create secure temporary directory
|
||||||
|
local temp_dir=$(mktemp -d)
|
||||||
|
local temp_diff="$temp_dir/env_diff"
|
||||||
|
|
||||||
|
# Store diff file path as global variable
|
||||||
|
declare -g DIFF_FILE="$temp_diff"
|
||||||
|
declare -g TEMP_DIR="$temp_dir"
|
||||||
|
|
||||||
|
# Initialize difference file
|
||||||
|
> "$temp_diff"
|
||||||
|
|
||||||
|
# Use awk for efficient comparison (much faster for large files)
|
||||||
|
local diff_count=$(awk -F= '
|
||||||
|
BEGIN { OFS="\x01" }
|
||||||
|
FNR==NR {
|
||||||
|
if (!/^[[:space:]]*#/ && !/^[[:space:]]*$/ && /=/) {
|
||||||
|
gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1)
|
||||||
|
key = $1
|
||||||
|
value = substr($0, index($0,"=")+1)
|
||||||
|
gsub(/^[[:space:]]+|[[:space:]]+$/, "", value)
|
||||||
|
env_values[key] = value
|
||||||
|
}
|
||||||
|
next
|
||||||
|
}
|
||||||
|
{
|
||||||
|
if (!/^[[:space:]]*#/ && !/^[[:space:]]*$/ && /=/) {
|
||||||
|
gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1)
|
||||||
|
key = $1
|
||||||
|
example_value = substr($0, index($0,"=")+1)
|
||||||
|
gsub(/^[[:space:]]+|[[:space:]]+$/, "", example_value)
|
||||||
|
|
||||||
|
if (key in env_values && env_values[key] != example_value) {
|
||||||
|
print key, env_values[key], example_value > "'$temp_diff'"
|
||||||
|
diff_count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END { print diff_count }
|
||||||
|
' .env .env.example)
|
||||||
|
|
||||||
|
if [[ $diff_count -gt 0 ]]; then
|
||||||
|
log_success "Detected differences in $diff_count environment variables"
|
||||||
|
# Show detailed differences
|
||||||
|
show_differences_detail
|
||||||
|
else
|
||||||
|
log_info "No differences detected"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse environment variable line
|
||||||
|
# Extracts key-value pairs from .env file format lines
|
||||||
|
# Arguments:
|
||||||
|
# $1 - Line to parse
|
||||||
|
# Returns:
|
||||||
|
# 0 - Success, outputs "key|value" format
|
||||||
|
# 1 - Skip (empty line, comment, or invalid format)
|
||||||
|
parse_env_line() {
|
||||||
|
local line="$1"
|
||||||
|
local key=""
|
||||||
|
local value=""
|
||||||
|
|
||||||
|
# Skip empty lines or comment lines
|
||||||
|
[[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && return 1
|
||||||
|
|
||||||
|
# Split by =
|
||||||
|
if [[ "$line" =~ ^([^=]+)=(.*)$ ]]; then
|
||||||
|
key="${BASH_REMATCH[1]}"
|
||||||
|
value="${BASH_REMATCH[2]}"
|
||||||
|
|
||||||
|
# Remove leading and trailing whitespace
|
||||||
|
key=$(echo "$key" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')
|
||||||
|
value=$(echo "$value" | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')
|
||||||
|
|
||||||
|
if [[ -n "$key" ]]; then
|
||||||
|
echo "$key|$value"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show detailed differences
|
||||||
|
show_differences_detail() {
|
||||||
|
log_info ""
|
||||||
|
log_info "=== Environment Variable Differences ==="
|
||||||
|
|
||||||
|
# Read differences from the already created diff file
|
||||||
|
if [[ ! -s "$DIFF_FILE" ]]; then
|
||||||
|
log_info "No differences to display"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Display differences
|
||||||
|
local count=1
|
||||||
|
while IFS=$'\x01' read -r key env_value example_value; do
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}[$count] $key${NC}"
|
||||||
|
echo -e " ${GREEN}.env (current)${NC} : ${env_value}"
|
||||||
|
echo -e " ${BLUE}.env.example (recommended)${NC}: ${example_value}"
|
||||||
|
|
||||||
|
# Analyze value changes
|
||||||
|
analyze_value_change "$env_value" "$example_value"
|
||||||
|
((count++))
|
||||||
|
done < "$DIFF_FILE"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
log_info "=== Difference Analysis Complete ==="
|
||||||
|
log_info "Note: Consider changing to the recommended values above."
|
||||||
|
log_info "Current implementation preserves .env values."
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Analyze value changes
|
||||||
|
analyze_value_change() {
|
||||||
|
local current_value="$1"
|
||||||
|
local recommended_value="$2"
|
||||||
|
|
||||||
|
# Analyze value characteristics
|
||||||
|
local analysis=""
|
||||||
|
|
||||||
|
# Empty value check
|
||||||
|
if [[ -z "$current_value" && -n "$recommended_value" ]]; then
|
||||||
|
analysis=" ${RED}→ Setting from empty to recommended value${NC}"
|
||||||
|
elif [[ -n "$current_value" && -z "$recommended_value" ]]; then
|
||||||
|
analysis=" ${RED}→ Recommended value changed to empty${NC}"
|
||||||
|
# Numeric check - using arithmetic evaluation for robust comparison
|
||||||
|
elif [[ "$current_value" =~ ^[0-9]+$ && "$recommended_value" =~ ^[0-9]+$ ]]; then
|
||||||
|
# Use arithmetic evaluation to handle leading zeros correctly
|
||||||
|
if (( 10#$current_value < 10#$recommended_value )); then
|
||||||
|
analysis=" ${BLUE}→ Numeric increase (${current_value} < ${recommended_value})${NC}"
|
||||||
|
elif (( 10#$current_value > 10#$recommended_value )); then
|
||||||
|
analysis=" ${YELLOW}→ Numeric decrease (${current_value} > ${recommended_value})${NC}"
|
||||||
|
fi
|
||||||
|
# Boolean check
|
||||||
|
elif [[ "$current_value" =~ ^(true|false)$ && "$recommended_value" =~ ^(true|false)$ ]]; then
|
||||||
|
if [[ "$current_value" != "$recommended_value" ]]; then
|
||||||
|
analysis=" ${BLUE}→ Boolean value change (${current_value} → ${recommended_value})${NC}"
|
||||||
|
fi
|
||||||
|
# URL/endpoint check
|
||||||
|
elif [[ "$current_value" =~ ^https?:// || "$recommended_value" =~ ^https?:// ]]; then
|
||||||
|
analysis=" ${BLUE}→ URL/endpoint change${NC}"
|
||||||
|
# File path check
|
||||||
|
elif [[ "$current_value" =~ ^/ || "$recommended_value" =~ ^/ ]]; then
|
||||||
|
analysis=" ${BLUE}→ File path change${NC}"
|
||||||
|
else
|
||||||
|
# Length comparison
|
||||||
|
local current_len=${#current_value}
|
||||||
|
local recommended_len=${#recommended_value}
|
||||||
|
if [[ $current_len -ne $recommended_len ]]; then
|
||||||
|
analysis=" ${YELLOW}→ String length change (${current_len} → ${recommended_len} characters)${NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$analysis" ]]; then
|
||||||
|
echo -e "$analysis"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Synchronize .env file with .env.example while preserving custom values
|
||||||
|
# Creates a new .env file based on .env.example structure, preserving existing custom values
|
||||||
|
# Global variables used: DIFF_FILE, TEMP_DIR
|
||||||
|
sync_env_file() {
|
||||||
|
log_info "Starting partial synchronization of .env file..."
|
||||||
|
|
||||||
|
local new_env_file=".env.new"
|
||||||
|
local preserved_count=0
|
||||||
|
local updated_count=0
|
||||||
|
|
||||||
|
# Pre-process diff file for efficient lookup
|
||||||
|
local lookup_file=""
|
||||||
|
if [[ -f "$DIFF_FILE" && -s "$DIFF_FILE" ]]; then
|
||||||
|
lookup_file="${DIFF_FILE}.lookup"
|
||||||
|
# Create sorted lookup file for fast search
|
||||||
|
sort "$DIFF_FILE" > "$lookup_file"
|
||||||
|
log_info "Created lookup file for $(wc -l < "$DIFF_FILE") preserved values"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use AWK for efficient processing (much faster than bash loop for large files)
|
||||||
|
log_info "Processing $(wc -l < .env.example) lines with AWK..."
|
||||||
|
|
||||||
|
local preserved_keys_file="${TEMP_DIR}/preserved_keys"
|
||||||
|
local awk_preserved_count_file="${TEMP_DIR}/awk_preserved_count"
|
||||||
|
local awk_updated_count_file="${TEMP_DIR}/awk_updated_count"
|
||||||
|
|
||||||
|
awk -F'=' -v lookup_file="$lookup_file" -v preserved_file="$preserved_keys_file" \
|
||||||
|
-v preserved_count_file="$awk_preserved_count_file" -v updated_count_file="$awk_updated_count_file" '
|
||||||
|
BEGIN {
|
||||||
|
preserved_count = 0
|
||||||
|
updated_count = 0
|
||||||
|
|
||||||
|
# Load preserved values if lookup file exists
|
||||||
|
if (lookup_file != "") {
|
||||||
|
while ((getline line < lookup_file) > 0) {
|
||||||
|
split(line, parts, "\x01")
|
||||||
|
key = parts[1]
|
||||||
|
value = parts[2]
|
||||||
|
preserved_values[key] = value
|
||||||
|
}
|
||||||
|
close(lookup_file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Process each line
|
||||||
|
{
|
||||||
|
# Check if this is an environment variable line
|
||||||
|
if (/^[[:space:]]*[A-Za-z_][A-Za-z0-9_]*[[:space:]]*=/) {
|
||||||
|
# Extract key
|
||||||
|
key = $1
|
||||||
|
gsub(/^[[:space:]]+|[[:space:]]+$/, "", key)
|
||||||
|
|
||||||
|
# Check if key should be preserved
|
||||||
|
if (key in preserved_values) {
|
||||||
|
print key "=" preserved_values[key]
|
||||||
|
print key > preserved_file
|
||||||
|
preserved_count++
|
||||||
|
} else {
|
||||||
|
print $0
|
||||||
|
updated_count++
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
# Not an env var line, preserve as-is
|
||||||
|
print $0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
END {
|
||||||
|
print preserved_count > preserved_count_file
|
||||||
|
print updated_count > updated_count_file
|
||||||
|
}
|
||||||
|
' .env.example > "$new_env_file"
|
||||||
|
|
||||||
|
# Read counters and preserved keys
|
||||||
|
if [[ -f "$awk_preserved_count_file" ]]; then
|
||||||
|
preserved_count=$(cat "$awk_preserved_count_file")
|
||||||
|
fi
|
||||||
|
if [[ -f "$awk_updated_count_file" ]]; then
|
||||||
|
updated_count=$(cat "$awk_updated_count_file")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Show what was preserved
|
||||||
|
if [[ -f "$preserved_keys_file" ]]; then
|
||||||
|
while read -r key; do
|
||||||
|
[[ -n "$key" ]] && log_info " Preserved: $key (.env value)"
|
||||||
|
done < "$preserved_keys_file"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up lookup file
|
||||||
|
[[ -n "$lookup_file" ]] && rm -f "$lookup_file"
|
||||||
|
|
||||||
|
# Replace the original .env file
|
||||||
|
if mv "$new_env_file" ".env"; then
|
||||||
|
log_success "Successfully created new .env file"
|
||||||
|
else
|
||||||
|
log_error "Failed to replace .env file"
|
||||||
|
rm -f "$new_env_file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up difference file and temporary directory
|
||||||
|
if [[ -n "${TEMP_DIR:-}" ]]; then
|
||||||
|
rm -rf "${TEMP_DIR}"
|
||||||
|
unset TEMP_DIR
|
||||||
|
fi
|
||||||
|
if [[ -n "${DIFF_FILE:-}" ]]; then
|
||||||
|
unset DIFF_FILE
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_success "Partial synchronization of .env file completed"
|
||||||
|
log_info " Preserved .env values: $preserved_count"
|
||||||
|
log_info " Updated to .env.example values: $updated_count"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Detect removed environment variables
|
||||||
|
detect_removed_variables() {
|
||||||
|
log_info "Detecting removed environment variables..."
|
||||||
|
|
||||||
|
if [[ ! -f ".env" ]]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use temporary files for efficient lookup
|
||||||
|
local temp_dir="${TEMP_DIR:-$(mktemp -d)}"
|
||||||
|
local temp_example_keys="$temp_dir/example_keys"
|
||||||
|
local temp_current_keys="$temp_dir/current_keys"
|
||||||
|
local cleanup_temp_dir=""
|
||||||
|
|
||||||
|
# Set flag if we created a new temp directory
|
||||||
|
if [[ -z "${TEMP_DIR:-}" ]]; then
|
||||||
|
cleanup_temp_dir="$temp_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get keys from .env.example and .env, sorted for comm
|
||||||
|
awk -F= '!/^[[:space:]]*#/ && /=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1); print $1}' .env.example | sort > "$temp_example_keys"
|
||||||
|
awk -F= '!/^[[:space:]]*#/ && /=/ {gsub(/^[[:space:]]+|[[:space:]]+$/, "", $1); print $1}' .env | sort > "$temp_current_keys"
|
||||||
|
|
||||||
|
# Get keys from existing .env and check for removals
|
||||||
|
local removed_vars=()
|
||||||
|
while IFS= read -r var; do
|
||||||
|
removed_vars+=("$var")
|
||||||
|
done < <(comm -13 "$temp_example_keys" "$temp_current_keys")
|
||||||
|
|
||||||
|
# Clean up temporary files if we created a new temp directory
|
||||||
|
if [[ -n "$cleanup_temp_dir" ]]; then
|
||||||
|
rm -rf "$cleanup_temp_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${#removed_vars[@]} -gt 0 ]]; then
|
||||||
|
log_warning "The following environment variables have been removed from .env.example:"
|
||||||
|
for var in "${removed_vars[@]}"; do
|
||||||
|
log_warning " - $var"
|
||||||
|
done
|
||||||
|
log_warning "Consider manually removing these variables from .env"
|
||||||
|
else
|
||||||
|
log_success "No removed environment variables found"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show statistics
|
||||||
|
show_statistics() {
|
||||||
|
log_info "Synchronization statistics:"
|
||||||
|
|
||||||
|
local total_example=$(grep -c "^[^#]*=" .env.example 2>/dev/null || echo "0")
|
||||||
|
local total_env=$(grep -c "^[^#]*=" .env 2>/dev/null || echo "0")
|
||||||
|
|
||||||
|
log_info " .env.example environment variables: $total_example"
|
||||||
|
log_info " .env environment variables: $total_env"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main execution function
|
||||||
|
# Orchestrates the complete synchronization process in the correct order
|
||||||
|
main() {
|
||||||
|
log_info "=== Dify Environment Variables Synchronization Script ==="
|
||||||
|
log_info "Execution started: $(date)"
|
||||||
|
|
||||||
|
# Check prerequisites
|
||||||
|
check_files
|
||||||
|
|
||||||
|
# Create backup
|
||||||
|
create_backup
|
||||||
|
|
||||||
|
# Detect differences
|
||||||
|
detect_differences
|
||||||
|
|
||||||
|
# Detect removed variables (before sync)
|
||||||
|
detect_removed_variables
|
||||||
|
|
||||||
|
# Synchronize environment file
|
||||||
|
sync_env_file
|
||||||
|
|
||||||
|
# Show statistics
|
||||||
|
show_statistics
|
||||||
|
|
||||||
|
log_success "=== Synchronization process completed successfully ==="
|
||||||
|
log_info "Execution finished: $(date)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Execute main function only when script is run directly
|
||||||
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||||
|
main "$@"
|
||||||
|
fi
|
||||||
@@ -0,0 +1,928 @@
|
|||||||
|
x-shared-env: &shared-api-worker-env
|
||||||
|
services:
|
||||||
|
# Init container to fix permissions
|
||||||
|
init_permissions:
|
||||||
|
image: busybox:latest
|
||||||
|
command:
|
||||||
|
- sh
|
||||||
|
- -c
|
||||||
|
- |
|
||||||
|
FLAG_FILE="/app/api/storage/.init_permissions"
|
||||||
|
if [ -f "$${FLAG_FILE}" ]; then
|
||||||
|
echo "Permissions already initialized. Exiting."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "Initializing permissions for /app/api/storage"
|
||||||
|
chown -R 1001:1001 /app/api/storage && touch "$${FLAG_FILE}"
|
||||||
|
echo "Permissions initialized. Exiting."
|
||||||
|
volumes:
|
||||||
|
- ./volumes/app/storage:/app/api/storage
|
||||||
|
restart: "no"
|
||||||
|
|
||||||
|
# API service
|
||||||
|
api:
|
||||||
|
image: langgenius/dify-api:1.11.2
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
# Use the shared environment variables.
|
||||||
|
<<: *shared-api-worker-env
|
||||||
|
# Startup mode, 'api' starts the API server.
|
||||||
|
MODE: api
|
||||||
|
SENTRY_DSN: ${API_SENTRY_DSN:-}
|
||||||
|
SENTRY_TRACES_SAMPLE_RATE: ${API_SENTRY_TRACES_SAMPLE_RATE:-1.0}
|
||||||
|
SENTRY_PROFILES_SAMPLE_RATE: ${API_SENTRY_PROFILES_SAMPLE_RATE:-1.0}
|
||||||
|
PLUGIN_REMOTE_INSTALL_HOST: ${EXPOSE_PLUGIN_DEBUGGING_HOST:-localhost}
|
||||||
|
PLUGIN_REMOTE_INSTALL_PORT: ${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}
|
||||||
|
PLUGIN_MAX_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800}
|
||||||
|
PLUGIN_DAEMON_TIMEOUT: ${PLUGIN_DAEMON_TIMEOUT:-600.0}
|
||||||
|
INNER_API_KEY_FOR_PLUGIN: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1}
|
||||||
|
depends_on:
|
||||||
|
init_permissions:
|
||||||
|
condition: service_completed_successfully
|
||||||
|
db_postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
required: false
|
||||||
|
db_mysql:
|
||||||
|
condition: service_healthy
|
||||||
|
required: false
|
||||||
|
oceanbase:
|
||||||
|
condition: service_healthy
|
||||||
|
required: false
|
||||||
|
seekdb:
|
||||||
|
condition: service_healthy
|
||||||
|
required: false
|
||||||
|
redis:
|
||||||
|
condition: service_started
|
||||||
|
volumes:
|
||||||
|
# Mount the storage directory to the container, for storing user files.
|
||||||
|
- ./volumes/app/storage:/app/api/storage
|
||||||
|
networks:
|
||||||
|
- ssrf_proxy_network
|
||||||
|
- default
|
||||||
|
|
||||||
|
# worker service
|
||||||
|
# The Celery worker for processing all queues (dataset, workflow, mail, etc.)
|
||||||
|
worker:
|
||||||
|
image: langgenius/dify-api:1.11.2
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
# Use the shared environment variables.
|
||||||
|
<<: *shared-api-worker-env
|
||||||
|
# Startup mode, 'worker' starts the Celery worker for processing all queues.
|
||||||
|
MODE: worker
|
||||||
|
SENTRY_DSN: ${API_SENTRY_DSN:-}
|
||||||
|
SENTRY_TRACES_SAMPLE_RATE: ${API_SENTRY_TRACES_SAMPLE_RATE:-1.0}
|
||||||
|
SENTRY_PROFILES_SAMPLE_RATE: ${API_SENTRY_PROFILES_SAMPLE_RATE:-1.0}
|
||||||
|
PLUGIN_MAX_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800}
|
||||||
|
INNER_API_KEY_FOR_PLUGIN: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1}
|
||||||
|
depends_on:
|
||||||
|
init_permissions:
|
||||||
|
condition: service_completed_successfully
|
||||||
|
db_postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
required: false
|
||||||
|
db_mysql:
|
||||||
|
condition: service_healthy
|
||||||
|
required: false
|
||||||
|
oceanbase:
|
||||||
|
condition: service_healthy
|
||||||
|
required: false
|
||||||
|
seekdb:
|
||||||
|
condition: service_healthy
|
||||||
|
required: false
|
||||||
|
redis:
|
||||||
|
condition: service_started
|
||||||
|
volumes:
|
||||||
|
# Mount the storage directory to the container, for storing user files.
|
||||||
|
- ./volumes/app/storage:/app/api/storage
|
||||||
|
networks:
|
||||||
|
- ssrf_proxy_network
|
||||||
|
- default
|
||||||
|
|
||||||
|
# worker_beat service
|
||||||
|
# Celery beat for scheduling periodic tasks.
|
||||||
|
worker_beat:
|
||||||
|
image: langgenius/dify-api:1.11.2
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
# Use the shared environment variables.
|
||||||
|
<<: *shared-api-worker-env
|
||||||
|
# Startup mode, 'worker_beat' starts the Celery beat for scheduling periodic tasks.
|
||||||
|
MODE: beat
|
||||||
|
depends_on:
|
||||||
|
init_permissions:
|
||||||
|
condition: service_completed_successfully
|
||||||
|
db_postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
required: false
|
||||||
|
db_mysql:
|
||||||
|
condition: service_healthy
|
||||||
|
required: false
|
||||||
|
oceanbase:
|
||||||
|
condition: service_healthy
|
||||||
|
required: false
|
||||||
|
seekdb:
|
||||||
|
condition: service_healthy
|
||||||
|
required: false
|
||||||
|
redis:
|
||||||
|
condition: service_started
|
||||||
|
networks:
|
||||||
|
- ssrf_proxy_network
|
||||||
|
- default
|
||||||
|
|
||||||
|
# Frontend web application.
|
||||||
|
web:
|
||||||
|
image: langgenius/dify-web:1.11.2
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
CONSOLE_API_URL: ${CONSOLE_API_URL:-}
|
||||||
|
APP_API_URL: ${APP_API_URL:-}
|
||||||
|
AMPLITUDE_API_KEY: ${AMPLITUDE_API_KEY:-}
|
||||||
|
NEXT_PUBLIC_COOKIE_DOMAIN: ${NEXT_PUBLIC_COOKIE_DOMAIN:-}
|
||||||
|
SENTRY_DSN: ${WEB_SENTRY_DSN:-}
|
||||||
|
NEXT_TELEMETRY_DISABLED: ${NEXT_TELEMETRY_DISABLED:-0}
|
||||||
|
TEXT_GENERATION_TIMEOUT_MS: ${TEXT_GENERATION_TIMEOUT_MS:-60000}
|
||||||
|
CSP_WHITELIST: ${CSP_WHITELIST:-}
|
||||||
|
ALLOW_EMBED: ${ALLOW_EMBED:-false}
|
||||||
|
ALLOW_UNSAFE_DATA_SCHEME: ${ALLOW_UNSAFE_DATA_SCHEME:-false}
|
||||||
|
MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace.dify.ai}
|
||||||
|
MARKETPLACE_URL: ${MARKETPLACE_URL:-https://marketplace.dify.ai}
|
||||||
|
TOP_K_MAX_VALUE: ${TOP_K_MAX_VALUE:-}
|
||||||
|
INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH: ${INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH:-}
|
||||||
|
PM2_INSTANCES: ${PM2_INSTANCES:-2}
|
||||||
|
LOOP_NODE_MAX_COUNT: ${LOOP_NODE_MAX_COUNT:-100}
|
||||||
|
MAX_TOOLS_NUM: ${MAX_TOOLS_NUM:-10}
|
||||||
|
MAX_PARALLEL_LIMIT: ${MAX_PARALLEL_LIMIT:-10}
|
||||||
|
MAX_ITERATIONS_NUM: ${MAX_ITERATIONS_NUM:-99}
|
||||||
|
MAX_TREE_DEPTH: ${MAX_TREE_DEPTH:-50}
|
||||||
|
ENABLE_WEBSITE_JINAREADER: ${ENABLE_WEBSITE_JINAREADER:-true}
|
||||||
|
ENABLE_WEBSITE_FIRECRAWL: ${ENABLE_WEBSITE_FIRECRAWL:-true}
|
||||||
|
ENABLE_WEBSITE_WATERCRAWL: ${ENABLE_WEBSITE_WATERCRAWL:-true}
|
||||||
|
|
||||||
|
# The PostgreSQL database.
|
||||||
|
db_postgres:
|
||||||
|
image: postgres:15-alpine
|
||||||
|
profiles:
|
||||||
|
- postgresql
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: ${DB_USERNAME:-postgres}
|
||||||
|
POSTGRES_PASSWORD: ${DB_PASSWORD:-difyai123456}
|
||||||
|
POSTGRES_DB: ${DB_DATABASE:-dify}
|
||||||
|
PGDATA: ${PGDATA:-/var/lib/postgresql/data/pgdata}
|
||||||
|
command: >
|
||||||
|
postgres -c 'max_connections=${POSTGRES_MAX_CONNECTIONS:-100}'
|
||||||
|
-c 'shared_buffers=${POSTGRES_SHARED_BUFFERS:-128MB}'
|
||||||
|
-c 'work_mem=${POSTGRES_WORK_MEM:-4MB}'
|
||||||
|
-c 'maintenance_work_mem=${POSTGRES_MAINTENANCE_WORK_MEM:-64MB}'
|
||||||
|
-c 'effective_cache_size=${POSTGRES_EFFECTIVE_CACHE_SIZE:-4096MB}'
|
||||||
|
-c 'statement_timeout=${POSTGRES_STATEMENT_TIMEOUT:-0}'
|
||||||
|
-c 'idle_in_transaction_session_timeout=${POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT:-0}'
|
||||||
|
volumes:
|
||||||
|
- ./volumes/db/data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
[
|
||||||
|
"CMD",
|
||||||
|
"pg_isready",
|
||||||
|
"-h",
|
||||||
|
"db_postgres",
|
||||||
|
"-U",
|
||||||
|
"${DB_USERNAME:-postgres}",
|
||||||
|
"-d",
|
||||||
|
"${DB_DATABASE:-dify}",
|
||||||
|
]
|
||||||
|
interval: 1s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 60
|
||||||
|
|
||||||
|
# The mysql database.
|
||||||
|
db_mysql:
|
||||||
|
image: mysql:8.0
|
||||||
|
profiles:
|
||||||
|
- mysql
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD:-difyai123456}
|
||||||
|
MYSQL_DATABASE: ${DB_DATABASE:-dify}
|
||||||
|
command: >
|
||||||
|
--max_connections=1000
|
||||||
|
--innodb_buffer_pool_size=${MYSQL_INNODB_BUFFER_POOL_SIZE:-512M}
|
||||||
|
--innodb_log_file_size=${MYSQL_INNODB_LOG_FILE_SIZE:-128M}
|
||||||
|
--innodb_flush_log_at_trx_commit=${MYSQL_INNODB_FLUSH_LOG_AT_TRX_COMMIT:-2}
|
||||||
|
volumes:
|
||||||
|
- ${MYSQL_HOST_VOLUME:-./volumes/mysql/data}:/var/lib/mysql
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
[
|
||||||
|
"CMD",
|
||||||
|
"mysqladmin",
|
||||||
|
"ping",
|
||||||
|
"-u",
|
||||||
|
"root",
|
||||||
|
"-p${DB_PASSWORD:-difyai123456}",
|
||||||
|
]
|
||||||
|
interval: 1s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 30
|
||||||
|
|
||||||
|
# The redis cache.
|
||||||
|
redis:
|
||||||
|
image: redis:6-alpine
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
REDISCLI_AUTH: ${REDIS_PASSWORD:-difyai123456}
|
||||||
|
volumes:
|
||||||
|
# Mount the redis data directory to the container.
|
||||||
|
- ./volumes/redis/data:/data
|
||||||
|
# Set the redis password when startup redis server.
|
||||||
|
command: redis-server --requirepass ${REDIS_PASSWORD:-difyai123456}
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
[
|
||||||
|
"CMD-SHELL",
|
||||||
|
"redis-cli -a ${REDIS_PASSWORD:-difyai123456} ping | grep -q PONG",
|
||||||
|
]
|
||||||
|
|
||||||
|
# The DifySandbox
|
||||||
|
sandbox:
|
||||||
|
image: langgenius/dify-sandbox:0.2.12
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
# The DifySandbox configurations
|
||||||
|
# Make sure you are changing this key for your deployment with a strong key.
|
||||||
|
# You can generate a strong key using `openssl rand -base64 42`.
|
||||||
|
API_KEY: ${SANDBOX_API_KEY:-dify-sandbox}
|
||||||
|
GIN_MODE: ${SANDBOX_GIN_MODE:-release}
|
||||||
|
WORKER_TIMEOUT: ${SANDBOX_WORKER_TIMEOUT:-15}
|
||||||
|
ENABLE_NETWORK: ${SANDBOX_ENABLE_NETWORK:-true}
|
||||||
|
HTTP_PROXY: ${SANDBOX_HTTP_PROXY:-http://ssrf_proxy:3128}
|
||||||
|
HTTPS_PROXY: ${SANDBOX_HTTPS_PROXY:-http://ssrf_proxy:3128}
|
||||||
|
SANDBOX_PORT: ${SANDBOX_PORT:-8194}
|
||||||
|
PIP_MIRROR_URL: ${PIP_MIRROR_URL:-}
|
||||||
|
volumes:
|
||||||
|
- ./volumes/sandbox/dependencies:/dependencies
|
||||||
|
- ./volumes/sandbox/conf:/conf
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8194/health"]
|
||||||
|
networks:
|
||||||
|
- ssrf_proxy_network
|
||||||
|
|
||||||
|
# plugin daemon
|
||||||
|
plugin_daemon:
|
||||||
|
image: langgenius/dify-plugin-daemon:0.5.2-local
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
# Use the shared environment variables.
|
||||||
|
<<: *shared-api-worker-env
|
||||||
|
DB_DATABASE: ${DB_PLUGIN_DATABASE:-dify_plugin}
|
||||||
|
SERVER_PORT: ${PLUGIN_DAEMON_PORT:-5002}
|
||||||
|
SERVER_KEY: ${PLUGIN_DAEMON_KEY:-lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi}
|
||||||
|
MAX_PLUGIN_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800}
|
||||||
|
PPROF_ENABLED: ${PLUGIN_PPROF_ENABLED:-false}
|
||||||
|
DIFY_INNER_API_URL: ${PLUGIN_DIFY_INNER_API_URL:-http://api:5001}
|
||||||
|
DIFY_INNER_API_KEY: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1}
|
||||||
|
PLUGIN_REMOTE_INSTALLING_HOST: ${PLUGIN_DEBUGGING_HOST:-0.0.0.0}
|
||||||
|
PLUGIN_REMOTE_INSTALLING_PORT: ${PLUGIN_DEBUGGING_PORT:-5003}
|
||||||
|
PLUGIN_WORKING_PATH: ${PLUGIN_WORKING_PATH:-/app/storage/cwd}
|
||||||
|
FORCE_VERIFYING_SIGNATURE: ${FORCE_VERIFYING_SIGNATURE:-true}
|
||||||
|
PYTHON_ENV_INIT_TIMEOUT: ${PLUGIN_PYTHON_ENV_INIT_TIMEOUT:-120}
|
||||||
|
PLUGIN_MAX_EXECUTION_TIMEOUT: ${PLUGIN_MAX_EXECUTION_TIMEOUT:-600}
|
||||||
|
PLUGIN_STDIO_BUFFER_SIZE: ${PLUGIN_STDIO_BUFFER_SIZE:-1024}
|
||||||
|
PLUGIN_STDIO_MAX_BUFFER_SIZE: ${PLUGIN_STDIO_MAX_BUFFER_SIZE:-5242880}
|
||||||
|
PIP_MIRROR_URL: ${PIP_MIRROR_URL:-}
|
||||||
|
PLUGIN_STORAGE_TYPE: ${PLUGIN_STORAGE_TYPE:-local}
|
||||||
|
PLUGIN_STORAGE_LOCAL_ROOT: ${PLUGIN_STORAGE_LOCAL_ROOT:-/app/storage}
|
||||||
|
PLUGIN_INSTALLED_PATH: ${PLUGIN_INSTALLED_PATH:-plugin}
|
||||||
|
PLUGIN_PACKAGE_CACHE_PATH: ${PLUGIN_PACKAGE_CACHE_PATH:-plugin_packages}
|
||||||
|
PLUGIN_MEDIA_CACHE_PATH: ${PLUGIN_MEDIA_CACHE_PATH:-assets}
|
||||||
|
PLUGIN_STORAGE_OSS_BUCKET: ${PLUGIN_STORAGE_OSS_BUCKET:-}
|
||||||
|
S3_USE_AWS_MANAGED_IAM: ${PLUGIN_S3_USE_AWS_MANAGED_IAM:-false}
|
||||||
|
S3_USE_AWS: ${PLUGIN_S3_USE_AWS:-false}
|
||||||
|
S3_ENDPOINT: ${PLUGIN_S3_ENDPOINT:-}
|
||||||
|
S3_USE_PATH_STYLE: ${PLUGIN_S3_USE_PATH_STYLE:-false}
|
||||||
|
AWS_ACCESS_KEY: ${PLUGIN_AWS_ACCESS_KEY:-}
|
||||||
|
AWS_SECRET_KEY: ${PLUGIN_AWS_SECRET_KEY:-}
|
||||||
|
AWS_REGION: ${PLUGIN_AWS_REGION:-}
|
||||||
|
AZURE_BLOB_STORAGE_CONNECTION_STRING: ${PLUGIN_AZURE_BLOB_STORAGE_CONNECTION_STRING:-}
|
||||||
|
AZURE_BLOB_STORAGE_CONTAINER_NAME: ${PLUGIN_AZURE_BLOB_STORAGE_CONTAINER_NAME:-}
|
||||||
|
TENCENT_COS_SECRET_KEY: ${PLUGIN_TENCENT_COS_SECRET_KEY:-}
|
||||||
|
TENCENT_COS_SECRET_ID: ${PLUGIN_TENCENT_COS_SECRET_ID:-}
|
||||||
|
TENCENT_COS_REGION: ${PLUGIN_TENCENT_COS_REGION:-}
|
||||||
|
ALIYUN_OSS_REGION: ${PLUGIN_ALIYUN_OSS_REGION:-}
|
||||||
|
ALIYUN_OSS_ENDPOINT: ${PLUGIN_ALIYUN_OSS_ENDPOINT:-}
|
||||||
|
ALIYUN_OSS_ACCESS_KEY_ID: ${PLUGIN_ALIYUN_OSS_ACCESS_KEY_ID:-}
|
||||||
|
ALIYUN_OSS_ACCESS_KEY_SECRET: ${PLUGIN_ALIYUN_OSS_ACCESS_KEY_SECRET:-}
|
||||||
|
ALIYUN_OSS_AUTH_VERSION: ${PLUGIN_ALIYUN_OSS_AUTH_VERSION:-v4}
|
||||||
|
ALIYUN_OSS_PATH: ${PLUGIN_ALIYUN_OSS_PATH:-}
|
||||||
|
VOLCENGINE_TOS_ENDPOINT: ${PLUGIN_VOLCENGINE_TOS_ENDPOINT:-}
|
||||||
|
VOLCENGINE_TOS_ACCESS_KEY: ${PLUGIN_VOLCENGINE_TOS_ACCESS_KEY:-}
|
||||||
|
VOLCENGINE_TOS_SECRET_KEY: ${PLUGIN_VOLCENGINE_TOS_SECRET_KEY:-}
|
||||||
|
VOLCENGINE_TOS_REGION: ${PLUGIN_VOLCENGINE_TOS_REGION:-}
|
||||||
|
SENTRY_ENABLED: ${PLUGIN_SENTRY_ENABLED:-false}
|
||||||
|
SENTRY_DSN: ${PLUGIN_SENTRY_DSN:-}
|
||||||
|
ports:
|
||||||
|
- "${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}:${PLUGIN_DEBUGGING_PORT:-5003}"
|
||||||
|
volumes:
|
||||||
|
- ./volumes/plugin_daemon:/app/storage
|
||||||
|
depends_on:
|
||||||
|
db_postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
required: false
|
||||||
|
db_mysql:
|
||||||
|
condition: service_healthy
|
||||||
|
required: false
|
||||||
|
oceanbase:
|
||||||
|
condition: service_healthy
|
||||||
|
required: false
|
||||||
|
seekdb:
|
||||||
|
condition: service_healthy
|
||||||
|
required: false
|
||||||
|
|
||||||
|
# ssrf_proxy server
|
||||||
|
# for more information, please refer to
|
||||||
|
# https://docs.dify.ai/learn-more/faq/install-faq#18-why-is-ssrf-proxy-needed%3F
|
||||||
|
ssrf_proxy:
|
||||||
|
image: ubuntu/squid:latest
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./ssrf_proxy/squid.conf.template:/etc/squid/squid.conf.template
|
||||||
|
- ./ssrf_proxy/docker-entrypoint.sh:/docker-entrypoint-mount.sh
|
||||||
|
entrypoint:
|
||||||
|
[
|
||||||
|
"sh",
|
||||||
|
"-c",
|
||||||
|
"cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh",
|
||||||
|
]
|
||||||
|
environment:
|
||||||
|
# pls clearly modify the squid env vars to fit your network environment.
|
||||||
|
HTTP_PORT: ${SSRF_HTTP_PORT:-3128}
|
||||||
|
COREDUMP_DIR: ${SSRF_COREDUMP_DIR:-/var/spool/squid}
|
||||||
|
REVERSE_PROXY_PORT: ${SSRF_REVERSE_PROXY_PORT:-8194}
|
||||||
|
SANDBOX_HOST: ${SSRF_SANDBOX_HOST:-sandbox}
|
||||||
|
SANDBOX_PORT: ${SANDBOX_PORT:-8194}
|
||||||
|
networks:
|
||||||
|
- ssrf_proxy_network
|
||||||
|
- default
|
||||||
|
|
||||||
|
# Certbot service
|
||||||
|
# use `docker-compose --profile certbot up` to start the certbot service.
|
||||||
|
certbot:
|
||||||
|
image: certbot/certbot
|
||||||
|
profiles:
|
||||||
|
- certbot
|
||||||
|
volumes:
|
||||||
|
- ./volumes/certbot/conf:/etc/letsencrypt
|
||||||
|
- ./volumes/certbot/www:/var/www/html
|
||||||
|
- ./volumes/certbot/logs:/var/log/letsencrypt
|
||||||
|
- ./volumes/certbot/conf/live:/etc/letsencrypt/live
|
||||||
|
- ./certbot/update-cert.template.txt:/update-cert.template.txt
|
||||||
|
- ./certbot/docker-entrypoint.sh:/docker-entrypoint.sh
|
||||||
|
environment:
|
||||||
|
- CERTBOT_EMAIL=${CERTBOT_EMAIL}
|
||||||
|
- CERTBOT_DOMAIN=${CERTBOT_DOMAIN}
|
||||||
|
- CERTBOT_OPTIONS=${CERTBOT_OPTIONS:-}
|
||||||
|
entrypoint: ["/docker-entrypoint.sh"]
|
||||||
|
command: ["tail", "-f", "/dev/null"]
|
||||||
|
|
||||||
|
# The nginx reverse proxy.
|
||||||
|
# used for reverse proxying the API service and Web service.
|
||||||
|
nginx:
|
||||||
|
image: nginx:latest
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./nginx/nginx.conf.template:/etc/nginx/nginx.conf.template
|
||||||
|
- ./nginx/proxy.conf.template:/etc/nginx/proxy.conf.template
|
||||||
|
- ./nginx/https.conf.template:/etc/nginx/https.conf.template
|
||||||
|
- ./nginx/conf.d:/etc/nginx/conf.d
|
||||||
|
- ./nginx/docker-entrypoint.sh:/docker-entrypoint-mount.sh
|
||||||
|
- ./nginx/ssl:/etc/ssl # cert dir (legacy)
|
||||||
|
- ./volumes/certbot/conf/live:/etc/letsencrypt/live # cert dir (with certbot container)
|
||||||
|
- ./volumes/certbot/conf:/etc/letsencrypt
|
||||||
|
- ./volumes/certbot/www:/var/www/html
|
||||||
|
entrypoint:
|
||||||
|
[
|
||||||
|
"sh",
|
||||||
|
"-c",
|
||||||
|
"cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh",
|
||||||
|
]
|
||||||
|
environment:
|
||||||
|
NGINX_SERVER_NAME: ${NGINX_SERVER_NAME:-_}
|
||||||
|
NGINX_HTTPS_ENABLED: ${NGINX_HTTPS_ENABLED:-false}
|
||||||
|
NGINX_SSL_PORT: ${NGINX_SSL_PORT:-443}
|
||||||
|
NGINX_PORT: ${NGINX_PORT:-80}
|
||||||
|
# You're required to add your own SSL certificates/keys to the `./nginx/ssl` directory
|
||||||
|
# and modify the env vars below in .env if HTTPS_ENABLED is true.
|
||||||
|
NGINX_SSL_CERT_FILENAME: ${NGINX_SSL_CERT_FILENAME:-dify.crt}
|
||||||
|
NGINX_SSL_CERT_KEY_FILENAME: ${NGINX_SSL_CERT_KEY_FILENAME:-dify.key}
|
||||||
|
NGINX_SSL_PROTOCOLS: ${NGINX_SSL_PROTOCOLS:-TLSv1.2 TLSv1.3}
|
||||||
|
NGINX_WORKER_PROCESSES: ${NGINX_WORKER_PROCESSES:-auto}
|
||||||
|
NGINX_CLIENT_MAX_BODY_SIZE: ${NGINX_CLIENT_MAX_BODY_SIZE:-100M}
|
||||||
|
NGINX_KEEPALIVE_TIMEOUT: ${NGINX_KEEPALIVE_TIMEOUT:-65}
|
||||||
|
NGINX_PROXY_READ_TIMEOUT: ${NGINX_PROXY_READ_TIMEOUT:-3600s}
|
||||||
|
NGINX_PROXY_SEND_TIMEOUT: ${NGINX_PROXY_SEND_TIMEOUT:-3600s}
|
||||||
|
NGINX_ENABLE_CERTBOT_CHALLENGE: ${NGINX_ENABLE_CERTBOT_CHALLENGE:-false}
|
||||||
|
CERTBOT_DOMAIN: ${CERTBOT_DOMAIN:-}
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
- web
|
||||||
|
ports:
|
||||||
|
- "${EXPOSE_NGINX_PORT:-80}:${NGINX_PORT:-80}"
|
||||||
|
- "${EXPOSE_NGINX_SSL_PORT:-443}:${NGINX_SSL_PORT:-443}"
|
||||||
|
|
||||||
|
# The Weaviate vector store.
|
||||||
|
weaviate:
|
||||||
|
image: semitechnologies/weaviate:1.27.0
|
||||||
|
profiles:
|
||||||
|
- weaviate
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
# Mount the Weaviate data directory to the con tainer.
|
||||||
|
- ./volumes/weaviate:/var/lib/weaviate
|
||||||
|
environment:
|
||||||
|
# The Weaviate configurations
|
||||||
|
# You can refer to the [Weaviate](https://weaviate.io/developers/weaviate/config-refs/env-vars) documentation for more information.
|
||||||
|
PERSISTENCE_DATA_PATH: ${WEAVIATE_PERSISTENCE_DATA_PATH:-/var/lib/weaviate}
|
||||||
|
QUERY_DEFAULTS_LIMIT: ${WEAVIATE_QUERY_DEFAULTS_LIMIT:-25}
|
||||||
|
AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: ${WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED:-false}
|
||||||
|
DEFAULT_VECTORIZER_MODULE: ${WEAVIATE_DEFAULT_VECTORIZER_MODULE:-none}
|
||||||
|
CLUSTER_HOSTNAME: ${WEAVIATE_CLUSTER_HOSTNAME:-node1}
|
||||||
|
AUTHENTICATION_APIKEY_ENABLED: ${WEAVIATE_AUTHENTICATION_APIKEY_ENABLED:-true}
|
||||||
|
AUTHENTICATION_APIKEY_ALLOWED_KEYS: ${WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS:-WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih}
|
||||||
|
AUTHENTICATION_APIKEY_USERS: ${WEAVIATE_AUTHENTICATION_APIKEY_USERS:-hello@dify.ai}
|
||||||
|
AUTHORIZATION_ADMINLIST_ENABLED: ${WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED:-true}
|
||||||
|
AUTHORIZATION_ADMINLIST_USERS: ${WEAVIATE_AUTHORIZATION_ADMINLIST_USERS:-hello@dify.ai}
|
||||||
|
DISABLE_TELEMETRY: ${WEAVIATE_DISABLE_TELEMETRY:-false}
|
||||||
|
ENABLE_TOKENIZER_GSE: ${WEAVIATE_ENABLE_TOKENIZER_GSE:-false}
|
||||||
|
ENABLE_TOKENIZER_KAGOME_JA: ${WEAVIATE_ENABLE_TOKENIZER_KAGOME_JA:-false}
|
||||||
|
ENABLE_TOKENIZER_KAGOME_KR: ${WEAVIATE_ENABLE_TOKENIZER_KAGOME_KR:-false}
|
||||||
|
|
||||||
|
# OceanBase vector database
|
||||||
|
oceanbase:
|
||||||
|
image: oceanbase/oceanbase-ce:4.3.5-lts
|
||||||
|
container_name: oceanbase
|
||||||
|
profiles:
|
||||||
|
- oceanbase
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./volumes/oceanbase/data:/root/ob
|
||||||
|
- ./volumes/oceanbase/conf:/root/.obd/cluster
|
||||||
|
- ./volumes/oceanbase/init.d:/root/boot/init.d
|
||||||
|
environment:
|
||||||
|
OB_MEMORY_LIMIT: ${OCEANBASE_MEMORY_LIMIT:-6G}
|
||||||
|
OB_SYS_PASSWORD: ${OCEANBASE_VECTOR_PASSWORD:-difyai123456}
|
||||||
|
OB_TENANT_PASSWORD: ${OCEANBASE_VECTOR_PASSWORD:-difyai123456}
|
||||||
|
OB_CLUSTER_NAME: ${OCEANBASE_CLUSTER_NAME:-difyai}
|
||||||
|
OB_SERVER_IP: 127.0.0.1
|
||||||
|
MODE: mini
|
||||||
|
LANG: en_US.UTF-8
|
||||||
|
ports:
|
||||||
|
- "${OCEANBASE_VECTOR_PORT:-2881}:2881"
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
[
|
||||||
|
"CMD-SHELL",
|
||||||
|
'obclient -h127.0.0.1 -P2881 -uroot@test -p${OCEANBASE_VECTOR_PASSWORD:-difyai123456} -e "SELECT 1;"',
|
||||||
|
]
|
||||||
|
interval: 10s
|
||||||
|
retries: 30
|
||||||
|
start_period: 30s
|
||||||
|
timeout: 10s
|
||||||
|
|
||||||
|
# seekdb vector database
|
||||||
|
seekdb:
|
||||||
|
image: oceanbase/seekdb:latest
|
||||||
|
container_name: seekdb
|
||||||
|
profiles:
|
||||||
|
- seekdb
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./volumes/seekdb:/var/lib/oceanbase
|
||||||
|
environment:
|
||||||
|
ROOT_PASSWORD: ${OCEANBASE_VECTOR_PASSWORD:-difyai123456}
|
||||||
|
MEMORY_LIMIT: ${SEEKDB_MEMORY_LIMIT:-2G}
|
||||||
|
REPORTER: dify-ai-seekdb
|
||||||
|
ports:
|
||||||
|
- "${OCEANBASE_VECTOR_PORT:-2881}:2881"
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
[
|
||||||
|
"CMD-SHELL",
|
||||||
|
'mysql -h127.0.0.1 -P2881 -uroot -p${OCEANBASE_VECTOR_PASSWORD:-difyai123456} -e "SELECT 1;"',
|
||||||
|
]
|
||||||
|
interval: 5s
|
||||||
|
retries: 60
|
||||||
|
timeout: 5s
|
||||||
|
|
||||||
|
# Qdrant vector store.
|
||||||
|
# (if used, you need to set VECTOR_STORE to qdrant in the api & worker service.)
|
||||||
|
qdrant:
|
||||||
|
image: langgenius/qdrant:v1.8.3
|
||||||
|
profiles:
|
||||||
|
- qdrant
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./volumes/qdrant:/qdrant/storage
|
||||||
|
environment:
|
||||||
|
QDRANT_API_KEY: ${QDRANT_API_KEY:-difyai123456}
|
||||||
|
|
||||||
|
# The Couchbase vector store.
|
||||||
|
couchbase-server:
|
||||||
|
build: ./couchbase-server
|
||||||
|
profiles:
|
||||||
|
- couchbase
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
- CLUSTER_NAME=dify_search
|
||||||
|
- COUCHBASE_ADMINISTRATOR_USERNAME=${COUCHBASE_USER:-Administrator}
|
||||||
|
- COUCHBASE_ADMINISTRATOR_PASSWORD=${COUCHBASE_PASSWORD:-password}
|
||||||
|
- COUCHBASE_BUCKET=${COUCHBASE_BUCKET_NAME:-Embeddings}
|
||||||
|
- COUCHBASE_BUCKET_RAMSIZE=512
|
||||||
|
- COUCHBASE_RAM_SIZE=2048
|
||||||
|
- COUCHBASE_EVENTING_RAM_SIZE=512
|
||||||
|
- COUCHBASE_INDEX_RAM_SIZE=512
|
||||||
|
- COUCHBASE_FTS_RAM_SIZE=1024
|
||||||
|
hostname: couchbase-server
|
||||||
|
container_name: couchbase-server
|
||||||
|
working_dir: /opt/couchbase
|
||||||
|
stdin_open: true
|
||||||
|
tty: true
|
||||||
|
entrypoint: [""]
|
||||||
|
command: sh -c "/opt/couchbase/init/init-cbserver.sh"
|
||||||
|
volumes:
|
||||||
|
- ./volumes/couchbase/data:/opt/couchbase/var/lib/couchbase/data
|
||||||
|
healthcheck:
|
||||||
|
# ensure bucket was created before proceeding
|
||||||
|
test:
|
||||||
|
[
|
||||||
|
"CMD-SHELL",
|
||||||
|
"curl -s -f -u Administrator:password http://localhost:8091/pools/default/buckets | grep -q '\\[{' || exit 1",
|
||||||
|
]
|
||||||
|
interval: 10s
|
||||||
|
retries: 10
|
||||||
|
start_period: 30s
|
||||||
|
timeout: 10s
|
||||||
|
|
||||||
|
# The pgvector vector database.
|
||||||
|
pgvector:
|
||||||
|
image: pgvector/pgvector:pg16
|
||||||
|
profiles:
|
||||||
|
- pgvector
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
PGUSER: ${PGVECTOR_PGUSER:-postgres}
|
||||||
|
# The password for the default postgres user.
|
||||||
|
POSTGRES_PASSWORD: ${PGVECTOR_POSTGRES_PASSWORD:-difyai123456}
|
||||||
|
# The name of the default postgres database.
|
||||||
|
POSTGRES_DB: ${PGVECTOR_POSTGRES_DB:-dify}
|
||||||
|
# postgres data directory
|
||||||
|
PGDATA: ${PGVECTOR_PGDATA:-/var/lib/postgresql/data/pgdata}
|
||||||
|
# pg_bigm module for full text search
|
||||||
|
PG_BIGM: ${PGVECTOR_PG_BIGM:-false}
|
||||||
|
PG_BIGM_VERSION: ${PGVECTOR_PG_BIGM_VERSION:-1.2-20240606}
|
||||||
|
volumes:
|
||||||
|
- ./volumes/pgvector/data:/var/lib/postgresql/data
|
||||||
|
- ./pgvector/docker-entrypoint.sh:/docker-entrypoint.sh
|
||||||
|
entrypoint: ["/docker-entrypoint.sh"]
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "pg_isready"]
|
||||||
|
interval: 1s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 30
|
||||||
|
|
||||||
|
# get image from https://www.vastdata.com.cn/
|
||||||
|
vastbase:
|
||||||
|
image: vastdata/vastbase-vector
|
||||||
|
profiles:
|
||||||
|
- vastbase
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
- VB_DBCOMPATIBILITY=PG
|
||||||
|
- VB_DB=dify
|
||||||
|
- VB_USERNAME=dify
|
||||||
|
- VB_PASSWORD=Difyai123456
|
||||||
|
ports:
|
||||||
|
- "5434:5432"
|
||||||
|
volumes:
|
||||||
|
- ./vastbase/lic:/home/vastbase/vastbase/lic
|
||||||
|
- ./vastbase/data:/home/vastbase/data
|
||||||
|
- ./vastbase/backup:/home/vastbase/backup
|
||||||
|
- ./vastbase/backup_log:/home/vastbase/backup_log
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "pg_isready"]
|
||||||
|
interval: 1s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 30
|
||||||
|
|
||||||
|
# pgvecto-rs vector store
|
||||||
|
pgvecto-rs:
|
||||||
|
image: tensorchord/pgvecto-rs:pg16-v0.3.0
|
||||||
|
profiles:
|
||||||
|
- pgvecto-rs
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
PGUSER: ${PGVECTOR_PGUSER:-postgres}
|
||||||
|
# The password for the default postgres user.
|
||||||
|
POSTGRES_PASSWORD: ${PGVECTOR_POSTGRES_PASSWORD:-difyai123456}
|
||||||
|
# The name of the default postgres database.
|
||||||
|
POSTGRES_DB: ${PGVECTOR_POSTGRES_DB:-dify}
|
||||||
|
# postgres data directory
|
||||||
|
PGDATA: ${PGVECTOR_PGDATA:-/var/lib/postgresql/data/pgdata}
|
||||||
|
volumes:
|
||||||
|
- ./volumes/pgvecto_rs/data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "pg_isready"]
|
||||||
|
interval: 1s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 30
|
||||||
|
|
||||||
|
# Chroma vector database
|
||||||
|
chroma:
|
||||||
|
image: ghcr.io/chroma-core/chroma:0.5.20
|
||||||
|
profiles:
|
||||||
|
- chroma
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./volumes/chroma:/chroma/chroma
|
||||||
|
environment:
|
||||||
|
CHROMA_SERVER_AUTHN_CREDENTIALS: ${CHROMA_SERVER_AUTHN_CREDENTIALS:-difyai123456}
|
||||||
|
CHROMA_SERVER_AUTHN_PROVIDER: ${CHROMA_SERVER_AUTHN_PROVIDER:-chromadb.auth.token_authn.TokenAuthenticationServerProvider}
|
||||||
|
IS_PERSISTENT: ${CHROMA_IS_PERSISTENT:-TRUE}
|
||||||
|
|
||||||
|
# InterSystems IRIS vector database
|
||||||
|
iris:
|
||||||
|
image: containers.intersystems.com/intersystems/iris-community:2025.3
|
||||||
|
profiles:
|
||||||
|
- iris
|
||||||
|
container_name: iris
|
||||||
|
restart: always
|
||||||
|
init: true
|
||||||
|
ports:
|
||||||
|
- "${IRIS_SUPER_SERVER_PORT:-1972}:1972"
|
||||||
|
- "${IRIS_WEB_SERVER_PORT:-52773}:52773"
|
||||||
|
volumes:
|
||||||
|
- ./volumes/iris:/opt/iris
|
||||||
|
- ./iris/iris-init.script:/iris-init.script
|
||||||
|
- ./iris/docker-entrypoint.sh:/custom-entrypoint.sh
|
||||||
|
entrypoint: ["/custom-entrypoint.sh"]
|
||||||
|
tty: true
|
||||||
|
environment:
|
||||||
|
TZ: ${IRIS_TIMEZONE:-UTC}
|
||||||
|
|
||||||
|
# Oracle vector database
|
||||||
|
oracle:
|
||||||
|
image: container-registry.oracle.com/database/free:latest
|
||||||
|
profiles:
|
||||||
|
- oracle
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- source: oradata
|
||||||
|
type: volume
|
||||||
|
target: /opt/oracle/oradata
|
||||||
|
- ./startupscripts:/opt/oracle/scripts/startup
|
||||||
|
environment:
|
||||||
|
ORACLE_PWD: ${ORACLE_PWD:-Dify123456}
|
||||||
|
ORACLE_CHARACTERSET: ${ORACLE_CHARACTERSET:-AL32UTF8}
|
||||||
|
|
||||||
|
# Milvus vector database services
|
||||||
|
etcd:
|
||||||
|
container_name: milvus-etcd
|
||||||
|
image: quay.io/coreos/etcd:v3.5.5
|
||||||
|
profiles:
|
||||||
|
- milvus
|
||||||
|
environment:
|
||||||
|
ETCD_AUTO_COMPACTION_MODE: ${ETCD_AUTO_COMPACTION_MODE:-revision}
|
||||||
|
ETCD_AUTO_COMPACTION_RETENTION: ${ETCD_AUTO_COMPACTION_RETENTION:-1000}
|
||||||
|
ETCD_QUOTA_BACKEND_BYTES: ${ETCD_QUOTA_BACKEND_BYTES:-4294967296}
|
||||||
|
ETCD_SNAPSHOT_COUNT: ${ETCD_SNAPSHOT_COUNT:-50000}
|
||||||
|
volumes:
|
||||||
|
- ./volumes/milvus/etcd:/etcd
|
||||||
|
command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "etcdctl", "endpoint", "health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 20s
|
||||||
|
retries: 3
|
||||||
|
networks:
|
||||||
|
- milvus
|
||||||
|
|
||||||
|
minio:
|
||||||
|
container_name: milvus-minio
|
||||||
|
image: minio/minio:RELEASE.2023-03-20T20-16-18Z
|
||||||
|
profiles:
|
||||||
|
- milvus
|
||||||
|
environment:
|
||||||
|
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin}
|
||||||
|
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin}
|
||||||
|
volumes:
|
||||||
|
- ./volumes/milvus/minio:/minio_data
|
||||||
|
command: minio server /minio_data --console-address ":9001"
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 20s
|
||||||
|
retries: 3
|
||||||
|
networks:
|
||||||
|
- milvus
|
||||||
|
|
||||||
|
milvus-standalone:
|
||||||
|
container_name: milvus-standalone
|
||||||
|
image: milvusdb/milvus:v2.6.3
|
||||||
|
profiles:
|
||||||
|
- milvus
|
||||||
|
command: ["milvus", "run", "standalone"]
|
||||||
|
environment:
|
||||||
|
ETCD_ENDPOINTS: ${ETCD_ENDPOINTS:-etcd:2379}
|
||||||
|
MINIO_ADDRESS: ${MINIO_ADDRESS:-minio:9000}
|
||||||
|
common.security.authorizationEnabled: ${MILVUS_AUTHORIZATION_ENABLED:-true}
|
||||||
|
volumes:
|
||||||
|
- ./volumes/milvus/milvus:/var/lib/milvus
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:9091/healthz"]
|
||||||
|
interval: 30s
|
||||||
|
start_period: 90s
|
||||||
|
timeout: 20s
|
||||||
|
retries: 3
|
||||||
|
depends_on:
|
||||||
|
- etcd
|
||||||
|
- minio
|
||||||
|
ports:
|
||||||
|
- 19530:19530
|
||||||
|
- 9091:9091
|
||||||
|
networks:
|
||||||
|
- milvus
|
||||||
|
|
||||||
|
# Opensearch vector database
|
||||||
|
opensearch:
|
||||||
|
container_name: opensearch
|
||||||
|
image: opensearchproject/opensearch:latest
|
||||||
|
profiles:
|
||||||
|
- opensearch
|
||||||
|
environment:
|
||||||
|
discovery.type: ${OPENSEARCH_DISCOVERY_TYPE:-single-node}
|
||||||
|
bootstrap.memory_lock: ${OPENSEARCH_BOOTSTRAP_MEMORY_LOCK:-true}
|
||||||
|
OPENSEARCH_JAVA_OPTS: -Xms${OPENSEARCH_JAVA_OPTS_MIN:-512m} -Xmx${OPENSEARCH_JAVA_OPTS_MAX:-1024m}
|
||||||
|
OPENSEARCH_INITIAL_ADMIN_PASSWORD: ${OPENSEARCH_INITIAL_ADMIN_PASSWORD:-Qazwsxedc!@#123}
|
||||||
|
ulimits:
|
||||||
|
memlock:
|
||||||
|
soft: ${OPENSEARCH_MEMLOCK_SOFT:--1}
|
||||||
|
hard: ${OPENSEARCH_MEMLOCK_HARD:--1}
|
||||||
|
nofile:
|
||||||
|
soft: ${OPENSEARCH_NOFILE_SOFT:-65536}
|
||||||
|
hard: ${OPENSEARCH_NOFILE_HARD:-65536}
|
||||||
|
volumes:
|
||||||
|
- ./volumes/opensearch/data:/usr/share/opensearch/data
|
||||||
|
networks:
|
||||||
|
- opensearch-net
|
||||||
|
|
||||||
|
opensearch-dashboards:
|
||||||
|
container_name: opensearch-dashboards
|
||||||
|
image: opensearchproject/opensearch-dashboards:latest
|
||||||
|
profiles:
|
||||||
|
- opensearch
|
||||||
|
environment:
|
||||||
|
OPENSEARCH_HOSTS: '["https://opensearch:9200"]'
|
||||||
|
volumes:
|
||||||
|
- ./volumes/opensearch/opensearch_dashboards.yml:/usr/share/opensearch-dashboards/config/opensearch_dashboards.yml
|
||||||
|
networks:
|
||||||
|
- opensearch-net
|
||||||
|
depends_on:
|
||||||
|
- opensearch
|
||||||
|
|
||||||
|
# opengauss vector database.
|
||||||
|
opengauss:
|
||||||
|
image: opengauss/opengauss:7.0.0-RC1
|
||||||
|
profiles:
|
||||||
|
- opengauss
|
||||||
|
privileged: true
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
GS_USERNAME: ${OPENGAUSS_USER:-postgres}
|
||||||
|
GS_PASSWORD: ${OPENGAUSS_PASSWORD:-Dify@123}
|
||||||
|
GS_PORT: ${OPENGAUSS_PORT:-6600}
|
||||||
|
GS_DB: ${OPENGAUSS_DATABASE:-dify}
|
||||||
|
volumes:
|
||||||
|
- ./volumes/opengauss/data:/var/lib/opengauss/data
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "netstat -lntp | grep tcp6 > /dev/null 2>&1"]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 10
|
||||||
|
ports:
|
||||||
|
- ${OPENGAUSS_PORT:-6600}:${OPENGAUSS_PORT:-6600}
|
||||||
|
|
||||||
|
# MyScale vector database
|
||||||
|
myscale:
|
||||||
|
container_name: myscale
|
||||||
|
image: myscale/myscaledb:1.6.4
|
||||||
|
profiles:
|
||||||
|
- myscale
|
||||||
|
restart: always
|
||||||
|
tty: true
|
||||||
|
volumes:
|
||||||
|
- ./volumes/myscale/data:/var/lib/clickhouse
|
||||||
|
- ./volumes/myscale/log:/var/log/clickhouse-server
|
||||||
|
- ./volumes/myscale/config/users.d/custom_users_config.xml:/etc/clickhouse-server/users.d/custom_users_config.xml
|
||||||
|
ports:
|
||||||
|
- ${MYSCALE_PORT:-8123}:${MYSCALE_PORT:-8123}
|
||||||
|
|
||||||
|
# Matrixone vector store.
|
||||||
|
matrixone:
|
||||||
|
hostname: matrixone
|
||||||
|
image: matrixorigin/matrixone:2.1.1
|
||||||
|
profiles:
|
||||||
|
- matrixone
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./volumes/matrixone/data:/mo-data
|
||||||
|
ports:
|
||||||
|
- ${MATRIXONE_PORT:-6001}:${MATRIXONE_PORT:-6001}
|
||||||
|
|
||||||
|
# https://www.elastic.co/guide/en/elasticsearch/reference/current/settings.html
|
||||||
|
# https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html#docker-prod-prerequisites
|
||||||
|
elasticsearch:
|
||||||
|
image: docker.elastic.co/elasticsearch/elasticsearch:8.14.3
|
||||||
|
container_name: elasticsearch
|
||||||
|
profiles:
|
||||||
|
- elasticsearch
|
||||||
|
- elasticsearch-ja
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./elasticsearch/docker-entrypoint.sh:/docker-entrypoint-mount.sh
|
||||||
|
- dify_es01_data:/usr/share/elasticsearch/data
|
||||||
|
environment:
|
||||||
|
ELASTIC_PASSWORD: ${ELASTICSEARCH_PASSWORD:-elastic}
|
||||||
|
VECTOR_STORE: ${VECTOR_STORE:-}
|
||||||
|
cluster.name: dify-es-cluster
|
||||||
|
node.name: dify-es0
|
||||||
|
discovery.type: single-node
|
||||||
|
xpack.license.self_generated.type: basic
|
||||||
|
xpack.security.enabled: "true"
|
||||||
|
xpack.security.enrollment.enabled: "false"
|
||||||
|
xpack.security.http.ssl.enabled: "false"
|
||||||
|
ports:
|
||||||
|
- ${ELASTICSEARCH_PORT:-9200}:9200
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: 2g
|
||||||
|
entrypoint: ["sh", "-c", "sh /docker-entrypoint-mount.sh"]
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
["CMD", "curl", "-s", "http://localhost:9200/_cluster/health?pretty"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 50
|
||||||
|
|
||||||
|
# https://www.elastic.co/guide/en/kibana/current/docker.html
|
||||||
|
# https://www.elastic.co/guide/en/kibana/current/settings.html
|
||||||
|
kibana:
|
||||||
|
image: docker.elastic.co/kibana/kibana:8.14.3
|
||||||
|
container_name: kibana
|
||||||
|
profiles:
|
||||||
|
- elasticsearch
|
||||||
|
depends_on:
|
||||||
|
- elasticsearch
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY: d1a66dfd-c4d3-4a0a-8290-2abcb83ab3aa
|
||||||
|
NO_PROXY: localhost,127.0.0.1,elasticsearch,kibana
|
||||||
|
XPACK_SECURITY_ENABLED: "true"
|
||||||
|
XPACK_SECURITY_ENROLLMENT_ENABLED: "false"
|
||||||
|
XPACK_SECURITY_HTTP_SSL_ENABLED: "false"
|
||||||
|
XPACK_FLEET_ISAIRGAPPED: "true"
|
||||||
|
I18N_LOCALE: zh-CN
|
||||||
|
SERVER_PORT: "5601"
|
||||||
|
ELASTICSEARCH_HOSTS: http://elasticsearch:9200
|
||||||
|
ports:
|
||||||
|
- ${KIBANA_PORT:-5601}:5601
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD-SHELL", "curl -s http://localhost:5601 >/dev/null || exit 1"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
|
||||||
|
# unstructured .
|
||||||
|
# (if used, you need to set ETL_TYPE to Unstructured in the api & worker service.)
|
||||||
|
unstructured:
|
||||||
|
image: downloads.unstructured.io/unstructured-io/unstructured-api:latest
|
||||||
|
profiles:
|
||||||
|
- unstructured
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- ./volumes/unstructured:/app/data
|
||||||
|
|
||||||
|
networks:
|
||||||
|
# create a network between sandbox, api and ssrf_proxy, and can not access outside.
|
||||||
|
ssrf_proxy_network:
|
||||||
|
driver: bridge
|
||||||
|
internal: true
|
||||||
|
milvus:
|
||||||
|
driver: bridge
|
||||||
|
opensearch-net:
|
||||||
|
driver: bridge
|
||||||
|
internal: true
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
oradata:
|
||||||
|
dify_es01_data:
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
services:
|
services:
|
||||||
# The postgres database.
|
# The postgres database.
|
||||||
db:
|
db_postgres:
|
||||||
image: postgres:15-alpine
|
image: postgres:15-alpine
|
||||||
|
profiles:
|
||||||
|
- ""
|
||||||
|
- postgresql
|
||||||
restart: always
|
restart: always
|
||||||
env_file:
|
env_file:
|
||||||
- ./middleware.env
|
- ./middleware.env
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-difyai123456}
|
POSTGRES_PASSWORD: ${DB_PASSWORD:-difyai123456}
|
||||||
POSTGRES_DB: ${POSTGRES_DB:-dify}
|
POSTGRES_DB: ${DB_DATABASE:-dify}
|
||||||
PGDATA: ${PGDATA:-/var/lib/postgresql/data/pgdata}
|
PGDATA: ${PGDATA:-/var/lib/postgresql/data/pgdata}
|
||||||
command: >
|
command: >
|
||||||
postgres -c 'max_connections=${POSTGRES_MAX_CONNECTIONS:-100}'
|
postgres -c 'max_connections=${POSTGRES_MAX_CONNECTIONS:-100}'
|
||||||
@@ -15,27 +18,89 @@ services:
|
|||||||
-c 'work_mem=${POSTGRES_WORK_MEM:-4MB}'
|
-c 'work_mem=${POSTGRES_WORK_MEM:-4MB}'
|
||||||
-c 'maintenance_work_mem=${POSTGRES_MAINTENANCE_WORK_MEM:-64MB}'
|
-c 'maintenance_work_mem=${POSTGRES_MAINTENANCE_WORK_MEM:-64MB}'
|
||||||
-c 'effective_cache_size=${POSTGRES_EFFECTIVE_CACHE_SIZE:-4096MB}'
|
-c 'effective_cache_size=${POSTGRES_EFFECTIVE_CACHE_SIZE:-4096MB}'
|
||||||
|
-c 'statement_timeout=${POSTGRES_STATEMENT_TIMEOUT:-0}'
|
||||||
|
-c 'idle_in_transaction_session_timeout=${POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT:-0}'
|
||||||
volumes:
|
volumes:
|
||||||
- ./volumes/db/data:/var/lib/postgresql/data
|
- ${PGDATA_HOST_VOLUME:-./volumes/db/data}:/var/lib/postgresql/data
|
||||||
ports:
|
ports:
|
||||||
- "${EXPOSE_POSTGRES_PORT:-5432}:5432"
|
- "${EXPOSE_POSTGRES_PORT:-5432}:5432"
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
[
|
||||||
|
"CMD",
|
||||||
|
"pg_isready",
|
||||||
|
"-h",
|
||||||
|
"db_postgres",
|
||||||
|
"-U",
|
||||||
|
"${DB_USERNAME:-postgres}",
|
||||||
|
"-d",
|
||||||
|
"${DB_DATABASE:-dify}",
|
||||||
|
]
|
||||||
|
interval: 1s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 30
|
||||||
|
|
||||||
|
db_mysql:
|
||||||
|
image: mysql:8.0
|
||||||
|
profiles:
|
||||||
|
- mysql
|
||||||
|
restart: always
|
||||||
|
env_file:
|
||||||
|
- ./middleware.env
|
||||||
|
environment:
|
||||||
|
MYSQL_ROOT_PASSWORD: ${DB_PASSWORD:-difyai123456}
|
||||||
|
MYSQL_DATABASE: ${DB_DATABASE:-dify}
|
||||||
|
command: >
|
||||||
|
--max_connections=1000
|
||||||
|
--innodb_buffer_pool_size=${MYSQL_INNODB_BUFFER_POOL_SIZE:-512M}
|
||||||
|
--innodb_log_file_size=${MYSQL_INNODB_LOG_FILE_SIZE:-128M}
|
||||||
|
--innodb_flush_log_at_trx_commit=${MYSQL_INNODB_FLUSH_LOG_AT_TRX_COMMIT:-2}
|
||||||
|
volumes:
|
||||||
|
- ${MYSQL_HOST_VOLUME:-./volumes/mysql/data}:/var/lib/mysql
|
||||||
|
ports:
|
||||||
|
- "${EXPOSE_MYSQL_PORT:-3306}:3306"
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
[
|
||||||
|
"CMD",
|
||||||
|
"mysqladmin",
|
||||||
|
"ping",
|
||||||
|
"-u",
|
||||||
|
"root",
|
||||||
|
"-p${DB_PASSWORD:-difyai123456}",
|
||||||
|
]
|
||||||
|
interval: 1s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 30
|
||||||
|
|
||||||
# The redis cache.
|
# The redis cache.
|
||||||
redis:
|
redis:
|
||||||
image: redis:6-alpine
|
image: redis:6-alpine
|
||||||
restart: always
|
restart: always
|
||||||
|
env_file:
|
||||||
|
- ./middleware.env
|
||||||
|
environment:
|
||||||
|
REDISCLI_AUTH: ${REDIS_PASSWORD:-difyai123456}
|
||||||
volumes:
|
volumes:
|
||||||
# Mount the redis data directory to the container.
|
# Mount the redis data directory to the container.
|
||||||
- ./volumes/redis/data:/data
|
- ${REDIS_HOST_VOLUME:-./volumes/redis/data}:/data
|
||||||
# Set the redis password when startup redis server.
|
# Set the redis password when startup redis server.
|
||||||
command: redis-server --requirepass difyai123456
|
command: redis-server --requirepass ${REDIS_PASSWORD:-difyai123456}
|
||||||
ports:
|
ports:
|
||||||
- "${EXPOSE_REDIS_PORT:-6379}:6379"
|
- "${EXPOSE_REDIS_PORT:-6379}:6379"
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
[
|
||||||
|
"CMD-SHELL",
|
||||||
|
"redis-cli -a ${REDIS_PASSWORD:-difyai123456} ping | grep -q PONG",
|
||||||
|
]
|
||||||
|
|
||||||
# The DifySandbox
|
# The DifySandbox
|
||||||
sandbox:
|
sandbox:
|
||||||
image: langgenius/dify-sandbox:0.2.6
|
image: langgenius/dify-sandbox:0.2.12
|
||||||
restart: always
|
restart: always
|
||||||
|
env_file:
|
||||||
|
- ./middleware.env
|
||||||
environment:
|
environment:
|
||||||
# The DifySandbox configurations
|
# The DifySandbox configurations
|
||||||
# Make sure you are changing this key for your deployment with a strong key.
|
# Make sure you are changing this key for your deployment with a strong key.
|
||||||
@@ -47,21 +112,93 @@ services:
|
|||||||
HTTP_PROXY: ${SANDBOX_HTTP_PROXY:-http://ssrf_proxy:3128}
|
HTTP_PROXY: ${SANDBOX_HTTP_PROXY:-http://ssrf_proxy:3128}
|
||||||
HTTPS_PROXY: ${SANDBOX_HTTPS_PROXY:-http://ssrf_proxy:3128}
|
HTTPS_PROXY: ${SANDBOX_HTTPS_PROXY:-http://ssrf_proxy:3128}
|
||||||
SANDBOX_PORT: ${SANDBOX_PORT:-8194}
|
SANDBOX_PORT: ${SANDBOX_PORT:-8194}
|
||||||
|
PIP_MIRROR_URL: ${PIP_MIRROR_URL:-}
|
||||||
volumes:
|
volumes:
|
||||||
- ./volumes/sandbox/dependencies:/dependencies
|
- ./volumes/sandbox/dependencies:/dependencies
|
||||||
|
- ./volumes/sandbox/conf:/conf
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:8194/health"]
|
||||||
networks:
|
networks:
|
||||||
- ssrf_proxy_network
|
- ssrf_proxy_network
|
||||||
|
|
||||||
|
# plugin daemon
|
||||||
|
plugin_daemon:
|
||||||
|
image: langgenius/dify-plugin-daemon:0.5.2-local
|
||||||
|
restart: always
|
||||||
|
env_file:
|
||||||
|
- ./middleware.env
|
||||||
|
environment:
|
||||||
|
# Use the shared environment variables.
|
||||||
|
DB_DATABASE: ${DB_PLUGIN_DATABASE:-dify_plugin}
|
||||||
|
REDIS_HOST: ${REDIS_HOST:-redis}
|
||||||
|
REDIS_PORT: ${REDIS_PORT:-6379}
|
||||||
|
REDIS_PASSWORD: ${REDIS_PASSWORD:-difyai123456}
|
||||||
|
SERVER_PORT: ${PLUGIN_DAEMON_PORT:-5002}
|
||||||
|
SERVER_KEY: ${PLUGIN_DAEMON_KEY:-lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi}
|
||||||
|
MAX_PLUGIN_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800}
|
||||||
|
PPROF_ENABLED: ${PLUGIN_PPROF_ENABLED:-false}
|
||||||
|
DIFY_INNER_API_URL: ${PLUGIN_DIFY_INNER_API_URL:-http://host.docker.internal:5001}
|
||||||
|
DIFY_INNER_API_KEY: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1}
|
||||||
|
PLUGIN_REMOTE_INSTALLING_HOST: ${PLUGIN_DEBUGGING_HOST:-0.0.0.0}
|
||||||
|
PLUGIN_REMOTE_INSTALLING_PORT: ${PLUGIN_DEBUGGING_PORT:-5003}
|
||||||
|
PLUGIN_WORKING_PATH: ${PLUGIN_WORKING_PATH:-/app/storage/cwd}
|
||||||
|
PYTHON_ENV_INIT_TIMEOUT: ${PLUGIN_PYTHON_ENV_INIT_TIMEOUT:-120}
|
||||||
|
PLUGIN_MAX_EXECUTION_TIMEOUT: ${PLUGIN_MAX_EXECUTION_TIMEOUT:-600}
|
||||||
|
PIP_MIRROR_URL: ${PIP_MIRROR_URL:-}
|
||||||
|
PLUGIN_STORAGE_TYPE: ${PLUGIN_STORAGE_TYPE:-local}
|
||||||
|
PLUGIN_STORAGE_LOCAL_ROOT: ${PLUGIN_STORAGE_LOCAL_ROOT:-/app/storage}
|
||||||
|
PLUGIN_INSTALLED_PATH: ${PLUGIN_INSTALLED_PATH:-plugin}
|
||||||
|
PLUGIN_PACKAGE_CACHE_PATH: ${PLUGIN_PACKAGE_CACHE_PATH:-plugin_packages}
|
||||||
|
PLUGIN_MEDIA_CACHE_PATH: ${PLUGIN_MEDIA_CACHE_PATH:-assets}
|
||||||
|
PLUGIN_STORAGE_OSS_BUCKET: ${PLUGIN_STORAGE_OSS_BUCKET:-}
|
||||||
|
S3_USE_AWS: ${PLUGIN_S3_USE_AWS:-false}
|
||||||
|
S3_USE_AWS_MANAGED_IAM: ${PLUGIN_S3_USE_AWS_MANAGED_IAM:-false}
|
||||||
|
S3_ENDPOINT: ${PLUGIN_S3_ENDPOINT:-}
|
||||||
|
S3_USE_PATH_STYLE: ${PLUGIN_S3_USE_PATH_STYLE:-false}
|
||||||
|
AWS_ACCESS_KEY: ${PLUGIN_AWS_ACCESS_KEY:-}
|
||||||
|
AWS_SECRET_KEY: ${PLUGIN_AWS_SECRET_KEY:-}
|
||||||
|
AWS_REGION: ${PLUGIN_AWS_REGION:-}
|
||||||
|
AZURE_BLOB_STORAGE_CONNECTION_STRING: ${PLUGIN_AZURE_BLOB_STORAGE_CONNECTION_STRING:-}
|
||||||
|
AZURE_BLOB_STORAGE_CONTAINER_NAME: ${PLUGIN_AZURE_BLOB_STORAGE_CONTAINER_NAME:-}
|
||||||
|
TENCENT_COS_SECRET_KEY: ${PLUGIN_TENCENT_COS_SECRET_KEY:-}
|
||||||
|
TENCENT_COS_SECRET_ID: ${PLUGIN_TENCENT_COS_SECRET_ID:-}
|
||||||
|
TENCENT_COS_REGION: ${PLUGIN_TENCENT_COS_REGION:-}
|
||||||
|
ALIYUN_OSS_REGION: ${PLUGIN_ALIYUN_OSS_REGION:-}
|
||||||
|
ALIYUN_OSS_ENDPOINT: ${PLUGIN_ALIYUN_OSS_ENDPOINT:-}
|
||||||
|
ALIYUN_OSS_ACCESS_KEY_ID: ${PLUGIN_ALIYUN_OSS_ACCESS_KEY_ID:-}
|
||||||
|
ALIYUN_OSS_ACCESS_KEY_SECRET: ${PLUGIN_ALIYUN_OSS_ACCESS_KEY_SECRET:-}
|
||||||
|
ALIYUN_OSS_AUTH_VERSION: ${PLUGIN_ALIYUN_OSS_AUTH_VERSION:-v4}
|
||||||
|
ALIYUN_OSS_PATH: ${PLUGIN_ALIYUN_OSS_PATH:-}
|
||||||
|
VOLCENGINE_TOS_ENDPOINT: ${PLUGIN_VOLCENGINE_TOS_ENDPOINT:-}
|
||||||
|
VOLCENGINE_TOS_ACCESS_KEY: ${PLUGIN_VOLCENGINE_TOS_ACCESS_KEY:-}
|
||||||
|
VOLCENGINE_TOS_SECRET_KEY: ${PLUGIN_VOLCENGINE_TOS_SECRET_KEY:-}
|
||||||
|
VOLCENGINE_TOS_REGION: ${PLUGIN_VOLCENGINE_TOS_REGION:-}
|
||||||
|
THIRD_PARTY_SIGNATURE_VERIFICATION_ENABLED: true
|
||||||
|
THIRD_PARTY_SIGNATURE_VERIFICATION_PUBLIC_KEYS: /app/keys/publickey.pem
|
||||||
|
FORCE_VERIFYING_SIGNATURE: false
|
||||||
|
ports:
|
||||||
|
- "${EXPOSE_PLUGIN_DAEMON_PORT:-5002}:${PLUGIN_DAEMON_PORT:-5002}"
|
||||||
|
- "${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}:${PLUGIN_DEBUGGING_PORT:-5003}"
|
||||||
|
volumes:
|
||||||
|
- ./volumes/plugin_daemon:/app/storage
|
||||||
|
|
||||||
# ssrf_proxy server
|
# ssrf_proxy server
|
||||||
# for more information, please refer to
|
# for more information, please refer to
|
||||||
# https://docs.dify.ai/learn-more/faq/self-host-faq#id-18.-why-is-ssrf_proxy-needed
|
# https://docs.dify.ai/learn-more/faq/install-faq#18-why-is-ssrf-proxy-needed%3F
|
||||||
ssrf_proxy:
|
ssrf_proxy:
|
||||||
image: ubuntu/squid:latest
|
image: ubuntu/squid:latest
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
- ./ssrf_proxy/squid.conf.template:/etc/squid/squid.conf.template
|
- ./ssrf_proxy/squid.conf.template:/etc/squid/squid.conf.template
|
||||||
- ./ssrf_proxy/docker-entrypoint.sh:/docker-entrypoint-mount.sh
|
- ./ssrf_proxy/docker-entrypoint.sh:/docker-entrypoint-mount.sh
|
||||||
entrypoint: [ "sh", "-c", "cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh" ]
|
entrypoint:
|
||||||
|
[
|
||||||
|
"sh",
|
||||||
|
"-c",
|
||||||
|
"cp /docker-entrypoint-mount.sh /docker-entrypoint.sh && sed -i 's/\r$$//' /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh && /docker-entrypoint.sh",
|
||||||
|
]
|
||||||
|
env_file:
|
||||||
|
- ./middleware.env
|
||||||
environment:
|
environment:
|
||||||
# pls clearly modify the squid env vars to fit your network environment.
|
# pls clearly modify the squid env vars to fit your network environment.
|
||||||
HTTP_PORT: ${SSRF_HTTP_PORT:-3128}
|
HTTP_PORT: ${SSRF_HTTP_PORT:-3128}
|
||||||
@@ -78,13 +215,14 @@ services:
|
|||||||
|
|
||||||
# The Weaviate vector store.
|
# The Weaviate vector store.
|
||||||
weaviate:
|
weaviate:
|
||||||
image: semitechnologies/weaviate:1.19.0
|
image: semitechnologies/weaviate:1.27.0
|
||||||
profiles:
|
profiles:
|
||||||
|
- ""
|
||||||
- weaviate
|
- weaviate
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
# Mount the Weaviate data directory to the container.
|
# Mount the Weaviate data directory to the container.
|
||||||
- ./volumes/weaviate:/var/lib/weaviate
|
- ${WEAVIATE_HOST_VOLUME:-./volumes/weaviate}:/var/lib/weaviate
|
||||||
env_file:
|
env_file:
|
||||||
- ./middleware.env
|
- ./middleware.env
|
||||||
environment:
|
environment:
|
||||||
@@ -100,8 +238,10 @@ services:
|
|||||||
AUTHENTICATION_APIKEY_USERS: ${WEAVIATE_AUTHENTICATION_APIKEY_USERS:-hello@dify.ai}
|
AUTHENTICATION_APIKEY_USERS: ${WEAVIATE_AUTHENTICATION_APIKEY_USERS:-hello@dify.ai}
|
||||||
AUTHORIZATION_ADMINLIST_ENABLED: ${WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED:-true}
|
AUTHORIZATION_ADMINLIST_ENABLED: ${WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED:-true}
|
||||||
AUTHORIZATION_ADMINLIST_USERS: ${WEAVIATE_AUTHORIZATION_ADMINLIST_USERS:-hello@dify.ai}
|
AUTHORIZATION_ADMINLIST_USERS: ${WEAVIATE_AUTHORIZATION_ADMINLIST_USERS:-hello@dify.ai}
|
||||||
|
DISABLE_TELEMETRY: ${WEAVIATE_DISABLE_TELEMETRY:-false}
|
||||||
ports:
|
ports:
|
||||||
- "${EXPOSE_WEAVIATE_PORT:-8080}:8080"
|
- "${EXPOSE_WEAVIATE_PORT:-8080}:8080"
|
||||||
|
- "${EXPOSE_WEAVIATE_GRPC_PORT:-50051}:50051"
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
# create a network between sandbox, api and ssrf_proxy, and can not access outside.
|
# create a network between sandbox, api and ssrf_proxy, and can not access outside.
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 170 KiB |
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
if [ "${VECTOR_STORE}" = "elasticsearch-ja" ]; then
|
||||||
|
# Check if the ICU tokenizer plugin is installed
|
||||||
|
if ! /usr/share/elasticsearch/bin/elasticsearch-plugin list | grep -q analysis-icu; then
|
||||||
|
printf '%s\n' "Installing the ICU tokenizer plugin"
|
||||||
|
if ! /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-icu; then
|
||||||
|
printf '%s\n' "Failed to install the ICU tokenizer plugin"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# Check if the Japanese language analyzer plugin is installed
|
||||||
|
if ! /usr/share/elasticsearch/bin/elasticsearch-plugin list | grep -q analysis-kuromoji; then
|
||||||
|
printf '%s\n' "Installing the Japanese language analyzer plugin"
|
||||||
|
if ! /usr/share/elasticsearch/bin/elasticsearch-plugin install analysis-kuromoji; then
|
||||||
|
printf '%s\n' "Failed to install the Japanese language analyzer plugin"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run the original entrypoint script
|
||||||
|
exec /bin/tini -- /usr/local/bin/docker-entrypoint.sh
|
||||||
@@ -0,0 +1,112 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
def parse_env_example(file_path):
|
||||||
|
"""
|
||||||
|
Parses the .env.example file and returns a dictionary with variable names as keys and default values as values.
|
||||||
|
"""
|
||||||
|
env_vars = {}
|
||||||
|
with open(file_path, "r") as f:
|
||||||
|
for line_number, line in enumerate(f, 1):
|
||||||
|
line = line.strip()
|
||||||
|
# Ignore empty lines and comments
|
||||||
|
if not line or line.startswith("#"):
|
||||||
|
continue
|
||||||
|
# Use regex to parse KEY=VALUE
|
||||||
|
match = re.match(r"^([^=]+)=(.*)$", line)
|
||||||
|
if match:
|
||||||
|
key = match.group(1).strip()
|
||||||
|
value = match.group(2).strip()
|
||||||
|
# Remove possible quotes around the value
|
||||||
|
if (value.startswith('"') and value.endswith('"')) or (
|
||||||
|
value.startswith("'") and value.endswith("'")
|
||||||
|
):
|
||||||
|
value = value[1:-1]
|
||||||
|
env_vars[key] = value
|
||||||
|
else:
|
||||||
|
print(f"Warning: Unable to parse line {line_number}: {line}")
|
||||||
|
return env_vars
|
||||||
|
|
||||||
|
|
||||||
|
def generate_shared_env_block(env_vars, anchor_name="shared-api-worker-env"):
|
||||||
|
"""
|
||||||
|
Generates a shared environment variables block as a YAML string.
|
||||||
|
"""
|
||||||
|
lines = [f"x-shared-env: &{anchor_name}"]
|
||||||
|
for key, default in env_vars.items():
|
||||||
|
if key == "COMPOSE_PROFILES":
|
||||||
|
continue
|
||||||
|
# If default value is empty, use ${KEY:-}
|
||||||
|
if default == "":
|
||||||
|
lines.append(f" {key}: ${{{key}:-}}")
|
||||||
|
else:
|
||||||
|
# If default value contains special characters, wrap it in quotes
|
||||||
|
if re.search(r"[:\s]", default):
|
||||||
|
default = f"{default}"
|
||||||
|
lines.append(f" {key}: ${{{key}:-{default}}}")
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
def insert_shared_env(template_path, output_path, shared_env_block, header_comments):
|
||||||
|
"""
|
||||||
|
Inserts the shared environment variables block and header comments into the template file,
|
||||||
|
removing any existing x-shared-env anchors, and generates the final docker-compose.yaml file.
|
||||||
|
"""
|
||||||
|
with open(template_path, "r") as f:
|
||||||
|
template_content = f.read()
|
||||||
|
|
||||||
|
# Remove existing x-shared-env: &shared-api-worker-env lines
|
||||||
|
template_content = re.sub(
|
||||||
|
r"^x-shared-env: &shared-api-worker-env\s*\n?",
|
||||||
|
"",
|
||||||
|
template_content,
|
||||||
|
flags=re.MULTILINE,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Prepare the final content with header comments and shared env block
|
||||||
|
final_content = f"{header_comments}\n{shared_env_block}\n\n{template_content}"
|
||||||
|
|
||||||
|
with open(output_path, "w") as f:
|
||||||
|
f.write(final_content)
|
||||||
|
print(f"Generated {output_path}")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
env_example_path = ".env.example"
|
||||||
|
template_path = "docker-compose-template.yaml"
|
||||||
|
output_path = "docker-compose.yaml"
|
||||||
|
anchor_name = "shared-api-worker-env" # Can be modified as needed
|
||||||
|
|
||||||
|
# Define header comments to be added at the top of docker-compose.yaml
|
||||||
|
header_comments = (
|
||||||
|
"# ==================================================================\n"
|
||||||
|
"# WARNING: This file is auto-generated by generate_docker_compose\n"
|
||||||
|
"# Do not modify this file directly. Instead, update the .env.example\n"
|
||||||
|
"# or docker-compose-template.yaml and regenerate this file.\n"
|
||||||
|
"# ==================================================================\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check if required files exist
|
||||||
|
for path in [env_example_path, template_path]:
|
||||||
|
if not os.path.isfile(path):
|
||||||
|
print(f"Error: File {path} does not exist.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Parse .env.example file
|
||||||
|
env_vars = parse_env_example(env_example_path)
|
||||||
|
|
||||||
|
if not env_vars:
|
||||||
|
print("Warning: No environment variables found in .env.example.")
|
||||||
|
|
||||||
|
# Generate shared environment variables block
|
||||||
|
shared_env_block = generate_shared_env_block(env_vars, anchor_name)
|
||||||
|
|
||||||
|
# Insert shared environment variables block and header comments into the template
|
||||||
|
insert_shared_env(template_path, output_path, shared_env_block, header_comments)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# IRIS configuration flag file
|
||||||
|
IRIS_CONFIG_DONE="/opt/iris/.iris-configured"
|
||||||
|
|
||||||
|
# Function to configure IRIS
|
||||||
|
configure_iris() {
|
||||||
|
echo "Configuring IRIS for first-time setup..."
|
||||||
|
|
||||||
|
# Wait for IRIS to be fully started
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
# Execute the initialization script
|
||||||
|
iris session IRIS < /iris-init.script
|
||||||
|
|
||||||
|
# Mark configuration as done
|
||||||
|
touch "$IRIS_CONFIG_DONE"
|
||||||
|
|
||||||
|
echo "IRIS configuration completed."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Start IRIS in background for initial configuration if not already configured
|
||||||
|
if [ ! -f "$IRIS_CONFIG_DONE" ]; then
|
||||||
|
echo "First-time IRIS setup detected. Starting IRIS for configuration..."
|
||||||
|
|
||||||
|
# Start IRIS
|
||||||
|
iris start IRIS
|
||||||
|
|
||||||
|
# Configure IRIS
|
||||||
|
configure_iris
|
||||||
|
|
||||||
|
# Stop IRIS
|
||||||
|
iris stop IRIS quietly
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run the original IRIS entrypoint
|
||||||
|
exec /iris-main "$@"
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// Switch to the %SYS namespace to modify system settings
|
||||||
|
set $namespace="%SYS"
|
||||||
|
|
||||||
|
// Set predefined user passwords to never expire (default password: SYS)
|
||||||
|
Do ##class(Security.Users).UnExpireUserPasswords("*")
|
||||||
|
|
||||||
|
// Change the default password
|
||||||
|
Do $SYSTEM.Security.ChangePassword("_SYSTEM","Dify@1234")
|
||||||
|
|
||||||
|
// Install the Japanese locale (default is English since the container is Ubuntu-based)
|
||||||
|
// Do ##class(Config.NLS.Locales).Install("jpuw")
|
||||||
@@ -1,13 +1,20 @@
|
|||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Environment Variables for db Service
|
# Environment Variables for db Service
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
PGUSER=postgres
|
# Database Configuration
|
||||||
# The password for the default postgres user.
|
# Database type, supported values are `postgresql` and `mysql`
|
||||||
POSTGRES_PASSWORD=difyai123456
|
DB_TYPE=postgresql
|
||||||
# The name of the default postgres database.
|
# For MySQL, only `root` user is supported for now
|
||||||
POSTGRES_DB=dify
|
DB_USERNAME=postgres
|
||||||
|
DB_PASSWORD=difyai123456
|
||||||
|
DB_HOST=db_postgres
|
||||||
|
DB_PORT=5432
|
||||||
|
DB_DATABASE=dify
|
||||||
|
|
||||||
|
# PostgreSQL Configuration
|
||||||
# postgres data directory
|
# postgres data directory
|
||||||
PGDATA=/var/lib/postgresql/data/pgdata
|
PGDATA=/var/lib/postgresql/data/pgdata
|
||||||
|
PGDATA_HOST_VOLUME=./volumes/db/data
|
||||||
|
|
||||||
# Maximum number of connections to the database
|
# Maximum number of connections to the database
|
||||||
# Default is 100
|
# Default is 100
|
||||||
@@ -39,8 +46,55 @@ POSTGRES_MAINTENANCE_WORK_MEM=64MB
|
|||||||
# Reference: https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-EFFECTIVE-CACHE-SIZE
|
# Reference: https://www.postgresql.org/docs/current/runtime-config-query.html#GUC-EFFECTIVE-CACHE-SIZE
|
||||||
POSTGRES_EFFECTIVE_CACHE_SIZE=4096MB
|
POSTGRES_EFFECTIVE_CACHE_SIZE=4096MB
|
||||||
|
|
||||||
|
# Sets the maximum allowed duration of any statement before termination.
|
||||||
|
# Default is 0 (no timeout).
|
||||||
|
#
|
||||||
|
# Reference: https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-STATEMENT-TIMEOUT
|
||||||
|
# A value of 0 prevents the server from timing out statements.
|
||||||
|
POSTGRES_STATEMENT_TIMEOUT=0
|
||||||
|
|
||||||
|
# Sets the maximum allowed duration of any idle in-transaction session before termination.
|
||||||
|
# Default is 0 (no timeout).
|
||||||
|
#
|
||||||
|
# Reference: https://www.postgresql.org/docs/current/runtime-config-client.html#GUC-IDLE-IN-TRANSACTION-SESSION-TIMEOUT
|
||||||
|
# A value of 0 prevents the server from terminating idle sessions.
|
||||||
|
POSTGRES_IDLE_IN_TRANSACTION_SESSION_TIMEOUT=0
|
||||||
|
|
||||||
|
# MySQL Configuration
|
||||||
|
# MySQL data directory host volume
|
||||||
|
MYSQL_HOST_VOLUME=./volumes/mysql/data
|
||||||
|
|
||||||
|
# MySQL Performance Configuration
|
||||||
|
# Maximum number of connections to MySQL
|
||||||
|
# Default is 1000
|
||||||
|
MYSQL_MAX_CONNECTIONS=1000
|
||||||
|
|
||||||
|
# InnoDB buffer pool size
|
||||||
|
# Default is 512M
|
||||||
|
# Recommended value: 70-80% of available memory for dedicated MySQL server
|
||||||
|
# Reference: https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_buffer_pool_size
|
||||||
|
MYSQL_INNODB_BUFFER_POOL_SIZE=512M
|
||||||
|
|
||||||
|
# InnoDB log file size
|
||||||
|
# Default is 128M
|
||||||
|
# Reference: https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_log_file_size
|
||||||
|
MYSQL_INNODB_LOG_FILE_SIZE=128M
|
||||||
|
|
||||||
|
# InnoDB flush log at transaction commit
|
||||||
|
# Default is 2 (flush to OS cache, sync every second)
|
||||||
|
# Options: 0 (no flush), 1 (flush and sync), 2 (flush to OS cache)
|
||||||
|
# Reference: https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit
|
||||||
|
MYSQL_INNODB_FLUSH_LOG_AT_TRX_COMMIT=2
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# Environment Variables for redis Service
|
||||||
|
# -----------------------------
|
||||||
|
REDIS_HOST_VOLUME=./volumes/redis/data
|
||||||
|
REDIS_PASSWORD=difyai123456
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Environment Variables for sandbox Service
|
# Environment Variables for sandbox Service
|
||||||
|
# ------------------------------
|
||||||
SANDBOX_API_KEY=dify-sandbox
|
SANDBOX_API_KEY=dify-sandbox
|
||||||
SANDBOX_GIN_MODE=release
|
SANDBOX_GIN_MODE=release
|
||||||
SANDBOX_WORKER_TIMEOUT=15
|
SANDBOX_WORKER_TIMEOUT=15
|
||||||
@@ -48,7 +102,6 @@ SANDBOX_ENABLE_NETWORK=true
|
|||||||
SANDBOX_HTTP_PROXY=http://ssrf_proxy:3128
|
SANDBOX_HTTP_PROXY=http://ssrf_proxy:3128
|
||||||
SANDBOX_HTTPS_PROXY=http://ssrf_proxy:3128
|
SANDBOX_HTTPS_PROXY=http://ssrf_proxy:3128
|
||||||
SANDBOX_PORT=8194
|
SANDBOX_PORT=8194
|
||||||
# ------------------------------
|
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Environment Variables for ssrf_proxy Service
|
# Environment Variables for ssrf_proxy Service
|
||||||
@@ -70,12 +123,114 @@ WEAVIATE_AUTHENTICATION_APIKEY_ALLOWED_KEYS=WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih
|
|||||||
WEAVIATE_AUTHENTICATION_APIKEY_USERS=hello@dify.ai
|
WEAVIATE_AUTHENTICATION_APIKEY_USERS=hello@dify.ai
|
||||||
WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED=true
|
WEAVIATE_AUTHORIZATION_ADMINLIST_ENABLED=true
|
||||||
WEAVIATE_AUTHORIZATION_ADMINLIST_USERS=hello@dify.ai
|
WEAVIATE_AUTHORIZATION_ADMINLIST_USERS=hello@dify.ai
|
||||||
|
WEAVIATE_DISABLE_TELEMETRY=false
|
||||||
|
WEAVIATE_HOST_VOLUME=./volumes/weaviate
|
||||||
|
|
||||||
|
# ------------------------------
|
||||||
|
# Docker Compose profile configuration
|
||||||
|
# ------------------------------
|
||||||
|
# Loaded automatically when running `docker compose --env-file middleware.env ...`.
|
||||||
|
# Controls which DB/vector services start, so no extra `--profile` flag is needed.
|
||||||
|
COMPOSE_PROFILES=${DB_TYPE:-postgresql},weaviate
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Docker Compose Service Expose Host Port Configurations
|
# Docker Compose Service Expose Host Port Configurations
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
EXPOSE_POSTGRES_PORT=5432
|
EXPOSE_POSTGRES_PORT=5432
|
||||||
|
EXPOSE_MYSQL_PORT=3306
|
||||||
EXPOSE_REDIS_PORT=6379
|
EXPOSE_REDIS_PORT=6379
|
||||||
EXPOSE_SANDBOX_PORT=8194
|
EXPOSE_SANDBOX_PORT=8194
|
||||||
EXPOSE_SSRF_PROXY_PORT=3128
|
EXPOSE_SSRF_PROXY_PORT=3128
|
||||||
EXPOSE_WEAVIATE_PORT=8080
|
EXPOSE_WEAVIATE_PORT=8080
|
||||||
|
|
||||||
|
# ------------------------------
|
||||||
|
# Plugin Daemon Configuration
|
||||||
|
# ------------------------------
|
||||||
|
|
||||||
|
DB_PLUGIN_DATABASE=dify_plugin
|
||||||
|
EXPOSE_PLUGIN_DAEMON_PORT=5002
|
||||||
|
PLUGIN_DAEMON_PORT=5002
|
||||||
|
PLUGIN_DAEMON_KEY=lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi
|
||||||
|
PLUGIN_DAEMON_URL=http://host.docker.internal:5002
|
||||||
|
PLUGIN_MAX_PACKAGE_SIZE=52428800
|
||||||
|
PLUGIN_PPROF_ENABLED=false
|
||||||
|
PLUGIN_WORKING_PATH=/app/storage/cwd
|
||||||
|
|
||||||
|
ENDPOINT_URL_TEMPLATE=http://localhost:5002/e/{hook_id}
|
||||||
|
|
||||||
|
PLUGIN_DEBUGGING_PORT=5003
|
||||||
|
PLUGIN_DEBUGGING_HOST=0.0.0.0
|
||||||
|
EXPOSE_PLUGIN_DEBUGGING_HOST=localhost
|
||||||
|
EXPOSE_PLUGIN_DEBUGGING_PORT=5003
|
||||||
|
|
||||||
|
PLUGIN_DIFY_INNER_API_KEY=QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1
|
||||||
|
PLUGIN_DIFY_INNER_API_URL=http://host.docker.internal:5001
|
||||||
|
|
||||||
|
MARKETPLACE_ENABLED=true
|
||||||
|
MARKETPLACE_API_URL=https://marketplace.dify.ai
|
||||||
|
|
||||||
|
FORCE_VERIFYING_SIGNATURE=true
|
||||||
|
|
||||||
|
PLUGIN_PYTHON_ENV_INIT_TIMEOUT=120
|
||||||
|
PLUGIN_MAX_EXECUTION_TIMEOUT=600
|
||||||
|
# PIP_MIRROR_URL=https://pypi.tuna.tsinghua.edu.cn/simple
|
||||||
|
PIP_MIRROR_URL=
|
||||||
|
|
||||||
|
# https://github.com/langgenius/dify-plugin-daemon/blob/main/.env.example
|
||||||
|
# Plugin storage type, local aws_s3 tencent_cos azure_blob
|
||||||
|
PLUGIN_STORAGE_TYPE=local
|
||||||
|
PLUGIN_STORAGE_LOCAL_ROOT=/app/storage
|
||||||
|
PLUGIN_WORKING_PATH=/app/storage/cwd
|
||||||
|
PLUGIN_INSTALLED_PATH=plugin
|
||||||
|
PLUGIN_PACKAGE_CACHE_PATH=plugin_packages
|
||||||
|
PLUGIN_MEDIA_CACHE_PATH=assets
|
||||||
|
# Plugin oss bucket
|
||||||
|
PLUGIN_STORAGE_OSS_BUCKET=
|
||||||
|
# Plugin oss s3 credentials
|
||||||
|
PLUGIN_S3_USE_AWS_MANAGED_IAM=false
|
||||||
|
PLUGIN_S3_USE_AWS=false
|
||||||
|
PLUGIN_S3_ENDPOINT=
|
||||||
|
PLUGIN_S3_USE_PATH_STYLE=false
|
||||||
|
PLUGIN_AWS_ACCESS_KEY=
|
||||||
|
PLUGIN_AWS_SECRET_KEY=
|
||||||
|
PLUGIN_AWS_REGION=
|
||||||
|
# Plugin oss azure blob
|
||||||
|
PLUGIN_AZURE_BLOB_STORAGE_CONTAINER_NAME=
|
||||||
|
PLUGIN_AZURE_BLOB_STORAGE_CONNECTION_STRING=
|
||||||
|
# Plugin oss tencent cos
|
||||||
|
PLUGIN_TENCENT_COS_SECRET_KEY=
|
||||||
|
PLUGIN_TENCENT_COS_SECRET_ID=
|
||||||
|
PLUGIN_TENCENT_COS_REGION=
|
||||||
|
# Plugin oss aliyun oss
|
||||||
|
PLUGIN_ALIYUN_OSS_REGION=
|
||||||
|
PLUGIN_ALIYUN_OSS_ENDPOINT=
|
||||||
|
PLUGIN_ALIYUN_OSS_ACCESS_KEY_ID=
|
||||||
|
PLUGIN_ALIYUN_OSS_ACCESS_KEY_SECRET=
|
||||||
|
PLUGIN_ALIYUN_OSS_AUTH_VERSION=v4
|
||||||
|
PLUGIN_ALIYUN_OSS_PATH=
|
||||||
|
# Plugin oss volcengine tos
|
||||||
|
PLUGIN_VOLCENGINE_TOS_ENDPOINT=
|
||||||
|
PLUGIN_VOLCENGINE_TOS_ACCESS_KEY=
|
||||||
|
PLUGIN_VOLCENGINE_TOS_SECRET_KEY=
|
||||||
|
PLUGIN_VOLCENGINE_TOS_REGION=
|
||||||
|
|
||||||
|
# ------------------------------
|
||||||
|
# Environment Variables for Aliyun SLS (Simple Log Service)
|
||||||
|
# ------------------------------
|
||||||
|
# Aliyun SLS Access Key ID
|
||||||
|
ALIYUN_SLS_ACCESS_KEY_ID=
|
||||||
|
# Aliyun SLS Access Key Secret
|
||||||
|
ALIYUN_SLS_ACCESS_KEY_SECRET=
|
||||||
|
# Aliyun SLS Endpoint (e.g., cn-hangzhou.log.aliyuncs.com)
|
||||||
|
ALIYUN_SLS_ENDPOINT=
|
||||||
|
# Aliyun SLS Region (e.g., cn-hangzhou)
|
||||||
|
ALIYUN_SLS_REGION=
|
||||||
|
# Aliyun SLS Project Name
|
||||||
|
ALIYUN_SLS_PROJECT_NAME=
|
||||||
|
# Aliyun SLS Logstore TTL (default: 365 days, 3650 for permanent storage)
|
||||||
|
ALIYUN_SLS_LOGSTORE_TTL=365
|
||||||
|
# Enable dual-write to both LogStore and SQL database (default: true)
|
||||||
|
LOGSTORE_DUAL_WRITE_ENABLED=true
|
||||||
|
# Enable dual-read fallback to SQL database when LogStore returns no results (default: true)
|
||||||
|
# Useful for migration scenarios where historical data exists only in SQL database
|
||||||
|
LOGSTORE_DUAL_READ_ENABLED=true
|
||||||
@@ -24,11 +24,32 @@ server {
|
|||||||
include proxy.conf;
|
include proxy.conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /explore {
|
||||||
|
proxy_pass http://web:3000;
|
||||||
|
include proxy.conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /e/ {
|
||||||
|
proxy_pass http://plugin_daemon:5002;
|
||||||
|
proxy_set_header Dify-Hook-Url $scheme://$host$request_uri;
|
||||||
|
include proxy.conf;
|
||||||
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
proxy_pass http://web:3000;
|
proxy_pass http://web:3000;
|
||||||
include proxy.conf;
|
include proxy.conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /mcp {
|
||||||
|
proxy_pass http://api:5001;
|
||||||
|
include proxy.conf;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /triggers {
|
||||||
|
proxy_pass http://api:5001;
|
||||||
|
include proxy.conf;
|
||||||
|
}
|
||||||
|
|
||||||
# placeholder for acme challenge location
|
# placeholder for acme challenge location
|
||||||
${ACME_CHALLENGE_LOCATION}
|
${ACME_CHALLENGE_LOCATION}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
HTTPS_CONFIG=''
|
||||||
|
|
||||||
if [ "${NGINX_HTTPS_ENABLED}" = "true" ]; then
|
if [ "${NGINX_HTTPS_ENABLED}" = "true" ]; then
|
||||||
# Check if the certificate and key files for the specified domain exist
|
# Check if the certificate and key files for the specified domain exist
|
||||||
if [ -n "${CERTBOT_DOMAIN}" ] && \
|
if [ -n "${CERTBOT_DOMAIN}" ] && \
|
||||||
@@ -20,6 +22,7 @@ if [ "${NGINX_HTTPS_ENABLED}" = "true" ]; then
|
|||||||
# Substitute the HTTPS_CONFIG in the default.conf.template with content from https.conf.template
|
# Substitute the HTTPS_CONFIG in the default.conf.template with content from https.conf.template
|
||||||
envsubst '${HTTPS_CONFIG}' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf
|
envsubst '${HTTPS_CONFIG}' < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf
|
||||||
fi
|
fi
|
||||||
|
export HTTPS_CONFIG
|
||||||
|
|
||||||
if [ "${NGINX_ENABLE_CERTBOT_CHALLENGE}" = "true" ]; then
|
if [ "${NGINX_ENABLE_CERTBOT_CHALLENGE}" = "true" ]; then
|
||||||
ACME_CHALLENGE_LOCATION='location /.well-known/acme-challenge/ { root /var/www/html; }'
|
ACME_CHALLENGE_LOCATION='location /.well-known/acme-challenge/ { root /var/www/html; }'
|
||||||
@@ -33,7 +36,7 @@ env_vars=$(printenv | cut -d= -f1 | sed 's/^/$/g' | paste -sd, -)
|
|||||||
envsubst "$env_vars" < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf
|
envsubst "$env_vars" < /etc/nginx/nginx.conf.template > /etc/nginx/nginx.conf
|
||||||
envsubst "$env_vars" < /etc/nginx/proxy.conf.template > /etc/nginx/proxy.conf
|
envsubst "$env_vars" < /etc/nginx/proxy.conf.template > /etc/nginx/proxy.conf
|
||||||
|
|
||||||
envsubst < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf
|
envsubst "$env_vars" < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
# Start Nginx using the default entrypoint
|
# Start Nginx using the default entrypoint
|
||||||
exec nginx -g 'daemon off;'
|
exec nginx -g 'daemon off;'
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header X-Forwarded-Port $server_port;
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Connection "";
|
proxy_set_header Connection "";
|
||||||
proxy_buffering off;
|
proxy_buffering off;
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
PG_MAJOR=16
|
||||||
|
|
||||||
|
if [ "${PG_BIGM}" = "true" ]; then
|
||||||
|
# install pg_bigm
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y curl make gcc postgresql-server-dev-${PG_MAJOR}
|
||||||
|
|
||||||
|
curl -LO https://github.com/pgbigm/pg_bigm/archive/refs/tags/v${PG_BIGM_VERSION}.tar.gz
|
||||||
|
tar xf v${PG_BIGM_VERSION}.tar.gz
|
||||||
|
cd pg_bigm-${PG_BIGM_VERSION} || exit 1
|
||||||
|
make USE_PGXS=1 PG_CONFIG=/usr/bin/pg_config
|
||||||
|
make USE_PGXS=1 PG_CONFIG=/usr/bin/pg_config install
|
||||||
|
|
||||||
|
cd - || exit 1
|
||||||
|
rm -rf v${PG_BIGM_VERSION}.tar.gz pg_bigm-${PG_BIGM_VERSION}
|
||||||
|
|
||||||
|
# enable pg_bigm
|
||||||
|
sed -i -e 's/^#\s*shared_preload_libraries.*/shared_preload_libraries = '\''pg_bigm'\''/' /var/lib/postgresql/data/pgdata/postgresql.conf
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run the original entrypoint script
|
||||||
|
exec /usr/local/bin/docker-entrypoint.sh postgres
|
||||||
@@ -7,6 +7,7 @@ acl localnet src 192.168.0.0/16 # RFC 1918 local private network (LAN)
|
|||||||
acl localnet src fc00::/7 # RFC 4193 local private network range
|
acl localnet src fc00::/7 # RFC 4193 local private network range
|
||||||
acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines
|
acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines
|
||||||
acl SSL_ports port 443
|
acl SSL_ports port 443
|
||||||
|
# acl SSL_ports port 1025-65535 # Enable the configuration to resolve this issue: https://github.com/langgenius/dify/issues/12792
|
||||||
acl Safe_ports port 80 # http
|
acl Safe_ports port 80 # http
|
||||||
acl Safe_ports port 21 # ftp
|
acl Safe_ports port 21 # ftp
|
||||||
acl Safe_ports port 443 # https
|
acl Safe_ports port 443 # https
|
||||||
@@ -18,6 +19,8 @@ acl Safe_ports port 488 # gss-http
|
|||||||
acl Safe_ports port 591 # filemaker
|
acl Safe_ports port 591 # filemaker
|
||||||
acl Safe_ports port 777 # multiling http
|
acl Safe_ports port 777 # multiling http
|
||||||
acl CONNECT method CONNECT
|
acl CONNECT method CONNECT
|
||||||
|
acl allowed_domains dstdomain .marketplace.dify.ai
|
||||||
|
http_access allow allowed_domains
|
||||||
http_access deny !Safe_ports
|
http_access deny !Safe_ports
|
||||||
http_access deny CONNECT !SSL_ports
|
http_access deny CONNECT !SSL_ports
|
||||||
http_access allow localhost manager
|
http_access allow localhost manager
|
||||||
@@ -48,3 +51,6 @@ http_port ${REVERSE_PROXY_PORT} accel vhost
|
|||||||
cache_peer ${SANDBOX_HOST} parent ${SANDBOX_PORT} 0 no-query originserver
|
cache_peer ${SANDBOX_HOST} parent ${SANDBOX_PORT} 0 no-query originserver
|
||||||
acl src_all src all
|
acl src_all src all
|
||||||
http_access allow src_all
|
http_access allow src_all
|
||||||
|
|
||||||
|
# Unless the option's size is increased, an error will occur when uploading more than two files.
|
||||||
|
client_request_buffer_max_size 100 MB
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
DB_INITIALISED="/opt/oracle/oradata/dbinit"
|
DB_INITIALIZED="/opt/oracle/oradata/dbinit"
|
||||||
#[ -f ${DB_INITIALISED} ] && exit
|
#[ -f ${DB_INITIALIZED} ] && exit
|
||||||
#touch ${DB_INITIALISED}
|
#touch ${DB_INITIALIZED}
|
||||||
if [ -f ${DB_INITIALISED} ]; then
|
if [ -f ${DB_INITIALIZED} ]; then
|
||||||
echo 'File exists. Standards for have been Init'
|
echo 'File exists. Standards for have been Init'
|
||||||
exit
|
exit
|
||||||
else
|
else
|
||||||
echo 'File does not exist. Standards for first time Strart up this DB'
|
echo 'File does not exist. Standards for first time Start up this DB'
|
||||||
"$ORACLE_HOME"/bin/sqlplus -s "/ as sysdba" @"/opt/oracle/scripts/startup/init_user.script";
|
"$ORACLE_HOME"/bin/sqlplus -s "/ as sysdba" @"/opt/oracle/scripts/startup/init_user.script";
|
||||||
touch ${DB_INITIALISED}
|
touch ${DB_INITIALIZED}
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -5,6 +5,6 @@ create user dify identified by dify DEFAULT TABLESPACE users quota unlimited on
|
|||||||
grant DB_DEVELOPER_ROLE to dify;
|
grant DB_DEVELOPER_ROLE to dify;
|
||||||
|
|
||||||
BEGIN
|
BEGIN
|
||||||
CTX_DDL.CREATE_PREFERENCE('my_chinese_vgram_lexer','CHINESE_VGRAM_LEXER');
|
CTX_DDL.CREATE_PREFERENCE('dify.world_lexer','WORLD_LEXER');
|
||||||
END;
|
END;
|
||||||
/
|
/
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
# PD Configuration File reference:
|
||||||
|
# https://docs.pingcap.com/tidb/stable/pd-configuration-file#pd-configuration-file
|
||||||
|
[replication]
|
||||||
|
max-replicas = 1
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# TiFlash tiflash-learner.toml Configuration File reference:
|
||||||
|
# https://docs.pingcap.com/tidb/stable/tiflash-configuration#configure-the-tiflash-learnertoml-file
|
||||||
|
|
||||||
|
log-file = "/logs/tiflash_tikv.log"
|
||||||
|
|
||||||
|
[server]
|
||||||
|
engine-addr = "tiflash:4030"
|
||||||
|
addr = "0.0.0.0:20280"
|
||||||
|
advertise-addr = "tiflash:20280"
|
||||||
|
status-addr = "tiflash:20292"
|
||||||
|
|
||||||
|
[storage]
|
||||||
|
data-dir = "/data/flash"
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# TiFlash tiflash.toml Configuration File reference:
|
||||||
|
# https://docs.pingcap.com/tidb/stable/tiflash-configuration#configure-the-tiflashtoml-file
|
||||||
|
|
||||||
|
listen_host = "0.0.0.0"
|
||||||
|
path = "/data"
|
||||||
|
|
||||||
|
[flash]
|
||||||
|
tidb_status_addr = "tidb:10080"
|
||||||
|
service_addr = "tiflash:4030"
|
||||||
|
|
||||||
|
[flash.proxy]
|
||||||
|
config = "/tiflash-learner.toml"
|
||||||
|
|
||||||
|
[logger]
|
||||||
|
errorlog = "/logs/tiflash_error.log"
|
||||||
|
log = "/logs/tiflash.log"
|
||||||
|
|
||||||
|
[raft]
|
||||||
|
pd_addr = "pd0:2379"
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
services:
|
||||||
|
pd0:
|
||||||
|
image: pingcap/pd:v8.5.1
|
||||||
|
# ports:
|
||||||
|
# - "2379"
|
||||||
|
volumes:
|
||||||
|
- ./config/pd.toml:/pd.toml:ro
|
||||||
|
- ./volumes/data:/data
|
||||||
|
- ./volumes/logs:/logs
|
||||||
|
command:
|
||||||
|
- --name=pd0
|
||||||
|
- --client-urls=http://0.0.0.0:2379
|
||||||
|
- --peer-urls=http://0.0.0.0:2380
|
||||||
|
- --advertise-client-urls=http://pd0:2379
|
||||||
|
- --advertise-peer-urls=http://pd0:2380
|
||||||
|
- --initial-cluster=pd0=http://pd0:2380
|
||||||
|
- --data-dir=/data/pd
|
||||||
|
- --config=/pd.toml
|
||||||
|
- --log-file=/logs/pd.log
|
||||||
|
restart: on-failure
|
||||||
|
tikv:
|
||||||
|
image: pingcap/tikv:v8.5.1
|
||||||
|
volumes:
|
||||||
|
- ./volumes/data:/data
|
||||||
|
- ./volumes/logs:/logs
|
||||||
|
command:
|
||||||
|
- --addr=0.0.0.0:20160
|
||||||
|
- --advertise-addr=tikv:20160
|
||||||
|
- --status-addr=tikv:20180
|
||||||
|
- --data-dir=/data/tikv
|
||||||
|
- --pd=pd0:2379
|
||||||
|
- --log-file=/logs/tikv.log
|
||||||
|
depends_on:
|
||||||
|
- "pd0"
|
||||||
|
restart: on-failure
|
||||||
|
tidb:
|
||||||
|
image: pingcap/tidb:v8.5.1
|
||||||
|
# ports:
|
||||||
|
# - "4000:4000"
|
||||||
|
volumes:
|
||||||
|
- ./volumes/logs:/logs
|
||||||
|
command:
|
||||||
|
- --advertise-address=tidb
|
||||||
|
- --store=tikv
|
||||||
|
- --path=pd0:2379
|
||||||
|
- --log-file=/logs/tidb.log
|
||||||
|
depends_on:
|
||||||
|
- "tikv"
|
||||||
|
restart: on-failure
|
||||||
|
tiflash:
|
||||||
|
image: pingcap/tiflash:v8.5.1
|
||||||
|
volumes:
|
||||||
|
- ./config/tiflash.toml:/tiflash.toml:ro
|
||||||
|
- ./config/tiflash-learner.toml:/tiflash-learner.toml:ro
|
||||||
|
- ./volumes/data:/data
|
||||||
|
- ./volumes/logs:/logs
|
||||||
|
command:
|
||||||
|
- server
|
||||||
|
- --config-file=/tiflash.toml
|
||||||
|
depends_on:
|
||||||
|
- "tikv"
|
||||||
|
- "tidb"
|
||||||
|
restart: on-failure
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ALTER SYSTEM SET ob_vector_memory_limit_percentage = 30;
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
app:
|
||||||
|
port: 8194
|
||||||
|
debug: True
|
||||||
|
key: dify-sandbox
|
||||||
|
max_workers: 4
|
||||||
|
max_requests: 50
|
||||||
|
worker_timeout: 5
|
||||||
|
python_path: /usr/local/bin/python3
|
||||||
|
enable_network: True # please make sure there is no network risk in your environment
|
||||||
|
allowed_syscalls: # please leave it empty if you have no idea how seccomp works
|
||||||
|
proxy:
|
||||||
|
socks5: ''
|
||||||
|
http: ''
|
||||||
|
https: ''
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
app:
|
||||||
|
port: 8194
|
||||||
|
debug: True
|
||||||
|
key: dify-sandbox
|
||||||
|
max_workers: 4
|
||||||
|
max_requests: 50
|
||||||
|
worker_timeout: 5
|
||||||
|
python_path: /usr/local/bin/python3
|
||||||
|
python_lib_path:
|
||||||
|
- /usr/local/lib/python3.10
|
||||||
|
- /usr/lib/python3.10
|
||||||
|
- /usr/lib/python3
|
||||||
|
- /usr/lib/x86_64-linux-gnu
|
||||||
|
- /etc/ssl/certs/ca-certificates.crt
|
||||||
|
- /etc/nsswitch.conf
|
||||||
|
- /etc/hosts
|
||||||
|
- /etc/resolv.conf
|
||||||
|
- /run/systemd/resolve/stub-resolv.conf
|
||||||
|
- /run/resolvconf/resolv.conf
|
||||||
|
- /etc/localtime
|
||||||
|
- /usr/share/zoneinfo
|
||||||
|
- /etc/timezone
|
||||||
|
# add more paths if needed
|
||||||
|
python_pip_mirror_url: https://pypi.tuna.tsinghua.edu.cn/simple
|
||||||
|
nodejs_path: /usr/local/bin/node
|
||||||
|
enable_network: True
|
||||||
|
allowed_syscalls:
|
||||||
|
- 1
|
||||||
|
- 2
|
||||||
|
- 3
|
||||||
|
# add all the syscalls which you require
|
||||||
|
proxy:
|
||||||
|
socks5: ''
|
||||||
|
http: ''
|
||||||
|
https: ''
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import utils from "../utils.js";
|
||||||
|
|
||||||
|
await utils.cloneOrPullRepo({ repo: "https://github.com/langgenius/dify.git" });
|
||||||
|
await utils.copyDir("./repo/docker", "./code");
|
||||||
|
await utils.removeContainerNames("./code/docker-compose.yaml");
|
||||||
|
await utils.removePorts("./code/docker-compose.yaml");
|
||||||
|
|
||||||
|
await utils.searchReplace(
|
||||||
|
"./code/.env.example",
|
||||||
|
"APP_WEB_URL=",
|
||||||
|
"APP_WEB_URL=https://$(PRIMARY_DOMAIN)"
|
||||||
|
);
|
||||||
|
|
||||||
|
await utils.searchReplace(
|
||||||
|
"./code/.env.example",
|
||||||
|
"SECRET_KEY=sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U",
|
||||||
|
"SECRET_KEY="
|
||||||
|
);
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [ ! -d "./repo" ]; then
|
|
||||||
git clone --depth 1 --branch main --single-branch https://github.com/langgenius/dify.git repo
|
|
||||||
else
|
|
||||||
cd repo
|
|
||||||
git pull
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
|
|
||||||
cp -r ./repo/docker/. ./code
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,705 @@
|
|||||||
|
{
|
||||||
|
"name": "compose",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"dependencies": {
|
||||||
|
"execa": "^9.5.1",
|
||||||
|
"glob": "^11.0.0",
|
||||||
|
"yaml": "^2.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@isaacs/cliui": {
|
||||||
|
"version": "8.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
|
||||||
|
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"string-width": "^5.1.2",
|
||||||
|
"string-width-cjs": "npm:string-width@^4.2.0",
|
||||||
|
"strip-ansi": "^7.0.1",
|
||||||
|
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
|
||||||
|
"wrap-ansi": "^8.1.0",
|
||||||
|
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@sec-ant/readable-stream": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/@sindresorhus/merge-streams": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ansi-regex": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/ansi-styles": {
|
||||||
|
"version": "6.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
||||||
|
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/balanced-match": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/brace-expansion": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/color-convert": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"color-name": "~1.1.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/color-name": {
|
||||||
|
"version": "1.1.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||||
|
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/cross-spawn": {
|
||||||
|
"version": "7.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
|
||||||
|
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"path-key": "^3.1.0",
|
||||||
|
"shebang-command": "^2.0.0",
|
||||||
|
"which": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/eastasianwidth": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/emoji-regex": {
|
||||||
|
"version": "9.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||||
|
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/execa": {
|
||||||
|
"version": "9.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/execa/-/execa-9.5.1.tgz",
|
||||||
|
"integrity": "sha512-QY5PPtSonnGwhhHDNI7+3RvY285c7iuJFFB+lU+oEzMY/gEGJ808owqJsrr8Otd1E/x07po1LkUBmdAc5duPAg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@sindresorhus/merge-streams": "^4.0.0",
|
||||||
|
"cross-spawn": "^7.0.3",
|
||||||
|
"figures": "^6.1.0",
|
||||||
|
"get-stream": "^9.0.0",
|
||||||
|
"human-signals": "^8.0.0",
|
||||||
|
"is-plain-obj": "^4.1.0",
|
||||||
|
"is-stream": "^4.0.1",
|
||||||
|
"npm-run-path": "^6.0.0",
|
||||||
|
"pretty-ms": "^9.0.0",
|
||||||
|
"signal-exit": "^4.1.0",
|
||||||
|
"strip-final-newline": "^4.0.0",
|
||||||
|
"yoctocolors": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^18.19.0 || >=20.5.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sindresorhus/execa?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/figures": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-unicode-supported": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/foreground-child": {
|
||||||
|
"version": "3.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
|
||||||
|
"integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"cross-spawn": "^7.0.0",
|
||||||
|
"signal-exit": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/get-stream": {
|
||||||
|
"version": "9.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-9.0.1.tgz",
|
||||||
|
"integrity": "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@sec-ant/readable-stream": "^0.4.1",
|
||||||
|
"is-stream": "^4.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/glob": {
|
||||||
|
"version": "11.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz",
|
||||||
|
"integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"foreground-child": "^3.1.0",
|
||||||
|
"jackspeak": "^4.0.1",
|
||||||
|
"minimatch": "^10.0.0",
|
||||||
|
"minipass": "^7.1.2",
|
||||||
|
"package-json-from-dist": "^1.0.0",
|
||||||
|
"path-scurry": "^2.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"glob": "dist/esm/bin.mjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "20 || >=22"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/human-signals": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA==",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.18.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-fullwidth-code-point": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-plain-obj": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-stream": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/is-unicode-supported": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.1.0.tgz",
|
||||||
|
"integrity": "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/isexe": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||||
|
"license": "ISC"
|
||||||
|
},
|
||||||
|
"node_modules/jackspeak": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==",
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@isaacs/cliui": "^8.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "20 || >=22"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lru-cache": {
|
||||||
|
"version": "11.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz",
|
||||||
|
"integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": "20 || >=22"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/minimatch": {
|
||||||
|
"version": "10.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
|
||||||
|
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"brace-expansion": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "20 || >=22"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/minipass": {
|
||||||
|
"version": "7.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
|
||||||
|
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16 || 14 >=14.17"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/npm-run-path": {
|
||||||
|
"version": "6.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz",
|
||||||
|
"integrity": "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"path-key": "^4.0.0",
|
||||||
|
"unicorn-magic": "^0.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/npm-run-path/node_modules/path-key": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/package-json-from-dist": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
|
||||||
|
"license": "BlueOak-1.0.0"
|
||||||
|
},
|
||||||
|
"node_modules/parse-ms": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/path-key": {
|
||||||
|
"version": "3.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
|
||||||
|
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/path-scurry": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
|
||||||
|
"license": "BlueOak-1.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"lru-cache": "^11.0.0",
|
||||||
|
"minipass": "^7.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "20 || >=22"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pretty-ms": {
|
||||||
|
"version": "9.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-9.2.0.tgz",
|
||||||
|
"integrity": "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"parse-ms": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/shebang-command": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"shebang-regex": "^3.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/shebang-regex": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/signal-exit": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
|
||||||
|
"license": "ISC",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/isaacs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/string-width": {
|
||||||
|
"version": "5.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
|
||||||
|
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"eastasianwidth": "^0.2.0",
|
||||||
|
"emoji-regex": "^9.2.2",
|
||||||
|
"strip-ansi": "^7.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/string-width-cjs": {
|
||||||
|
"name": "string-width",
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"emoji-regex": "^8.0.0",
|
||||||
|
"is-fullwidth-code-point": "^3.0.0",
|
||||||
|
"strip-ansi": "^6.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/string-width-cjs/node_modules/ansi-regex": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/string-width-cjs/node_modules/emoji-regex": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/string-width-cjs/node_modules/strip-ansi": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-regex": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/strip-ansi": {
|
||||||
|
"version": "7.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
|
||||||
|
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-regex": "^6.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/strip-ansi-cjs": {
|
||||||
|
"name": "strip-ansi",
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-regex": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/strip-final-newline": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz",
|
||||||
|
"integrity": "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/unicorn-magic": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/which": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||||
|
"license": "ISC",
|
||||||
|
"dependencies": {
|
||||||
|
"isexe": "^2.0.0"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"node-which": "bin/node-which"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/wrap-ansi": {
|
||||||
|
"version": "8.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
|
||||||
|
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^6.1.0",
|
||||||
|
"string-width": "^5.0.1",
|
||||||
|
"strip-ansi": "^7.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/wrap-ansi-cjs": {
|
||||||
|
"name": "wrap-ansi",
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-styles": "^4.0.0",
|
||||||
|
"string-width": "^4.1.0",
|
||||||
|
"strip-ansi": "^6.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/wrap-ansi-cjs/node_modules/ansi-styles": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"color-convert": "^2.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/wrap-ansi-cjs/node_modules/string-width": {
|
||||||
|
"version": "4.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
|
||||||
|
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"emoji-regex": "^8.0.0",
|
||||||
|
"is-fullwidth-code-point": "^3.0.0",
|
||||||
|
"strip-ansi": "^6.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"ansi-regex": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yaml": {
|
||||||
|
"version": "2.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz",
|
||||||
|
"integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==",
|
||||||
|
"license": "ISC",
|
||||||
|
"bin": {
|
||||||
|
"yaml": "bin.mjs"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 14"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yoctocolors": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"update": "node update.js"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"execa": "^9.5.1",
|
||||||
|
"glob": "^11.0.0",
|
||||||
|
"yaml": "^2.6.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,42 @@
|
|||||||
# Plane
|
# Plane - Project Management Script
|
||||||
|
|
||||||
- copied from https://github.com/makeplane/plane
|
This directory contains the Plane project management tool deployment for Easypanel.
|
||||||
- removed `ports`
|
|
||||||
|
## Update Process
|
||||||
|
|
||||||
|
To update Plane to the latest version, follow these steps in order:
|
||||||
|
|
||||||
|
### Step 1: Run the Setup Script for Upgrade
|
||||||
|
|
||||||
|
First, run the `setup.sh` script and choose the upgrade option:
|
||||||
|
|
||||||
|
```
|
||||||
|
./setup.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
When prompted, select option **5** for "Upgrade". This will:
|
||||||
|
|
||||||
|
* Check for the latest available release
|
||||||
|
* Download the latest stable version
|
||||||
|
|
||||||
|
### Step 2: Run the Update Script
|
||||||
|
|
||||||
|
After the setup script completes successfully, run the `update.js` script:
|
||||||
|
|
||||||
|
```
|
||||||
|
node update.js
|
||||||
|
```
|
||||||
|
|
||||||
|
This script will:
|
||||||
|
|
||||||
|
* Removes the existing code directory and changes the name for the newly fetched directory to code.
|
||||||
|
* Rename `plane.env` to `.env.example`
|
||||||
|
* Rename `docker-compose.yaml` to `docker-compose.yml`
|
||||||
|
* Remove container names and ports from docker-compose.yml
|
||||||
|
* Update environment variables to use Easypanel's `PRIMARY_DOMAIN` variable
|
||||||
|
|
||||||
|
## Important Notes
|
||||||
|
|
||||||
|
* **Always run setup.sh first** - This ensures you get the latest official Plane release
|
||||||
|
* **Then run update.js** - This applies Easypanel-specific customizations
|
||||||
|
* The update process will preserve your existing data and configuration
|
||||||
@@ -1,17 +1,21 @@
|
|||||||
APP_DOMAIN=localhost
|
APP_DOMAIN=$(PRIMARY_DOMAIN)
|
||||||
APP_RELEASE=stable
|
APP_RELEASE=v1.2.1
|
||||||
|
|
||||||
WEB_REPLICAS=1
|
WEB_REPLICAS=1
|
||||||
SPACE_REPLICAS=1
|
SPACE_REPLICAS=1
|
||||||
ADMIN_REPLICAS=1
|
ADMIN_REPLICAS=1
|
||||||
API_REPLICAS=1
|
API_REPLICAS=1
|
||||||
|
WORKER_REPLICAS=1
|
||||||
|
BEAT_WORKER_REPLICAS=1
|
||||||
|
LIVE_REPLICAS=1
|
||||||
|
|
||||||
NGINX_PORT=80
|
LISTEN_HTTP_PORT=80
|
||||||
WEB_URL=http://${APP_DOMAIN}
|
LISTEN_HTTPS_PORT=443
|
||||||
|
|
||||||
|
WEB_URL=https://$(PRIMARY_DOMAIN)
|
||||||
DEBUG=0
|
DEBUG=0
|
||||||
SENTRY_DSN=
|
CORS_ALLOWED_ORIGINS=https://$(PRIMARY_DOMAIN)
|
||||||
SENTRY_ENVIRONMENT=production
|
API_BASE_URL=http://api:8000
|
||||||
CORS_ALLOWED_ORIGINS=http://${APP_DOMAIN}
|
|
||||||
|
|
||||||
#DB SETTINGS
|
#DB SETTINGS
|
||||||
PGHOST=plane-db
|
PGHOST=plane-db
|
||||||
@@ -28,6 +32,27 @@ REDIS_HOST=plane-redis
|
|||||||
REDIS_PORT=6379
|
REDIS_PORT=6379
|
||||||
REDIS_URL=
|
REDIS_URL=
|
||||||
|
|
||||||
|
# RabbitMQ Settings
|
||||||
|
RABBITMQ_HOST=plane-mq
|
||||||
|
RABBITMQ_PORT=5672
|
||||||
|
RABBITMQ_USER=plane
|
||||||
|
RABBITMQ_PASSWORD=plane
|
||||||
|
RABBITMQ_VHOST=plane
|
||||||
|
AMQP_URL=
|
||||||
|
|
||||||
|
# If SSL Cert to be generated, set CERT_EMAIl="email <EMAIL_ADDRESS>"
|
||||||
|
CERT_ACME_CA=https://acme-v02.api.letsencrypt.org/directory
|
||||||
|
TRUSTED_PROXIES=0.0.0.0/0
|
||||||
|
SITE_ADDRESS=:80
|
||||||
|
CERT_EMAIL=
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# For DNS Challenge based certificate generation, set the CERT_ACME_DNS, CERT_EMAIL
|
||||||
|
# CERT_ACME_DNS="acme_dns <CERT_DNS_PROVIDER> <CERT_DNS_PROVIDER_API_KEY>"
|
||||||
|
CERT_ACME_DNS=
|
||||||
|
|
||||||
|
|
||||||
# Secret Key
|
# Secret Key
|
||||||
SECRET_KEY=60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5
|
SECRET_KEY=60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5
|
||||||
|
|
||||||
@@ -38,9 +63,6 @@ AWS_ACCESS_KEY_ID=access-key
|
|||||||
AWS_SECRET_ACCESS_KEY=secret-key
|
AWS_SECRET_ACCESS_KEY=secret-key
|
||||||
AWS_S3_ENDPOINT_URL=http://plane-minio:9000
|
AWS_S3_ENDPOINT_URL=http://plane-minio:9000
|
||||||
AWS_S3_BUCKET_NAME=uploads
|
AWS_S3_BUCKET_NAME=uploads
|
||||||
MINIO_ROOT_USER=access-key
|
|
||||||
MINIO_ROOT_PASSWORD=secret-key
|
|
||||||
BUCKET_NAME=uploads
|
|
||||||
FILE_SIZE_LIMIT=5242880
|
FILE_SIZE_LIMIT=5242880
|
||||||
|
|
||||||
# Gunicorn Workers
|
# Gunicorn Workers
|
||||||
@@ -49,3 +71,15 @@ GUNICORN_WORKERS=1
|
|||||||
# UNCOMMENT `DOCKER_PLATFORM` IF YOU ARE ON `ARM64` AND DOCKER IMAGE IS NOT AVAILABLE FOR RESPECTIVE `APP_RELEASE`
|
# UNCOMMENT `DOCKER_PLATFORM` IF YOU ARE ON `ARM64` AND DOCKER IMAGE IS NOT AVAILABLE FOR RESPECTIVE `APP_RELEASE`
|
||||||
# DOCKER_PLATFORM=linux/amd64
|
# DOCKER_PLATFORM=linux/amd64
|
||||||
|
|
||||||
|
# Force HTTPS for handling SSL Termination
|
||||||
|
MINIO_ENDPOINT_SSL=0
|
||||||
|
|
||||||
|
# API key rate limit
|
||||||
|
API_KEY_RATE_LIMIT=60/minute
|
||||||
|
|
||||||
|
# Live server environment variables
|
||||||
|
# WARNING: You must set a secure value for LIVE_SERVER_SECRET_KEY in production environments.
|
||||||
|
LIVE_SERVER_SECRET_KEY=
|
||||||
|
DOCKERHUB_USER=artifacts.plane.so/makeplane
|
||||||
|
PULL_POLICY=if_not_present
|
||||||
|
CUSTOM_BUILD=false
|
||||||
|
|||||||
@@ -1,483 +0,0 @@
|
|||||||
# Self Hosting
|
|
||||||
|
|
||||||
In this guide, we will walk you through the process of setting up a self-hosted environment. Self-hosting allows you to have full control over your applications and data. It's a great way to ensure privacy, control, and customization.
|
|
||||||
|
|
||||||
We will cover two main options for setting up your self-hosted environment: using a cloud server or using your desktop. For the cloud server, we will use an AWS EC2 instance. For the desktop, we will use Docker to create a local environment.
|
|
||||||
|
|
||||||
Let's get started!
|
|
||||||
|
|
||||||
## Setting up Docker Environment
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Option 1 - Using Cloud Server</summary>
|
|
||||||
<p>Best way to start is to create EC2 machine on AWS. It must have minimum of 2vCPU and 4GB RAM.</p>
|
|
||||||
<p>Run the below command to install docker engine.</p>
|
|
||||||
|
|
||||||
`curl -fsSL https://get.docker.com | sh -`
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary>Option 2 - Using Desktop</summary>
|
|
||||||
|
|
||||||
#### For Mac
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li> Download Docker Desktop for Mac from the <a href="https://hub.docker.com/editions/community/docker-ce-desktop-mac/" target="_blank">Docker Hub</a>. </li>
|
|
||||||
<li> Double-click the downloaded `.dmg` file and drag the Docker app icon to the Applications folder. </li>
|
|
||||||
<li>Open Docker Desktop from the Applications folder. You might be asked to provide your system password to install additional software.</li>
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
#### For Windows:
|
|
||||||
|
|
||||||
<ol>
|
|
||||||
<li>Download Docker Desktop for Windows from the <a href="https://hub.docker.com/editions/community/docker-ce-desktop-windows/" target="_blank">Docker Hub</a>.</li>
|
|
||||||
<li>Run the installer and follow the instructions. You might be asked to enable Hyper-V and "Containers" Windows features.</li>
|
|
||||||
<li>Open Docker Desktop. You might be asked to log out and log back in, or restart your machine, for changes to take effect.</li>
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
After installation, you can verify the installation by opening a terminal (Command Prompt on Windows, Terminal app on Mac) and running the command `docker --version`. This should display the installed version of Docker.
|
|
||||||
|
|
||||||
</details>
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Installing Plane
|
|
||||||
|
|
||||||
Installing plane is a very easy and minimal step process.
|
|
||||||
|
|
||||||
### Prerequisite
|
|
||||||
|
|
||||||
- Docker installed and running
|
|
||||||
- OS with bash scripting enabled (Ubuntu, Linux AMI, macos). Windows systems need to have [gitbash](https://git-scm.com/download/win)
|
|
||||||
- User context used must have access to docker services. In most cases, use sudo su to switch as root user
|
|
||||||
- Use the terminal (or gitbash) window to run all the future steps
|
|
||||||
|
|
||||||
### Downloading Latest Stable Release
|
|
||||||
|
|
||||||
```
|
|
||||||
mkdir plane-selfhost
|
|
||||||
|
|
||||||
cd plane-selfhost
|
|
||||||
|
|
||||||
curl -fsSL -o setup.sh https://raw.githubusercontent.com/makeplane/plane/master/deploy/selfhost/install.sh
|
|
||||||
|
|
||||||
chmod +x setup.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Proceed with setup
|
|
||||||
|
|
||||||
Above steps will set you ready to install and start plane services.
|
|
||||||
|
|
||||||
Lets get started by running the `./setup.sh` command.
|
|
||||||
|
|
||||||
This will prompt you with the below options.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
Select a Action you want to perform:
|
|
||||||
1) Install (x86_64)
|
|
||||||
2) Start
|
|
||||||
3) Stop
|
|
||||||
4) Restart
|
|
||||||
5) Upgrade
|
|
||||||
6) View Logs
|
|
||||||
7) Backup Data
|
|
||||||
8) Exit
|
|
||||||
Action [2]: 1
|
|
||||||
```
|
|
||||||
|
|
||||||
For the 1st time setup, type "1" as action input.
|
|
||||||
|
|
||||||
This will create a create a folder `plane-app` or `plane-app-preview` (in case of preview deployment) and will download 2 files inside that
|
|
||||||
|
|
||||||
- `docker-compose.yaml`
|
|
||||||
- `plane.env`
|
|
||||||
|
|
||||||
Again the `options [1-8]` will be popped up and this time hit `8` to exit.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Continue with setup - Environment Settings
|
|
||||||
|
|
||||||
Before proceeding, we suggest used to review `.env` file and set the values.
|
|
||||||
Below are the most import keys you must refer to. _<span style="color: #fcba03">You can use any text editor to edit this file</span>_.
|
|
||||||
|
|
||||||
> `NGINX_PORT` - This is default set to `80`. Make sure the port you choose to use is not preoccupied. (e.g `NGINX_PORT=8080`)
|
|
||||||
|
|
||||||
> `WEB_URL` - This is default set to `http://localhost`. Change this to the FQDN you plan to use along with NGINX_PORT (eg. `https://plane.example.com:8080` or `http://[IP-ADDRESS]:8080`)
|
|
||||||
|
|
||||||
> `CORS_ALLOWED_ORIGINS` - This is default set to `http://localhost`. Change this to the FQDN you plan to use along with NGINX_PORT (eg. `https://plane.example.com:8080` or `http://[IP-ADDRESS]:8080`)
|
|
||||||
|
|
||||||
There are many other settings you can play with, but we suggest you configure `EMAIL SETTINGS` as it will enable you to invite your teammates onto the platform.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Continue with setup - Start Server
|
|
||||||
|
|
||||||
Lets again run the `./setup.sh` command. You will again be prompted with the below options. This time select `2` to start the sevices
|
|
||||||
|
|
||||||
```bash
|
|
||||||
Select a Action you want to perform:
|
|
||||||
1) Install (x86_64)
|
|
||||||
2) Start
|
|
||||||
3) Stop
|
|
||||||
4) Restart
|
|
||||||
5) Upgrade
|
|
||||||
6) View Logs
|
|
||||||
7) Backup Data
|
|
||||||
8) Exit
|
|
||||||
|
|
||||||
Action [2]: 2
|
|
||||||
```
|
|
||||||
|
|
||||||
Expect something like this.
|
|
||||||

|
|
||||||
|
|
||||||
Be patient as it might take sometime based on download speed and system configuration. If all goes well, you must see something like this
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
This is the confirmation that all images were downloaded and the services are up & running.
|
|
||||||
|
|
||||||
You have successfully self hosted `Plane` instance. Access the application by going to IP or domain you have configured it (e.g `https://plane.example.com:8080` or `http://[IP-ADDRESS]:8080`)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Stopping the Server
|
|
||||||
|
|
||||||
In case you want to make changes to `.env` variables, we suggest you to stop the services before doing that.
|
|
||||||
|
|
||||||
Lets again run the `./setup.sh` command. You will again be prompted with the below options. This time select `3` to stop the sevices
|
|
||||||
|
|
||||||
```bash
|
|
||||||
Select a Action you want to perform:
|
|
||||||
1) Install (x86_64)
|
|
||||||
2) Start
|
|
||||||
3) Stop
|
|
||||||
4) Restart
|
|
||||||
5) Upgrade
|
|
||||||
6) View Logs
|
|
||||||
7) Backup Data
|
|
||||||
8) Exit
|
|
||||||
|
|
||||||
Action [2]: 3
|
|
||||||
```
|
|
||||||
|
|
||||||
If all goes well, you must see something like this
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Restarting the Server
|
|
||||||
|
|
||||||
In case you want to make changes to `.env` variables, without stopping the server or you noticed some abnormalies in services, you can restart the services with RESTART option.
|
|
||||||
|
|
||||||
Lets again run the `./setup.sh` command. You will again be prompted with the below options. This time select `4` to restart the sevices
|
|
||||||
|
|
||||||
```bash
|
|
||||||
Select a Action you want to perform:
|
|
||||||
1) Install (x86_64)
|
|
||||||
2) Start
|
|
||||||
3) Stop
|
|
||||||
4) Restart
|
|
||||||
5) Upgrade
|
|
||||||
6) View Logs
|
|
||||||
7) Backup Data
|
|
||||||
8) Exit
|
|
||||||
|
|
||||||
Action [2]: 4
|
|
||||||
```
|
|
||||||
|
|
||||||
If all goes well, you must see something like this
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Upgrading Plane Version
|
|
||||||
|
|
||||||
It is always advised to keep Plane up to date with the latest release.
|
|
||||||
|
|
||||||
Lets again run the `./setup.sh` command. You will again be prompted with the below options. This time select `5` to upgrade the release.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
Select a Action you want to perform:
|
|
||||||
1) Install (x86_64)
|
|
||||||
2) Start
|
|
||||||
3) Stop
|
|
||||||
4) Restart
|
|
||||||
5) Upgrade
|
|
||||||
6) View Logs
|
|
||||||
7) Backup Data
|
|
||||||
8) Exit
|
|
||||||
|
|
||||||
Action [2]: 5
|
|
||||||
```
|
|
||||||
|
|
||||||
By choosing this, it will stop the services and then will download the latest `docker-compose.yaml` and `plane.env`.
|
|
||||||
|
|
||||||
You must expect the below message
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Once done, choose `8` to exit from prompt.
|
|
||||||
|
|
||||||
> It is very important for you to validate the `plane.env` for the new changes.
|
|
||||||
|
|
||||||
Once done with making changes in `plane.env` file, jump on to `Start Server`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### View Logs
|
|
||||||
|
|
||||||
There would a time when you might want to check what is happening inside the API, Worker or any other container.
|
|
||||||
|
|
||||||
Lets again run the `./setup.sh` command. You will again be prompted with the below options. This time select `6` to view logs.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
Select a Action you want to perform:
|
|
||||||
1) Install (x86_64)
|
|
||||||
2) Start
|
|
||||||
3) Stop
|
|
||||||
4) Restart
|
|
||||||
5) Upgrade
|
|
||||||
6) View Logs
|
|
||||||
7) Backup Data
|
|
||||||
8) Exit
|
|
||||||
|
|
||||||
Action [2]: 6
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
This will further open sub-menu with list of services
|
|
||||||
```bash
|
|
||||||
Select a Service you want to view the logs for:
|
|
||||||
1) Web
|
|
||||||
2) Space
|
|
||||||
3) API
|
|
||||||
4) Worker
|
|
||||||
5) Beat-Worker
|
|
||||||
6) Migrator
|
|
||||||
7) Proxy
|
|
||||||
8) Redis
|
|
||||||
9) Postgres
|
|
||||||
10) Minio
|
|
||||||
0) Back to Main Menu
|
|
||||||
|
|
||||||
Service:
|
|
||||||
```
|
|
||||||
|
|
||||||
Select any of the service to view the logs e.g. `3`. Expect something similar to this
|
|
||||||
```bash
|
|
||||||
api-1 | Waiting for database...
|
|
||||||
api-1 | Database available!
|
|
||||||
api-1 | Waiting for database migrations to complete...
|
|
||||||
api-1 | Waiting for database migrations to complete...
|
|
||||||
api-1 | Waiting for database migrations to complete...
|
|
||||||
api-1 | Waiting for database migrations to complete...
|
|
||||||
api-1 | Waiting for database migrations to complete...
|
|
||||||
api-1 | Waiting for database migrations to complete...
|
|
||||||
api-1 | Waiting for database migrations to complete...
|
|
||||||
api-1 | No migrations Pending. Starting processes ...
|
|
||||||
api-1 | Instance registered
|
|
||||||
api-1 | ENABLE_SIGNUP loaded with value from environment variable.
|
|
||||||
api-1 | ENABLE_EMAIL_PASSWORD loaded with value from environment variable.
|
|
||||||
api-1 | ENABLE_MAGIC_LINK_LOGIN loaded with value from environment variable.
|
|
||||||
api-1 | GOOGLE_CLIENT_ID loaded with value from environment variable.
|
|
||||||
api-1 | GITHUB_CLIENT_ID loaded with value from environment variable.
|
|
||||||
api-1 | GITHUB_CLIENT_SECRET loaded with value from environment variable.
|
|
||||||
api-1 | EMAIL_HOST loaded with value from environment variable.
|
|
||||||
api-1 | EMAIL_HOST_USER loaded with value from environment variable.
|
|
||||||
api-1 | EMAIL_HOST_PASSWORD loaded with value from environment variable.
|
|
||||||
api-1 | EMAIL_PORT loaded with value from environment variable.
|
|
||||||
api-1 | EMAIL_FROM loaded with value from environment variable.
|
|
||||||
api-1 | EMAIL_USE_TLS loaded with value from environment variable.
|
|
||||||
api-1 | EMAIL_USE_SSL loaded with value from environment variable.
|
|
||||||
api-1 | OPENAI_API_KEY loaded with value from environment variable.
|
|
||||||
api-1 | GPT_ENGINE loaded with value from environment variable.
|
|
||||||
api-1 | UNSPLASH_ACCESS_KEY loaded with value from environment variable.
|
|
||||||
api-1 | Checking bucket...
|
|
||||||
api-1 | Bucket 'uploads' does not exist. Creating bucket...
|
|
||||||
api-1 | Bucket 'uploads' created successfully.
|
|
||||||
api-1 | Public read access policy set for bucket 'uploads'.
|
|
||||||
api-1 | Cache Cleared
|
|
||||||
api-1 | [2024-05-02 03:56:01 +0000] [1] [INFO] Starting gunicorn 21.2.0
|
|
||||||
api-1 | [2024-05-02 03:56:01 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)
|
|
||||||
api-1 | [2024-05-02 03:56:01 +0000] [1] [INFO] Using worker: uvicorn.workers.UvicornWorker
|
|
||||||
api-1 | [2024-05-02 03:56:01 +0000] [25] [INFO] Booting worker with pid: 25
|
|
||||||
api-1 | [2024-05-02 03:56:03 +0000] [25] [INFO] Started server process [25]
|
|
||||||
api-1 | [2024-05-02 03:56:03 +0000] [25] [INFO] Waiting for application startup.
|
|
||||||
api-1 | [2024-05-02 03:56:03 +0000] [25] [INFO] ASGI 'lifespan' protocol appears unsupported.
|
|
||||||
api-1 | [2024-05-02 03:56:03 +0000] [25] [INFO] Application startup complete.
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
To exit this, use `CTRL+C` and then you will land on to the main-menu with the list of actions.
|
|
||||||
|
|
||||||
Similarly, you can view the logs of other services.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Backup Data
|
|
||||||
|
|
||||||
There would a time when you might want to backup your data from docker volumes to external storage like S3 or drives.
|
|
||||||
|
|
||||||
Lets again run the `./setup.sh` command. You will again be prompted with the below options. This time select `7` to Backup the data.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
Select a Action you want to perform:
|
|
||||||
1) Install (x86_64)
|
|
||||||
2) Start
|
|
||||||
3) Stop
|
|
||||||
4) Restart
|
|
||||||
5) Upgrade
|
|
||||||
6) View Logs
|
|
||||||
7) Backup Data
|
|
||||||
8) Exit
|
|
||||||
|
|
||||||
Action [2]: 7
|
|
||||||
```
|
|
||||||
|
|
||||||
In response, you can find the backup folder
|
|
||||||
|
|
||||||
```bash
|
|
||||||
Backing Up plane-app_pgdata
|
|
||||||
Backing Up plane-app_redisdata
|
|
||||||
Backing Up plane-app_uploads
|
|
||||||
|
|
||||||
Backup completed successfully. Backup files are stored in /....../plane-app/backup/20240502-1120
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Restore Data
|
|
||||||
|
|
||||||
When you want to restore the previously backed-up data, follow the instructions below.
|
|
||||||
|
|
||||||
1. Make sure that Plane-CE is installed, started, and then stopped. This ensures that the Docker volumes are created.
|
|
||||||
|
|
||||||
1. Download the restore script using the command below. We suggest downloading it in the same folder as `setup.sh`.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
curl -fsSL -o restore.sh https://raw.githubusercontent.com/makeplane/plane/master/deploy/selfhost/restore.sh
|
|
||||||
chmod +x restore.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Execute the command below to restore your data.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./restore.sh <path to backup folder containing *.tar.gz files>
|
|
||||||
```
|
|
||||||
|
|
||||||
As an example, for a backup folder `/opt/plane-selfhost/plane-app/backup/20240722-0914`, expect the response below:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
--------------------------------------------
|
|
||||||
____ _ /////////
|
|
||||||
| _ \| | __ _ _ __ ___ /////////
|
|
||||||
| |_) | |/ _` | '_ \ / _ \ ///// /////
|
|
||||||
| __/| | (_| | | | | __/ ///// /////
|
|
||||||
|_| |_|\__,_|_| |_|\___| ////
|
|
||||||
////
|
|
||||||
--------------------------------------------
|
|
||||||
Project management tool from the future
|
|
||||||
--------------------------------------------
|
|
||||||
Found /opt/plane-selfhost/plane-app/backup/20240722-0914/pgdata.tar.gz
|
|
||||||
.....Restoring plane-app_pgdata
|
|
||||||
.....Successfully restored volume plane-app_pgdata from pgdata.tar.gz
|
|
||||||
|
|
||||||
Found /opt/plane-selfhost/plane-app/backup/20240722-0914/redisdata.tar.gz
|
|
||||||
.....Restoring plane-app_redisdata
|
|
||||||
.....Successfully restored volume plane-app_redisdata from redisdata.tar.gz
|
|
||||||
|
|
||||||
Found /opt/plane-selfhost/plane-app/backup/20240722-0914/uploads.tar.gz
|
|
||||||
.....Restoring plane-app_uploads
|
|
||||||
.....Successfully restored volume plane-app_uploads from uploads.tar.gz
|
|
||||||
|
|
||||||
|
|
||||||
Restore completed successfully.
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Start the Plane instance using `./setup.sh start`.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
<details>
|
|
||||||
<summary><h2>Upgrading from v0.13.2 to v0.14.x</h2></summary>
|
|
||||||
|
|
||||||
This is one time activity for users who are upgrading from v0.13.2 to v0.14.0
|
|
||||||
|
|
||||||
As there has been significant changes to Self Hosting process, this step mainly covers the data migration from current (v0.13.2) docker volumes from newly created volumes
|
|
||||||
|
|
||||||
> Before we begin with migration, make sure your v0.14.0 was started and then stopped. This is required to know the newly created docker volume names.
|
|
||||||
|
|
||||||
Begin with downloading the migration script using below command
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
curl -fsSL -o migrate.sh https://raw.githubusercontent.com/makeplane/plane/master/deploy/selfhost/migration-0.13-0.14.sh
|
|
||||||
|
|
||||||
chmod +x migrate.sh
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Now run the `./migrate.sh` command and expect the instructions as below
|
|
||||||
|
|
||||||
```
|
|
||||||
******************************************************************
|
|
||||||
|
|
||||||
This script is solely for the migration purpose only.
|
|
||||||
This is a 1 time migration of volume data from v0.13.2 => v0.14.x
|
|
||||||
|
|
||||||
Assumption:
|
|
||||||
1. Postgres data volume name ends with _pgdata
|
|
||||||
2. Minio data volume name ends with _uploads
|
|
||||||
3. Redis data volume name ends with _redisdata
|
|
||||||
|
|
||||||
Any changes to this script can break the migration.
|
|
||||||
|
|
||||||
Before you proceed, make sure you run the below command
|
|
||||||
to know the docker volumes
|
|
||||||
|
|
||||||
docker volume ls -q | grep -i "_pgdata"
|
|
||||||
docker volume ls -q | grep -i "_uploads"
|
|
||||||
docker volume ls -q | grep -i "_redisdata"
|
|
||||||
|
|
||||||
*******************************************************
|
|
||||||
|
|
||||||
Given below list of REDIS volumes, identify the prefix of source and destination volumes leaving "_redisdata"
|
|
||||||
---------------------
|
|
||||||
plane-app_redisdata
|
|
||||||
v0132_redisdata
|
|
||||||
|
|
||||||
Provide the Source Volume Prefix :
|
|
||||||
```
|
|
||||||
|
|
||||||
**Open another terminal window**, and run the mentioned 3 command. This may be different for users who have changed the volume names in their previous setup (v0.13.2)
|
|
||||||
|
|
||||||
For every command you must see 2 records something like shown in above example of `redisdata`
|
|
||||||
|
|
||||||
To move forward, you would need PREFIX of old setup and new setup. As per above example, `v0132` is the prefix of v0.13.2 and `plane-app` is the prefix of v0.14.0 setup
|
|
||||||
|
|
||||||
**Back to original terminal window**, _Provide the Source Volume Prefix_ and hit ENTER.
|
|
||||||
|
|
||||||
Now you will be prompted to _Provide Destination Volume Prefix_. Provide the value and hit ENTER
|
|
||||||
|
|
||||||
```
|
|
||||||
Provide the Source Volume Prefix : v0132
|
|
||||||
Provide the Destination Volume Prefix : plane-app
|
|
||||||
```
|
|
||||||
|
|
||||||
In case the suffixes are wrong or the mentioned volumes are not found, you will receive the error shown below. The image below displays an error for source volumes.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
In case of successful migration, it will be a silent exit without error.
|
|
||||||
|
|
||||||
Now its time to restart v0.14.0 setup.
|
|
||||||
</details>
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
services:
|
|
||||||
web:
|
|
||||||
image: ${DOCKERHUB_USER:-local}/plane-frontend:${APP_RELEASE:-latest}
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: ./web/Dockerfile.web
|
|
||||||
|
|
||||||
space:
|
|
||||||
image: ${DOCKERHUB_USER:-local}/plane-space:${APP_RELEASE:-latest}
|
|
||||||
build:
|
|
||||||
context: ./
|
|
||||||
dockerfile: ./space/Dockerfile.space
|
|
||||||
|
|
||||||
admin:
|
|
||||||
image: ${DOCKERHUB_USER:-local}/plane-admin:${APP_RELEASE:-latest}
|
|
||||||
build:
|
|
||||||
context: ./
|
|
||||||
dockerfile: ./admin/Dockerfile.admin
|
|
||||||
|
|
||||||
api:
|
|
||||||
image: ${DOCKERHUB_USER:-local}/plane-backend:${APP_RELEASE:-latest}
|
|
||||||
build:
|
|
||||||
context: ./apiserver
|
|
||||||
dockerfile: ./Dockerfile.api
|
|
||||||
|
|
||||||
proxy:
|
|
||||||
image: ${DOCKERHUB_USER:-local}/plane-proxy:${APP_RELEASE:-latest}
|
|
||||||
build:
|
|
||||||
context: ./nginx
|
|
||||||
dockerfile: ./Dockerfile
|
|
||||||
@@ -1,178 +1,239 @@
|
|||||||
|
x-db-env: &db-env
|
||||||
|
PGHOST: ${PGHOST:-plane-db}
|
||||||
|
PGDATABASE: ${PGDATABASE:-plane}
|
||||||
|
POSTGRES_USER: ${POSTGRES_USER:-plane}
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-plane}
|
||||||
|
POSTGRES_DB: ${POSTGRES_DB:-plane}
|
||||||
|
POSTGRES_PORT: ${POSTGRES_PORT:-5432}
|
||||||
|
PGDATA: ${PGDATA:-/var/lib/postgresql/data}
|
||||||
|
|
||||||
|
x-redis-env: &redis-env
|
||||||
|
REDIS_HOST: ${REDIS_HOST:-plane-redis}
|
||||||
|
REDIS_PORT: ${REDIS_PORT:-6379}
|
||||||
|
REDIS_URL: ${REDIS_URL:-redis://plane-redis:6379/}
|
||||||
|
|
||||||
|
x-minio-env: &minio-env
|
||||||
|
MINIO_ROOT_USER: ${AWS_ACCESS_KEY_ID:-access-key}
|
||||||
|
MINIO_ROOT_PASSWORD: ${AWS_SECRET_ACCESS_KEY:-secret-key}
|
||||||
|
|
||||||
|
x-aws-s3-env: &aws-s3-env
|
||||||
|
AWS_REGION: ${AWS_REGION:-}
|
||||||
|
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID:-access-key}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY:-secret-key}
|
||||||
|
AWS_S3_ENDPOINT_URL: ${AWS_S3_ENDPOINT_URL:-http://plane-minio:9000}
|
||||||
|
AWS_S3_BUCKET_NAME: ${AWS_S3_BUCKET_NAME:-uploads}
|
||||||
|
|
||||||
|
x-proxy-env: &proxy-env
|
||||||
|
APP_DOMAIN: ${APP_DOMAIN:-localhost}
|
||||||
|
FILE_SIZE_LIMIT: ${FILE_SIZE_LIMIT:-5242880}
|
||||||
|
CERT_EMAIL: ${CERT_EMAIL}
|
||||||
|
CERT_ACME_CA: ${CERT_ACME_CA}
|
||||||
|
CERT_ACME_DNS: ${CERT_ACME_DNS}
|
||||||
|
LISTEN_HTTP_PORT: ${LISTEN_HTTP_PORT:-80}
|
||||||
|
LISTEN_HTTPS_PORT: ${LISTEN_HTTPS_PORT:-443}
|
||||||
|
BUCKET_NAME: ${AWS_S3_BUCKET_NAME:-uploads}
|
||||||
|
SITE_ADDRESS: ${SITE_ADDRESS:-:80}
|
||||||
|
|
||||||
|
x-mq-env:
|
||||||
|
# RabbitMQ Settings
|
||||||
|
&mq-env
|
||||||
|
RABBITMQ_HOST: ${RABBITMQ_HOST:-plane-mq}
|
||||||
|
RABBITMQ_PORT: ${RABBITMQ_PORT:-5672}
|
||||||
|
RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER:-plane}
|
||||||
|
RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD:-plane}
|
||||||
|
RABBITMQ_DEFAULT_VHOST: ${RABBITMQ_VHOST:-plane}
|
||||||
|
RABBITMQ_VHOST: ${RABBITMQ_VHOST:-plane}
|
||||||
|
|
||||||
|
x-live-env: &live-env
|
||||||
|
API_BASE_URL: ${API_BASE_URL:-http://api:8000}
|
||||||
|
LIVE_SERVER_SECRET_KEY: ${LIVE_SERVER_SECRET_KEY:-2FiJk1U2aiVPEQtzLehYGlTSnTnrs7LW}
|
||||||
|
|
||||||
x-app-env: &app-env
|
x-app-env: &app-env
|
||||||
environment:
|
WEB_URL: ${WEB_URL:-http://localhost}
|
||||||
- NGINX_PORT=${NGINX_PORT:-80}
|
DEBUG: ${DEBUG:-0}
|
||||||
- WEB_URL=${WEB_URL:-http://localhost}
|
CORS_ALLOWED_ORIGINS: ${CORS_ALLOWED_ORIGINS}
|
||||||
- DEBUG=${DEBUG:-0}
|
GUNICORN_WORKERS: 1
|
||||||
- SENTRY_DSN=${SENTRY_DSN}
|
USE_MINIO: ${USE_MINIO:-1}
|
||||||
- SENTRY_ENVIRONMENT=${SENTRY_ENVIRONMENT:-"production"}
|
DATABASE_URL: ${DATABASE_URL:-postgresql://plane:plane@plane-db/plane}
|
||||||
- CORS_ALLOWED_ORIGINS=${CORS_ALLOWED_ORIGINS}
|
SECRET_KEY: ${SECRET_KEY:-60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5}
|
||||||
# Gunicorn Workers
|
AMQP_URL: ${AMQP_URL:-amqp://plane:plane@plane-mq:5672/plane}
|
||||||
- GUNICORN_WORKERS=${GUNICORN_WORKERS:-1}
|
API_KEY_RATE_LIMIT: ${API_KEY_RATE_LIMIT:-60/minute}
|
||||||
#DB SETTINGS
|
MINIO_ENDPOINT_SSL: ${MINIO_ENDPOINT_SSL:-0}
|
||||||
- PGHOST=${PGHOST:-plane-db}
|
LIVE_SERVER_SECRET_KEY: ${LIVE_SERVER_SECRET_KEY:-2FiJk1U2aiVPEQtzLehYGlTSnTnrs7LW}
|
||||||
- PGDATABASE=${PGDATABASE:-plane}
|
|
||||||
- POSTGRES_USER=${POSTGRES_USER:-plane}
|
|
||||||
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-plane}
|
|
||||||
- POSTGRES_DB=${POSTGRES_DB:-plane}
|
|
||||||
- POSTGRES_PORT=${POSTGRES_PORT:-5432}
|
|
||||||
- PGDATA=${PGDATA:-/var/lib/postgresql/data}
|
|
||||||
- DATABASE_URL=${DATABASE_URL:-postgresql://plane:plane@plane-db/plane}
|
|
||||||
# REDIS SETTINGS
|
|
||||||
- REDIS_HOST=${REDIS_HOST:-plane-redis}
|
|
||||||
- REDIS_PORT=${REDIS_PORT:-6379}
|
|
||||||
- REDIS_URL=${REDIS_URL:-redis://plane-redis:6379/}
|
|
||||||
# Application secret
|
|
||||||
- SECRET_KEY=${SECRET_KEY:-60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5}
|
|
||||||
# DATA STORE SETTINGS
|
|
||||||
- USE_MINIO=${USE_MINIO:-1}
|
|
||||||
- AWS_REGION=${AWS_REGION:-""}
|
|
||||||
- AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-"access-key"}
|
|
||||||
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-"secret-key"}
|
|
||||||
- AWS_S3_ENDPOINT_URL=${AWS_S3_ENDPOINT_URL:-http://plane-minio:9000}
|
|
||||||
- AWS_S3_BUCKET_NAME=${AWS_S3_BUCKET_NAME:-uploads}
|
|
||||||
- MINIO_ROOT_USER=${MINIO_ROOT_USER:-"access-key"}
|
|
||||||
- MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD:-"secret-key"}
|
|
||||||
- BUCKET_NAME=${BUCKET_NAME:-uploads}
|
|
||||||
- FILE_SIZE_LIMIT=${FILE_SIZE_LIMIT:-5242880}
|
|
||||||
# Admin and Space URLs
|
|
||||||
- ADMIN_BASE_URL=${ADMIN_BASE_URL}
|
|
||||||
- SPACE_BASE_URL=${SPACE_BASE_URL}
|
|
||||||
- APP_BASE_URL=${APP_BASE_URL}
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
web:
|
web:
|
||||||
<<: *app-env
|
image: artifacts.plane.so/makeplane/plane-frontend:${APP_RELEASE:-v1.2.1}
|
||||||
image: ${DOCKERHUB_USER:-makeplane}/plane-frontend:${APP_RELEASE:-stable}
|
|
||||||
platform: ${DOCKER_PLATFORM:-}
|
|
||||||
pull_policy: if_not_present
|
|
||||||
restart: unless-stopped
|
|
||||||
command: node web/server.js web
|
|
||||||
deploy:
|
deploy:
|
||||||
replicas: ${WEB_REPLICAS:-1}
|
replicas: ${WEB_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
depends_on:
|
depends_on:
|
||||||
- api
|
- api
|
||||||
- worker
|
- worker
|
||||||
|
|
||||||
space:
|
space:
|
||||||
<<: *app-env
|
image: artifacts.plane.so/makeplane/plane-space:${APP_RELEASE:-v1.2.1}
|
||||||
image: ${DOCKERHUB_USER:-makeplane}/plane-space:${APP_RELEASE:-stable}
|
|
||||||
platform: ${DOCKER_PLATFORM:-}
|
|
||||||
pull_policy: if_not_present
|
|
||||||
restart: unless-stopped
|
|
||||||
command: node space/server.js space
|
|
||||||
deploy:
|
deploy:
|
||||||
replicas: ${SPACE_REPLICAS:-1}
|
replicas: ${SPACE_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
depends_on:
|
depends_on:
|
||||||
- api
|
- api
|
||||||
- worker
|
- worker
|
||||||
- web
|
- web
|
||||||
|
|
||||||
admin:
|
admin:
|
||||||
<<: *app-env
|
image: artifacts.plane.so/makeplane/plane-admin:${APP_RELEASE:-v1.2.1}
|
||||||
image: ${DOCKERHUB_USER:-makeplane}/plane-admin:${APP_RELEASE:-stable}
|
|
||||||
platform: ${DOCKER_PLATFORM:-}
|
|
||||||
pull_policy: if_not_present
|
|
||||||
restart: unless-stopped
|
|
||||||
command: node admin/server.js admin
|
|
||||||
deploy:
|
deploy:
|
||||||
replicas: ${ADMIN_REPLICAS:-1}
|
replicas: ${ADMIN_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
- web
|
||||||
|
|
||||||
|
live:
|
||||||
|
image: artifacts.plane.so/makeplane/plane-live:${APP_RELEASE:-v1.2.1}
|
||||||
|
environment:
|
||||||
|
<<: [ *live-env, *redis-env ]
|
||||||
|
deploy:
|
||||||
|
replicas: ${LIVE_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
depends_on:
|
depends_on:
|
||||||
- api
|
- api
|
||||||
- web
|
- web
|
||||||
|
|
||||||
api:
|
api:
|
||||||
<<: *app-env
|
image: artifacts.plane.so/makeplane/plane-backend:${APP_RELEASE:-v1.2.1}
|
||||||
image: ${DOCKERHUB_USER:-makeplane}/plane-backend:${APP_RELEASE:-stable}
|
|
||||||
platform: ${DOCKER_PLATFORM:-}
|
|
||||||
pull_policy: if_not_present
|
|
||||||
restart: unless-stopped
|
|
||||||
command: ./bin/docker-entrypoint-api.sh
|
command: ./bin/docker-entrypoint-api.sh
|
||||||
deploy:
|
deploy:
|
||||||
replicas: ${API_REPLICAS:-1}
|
replicas: ${API_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
volumes:
|
volumes:
|
||||||
- logs_api:/code/plane/logs
|
- logs_api:/code/plane/logs
|
||||||
|
environment:
|
||||||
|
<<: [ *app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env ]
|
||||||
depends_on:
|
depends_on:
|
||||||
- plane-db
|
- plane-db
|
||||||
- plane-redis
|
- plane-redis
|
||||||
|
- plane-mq
|
||||||
|
|
||||||
worker:
|
worker:
|
||||||
<<: *app-env
|
image: artifacts.plane.so/makeplane/plane-backend:${APP_RELEASE:-v1.2.1}
|
||||||
image: ${DOCKERHUB_USER:-makeplane}/plane-backend:${APP_RELEASE:-stable}
|
|
||||||
platform: ${DOCKER_PLATFORM:-}
|
|
||||||
pull_policy: if_not_present
|
|
||||||
restart: unless-stopped
|
|
||||||
command: ./bin/docker-entrypoint-worker.sh
|
command: ./bin/docker-entrypoint-worker.sh
|
||||||
|
deploy:
|
||||||
|
replicas: ${WORKER_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
volumes:
|
volumes:
|
||||||
- logs_worker:/code/plane/logs
|
- logs_worker:/code/plane/logs
|
||||||
|
environment:
|
||||||
|
<<: [ *app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env ]
|
||||||
depends_on:
|
depends_on:
|
||||||
- api
|
- api
|
||||||
- plane-db
|
- plane-db
|
||||||
- plane-redis
|
- plane-redis
|
||||||
|
- plane-mq
|
||||||
|
|
||||||
beat-worker:
|
beat-worker:
|
||||||
<<: *app-env
|
image: artifacts.plane.so/makeplane/plane-backend:${APP_RELEASE:-v1.2.1}
|
||||||
image: ${DOCKERHUB_USER:-makeplane}/plane-backend:${APP_RELEASE:-stable}
|
|
||||||
platform: ${DOCKER_PLATFORM:-}
|
|
||||||
pull_policy: if_not_present
|
|
||||||
restart: unless-stopped
|
|
||||||
command: ./bin/docker-entrypoint-beat.sh
|
command: ./bin/docker-entrypoint-beat.sh
|
||||||
|
deploy:
|
||||||
|
replicas: ${BEAT_WORKER_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
volumes:
|
volumes:
|
||||||
- logs_beat-worker:/code/plane/logs
|
- logs_beat-worker:/code/plane/logs
|
||||||
|
environment:
|
||||||
|
<<: [ *app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env ]
|
||||||
depends_on:
|
depends_on:
|
||||||
- api
|
- api
|
||||||
- plane-db
|
- plane-db
|
||||||
- plane-redis
|
- plane-redis
|
||||||
|
- plane-mq
|
||||||
|
|
||||||
migrator:
|
migrator:
|
||||||
<<: *app-env
|
image: artifacts.plane.so/makeplane/plane-backend:${APP_RELEASE:-v1.2.1}
|
||||||
image: ${DOCKERHUB_USER:-makeplane}/plane-backend:${APP_RELEASE:-stable}
|
|
||||||
platform: ${DOCKER_PLATFORM:-}
|
|
||||||
pull_policy: if_not_present
|
|
||||||
restart: "no"
|
|
||||||
command: ./bin/docker-entrypoint-migrator.sh
|
command: ./bin/docker-entrypoint-migrator.sh
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
volumes:
|
volumes:
|
||||||
- logs_migrator:/code/plane/logs
|
- logs_migrator:/code/plane/logs
|
||||||
|
environment:
|
||||||
|
<<: [ *app-env, *db-env, *redis-env, *minio-env, *aws-s3-env, *proxy-env ]
|
||||||
depends_on:
|
depends_on:
|
||||||
- plane-db
|
- plane-db
|
||||||
- plane-redis
|
- plane-redis
|
||||||
|
|
||||||
|
# Comment this if you already have a database running
|
||||||
plane-db:
|
plane-db:
|
||||||
<<: *app-env
|
|
||||||
image: postgres:15.7-alpine
|
image: postgres:15.7-alpine
|
||||||
pull_policy: if_not_present
|
|
||||||
restart: unless-stopped
|
|
||||||
command: postgres -c 'max_connections=1000'
|
command: postgres -c 'max_connections=1000'
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
environment:
|
||||||
|
<<: *db-env
|
||||||
volumes:
|
volumes:
|
||||||
- pgdata:/var/lib/postgresql/data
|
- pgdata:/var/lib/postgresql/data
|
||||||
|
|
||||||
plane-redis:
|
plane-redis:
|
||||||
<<: *app-env
|
image: valkey/valkey:7.2.11-alpine
|
||||||
image: valkey/valkey:7.2.5-alpine
|
deploy:
|
||||||
pull_policy: if_not_present
|
replicas: 1
|
||||||
restart: unless-stopped
|
restart_policy:
|
||||||
|
condition: any
|
||||||
volumes:
|
volumes:
|
||||||
- redisdata:/data
|
- redisdata:/data
|
||||||
|
|
||||||
|
plane-mq:
|
||||||
|
image: rabbitmq:3.13.6-management-alpine
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
environment:
|
||||||
|
<<: *mq-env
|
||||||
|
volumes:
|
||||||
|
- rabbitmq_data:/var/lib/rabbitmq
|
||||||
|
|
||||||
|
# Comment this if you using any external s3 compatible storage
|
||||||
plane-minio:
|
plane-minio:
|
||||||
<<: *app-env
|
|
||||||
image: minio/minio:latest
|
image: minio/minio:latest
|
||||||
pull_policy: if_not_present
|
|
||||||
restart: unless-stopped
|
|
||||||
command: server /export --console-address ":9090"
|
command: server /export --console-address ":9090"
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: any
|
||||||
|
environment:
|
||||||
|
<<: *minio-env
|
||||||
volumes:
|
volumes:
|
||||||
- uploads:/export
|
- uploads:/export
|
||||||
|
|
||||||
# Comment this if you already have a reverse proxy running
|
# Comment this if you already have a reverse proxy running
|
||||||
proxy:
|
proxy:
|
||||||
<<: *app-env
|
image: artifacts.plane.so/makeplane/plane-proxy:${APP_RELEASE:-v1.2.1}
|
||||||
image: ${DOCKERHUB_USER:-makeplane}/plane-proxy:${APP_RELEASE:-stable}
|
deploy:
|
||||||
platform: ${DOCKER_PLATFORM:-}
|
replicas: 1
|
||||||
pull_policy: if_not_present
|
restart_policy:
|
||||||
restart: unless-stopped
|
condition: any
|
||||||
|
environment:
|
||||||
|
<<: *proxy-env
|
||||||
|
volumes:
|
||||||
|
- proxy_config:/config
|
||||||
|
- proxy_data:/data
|
||||||
depends_on:
|
depends_on:
|
||||||
- web
|
- web
|
||||||
- api
|
- api
|
||||||
- space
|
- space
|
||||||
|
- admin
|
||||||
|
- live
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
pgdata:
|
pgdata:
|
||||||
@@ -182,3 +243,6 @@ volumes:
|
|||||||
logs_worker:
|
logs_worker:
|
||||||
logs_beat-worker:
|
logs_beat-worker:
|
||||||
logs_migrator:
|
logs_migrator:
|
||||||
|
rabbitmq_data:
|
||||||
|
proxy_config:
|
||||||
|
proxy_data:
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 21 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 54 KiB |
@@ -1,118 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
echo '
|
|
||||||
******************************************************************
|
|
||||||
|
|
||||||
This script is solely for the migration purpose only.
|
|
||||||
This is a 1 time migration of volume data from v0.13.2 => v0.14.x
|
|
||||||
|
|
||||||
Assumption:
|
|
||||||
1. Postgres data volume name ends with _pgdata
|
|
||||||
2. Minio data volume name ends with _uploads
|
|
||||||
3. Redis data volume name ends with _redisdata
|
|
||||||
|
|
||||||
Any changes to this script can break the migration.
|
|
||||||
|
|
||||||
Before you proceed, make sure you run the below command
|
|
||||||
to know the docker volumes
|
|
||||||
|
|
||||||
docker volume ls -q | grep -i "_pgdata"
|
|
||||||
docker volume ls -q | grep -i "_uploads"
|
|
||||||
docker volume ls -q | grep -i "_redisdata"
|
|
||||||
|
|
||||||
*******************************************************
|
|
||||||
'
|
|
||||||
|
|
||||||
DOWNLOAD_FOL=./download
|
|
||||||
rm -rf ${DOWNLOAD_FOL}
|
|
||||||
mkdir -p ${DOWNLOAD_FOL}
|
|
||||||
|
|
||||||
function volumeExists {
|
|
||||||
if [ "$(docker volume ls -f name=$1 | awk '{print $NF}' | grep -E '^'$1'$')" ]; then
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function readPrefixes(){
|
|
||||||
echo ''
|
|
||||||
echo 'Given below list of REDIS volumes, identify the prefix of source and destination volumes leaving "_redisdata" '
|
|
||||||
echo '---------------------'
|
|
||||||
docker volume ls -q | grep -i "_redisdata"
|
|
||||||
echo ''
|
|
||||||
|
|
||||||
read -p "Provide the Source Volume Prefix : " SRC_VOL_PREFIX
|
|
||||||
until [ "$SRC_VOL_PREFIX" ]; do
|
|
||||||
read -p "Provide the Source Volume Prefix : " SRC_VOL_PREFIX
|
|
||||||
done
|
|
||||||
|
|
||||||
read -p "Provide the Destination Volume Prefix : " DEST_VOL_PREFIX
|
|
||||||
until [ "$DEST_VOL_PREFIX" ]; do
|
|
||||||
read -p "Provide the Source Volume Prefix : " DEST_VOL_PREFIX
|
|
||||||
done
|
|
||||||
|
|
||||||
echo ''
|
|
||||||
echo 'Prefix Provided '
|
|
||||||
echo " Source : ${SRC_VOL_PREFIX}"
|
|
||||||
echo " Destination : ${DEST_VOL_PREFIX}"
|
|
||||||
echo '---------------------------------------'
|
|
||||||
}
|
|
||||||
|
|
||||||
function migrate(){
|
|
||||||
|
|
||||||
SRC_VOLUME=${SRC_VOL_PREFIX}_${VOL_NAME_SUFFIX}
|
|
||||||
DEST_VOLUME=${DEST_VOL_PREFIX}_${VOL_NAME_SUFFIX}
|
|
||||||
|
|
||||||
if volumeExists $SRC_VOLUME; then
|
|
||||||
if volumeExists $DEST_VOLUME; then
|
|
||||||
GOOD_TO_GO=1
|
|
||||||
else
|
|
||||||
echo "Destination Volume '$DEST_VOLUME' does not exist"
|
|
||||||
echo ''
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "Source Volume '$SRC_VOLUME' does not exist"
|
|
||||||
echo ''
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $GOOD_TO_GO = 1 ]; then
|
|
||||||
|
|
||||||
echo "MIGRATING ${VOL_NAME_SUFFIX} FROM ${SRC_VOLUME} => ${DEST_VOLUME}"
|
|
||||||
|
|
||||||
TEMP_CONTAINER=$(docker run -d -v $SRC_VOLUME:$CONTAINER_VOL_FOLDER busybox true)
|
|
||||||
docker cp -q $TEMP_CONTAINER:$CONTAINER_VOL_FOLDER ${DOWNLOAD_FOL}/${VOL_NAME_SUFFIX}
|
|
||||||
docker rm $TEMP_CONTAINER &> /dev/null
|
|
||||||
|
|
||||||
TEMP_CONTAINER=$(docker run -d -v $DEST_VOLUME:$CONTAINER_VOL_FOLDER busybox true)
|
|
||||||
if [ "$VOL_NAME_SUFFIX" = "pgdata" ]; then
|
|
||||||
docker cp -q ${DOWNLOAD_FOL}/${VOL_NAME_SUFFIX} $TEMP_CONTAINER:$CONTAINER_VOL_FOLDER/_temp
|
|
||||||
docker run --rm -v $DEST_VOLUME:$CONTAINER_VOL_FOLDER \
|
|
||||||
-e DATA_FOLDER="${CONTAINER_VOL_FOLDER}" \
|
|
||||||
busybox /bin/sh -c 'cp -Rf $DATA_FOLDER/_temp/* $DATA_FOLDER '
|
|
||||||
else
|
|
||||||
docker cp -q ${DOWNLOAD_FOL}/${VOL_NAME_SUFFIX} $TEMP_CONTAINER:$CONTAINER_VOL_FOLDER
|
|
||||||
fi
|
|
||||||
docker rm $TEMP_CONTAINER &> /dev/null
|
|
||||||
|
|
||||||
echo ''
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
readPrefixes
|
|
||||||
|
|
||||||
# MIGRATE DB
|
|
||||||
CONTAINER_VOL_FOLDER=/var/lib/postgresql/data
|
|
||||||
VOL_NAME_SUFFIX=pgdata
|
|
||||||
migrate
|
|
||||||
|
|
||||||
# MIGRATE REDIS
|
|
||||||
CONTAINER_VOL_FOLDER=/data
|
|
||||||
VOL_NAME_SUFFIX=redisdata
|
|
||||||
migrate
|
|
||||||
|
|
||||||
# MIGRATE MINIO
|
|
||||||
CONTAINER_VOL_FOLDER=/export
|
|
||||||
VOL_NAME_SUFFIX=uploads
|
|
||||||
migrate
|
|
||||||
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
function print_header() {
|
|
||||||
clear
|
|
||||||
|
|
||||||
cat <<"EOF"
|
|
||||||
--------------------------------------------
|
|
||||||
____ _ /////////
|
|
||||||
| _ \| | __ _ _ __ ___ /////////
|
|
||||||
| |_) | |/ _` | '_ \ / _ \ ///// /////
|
|
||||||
| __/| | (_| | | | | __/ ///// /////
|
|
||||||
|_| |_|\__,_|_| |_|\___| ////
|
|
||||||
////
|
|
||||||
--------------------------------------------
|
|
||||||
Project management tool from the future
|
|
||||||
--------------------------------------------
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
function restoreSingleVolume() {
|
|
||||||
selectedVolume=$1
|
|
||||||
backupFolder=$2
|
|
||||||
restoreFile=$3
|
|
||||||
|
|
||||||
docker volume rm "$selectedVolume" > /dev/null 2>&1
|
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "Error: Failed to remove volume $selectedVolume"
|
|
||||||
echo ""
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
docker volume create "$selectedVolume" > /dev/null 2>&1
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "Error: Failed to create volume $selectedVolume"
|
|
||||||
echo ""
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
docker run --rm \
|
|
||||||
-e TAR_NAME="$restoreFile" \
|
|
||||||
-v "$selectedVolume":"/vol" \
|
|
||||||
-v "$backupFolder":/backup \
|
|
||||||
busybox sh -c 'mkdir -p /restore && tar -xzf "/backup/${TAR_NAME}.tar.gz" -C /restore && mv /restore/${TAR_NAME}/* /vol'
|
|
||||||
|
|
||||||
if [ $? -ne 0 ]; then
|
|
||||||
echo "Error: Failed to restore volume ${selectedVolume} from ${restoreFile}.tar.gz"
|
|
||||||
echo ""
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
echo ".....Successfully restored volume $selectedVolume from ${restoreFile}.tar.gz"
|
|
||||||
echo ""
|
|
||||||
}
|
|
||||||
|
|
||||||
function restoreData() {
|
|
||||||
print_header
|
|
||||||
local BACKUP_FOLDER=${1:-$PWD}
|
|
||||||
|
|
||||||
local dockerServiceStatus
|
|
||||||
dockerServiceStatus=$($COMPOSE_CMD ls --filter name=plane-app --format=json | jq -r .[0].Status)
|
|
||||||
local dockerServicePrefix
|
|
||||||
dockerServicePrefix="running"
|
|
||||||
|
|
||||||
if [[ $dockerServiceStatus == $dockerServicePrefix* ]]; then
|
|
||||||
echo "Plane App is running. Please STOP the Plane App before restoring data."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
local volumes
|
|
||||||
volumes=$(docker volume ls -f "name=plane-app" --format "{{.Name}}" | grep -E "_pgdata|_redisdata|_uploads")
|
|
||||||
# Check if there are any matching volumes
|
|
||||||
if [ -z "$volumes" ]; then
|
|
||||||
echo ".....No volumes found starting with 'plane-app'"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
for BACKUP_FILE in $BACKUP_FOLDER/*.tar.gz; do
|
|
||||||
if [ -e "$BACKUP_FILE" ]; then
|
|
||||||
|
|
||||||
local restoreFileName
|
|
||||||
restoreFileName=$(basename "$BACKUP_FILE")
|
|
||||||
restoreFileName="${restoreFileName%.tar.gz}"
|
|
||||||
|
|
||||||
local restoreVolName
|
|
||||||
restoreVolName="plane-app_${restoreFileName}"
|
|
||||||
echo "Found $BACKUP_FILE"
|
|
||||||
|
|
||||||
local docVol
|
|
||||||
docVol=$(docker volume ls -f "name=$restoreVolName" --format "{{.Name}}" | grep -E "_pgdata|_redisdata|_uploads")
|
|
||||||
|
|
||||||
if [ -z "$docVol" ]; then
|
|
||||||
echo "Skipping: No volume found with name $restoreVolName"
|
|
||||||
else
|
|
||||||
echo ".....Restoring $docVol"
|
|
||||||
restoreSingleVolume "$docVol" "$BACKUP_FOLDER" "$restoreFileName"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "No .tar.gz files found in the current directory."
|
|
||||||
echo ""
|
|
||||||
echo "Please provide the path to the backup file."
|
|
||||||
echo ""
|
|
||||||
echo "Usage: ./restore.sh /path/to/backup"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Restore completed successfully."
|
|
||||||
echo ""
|
|
||||||
}
|
|
||||||
|
|
||||||
# if docker-compose is installed
|
|
||||||
if command -v docker-compose &> /dev/null
|
|
||||||
then
|
|
||||||
COMPOSE_CMD="docker-compose"
|
|
||||||
else
|
|
||||||
COMPOSE_CMD="docker compose"
|
|
||||||
fi
|
|
||||||
|
|
||||||
restoreData "$@"
|
|
||||||
@@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
BRANCH=${BRANCH:-master}
|
BRANCH=${BRANCH:-master}
|
||||||
SCRIPT_DIR=$PWD
|
SCRIPT_DIR=$PWD
|
||||||
SERVICE_FOLDER=plane-app
|
SERVICE_FOLDER=plane-code
|
||||||
PLANE_INSTALL_DIR=$PWD/$SERVICE_FOLDER
|
PLANE_INSTALL_DIR=$PWD/$SERVICE_FOLDER
|
||||||
export APP_RELEASE="stable"
|
export APP_RELEASE=stable
|
||||||
export DOCKERHUB_USER=makeplane
|
export DOCKERHUB_USER=artifacts.plane.so/makeplane
|
||||||
export PULL_POLICY=${PULL_POLICY:-if_not_present}
|
export PULL_POLICY=${PULL_POLICY:-if_not_present}
|
||||||
|
export GH_REPO=makeplane/plane
|
||||||
|
export RELEASE_DOWNLOAD_URL="https://github.com/$GH_REPO/releases/download"
|
||||||
|
export FALLBACK_DOWNLOAD_URL="https://raw.githubusercontent.com/$GH_REPO/$BRANCH/deployments/cli/community"
|
||||||
|
|
||||||
CPU_ARCH=$(uname -m)
|
CPU_ARCH=$(uname -m)
|
||||||
OS_NAME=$(uname)
|
OS_NAME=$(uname)
|
||||||
@@ -16,13 +19,6 @@ mkdir -p $PLANE_INSTALL_DIR/archive
|
|||||||
DOCKER_FILE_PATH=$PLANE_INSTALL_DIR/docker-compose.yaml
|
DOCKER_FILE_PATH=$PLANE_INSTALL_DIR/docker-compose.yaml
|
||||||
DOCKER_ENV_PATH=$PLANE_INSTALL_DIR/plane.env
|
DOCKER_ENV_PATH=$PLANE_INSTALL_DIR/plane.env
|
||||||
|
|
||||||
SED_PREFIX=()
|
|
||||||
if [ "$OS_NAME" == "Darwin" ]; then
|
|
||||||
SED_PREFIX=("-i" "")
|
|
||||||
else
|
|
||||||
SED_PREFIX=("-i")
|
|
||||||
fi
|
|
||||||
|
|
||||||
function print_header() {
|
function print_header() {
|
||||||
clear
|
clear
|
||||||
|
|
||||||
@@ -59,6 +55,17 @@ function spinner() {
|
|||||||
printf " \b\b\b\b" >&2
|
printf " \b\b\b\b" >&2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkLatestRelease(){
|
||||||
|
echo "Checking for the latest release..." >&2
|
||||||
|
local latest_release=$(curl -fsSL https://api.github.com/repos/$GH_REPO/releases/latest | grep -o '"tag_name": "[^"]*"' | sed 's/"tag_name": "//;s/"//g')
|
||||||
|
if [ -z "$latest_release" ]; then
|
||||||
|
echo "Failed to check for the latest release. Exiting..." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo $latest_release
|
||||||
|
}
|
||||||
|
|
||||||
function initialize(){
|
function initialize(){
|
||||||
printf "Please wait while we check the availability of Docker images for the selected release ($APP_RELEASE) with ${UPPER_CPU_ARCH} support." >&2
|
printf "Please wait while we check the availability of Docker images for the selected release ($APP_RELEASE) with ${UPPER_CPU_ARCH} support." >&2
|
||||||
|
|
||||||
@@ -130,8 +137,12 @@ function updateEnvFile() {
|
|||||||
echo "$key=$value" >> "$file"
|
echo "$key=$value" >> "$file"
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
# if key exists, update the value
|
if [ "$OS_NAME" == "Darwin" ]; then
|
||||||
sed "${SED_PREFIX[@]}" "s/^$key=.*/$key=$value/g" "$file"
|
value=$(echo "$value" | sed 's/|/\\|/g')
|
||||||
|
sed -i '' "s|^$key=.*|$key=$value|g" "$file"
|
||||||
|
else
|
||||||
|
sed -i "s/^$key=.*/$key=$value/g" "$file"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "File not found: $file"
|
echo "File not found: $file"
|
||||||
@@ -182,10 +193,10 @@ function buildYourOwnImage(){
|
|||||||
local PLANE_TEMP_CODE_DIR=~/tmp/plane
|
local PLANE_TEMP_CODE_DIR=~/tmp/plane
|
||||||
rm -rf $PLANE_TEMP_CODE_DIR
|
rm -rf $PLANE_TEMP_CODE_DIR
|
||||||
mkdir -p $PLANE_TEMP_CODE_DIR
|
mkdir -p $PLANE_TEMP_CODE_DIR
|
||||||
REPO=https://github.com/makeplane/plane.git
|
REPO=https://github.com/$GH_REPO.git
|
||||||
git clone "$REPO" "$PLANE_TEMP_CODE_DIR" --branch "$BRANCH" --single-branch --depth 1
|
git clone "$REPO" "$PLANE_TEMP_CODE_DIR" --branch "$BRANCH" --single-branch --depth 1
|
||||||
|
|
||||||
cp "$PLANE_TEMP_CODE_DIR/deploy/selfhost/build.yml" "$PLANE_TEMP_CODE_DIR/build.yml"
|
cp "$PLANE_TEMP_CODE_DIR/deployments/cli/community/build.yml" "$PLANE_TEMP_CODE_DIR/build.yml"
|
||||||
|
|
||||||
cd "$PLANE_TEMP_CODE_DIR" || exit
|
cd "$PLANE_TEMP_CODE_DIR" || exit
|
||||||
|
|
||||||
@@ -204,6 +215,10 @@ function install() {
|
|||||||
echo "Begin Installing Plane"
|
echo "Begin Installing Plane"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
|
if [ "$APP_RELEASE" == "stable" ]; then
|
||||||
|
export APP_RELEASE=$(checkLatestRelease)
|
||||||
|
fi
|
||||||
|
|
||||||
local build_image=$(initialize)
|
local build_image=$(initialize)
|
||||||
|
|
||||||
if [ "$build_image" == "build" ]; then
|
if [ "$build_image" == "build" ]; then
|
||||||
@@ -232,8 +247,49 @@ function download() {
|
|||||||
mv $PLANE_INSTALL_DIR/docker-compose.yaml $PLANE_INSTALL_DIR/archive/$TS.docker-compose.yaml
|
mv $PLANE_INSTALL_DIR/docker-compose.yaml $PLANE_INSTALL_DIR/archive/$TS.docker-compose.yaml
|
||||||
fi
|
fi
|
||||||
|
|
||||||
curl -H 'Cache-Control: no-cache, no-store' -s -o $PLANE_INSTALL_DIR/docker-compose.yaml https://raw.githubusercontent.com/makeplane/plane/$BRANCH/deploy/selfhost/docker-compose.yml?$(date +%s)
|
RESPONSE=$(curl -fsSL -H 'Cache-Control: no-cache, no-store' -s -w "HTTPSTATUS:%{http_code}" "$RELEASE_DOWNLOAD_URL/$APP_RELEASE/docker-compose.yml?$(date +%s)")
|
||||||
curl -H 'Cache-Control: no-cache, no-store' -s -o $PLANE_INSTALL_DIR/variables-upgrade.env https://raw.githubusercontent.com/makeplane/plane/$BRANCH/deploy/selfhost/variables.env?$(date +%s)
|
BODY=$(echo "$RESPONSE" | sed -e 's/HTTPSTATUS\:.*//g')
|
||||||
|
STATUS=$(echo "$RESPONSE" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
|
||||||
|
|
||||||
|
if [ "$STATUS" -eq 200 ]; then
|
||||||
|
echo "$BODY" > $PLANE_INSTALL_DIR/docker-compose.yaml
|
||||||
|
else
|
||||||
|
# Fallback to download from the raw github url
|
||||||
|
RESPONSE=$(curl -fsSL -H 'Cache-Control: no-cache, no-store' -s -w "HTTPSTATUS:%{http_code}" "$FALLBACK_DOWNLOAD_URL/docker-compose.yml?$(date +%s)")
|
||||||
|
BODY=$(echo "$RESPONSE" | sed -e 's/HTTPSTATUS\:.*//g')
|
||||||
|
STATUS=$(echo "$RESPONSE" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
|
||||||
|
|
||||||
|
if [ "$STATUS" -eq 200 ]; then
|
||||||
|
echo "$BODY" > $PLANE_INSTALL_DIR/docker-compose.yaml
|
||||||
|
else
|
||||||
|
echo "Failed to download docker-compose.yml. HTTP Status: $STATUS"
|
||||||
|
echo "URL: $RELEASE_DOWNLOAD_URL/$APP_RELEASE/docker-compose.yml"
|
||||||
|
mv $PLANE_INSTALL_DIR/archive/$TS.docker-compose.yaml $PLANE_INSTALL_DIR/docker-compose.yaml
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
RESPONSE=$(curl -fsSL -H 'Cache-Control: no-cache, no-store' -s -w "HTTPSTATUS:%{http_code}" "$RELEASE_DOWNLOAD_URL/$APP_RELEASE/variables.env?$(date +%s)")
|
||||||
|
BODY=$(echo "$RESPONSE" | sed -e 's/HTTPSTATUS\:.*//g')
|
||||||
|
STATUS=$(echo "$RESPONSE" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
|
||||||
|
|
||||||
|
if [ "$STATUS" -eq 200 ]; then
|
||||||
|
echo "$BODY" > $PLANE_INSTALL_DIR/variables-upgrade.env
|
||||||
|
else
|
||||||
|
# Fallback to download from the raw github url
|
||||||
|
RESPONSE=$(curl -fsSL -H 'Cache-Control: no-cache, no-store' -s -w "HTTPSTATUS:%{http_code}" "$FALLBACK_DOWNLOAD_URL/variables.env?$(date +%s)")
|
||||||
|
BODY=$(echo "$RESPONSE" | sed -e 's/HTTPSTATUS\:.*//g')
|
||||||
|
STATUS=$(echo "$RESPONSE" | tr -d '\n' | sed -e 's/.*HTTPSTATUS://')
|
||||||
|
|
||||||
|
if [ "$STATUS" -eq 200 ]; then
|
||||||
|
echo "$BODY" > $PLANE_INSTALL_DIR/variables-upgrade.env
|
||||||
|
else
|
||||||
|
echo "Failed to download variables.env. HTTP Status: $STATUS"
|
||||||
|
echo "URL: $RELEASE_DOWNLOAD_URL/$APP_RELEASE/variables.env"
|
||||||
|
mv $PLANE_INSTALL_DIR/archive/$TS.docker-compose.yaml $PLANE_INSTALL_DIR/docker-compose.yaml
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -f "$DOCKER_ENV_PATH" ];
|
if [ -f "$DOCKER_ENV_PATH" ];
|
||||||
then
|
then
|
||||||
@@ -310,7 +366,7 @@ function startServices() {
|
|||||||
|
|
||||||
local api_container_id=$(docker container ls -q -f "name=$SERVICE_FOLDER-api")
|
local api_container_id=$(docker container ls -q -f "name=$SERVICE_FOLDER-api")
|
||||||
local idx2=0
|
local idx2=0
|
||||||
while ! docker logs $api_container_id 2>&1 | grep -m 1 -i "Application startup complete" | grep -q ".";
|
while ! docker exec $api_container_id python3 -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/')" > /dev/null 2>&1;
|
||||||
do
|
do
|
||||||
local message=">> Waiting for API Service to Start"
|
local message=">> Waiting for API Service to Start"
|
||||||
local dots=$(printf '%*s' $idx2 | tr ' ' '.')
|
local dots=$(printf '%*s' $idx2 | tr ' ' '.')
|
||||||
@@ -335,6 +391,34 @@ function restartServices() {
|
|||||||
startServices
|
startServices
|
||||||
}
|
}
|
||||||
function upgrade() {
|
function upgrade() {
|
||||||
|
local latest_release=$(checkLatestRelease)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Current release: $APP_RELEASE"
|
||||||
|
|
||||||
|
if [ "$latest_release" == "$APP_RELEASE" ]; then
|
||||||
|
echo ""
|
||||||
|
echo "You are already using the latest release"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Latest release: $latest_release"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Check for confirmation to upgrade
|
||||||
|
echo "Do you want to upgrade to the latest release ($latest_release)?"
|
||||||
|
read -p "Continue? [y/N]: " confirm
|
||||||
|
|
||||||
|
if [[ ! "$confirm" =~ ^[Yy]$ ]]; then
|
||||||
|
echo "Exiting..."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
export APP_RELEASE=$latest_release
|
||||||
|
|
||||||
|
echo "Upgrading Plane to the latest release..."
|
||||||
|
echo ""
|
||||||
|
|
||||||
echo "***** STOPPING SERVICES ****"
|
echo "***** STOPPING SERVICES ****"
|
||||||
stopServices
|
stopServices
|
||||||
|
|
||||||
@@ -373,12 +457,13 @@ function viewLogs(){
|
|||||||
echo " 8) Redis"
|
echo " 8) Redis"
|
||||||
echo " 9) Postgres"
|
echo " 9) Postgres"
|
||||||
echo " 10) Minio"
|
echo " 10) Minio"
|
||||||
|
echo " 11) RabbitMQ"
|
||||||
echo " 0) Back to Main Menu"
|
echo " 0) Back to Main Menu"
|
||||||
echo
|
echo
|
||||||
read -p "Service: " DOCKER_SERVICE_NAME
|
read -p "Service: " DOCKER_SERVICE_NAME
|
||||||
|
|
||||||
until (( DOCKER_SERVICE_NAME >= 0 && DOCKER_SERVICE_NAME <= 10 )); do
|
until (( DOCKER_SERVICE_NAME >= 0 && DOCKER_SERVICE_NAME <= 11 )); do
|
||||||
echo "Invalid selection. Please enter a number between 1 and 11."
|
echo "Invalid selection. Please enter a number between 0 and 11."
|
||||||
read -p "Service: " DOCKER_SERVICE_NAME
|
read -p "Service: " DOCKER_SERVICE_NAME
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -397,6 +482,7 @@ function viewLogs(){
|
|||||||
8) viewSpecificLogs "plane-redis";;
|
8) viewSpecificLogs "plane-redis";;
|
||||||
9) viewSpecificLogs "plane-db";;
|
9) viewSpecificLogs "plane-db";;
|
||||||
10) viewSpecificLogs "plane-minio";;
|
10) viewSpecificLogs "plane-minio";;
|
||||||
|
11) viewSpecificLogs "plane-mq";;
|
||||||
0) askForAction;;
|
0) askForAction;;
|
||||||
*) echo "INVALID SERVICE NAME SUPPLIED";;
|
*) echo "INVALID SERVICE NAME SUPPLIED";;
|
||||||
esac
|
esac
|
||||||
@@ -415,49 +501,76 @@ function viewLogs(){
|
|||||||
redis) viewSpecificLogs "plane-redis";;
|
redis) viewSpecificLogs "plane-redis";;
|
||||||
postgres) viewSpecificLogs "plane-db";;
|
postgres) viewSpecificLogs "plane-db";;
|
||||||
minio) viewSpecificLogs "plane-minio";;
|
minio) viewSpecificLogs "plane-minio";;
|
||||||
|
rabbitmq) viewSpecificLogs "plane-mq";;
|
||||||
*) echo "INVALID SERVICE NAME SUPPLIED";;
|
*) echo "INVALID SERVICE NAME SUPPLIED";;
|
||||||
esac
|
esac
|
||||||
else
|
else
|
||||||
echo "INVALID SERVICE NAME SUPPLIED"
|
echo "INVALID SERVICE NAME SUPPLIED"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
function backupSingleVolume() {
|
function backup_container_dir() {
|
||||||
backupFolder=$1
|
local BACKUP_FOLDER=$1
|
||||||
selectedVolume=$2
|
local CONTAINER_NAME=$2
|
||||||
# Backup data from Docker volume to the backup folder
|
local CONTAINER_DATA_DIR=$3
|
||||||
# docker run --rm -v "$selectedVolume":/source -v "$backupFolder":/backup busybox sh -c 'cp -r /source/* /backup/'
|
local SERVICE_FOLDER=$4
|
||||||
local tobereplaced="plane-app_"
|
|
||||||
local replacewith=""
|
|
||||||
|
|
||||||
local svcName="${selectedVolume//$tobereplaced/$replacewith}"
|
echo "Backing up $CONTAINER_NAME data..."
|
||||||
|
local CONTAINER_ID=$(/bin/bash -c "$COMPOSE_CMD -f $DOCKER_FILE_PATH ps -q $CONTAINER_NAME")
|
||||||
|
if [ -z "$CONTAINER_ID" ]; then
|
||||||
|
echo "Error: $CONTAINER_NAME container not found. Make sure the services are running."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
docker run --rm \
|
# Create a temporary directory for the backup
|
||||||
-e TAR_NAME="$svcName" \
|
mkdir -p "$BACKUP_FOLDER/$SERVICE_FOLDER"
|
||||||
-v "$selectedVolume":/"$svcName" \
|
|
||||||
-v "$backupFolder":/backup \
|
# Copy the data directory from the running container
|
||||||
busybox sh -c 'tar -czf "/backup/${TAR_NAME}.tar.gz" /${TAR_NAME}'
|
echo "Copying $CONTAINER_NAME data directory..."
|
||||||
|
docker cp -q "$CONTAINER_ID:$CONTAINER_DATA_DIR/." "$BACKUP_FOLDER/$SERVICE_FOLDER/"
|
||||||
|
local cp_status=$?
|
||||||
|
|
||||||
|
if [ $cp_status -ne 0 ]; then
|
||||||
|
echo "Error: Failed to copy $SERVICE_FOLDER data"
|
||||||
|
rm -rf $BACKUP_FOLDER/$SERVICE_FOLDER
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create tar.gz of the data
|
||||||
|
cd "$BACKUP_FOLDER"
|
||||||
|
tar -czf "${SERVICE_FOLDER}.tar.gz" "$SERVICE_FOLDER/"
|
||||||
|
local tar_status=$?
|
||||||
|
if [ $tar_status -eq 0 ]; then
|
||||||
|
rm -rf "$SERVICE_FOLDER/"
|
||||||
|
fi
|
||||||
|
cd - > /dev/null
|
||||||
|
|
||||||
|
if [ $tar_status -ne 0 ]; then
|
||||||
|
echo "Error: Failed to create tar archive"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Successfully backed up $SERVICE_FOLDER data"
|
||||||
}
|
}
|
||||||
|
|
||||||
function backupData() {
|
function backupData() {
|
||||||
local datetime=$(date +"%Y%m%d-%H%M")
|
local datetime=$(date +"%Y%m%d-%H%M")
|
||||||
local BACKUP_FOLDER=$PLANE_INSTALL_DIR/backup/$datetime
|
local BACKUP_FOLDER=$PLANE_INSTALL_DIR/backup/$datetime
|
||||||
mkdir -p "$BACKUP_FOLDER"
|
mkdir -p "$BACKUP_FOLDER"
|
||||||
|
|
||||||
volumes=$(docker volume ls -f "name=plane-app" --format "{{.Name}}" | grep -E "_pgdata|_redisdata|_uploads")
|
# Check if docker-compose.yml exists
|
||||||
# Check if there are any matching volumes
|
if [ ! -f "$DOCKER_FILE_PATH" ]; then
|
||||||
if [ -z "$volumes" ]; then
|
echo "Error: docker-compose.yml not found at $DOCKER_FILE_PATH"
|
||||||
echo "No volumes found starting with 'plane-app'"
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for vol in $volumes; do
|
backup_container_dir "$BACKUP_FOLDER" "plane-db" "/var/lib/postgresql/data" "pgdata" || exit 1
|
||||||
echo "Backing Up $vol"
|
backup_container_dir "$BACKUP_FOLDER" "plane-minio" "/export" "uploads" || exit 1
|
||||||
backupSingleVolume "$BACKUP_FOLDER" "$vol"
|
backup_container_dir "$BACKUP_FOLDER" "plane-mq" "/var/lib/rabbitmq" "rabbitmq_data" || exit 1
|
||||||
done
|
backup_container_dir "$BACKUP_FOLDER" "plane-redis" "/data" "redisdata" || exit 1
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "Backup completed successfully. Backup files are stored in $BACKUP_FOLDER"
|
echo "Backup completed successfully. Backup files are stored in $BACKUP_FOLDER"
|
||||||
echo ""
|
echo ""
|
||||||
|
|
||||||
}
|
}
|
||||||
function askForAction() {
|
function askForAction() {
|
||||||
local DEFAULT_ACTION=$1
|
local DEFAULT_ACTION=$1
|
||||||
@@ -544,7 +657,7 @@ if [ -f "$DOCKER_ENV_PATH" ]; then
|
|||||||
CUSTOM_BUILD=$(getEnvValue "CUSTOM_BUILD" "$DOCKER_ENV_PATH")
|
CUSTOM_BUILD=$(getEnvValue "CUSTOM_BUILD" "$DOCKER_ENV_PATH")
|
||||||
|
|
||||||
if [ -z "$DOCKERHUB_USER" ]; then
|
if [ -z "$DOCKERHUB_USER" ]; then
|
||||||
DOCKERHUB_USER=makeplane
|
DOCKERHUB_USER=artifacts.plane.so/makeplane
|
||||||
updateEnvFile "DOCKERHUB_USER" "$DOCKERHUB_USER" "$DOCKER_ENV_PATH"
|
updateEnvFile "DOCKERHUB_USER" "$DOCKERHUB_USER" "$DOCKER_ENV_PATH"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
import utils from "../utils.js";
|
||||||
|
|
||||||
|
await utils.removeDir("./code");
|
||||||
|
await utils.renameDir("./plane-code", "./code");
|
||||||
|
await utils.removeDir("./code/archive");
|
||||||
|
await utils.renameFile("./code/plane.env", "./code/.env.example");
|
||||||
|
await utils.renameFile("./code/docker-compose.yaml", "./code/docker-compose.yml");
|
||||||
|
|
||||||
|
await utils.removeContainerNames("./code/docker-compose.yml");
|
||||||
|
await utils.removePorts("./code/docker-compose.yml");
|
||||||
|
|
||||||
|
await utils.searchReplace(
|
||||||
|
"./code/.env.example",
|
||||||
|
"APP_DOMAIN=localhost",
|
||||||
|
"APP_DOMAIN=$(PRIMARY_DOMAIN)"
|
||||||
|
);
|
||||||
|
|
||||||
|
await utils.searchReplace(
|
||||||
|
"./code/.env.example",
|
||||||
|
"WEB_URL=http://${APP_DOMAIN}",
|
||||||
|
"WEB_URL=https://$(PRIMARY_DOMAIN)"
|
||||||
|
);
|
||||||
|
|
||||||
|
await utils.searchReplace(
|
||||||
|
"./code/.env.example",
|
||||||
|
"CORS_ALLOWED_ORIGINS=http://${APP_DOMAIN}",
|
||||||
|
"CORS_ALLOWED_ORIGINS=https://$(PRIMARY_DOMAIN)"
|
||||||
|
);
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [ ! -d "./repo" ]; then
|
|
||||||
git clone --depth 1 --branch preview --single-branch https://github.com/makeplane/plane.git repo
|
|
||||||
else
|
|
||||||
cd repo
|
|
||||||
git pull
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
|
|
||||||
cp -r ./repo/deploy/selfhost/. ./code
|
|
||||||
mv ./code/variables.env ./code/.env.example
|
|
||||||
|
|
||||||
|
|
||||||
@@ -9,6 +9,9 @@ ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKIC
|
|||||||
SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q
|
SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q
|
||||||
DASHBOARD_USERNAME=supabase
|
DASHBOARD_USERNAME=supabase
|
||||||
DASHBOARD_PASSWORD=this_password_is_insecure_and_should_be_updated
|
DASHBOARD_PASSWORD=this_password_is_insecure_and_should_be_updated
|
||||||
|
SECRET_KEY_BASE=UpNVntn3cDxHJpq99YMc1T1AQgQpc8kfYTuRgBiYa15BLrx8etQoXz3gZv1/u2oq
|
||||||
|
VAULT_ENC_KEY=your-encryption-key-32-chars-min
|
||||||
|
|
||||||
|
|
||||||
############
|
############
|
||||||
# Database - You can change these to any PostgreSQL database that has logical replication enabled.
|
# Database - You can change these to any PostgreSQL database that has logical replication enabled.
|
||||||
@@ -19,6 +22,23 @@ POSTGRES_DB=postgres
|
|||||||
POSTGRES_PORT=5432
|
POSTGRES_PORT=5432
|
||||||
# default user is postgres
|
# default user is postgres
|
||||||
|
|
||||||
|
|
||||||
|
############
|
||||||
|
# Supavisor -- Database pooler
|
||||||
|
############
|
||||||
|
# Port Supavisor listens on for transaction pooling connections
|
||||||
|
POOLER_PROXY_PORT_TRANSACTION=6543
|
||||||
|
# Maximum number of PostgreSQL connections Supavisor opens per pool
|
||||||
|
POOLER_DEFAULT_POOL_SIZE=20
|
||||||
|
# Maximum number of client connections Supavisor accepts per pool
|
||||||
|
POOLER_MAX_CLIENT_CONN=100
|
||||||
|
# Unique tenant identifier
|
||||||
|
POOLER_TENANT_ID=your-tenant-id
|
||||||
|
# Pool size for internal metadata storage used by Supavisor
|
||||||
|
# This is separate from client connections and used only by Supavisor itself
|
||||||
|
POOLER_DB_POOL_SIZE=5
|
||||||
|
|
||||||
|
|
||||||
############
|
############
|
||||||
# API Proxy - Configuration for the Kong Reverse proxy.
|
# API Proxy - Configuration for the Kong Reverse proxy.
|
||||||
############
|
############
|
||||||
@@ -39,7 +59,7 @@ PGRST_DB_SCHEMAS=public,storage,graphql_public
|
|||||||
############
|
############
|
||||||
|
|
||||||
## General
|
## General
|
||||||
SITE_URL=http://localhost:3000
|
SITE_URL=https://$(PRIMARY_DOMAIN)
|
||||||
ADDITIONAL_REDIRECT_URLS=
|
ADDITIONAL_REDIRECT_URLS=
|
||||||
JWT_EXPIRY=3600
|
JWT_EXPIRY=3600
|
||||||
DISABLE_SIGNUP=false
|
DISABLE_SIGNUP=false
|
||||||
@@ -81,21 +101,26 @@ SUPABASE_PUBLIC_URL=http://localhost:8000
|
|||||||
# Enable webp support
|
# Enable webp support
|
||||||
IMGPROXY_ENABLE_WEBP_DETECTION=true
|
IMGPROXY_ENABLE_WEBP_DETECTION=true
|
||||||
|
|
||||||
|
# Add your OpenAI API key to enable SQL Editor Assistant
|
||||||
|
OPENAI_API_KEY=
|
||||||
|
|
||||||
|
|
||||||
############
|
############
|
||||||
# Functions - Configuration for Functions
|
# Functions - Configuration for Functions
|
||||||
############
|
############
|
||||||
# NOTE: VERIFY_JWT applies to all functions. Per-function VERIFY_JWT is not supported yet.
|
# NOTE: VERIFY_JWT applies to all functions. Per-function VERIFY_JWT is not supported yet.
|
||||||
FUNCTIONS_VERIFY_JWT=false
|
FUNCTIONS_VERIFY_JWT=false
|
||||||
|
|
||||||
|
|
||||||
############
|
############
|
||||||
# Logs - Configuration for Logflare
|
# Logs - Configuration for Analytics
|
||||||
# Please refer to https://supabase.com/docs/reference/self-hosting-analytics/introduction
|
# Please refer to https://supabase.com/docs/reference/self-hosting-analytics/introduction
|
||||||
############
|
############
|
||||||
|
|
||||||
LOGFLARE_LOGGER_BACKEND_API_KEY=your-super-secret-and-long-logflare-key
|
|
||||||
|
|
||||||
# Change vector.toml sinks to reflect this change
|
# Change vector.toml sinks to reflect this change
|
||||||
LOGFLARE_API_KEY=your-super-secret-and-long-logflare-key
|
# these cannot be the same value
|
||||||
|
LOGFLARE_PUBLIC_ACCESS_TOKEN=your-super-secret-and-long-logflare-key-public
|
||||||
|
LOGFLARE_PRIVATE_ACCESS_TOKEN=your-super-secret-and-long-logflare-key-private
|
||||||
|
|
||||||
# Docker socket location - this value will differ depending on your OS
|
# Docker socket location - this value will differ depending on your OS
|
||||||
DOCKER_SOCKET_LOCATION=/var/run/docker.sock
|
DOCKER_SOCKET_LOCATION=/var/run/docker.sock
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ services:
|
|||||||
studio:
|
studio:
|
||||||
build:
|
build:
|
||||||
context: ..
|
context: ..
|
||||||
dockerfile: studio/Dockerfile
|
dockerfile: apps/studio/Dockerfile
|
||||||
target: dev
|
target: dev
|
||||||
ports:
|
ports:
|
||||||
- 8082:8082
|
- 8082:8082
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
version: "3.8"
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
minio:
|
minio:
|
||||||
@@ -33,7 +31,7 @@ services:
|
|||||||
|
|
||||||
storage:
|
storage:
|
||||||
container_name: supabase-storage
|
container_name: supabase-storage
|
||||||
image: supabase/storage-api:v0.43.11
|
image: supabase/storage-api:v1.11.13
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
# Disable this if you are using an external Postgres database
|
# Disable this if you are using an external Postgres database
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
# With helpers: docker compose -f docker-compose.yml -f ./dev/docker-compose.dev.yml up
|
# With helpers: docker compose -f docker-compose.yml -f ./dev/docker-compose.dev.yml up
|
||||||
# Stop: docker compose down
|
# Stop: docker compose down
|
||||||
# Destroy: docker compose -f docker-compose.yml -f ./dev/docker-compose.dev.yml down -v --remove-orphans
|
# Destroy: docker compose -f docker-compose.yml -f ./dev/docker-compose.dev.yml down -v --remove-orphans
|
||||||
|
# Reset everything: ./reset.sh
|
||||||
|
|
||||||
name: supabase
|
name: supabase
|
||||||
version: "3.8"
|
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
studio:
|
studio:
|
||||||
image: supabase/studio:20240729-ce42139
|
image: supabase/studio:2025.06.30-sha-6f5982d
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test:
|
test:
|
||||||
@@ -17,9 +18,10 @@ services:
|
|||||||
"CMD",
|
"CMD",
|
||||||
"node",
|
"node",
|
||||||
"-e",
|
"-e",
|
||||||
"require('http').get('http://localhost:3000/api/profile', (r) => {if (r.statusCode !== 200) throw new Error(r.statusCode)})",
|
"fetch('http://studio:3000/api/platform/profile').then((r) => {if
|
||||||
|
(r.status !== 200) throw new Error(r.status)})"
|
||||||
]
|
]
|
||||||
timeout: 5s
|
timeout: 10s
|
||||||
interval: 5s
|
interval: 5s
|
||||||
retries: 3
|
retries: 3
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -31,6 +33,7 @@ services:
|
|||||||
|
|
||||||
DEFAULT_ORGANIZATION_NAME: ${STUDIO_DEFAULT_ORGANIZATION}
|
DEFAULT_ORGANIZATION_NAME: ${STUDIO_DEFAULT_ORGANIZATION}
|
||||||
DEFAULT_PROJECT_NAME: ${STUDIO_DEFAULT_PROJECT}
|
DEFAULT_PROJECT_NAME: ${STUDIO_DEFAULT_PROJECT}
|
||||||
|
OPENAI_API_KEY: ${OPENAI_API_KEY:-}
|
||||||
|
|
||||||
SUPABASE_URL: http://kong:8000
|
SUPABASE_URL: http://kong:8000
|
||||||
SUPABASE_PUBLIC_URL: ${SUPABASE_PUBLIC_URL}
|
SUPABASE_PUBLIC_URL: ${SUPABASE_PUBLIC_URL}
|
||||||
@@ -38,7 +41,7 @@ services:
|
|||||||
SUPABASE_SERVICE_KEY: ${SERVICE_ROLE_KEY}
|
SUPABASE_SERVICE_KEY: ${SERVICE_ROLE_KEY}
|
||||||
AUTH_JWT_SECRET: ${JWT_SECRET}
|
AUTH_JWT_SECRET: ${JWT_SECRET}
|
||||||
|
|
||||||
LOGFLARE_API_KEY: ${LOGFLARE_API_KEY}
|
LOGFLARE_PRIVATE_ACCESS_TOKEN: ${LOGFLARE_PRIVATE_ACCESS_TOKEN}
|
||||||
LOGFLARE_URL: http://analytics:4000
|
LOGFLARE_URL: http://analytics:4000
|
||||||
NEXT_PUBLIC_ENABLE_LOGS: true
|
NEXT_PUBLIC_ENABLE_LOGS: true
|
||||||
# Comment to use Big Query backend for analytics
|
# Comment to use Big Query backend for analytics
|
||||||
@@ -49,8 +52,9 @@ services:
|
|||||||
kong:
|
kong:
|
||||||
image: kong:2.8.1
|
image: kong:2.8.1
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
# https://unix.stackexchange.com/a/294837
|
volumes:
|
||||||
entrypoint: bash -c 'eval "echo \"$$(cat ~/temp.yml)\"" > ~/kong.yml && /docker-entrypoint.sh kong docker-start'
|
# https://github.com/supabase/supabase/issues/12661
|
||||||
|
- ./volumes/api/kong.yml:/home/kong/temp.yml:ro,z
|
||||||
depends_on:
|
depends_on:
|
||||||
analytics:
|
analytics:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
@@ -66,18 +70,13 @@ services:
|
|||||||
SUPABASE_SERVICE_KEY: ${SERVICE_ROLE_KEY}
|
SUPABASE_SERVICE_KEY: ${SERVICE_ROLE_KEY}
|
||||||
DASHBOARD_USERNAME: ${DASHBOARD_USERNAME}
|
DASHBOARD_USERNAME: ${DASHBOARD_USERNAME}
|
||||||
DASHBOARD_PASSWORD: ${DASHBOARD_PASSWORD}
|
DASHBOARD_PASSWORD: ${DASHBOARD_PASSWORD}
|
||||||
volumes:
|
# https://unix.stackexchange.com/a/294837
|
||||||
# https://github.com/supabase/supabase/issues/12661
|
entrypoint: bash -c 'eval "echo \"$$(cat ~/temp.yml)\"" > ~/kong.yml &&
|
||||||
- ./volumes/api/kong.yml:/home/kong/temp.yml:ro
|
/docker-entrypoint.sh kong docker-start'
|
||||||
|
|
||||||
auth:
|
auth:
|
||||||
image: supabase/gotrue:v2.158.1
|
image: supabase/gotrue:v2.177.0
|
||||||
depends_on:
|
restart: unless-stopped
|
||||||
db:
|
|
||||||
# Disable this if you are using an external Postgres database
|
|
||||||
condition: service_healthy
|
|
||||||
analytics:
|
|
||||||
condition: service_healthy
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test:
|
test:
|
||||||
[
|
[
|
||||||
@@ -86,12 +85,17 @@ services:
|
|||||||
"--no-verbose",
|
"--no-verbose",
|
||||||
"--tries=1",
|
"--tries=1",
|
||||||
"--spider",
|
"--spider",
|
||||||
"http://localhost:9999/health",
|
"http://localhost:9999/health"
|
||||||
]
|
]
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
interval: 5s
|
interval: 5s
|
||||||
retries: 3
|
retries: 3
|
||||||
restart: unless-stopped
|
depends_on:
|
||||||
|
db:
|
||||||
|
# Disable this if you are using an external Postgres database
|
||||||
|
condition: service_healthy
|
||||||
|
analytics:
|
||||||
|
condition: service_healthy
|
||||||
environment:
|
environment:
|
||||||
GOTRUE_API_HOST: 0.0.0.0
|
GOTRUE_API_HOST: 0.0.0.0
|
||||||
GOTRUE_API_PORT: 9999
|
GOTRUE_API_PORT: 9999
|
||||||
@@ -113,6 +117,10 @@ services:
|
|||||||
GOTRUE_EXTERNAL_EMAIL_ENABLED: ${ENABLE_EMAIL_SIGNUP}
|
GOTRUE_EXTERNAL_EMAIL_ENABLED: ${ENABLE_EMAIL_SIGNUP}
|
||||||
GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED: ${ENABLE_ANONYMOUS_USERS}
|
GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED: ${ENABLE_ANONYMOUS_USERS}
|
||||||
GOTRUE_MAILER_AUTOCONFIRM: ${ENABLE_EMAIL_AUTOCONFIRM}
|
GOTRUE_MAILER_AUTOCONFIRM: ${ENABLE_EMAIL_AUTOCONFIRM}
|
||||||
|
|
||||||
|
# Uncomment to bypass nonce check in ID Token flow. Commonly set to true when using Google Sign In on mobile.
|
||||||
|
# GOTRUE_EXTERNAL_SKIP_NONCE_CHECK: true
|
||||||
|
|
||||||
# GOTRUE_MAILER_SECURE_EMAIL_CHANGE_ENABLED: true
|
# GOTRUE_MAILER_SECURE_EMAIL_CHANGE_ENABLED: true
|
||||||
# GOTRUE_SMTP_MAX_FREQUENCY: 1s
|
# GOTRUE_SMTP_MAX_FREQUENCY: 1s
|
||||||
GOTRUE_SMTP_ADMIN_EMAIL: ${SMTP_ADMIN_EMAIL}
|
GOTRUE_SMTP_ADMIN_EMAIL: ${SMTP_ADMIN_EMAIL}
|
||||||
@@ -128,26 +136,35 @@ services:
|
|||||||
|
|
||||||
GOTRUE_EXTERNAL_PHONE_ENABLED: ${ENABLE_PHONE_SIGNUP}
|
GOTRUE_EXTERNAL_PHONE_ENABLED: ${ENABLE_PHONE_SIGNUP}
|
||||||
GOTRUE_SMS_AUTOCONFIRM: ${ENABLE_PHONE_AUTOCONFIRM}
|
GOTRUE_SMS_AUTOCONFIRM: ${ENABLE_PHONE_AUTOCONFIRM}
|
||||||
# Uncomment to enable custom access token hook. You'll need to create a public.custom_access_token_hook function and grant necessary permissions.
|
# Uncomment to enable custom access token hook. Please see: https://supabase.com/docs/guides/auth/auth-hooks for full list of hooks and additional details about custom_access_token_hook
|
||||||
# See: https://supabase.com/docs/guides/auth/auth-hooks#hook-custom-access-token for details
|
|
||||||
# GOTRUE_HOOK_CUSTOM_ACCESS_TOKEN_ENABLED="true"
|
|
||||||
# GOTRUE_HOOK_CUSTOM_ACCESS_TOKEN_URI="pg-functions://postgres/public/custom_access_token_hook"
|
|
||||||
|
|
||||||
# GOTRUE_HOOK_MFA_VERIFICATION_ATTEMPT_ENABLED="true"
|
# GOTRUE_HOOK_CUSTOM_ACCESS_TOKEN_ENABLED: "true"
|
||||||
# GOTRUE_HOOK_MFA_VERIFICATION_ATTEMPT_URI="pg-functions://postgres/public/mfa_verification_attempt"
|
# GOTRUE_HOOK_CUSTOM_ACCESS_TOKEN_URI: "pg-functions://postgres/public/custom_access_token_hook"
|
||||||
|
# GOTRUE_HOOK_CUSTOM_ACCESS_TOKEN_SECRETS: "<standard-base64-secret>"
|
||||||
|
|
||||||
# GOTRUE_HOOK_PASSWORD_VERIFICATION_ATTEMPT_ENABLED="true"
|
# GOTRUE_HOOK_MFA_VERIFICATION_ATTEMPT_ENABLED: "true"
|
||||||
# GOTRUE_HOOK_PASSWORD_VERIFICATION_ATTEMPT_URI="pg-functions://postgres/public/password_verification_attempt"
|
# GOTRUE_HOOK_MFA_VERIFICATION_ATTEMPT_URI: "pg-functions://postgres/public/mfa_verification_attempt"
|
||||||
|
|
||||||
|
# GOTRUE_HOOK_PASSWORD_VERIFICATION_ATTEMPT_ENABLED: "true"
|
||||||
|
# GOTRUE_HOOK_PASSWORD_VERIFICATION_ATTEMPT_URI: "pg-functions://postgres/public/password_verification_attempt"
|
||||||
|
|
||||||
|
# GOTRUE_HOOK_SEND_SMS_ENABLED: "false"
|
||||||
|
# GOTRUE_HOOK_SEND_SMS_URI: "pg-functions://postgres/public/custom_access_token_hook"
|
||||||
|
# GOTRUE_HOOK_SEND_SMS_SECRETS: "v1,whsec_VGhpcyBpcyBhbiBleGFtcGxlIG9mIGEgc2hvcnRlciBCYXNlNjQgc3RyaW5n"
|
||||||
|
|
||||||
|
# GOTRUE_HOOK_SEND_EMAIL_ENABLED: "false"
|
||||||
|
# GOTRUE_HOOK_SEND_EMAIL_URI: "http://host.docker.internal:54321/functions/v1/email_sender"
|
||||||
|
# GOTRUE_HOOK_SEND_EMAIL_SECRETS: "v1,whsec_VGhpcyBpcyBhbiBleGFtcGxlIG9mIGEgc2hvcnRlciBCYXNlNjQgc3RyaW5n"
|
||||||
|
|
||||||
rest:
|
rest:
|
||||||
image: postgrest/postgrest:v12.2.0
|
image: postgrest/postgrest:v12.2.12
|
||||||
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
# Disable this if you are using an external Postgres database
|
# Disable this if you are using an external Postgres database
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
analytics:
|
analytics:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
environment:
|
||||||
PGRST_DB_URI: postgres://authenticator:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
|
PGRST_DB_URI: postgres://authenticator:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
|
||||||
PGRST_DB_SCHEMAS: ${PGRST_DB_SCHEMAS}
|
PGRST_DB_SCHEMAS: ${PGRST_DB_SCHEMAS}
|
||||||
@@ -156,11 +173,12 @@ services:
|
|||||||
PGRST_DB_USE_LEGACY_GUCS: "false"
|
PGRST_DB_USE_LEGACY_GUCS: "false"
|
||||||
PGRST_APP_SETTINGS_JWT_SECRET: ${JWT_SECRET}
|
PGRST_APP_SETTINGS_JWT_SECRET: ${JWT_SECRET}
|
||||||
PGRST_APP_SETTINGS_JWT_EXP: ${JWT_EXPIRY}
|
PGRST_APP_SETTINGS_JWT_EXP: ${JWT_EXPIRY}
|
||||||
command: "postgrest"
|
command: [ "postgrest" ]
|
||||||
|
|
||||||
realtime:
|
realtime:
|
||||||
# This container name looks inconsistent but is correct because realtime constructs tenant id by parsing the subdomain
|
# This container name looks inconsistent but is correct because realtime constructs tenant id by parsing the subdomain
|
||||||
image: supabase/realtime:v2.30.23
|
image: supabase/realtime:v2.34.47
|
||||||
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
# Disable this if you are using an external Postgres database
|
# Disable this if you are using an external Postgres database
|
||||||
@@ -178,12 +196,11 @@ services:
|
|||||||
"/dev/null",
|
"/dev/null",
|
||||||
"-H",
|
"-H",
|
||||||
"Authorization: Bearer ${ANON_KEY}",
|
"Authorization: Bearer ${ANON_KEY}",
|
||||||
"http://localhost:4000/api/tenants/realtime-dev/health",
|
"http://localhost:4000/api/tenants/realtime-dev/health"
|
||||||
]
|
]
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
interval: 5s
|
interval: 5s
|
||||||
retries: 3
|
retries: 3
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
environment:
|
||||||
PORT: 4000
|
PORT: 4000
|
||||||
DB_HOST: ${POSTGRES_HOST}
|
DB_HOST: ${POSTGRES_HOST}
|
||||||
@@ -191,27 +208,23 @@ services:
|
|||||||
DB_USER: supabase_admin
|
DB_USER: supabase_admin
|
||||||
DB_PASSWORD: ${POSTGRES_PASSWORD}
|
DB_PASSWORD: ${POSTGRES_PASSWORD}
|
||||||
DB_NAME: ${POSTGRES_DB}
|
DB_NAME: ${POSTGRES_DB}
|
||||||
DB_AFTER_CONNECT_QUERY: "SET search_path TO _realtime"
|
DB_AFTER_CONNECT_QUERY: 'SET search_path TO _realtime'
|
||||||
DB_ENC_KEY: supabaserealtime
|
DB_ENC_KEY: supabaserealtime
|
||||||
API_JWT_SECRET: ${JWT_SECRET}
|
API_JWT_SECRET: ${JWT_SECRET}
|
||||||
SECRET_KEY_BASE: UpNVntn3cDxHJpq99YMc1T1AQgQpc8kfYTuRgBiYa15BLrx8etQoXz3gZv1/u2oq
|
SECRET_KEY_BASE: ${SECRET_KEY_BASE}
|
||||||
ERL_AFLAGS: -proto_dist inet_tcp
|
ERL_AFLAGS: -proto_dist inet_tcp
|
||||||
DNS_NODES: "''"
|
DNS_NODES: "''"
|
||||||
RLIMIT_NOFILE: "10000"
|
RLIMIT_NOFILE: "10000"
|
||||||
APP_NAME: realtime
|
APP_NAME: realtime
|
||||||
SEED_SELF_HOST: true
|
SEED_SELF_HOST: true
|
||||||
|
RUN_JANITOR: true
|
||||||
|
|
||||||
# To use S3 backed storage: docker compose -f docker-compose.yml -f docker-compose.s3.yml up
|
# To use S3 backed storage: docker compose -f docker-compose.yml -f docker-compose.s3.yml up
|
||||||
storage:
|
storage:
|
||||||
image: supabase/storage-api:v1.10.1
|
image: supabase/storage-api:v1.25.7
|
||||||
depends_on:
|
restart: unless-stopped
|
||||||
db:
|
volumes:
|
||||||
# Disable this if you are using an external Postgres database
|
- ./volumes/storage:/var/lib/storage:z
|
||||||
condition: service_healthy
|
|
||||||
rest:
|
|
||||||
condition: service_started
|
|
||||||
imgproxy:
|
|
||||||
condition: service_started
|
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test:
|
test:
|
||||||
[
|
[
|
||||||
@@ -220,12 +233,19 @@ services:
|
|||||||
"--no-verbose",
|
"--no-verbose",
|
||||||
"--tries=1",
|
"--tries=1",
|
||||||
"--spider",
|
"--spider",
|
||||||
"http://localhost:5000/status",
|
"http://storage:5000/status"
|
||||||
]
|
]
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
interval: 5s
|
interval: 5s
|
||||||
retries: 3
|
retries: 3
|
||||||
restart: unless-stopped
|
depends_on:
|
||||||
|
db:
|
||||||
|
# Disable this if you are using an external Postgres database
|
||||||
|
condition: service_healthy
|
||||||
|
rest:
|
||||||
|
condition: service_started
|
||||||
|
imgproxy:
|
||||||
|
condition: service_started
|
||||||
environment:
|
environment:
|
||||||
ANON_KEY: ${ANON_KEY}
|
ANON_KEY: ${ANON_KEY}
|
||||||
SERVICE_KEY: ${SERVICE_ROLE_KEY}
|
SERVICE_KEY: ${SERVICE_ROLE_KEY}
|
||||||
@@ -241,11 +261,12 @@ services:
|
|||||||
GLOBAL_S3_BUCKET: stub
|
GLOBAL_S3_BUCKET: stub
|
||||||
ENABLE_IMAGE_TRANSFORMATION: "true"
|
ENABLE_IMAGE_TRANSFORMATION: "true"
|
||||||
IMGPROXY_URL: http://imgproxy:5001
|
IMGPROXY_URL: http://imgproxy:5001
|
||||||
volumes:
|
|
||||||
- ./volumes/storage:/var/lib/storage:z
|
|
||||||
|
|
||||||
imgproxy:
|
imgproxy:
|
||||||
image: darthsim/imgproxy:v3.8.0
|
image: darthsim/imgproxy:v3.8.0
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./volumes/storage:/var/lib/storage:z
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: [ "CMD", "imgproxy", "health" ]
|
test: [ "CMD", "imgproxy", "health" ]
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
@@ -256,18 +277,16 @@ services:
|
|||||||
IMGPROXY_LOCAL_FILESYSTEM_ROOT: /
|
IMGPROXY_LOCAL_FILESYSTEM_ROOT: /
|
||||||
IMGPROXY_USE_ETAG: "true"
|
IMGPROXY_USE_ETAG: "true"
|
||||||
IMGPROXY_ENABLE_WEBP_DETECTION: ${IMGPROXY_ENABLE_WEBP_DETECTION}
|
IMGPROXY_ENABLE_WEBP_DETECTION: ${IMGPROXY_ENABLE_WEBP_DETECTION}
|
||||||
volumes:
|
|
||||||
- ./volumes/storage:/var/lib/storage:z
|
|
||||||
|
|
||||||
meta:
|
meta:
|
||||||
image: supabase/postgres-meta:v0.83.2
|
image: supabase/postgres-meta:v0.91.0
|
||||||
|
restart: unless-stopped
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
# Disable this if you are using an external Postgres database
|
# Disable this if you are using an external Postgres database
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
analytics:
|
analytics:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
restart: unless-stopped
|
|
||||||
environment:
|
environment:
|
||||||
PG_META_PORT: 8080
|
PG_META_PORT: 8080
|
||||||
PG_META_DB_HOST: ${POSTGRES_HOST}
|
PG_META_DB_HOST: ${POSTGRES_HOST}
|
||||||
@@ -277,8 +296,10 @@ services:
|
|||||||
PG_META_DB_PASSWORD: ${POSTGRES_PASSWORD}
|
PG_META_DB_PASSWORD: ${POSTGRES_PASSWORD}
|
||||||
|
|
||||||
functions:
|
functions:
|
||||||
image: supabase/edge-runtime:v1.56.1
|
image: supabase/edge-runtime:v1.67.4
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./volumes/functions:/home/deno/functions:Z
|
||||||
depends_on:
|
depends_on:
|
||||||
analytics:
|
analytics:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
@@ -290,46 +311,42 @@ services:
|
|||||||
SUPABASE_DB_URL: postgresql://postgres:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
|
SUPABASE_DB_URL: postgresql://postgres:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
|
||||||
# TODO: Allow configuring VERIFY_JWT per function. This PR might help: https://github.com/supabase/cli/pull/786
|
# TODO: Allow configuring VERIFY_JWT per function. This PR might help: https://github.com/supabase/cli/pull/786
|
||||||
VERIFY_JWT: "${FUNCTIONS_VERIFY_JWT}"
|
VERIFY_JWT: "${FUNCTIONS_VERIFY_JWT}"
|
||||||
volumes:
|
command: [ "start", "--main-service", "/home/deno/functions/main" ]
|
||||||
- ./volumes/functions:/home/deno/functions:Z
|
|
||||||
command:
|
|
||||||
- start
|
|
||||||
- --main-service
|
|
||||||
- /home/deno/functions/main
|
|
||||||
|
|
||||||
analytics:
|
analytics:
|
||||||
image: supabase/logflare:1.4.0
|
image: supabase/logflare:1.14.2
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "http://localhost:4000/health"]
|
|
||||||
timeout: 5s
|
|
||||||
interval: 5s
|
|
||||||
retries: 10
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
depends_on:
|
|
||||||
db:
|
|
||||||
# Disable this if you are using an external Postgres database
|
|
||||||
condition: service_healthy
|
|
||||||
# Uncomment to use Big Query backend for analytics
|
# Uncomment to use Big Query backend for analytics
|
||||||
# volumes:
|
# volumes:
|
||||||
# - type: bind
|
# - type: bind
|
||||||
# source: ${PWD}/gcloud.json
|
# source: ${PWD}/gcloud.json
|
||||||
# target: /opt/app/rel/logflare/bin/gcloud.json
|
# target: /opt/app/rel/logflare/bin/gcloud.json
|
||||||
# read_only: true
|
# read_only: true
|
||||||
|
healthcheck:
|
||||||
|
test: [ "CMD", "curl", "http://localhost:4000/health" ]
|
||||||
|
timeout: 5s
|
||||||
|
interval: 5s
|
||||||
|
retries: 10
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
# Disable this if you are using an external Postgres database
|
||||||
|
condition: service_healthy
|
||||||
environment:
|
environment:
|
||||||
LOGFLARE_NODE_HOST: 127.0.0.1
|
LOGFLARE_NODE_HOST: 127.0.0.1
|
||||||
DB_USERNAME: supabase_admin
|
DB_USERNAME: supabase_admin
|
||||||
DB_DATABASE: ${POSTGRES_DB}
|
DB_DATABASE: _supabase
|
||||||
DB_HOSTNAME: ${POSTGRES_HOST}
|
DB_HOSTNAME: ${POSTGRES_HOST}
|
||||||
DB_PORT: ${POSTGRES_PORT}
|
DB_PORT: ${POSTGRES_PORT}
|
||||||
DB_PASSWORD: ${POSTGRES_PASSWORD}
|
DB_PASSWORD: ${POSTGRES_PASSWORD}
|
||||||
DB_SCHEMA: _analytics
|
DB_SCHEMA: _analytics
|
||||||
LOGFLARE_API_KEY: ${LOGFLARE_API_KEY}
|
LOGFLARE_PUBLIC_ACCESS_TOKEN: ${LOGFLARE_PUBLIC_ACCESS_TOKEN}
|
||||||
|
LOGFLARE_PRIVATE_ACCESS_TOKEN: ${LOGFLARE_PRIVATE_ACCESS_TOKEN}
|
||||||
LOGFLARE_SINGLE_TENANT: true
|
LOGFLARE_SINGLE_TENANT: true
|
||||||
LOGFLARE_SUPABASE_MODE: true
|
LOGFLARE_SUPABASE_MODE: true
|
||||||
LOGFLARE_MIN_CLUSTER_SIZE: 1
|
LOGFLARE_MIN_CLUSTER_SIZE: 1
|
||||||
|
|
||||||
# Comment variables to use Big Query backend for analytics
|
# Comment variables to use Big Query backend for analytics
|
||||||
POSTGRES_BACKEND_URL: postgresql://supabase_admin:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
|
POSTGRES_BACKEND_URL: postgresql://supabase_admin:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/_supabase
|
||||||
POSTGRES_BACKEND_SCHEMA: _analytics
|
POSTGRES_BACKEND_SCHEMA: _analytics
|
||||||
LOGFLARE_FEATURE_FLAG_OVERRIDE: multibackend=true
|
LOGFLARE_FEATURE_FLAG_OVERRIDE: multibackend=true
|
||||||
# Uncomment to use Big Query backend for analytics
|
# Uncomment to use Big Query backend for analytics
|
||||||
@@ -338,32 +355,8 @@ services:
|
|||||||
|
|
||||||
# Comment out everything below this point if you are using an external Postgres database
|
# Comment out everything below this point if you are using an external Postgres database
|
||||||
db:
|
db:
|
||||||
image: supabase/postgres:15.1.1.78
|
image: supabase/postgres:15.8.1.060
|
||||||
healthcheck:
|
|
||||||
test: pg_isready -U postgres -h localhost
|
|
||||||
interval: 5s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 10
|
|
||||||
depends_on:
|
|
||||||
vector:
|
|
||||||
condition: service_healthy
|
|
||||||
command:
|
|
||||||
- postgres
|
|
||||||
- -c
|
|
||||||
- config_file=/etc/postgresql/postgresql.conf
|
|
||||||
- -c
|
|
||||||
- log_min_messages=fatal # prevents Realtime polling queries from appearing in logs
|
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
environment:
|
|
||||||
POSTGRES_HOST: /var/run/postgresql
|
|
||||||
PGPORT: ${POSTGRES_PORT}
|
|
||||||
POSTGRES_PORT: ${POSTGRES_PORT}
|
|
||||||
PGPASSWORD: ${POSTGRES_PASSWORD}
|
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
|
||||||
PGDATABASE: ${POSTGRES_DB}
|
|
||||||
POSTGRES_DB: ${POSTGRES_DB}
|
|
||||||
JWT_SECRET: ${JWT_SECRET}
|
|
||||||
JWT_EXP: ${JWT_EXPIRY}
|
|
||||||
volumes:
|
volumes:
|
||||||
- ./volumes/db/realtime.sql:/docker-entrypoint-initdb.d/migrations/99-realtime.sql:Z
|
- ./volumes/db/realtime.sql:/docker-entrypoint-initdb.d/migrations/99-realtime.sql:Z
|
||||||
# Must be superuser to create event trigger
|
# Must be superuser to create event trigger
|
||||||
@@ -374,13 +367,47 @@ services:
|
|||||||
- ./volumes/db/jwt.sql:/docker-entrypoint-initdb.d/init-scripts/99-jwt.sql:Z
|
- ./volumes/db/jwt.sql:/docker-entrypoint-initdb.d/init-scripts/99-jwt.sql:Z
|
||||||
# PGDATA directory is persisted between restarts
|
# PGDATA directory is persisted between restarts
|
||||||
- ./volumes/db/data:/var/lib/postgresql/data:Z
|
- ./volumes/db/data:/var/lib/postgresql/data:Z
|
||||||
|
# Changes required for internal supabase data such as _analytics
|
||||||
|
- ./volumes/db/_supabase.sql:/docker-entrypoint-initdb.d/migrations/97-_supabase.sql:Z
|
||||||
# Changes required for Analytics support
|
# Changes required for Analytics support
|
||||||
- ./volumes/db/logs.sql:/docker-entrypoint-initdb.d/migrations/99-logs.sql:Z
|
- ./volumes/db/logs.sql:/docker-entrypoint-initdb.d/migrations/99-logs.sql:Z
|
||||||
|
# Changes required for Pooler support
|
||||||
|
- ./volumes/db/pooler.sql:/docker-entrypoint-initdb.d/migrations/99-pooler.sql:Z
|
||||||
# Use named volume to persist pgsodium decryption key between restarts
|
# Use named volume to persist pgsodium decryption key between restarts
|
||||||
- db-config:/etc/postgresql-custom
|
- db-config:/etc/postgresql-custom
|
||||||
|
healthcheck:
|
||||||
|
test: [ "CMD", "pg_isready", "-U", "postgres", "-h", "localhost" ]
|
||||||
|
interval: 5s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 10
|
||||||
|
depends_on:
|
||||||
|
vector:
|
||||||
|
condition: service_healthy
|
||||||
|
environment:
|
||||||
|
POSTGRES_HOST: /var/run/postgresql
|
||||||
|
PGPORT: ${POSTGRES_PORT}
|
||||||
|
POSTGRES_PORT: ${POSTGRES_PORT}
|
||||||
|
PGPASSWORD: ${POSTGRES_PASSWORD}
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||||
|
PGDATABASE: ${POSTGRES_DB}
|
||||||
|
POSTGRES_DB: ${POSTGRES_DB}
|
||||||
|
JWT_SECRET: ${JWT_SECRET}
|
||||||
|
JWT_EXP: ${JWT_EXPIRY}
|
||||||
|
command:
|
||||||
|
[
|
||||||
|
"postgres",
|
||||||
|
"-c",
|
||||||
|
"config_file=/etc/postgresql/postgresql.conf",
|
||||||
|
"-c",
|
||||||
|
"log_min_messages=fatal" # prevents Realtime polling queries from appearing in logs
|
||||||
|
]
|
||||||
|
|
||||||
vector:
|
vector:
|
||||||
image: timberio/vector:0.28.1-alpine
|
image: timberio/vector:0.28.1-alpine
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./volumes/logs/vector.yml:/etc/vector/vector.yml:ro,z
|
||||||
|
- ${DOCKER_SOCKET_LOCATION}:/var/run/docker.sock:ro,z
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test:
|
test:
|
||||||
[
|
[
|
||||||
@@ -389,17 +416,67 @@ services:
|
|||||||
"--no-verbose",
|
"--no-verbose",
|
||||||
"--tries=1",
|
"--tries=1",
|
||||||
"--spider",
|
"--spider",
|
||||||
"http://vector:9001/health",
|
"http://vector:9001/health"
|
||||||
]
|
]
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
interval: 5s
|
interval: 5s
|
||||||
retries: 3
|
retries: 3
|
||||||
volumes:
|
|
||||||
- ./volumes/logs/vector.yml:/etc/vector/vector.yml:ro
|
|
||||||
- ${DOCKER_SOCKET_LOCATION}:/var/run/docker.sock:ro
|
|
||||||
environment:
|
environment:
|
||||||
LOGFLARE_API_KEY: ${LOGFLARE_API_KEY}
|
LOGFLARE_PUBLIC_ACCESS_TOKEN: ${LOGFLARE_PUBLIC_ACCESS_TOKEN}
|
||||||
command: ["--config", "etc/vector/vector.yml"]
|
command: [ "--config", "/etc/vector/vector.yml" ]
|
||||||
|
security_opt:
|
||||||
|
- "label=disable"
|
||||||
|
|
||||||
|
# Update the DATABASE_URL if you are using an external Postgres database
|
||||||
|
supavisor:
|
||||||
|
image: supabase/supavisor:2.5.7
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ./volumes/pooler/pooler.exs:/etc/pooler/pooler.exs:ro,z
|
||||||
|
healthcheck:
|
||||||
|
test:
|
||||||
|
[
|
||||||
|
"CMD",
|
||||||
|
"curl",
|
||||||
|
"-sSfL",
|
||||||
|
"--head",
|
||||||
|
"-o",
|
||||||
|
"/dev/null",
|
||||||
|
"http://127.0.0.1:4000/api/health"
|
||||||
|
]
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
analytics:
|
||||||
|
condition: service_healthy
|
||||||
|
environment:
|
||||||
|
PORT: 4000
|
||||||
|
POSTGRES_PORT: ${POSTGRES_PORT}
|
||||||
|
POSTGRES_DB: ${POSTGRES_DB}
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||||
|
DATABASE_URL: ecto://supabase_admin:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/_supabase
|
||||||
|
CLUSTER_POSTGRES: true
|
||||||
|
SECRET_KEY_BASE: ${SECRET_KEY_BASE}
|
||||||
|
VAULT_ENC_KEY: ${VAULT_ENC_KEY}
|
||||||
|
API_JWT_SECRET: ${JWT_SECRET}
|
||||||
|
METRICS_JWT_SECRET: ${JWT_SECRET}
|
||||||
|
REGION: local
|
||||||
|
ERL_AFLAGS: -proto_dist inet_tcp
|
||||||
|
POOLER_TENANT_ID: ${POOLER_TENANT_ID}
|
||||||
|
POOLER_DEFAULT_POOL_SIZE: ${POOLER_DEFAULT_POOL_SIZE}
|
||||||
|
POOLER_MAX_CLIENT_CONN: ${POOLER_MAX_CLIENT_CONN}
|
||||||
|
POOLER_POOL_MODE: transaction
|
||||||
|
DB_POOL_SIZE: ${POOLER_DB_POOL_SIZE}
|
||||||
|
command:
|
||||||
|
[
|
||||||
|
"/bin/sh",
|
||||||
|
"-c",
|
||||||
|
"/app/bin/migrate && /app/bin/supavisor eval \"$$(cat
|
||||||
|
/etc/pooler/pooler.exs)\" && /app/bin/server"
|
||||||
|
]
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
db-config:
|
db-config:
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "WARNING: This will remove all containers and container data, and will reset the .env file. This action cannot be undone!"
|
||||||
|
read -p "Are you sure you want to proceed? (y/N) " -n 1 -r
|
||||||
|
echo # Move to a new line
|
||||||
|
if [[ ! $REPLY =~ ^[Yy]$ ]]
|
||||||
|
then
|
||||||
|
echo "Operation cancelled."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Stopping and removing all containers..."
|
||||||
|
docker compose -f docker-compose.yml -f ./dev/docker-compose.dev.yml down -v --remove-orphans
|
||||||
|
|
||||||
|
echo "Cleaning up bind-mounted directories..."
|
||||||
|
BIND_MOUNTS=(
|
||||||
|
"./volumes/db/data"
|
||||||
|
)
|
||||||
|
|
||||||
|
for DIR in "${BIND_MOUNTS[@]}"; do
|
||||||
|
if [ -d "$DIR" ]; then
|
||||||
|
echo "Deleting $DIR..."
|
||||||
|
rm -rf "$DIR"
|
||||||
|
else
|
||||||
|
echo "Directory $DIR does not exist. Skipping bind mount deletion step..."
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Resetting .env file..."
|
||||||
|
if [ -f ".env" ]; then
|
||||||
|
echo "Removing existing .env file..."
|
||||||
|
rm -f .env
|
||||||
|
else
|
||||||
|
echo "No .env file found. Skipping .env removal step..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f ".env.example" ]; then
|
||||||
|
echo "Copying .env.example to .env..."
|
||||||
|
cp .env.example .env
|
||||||
|
else
|
||||||
|
echo ".env.example file not found. Skipping .env reset step..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Cleanup complete!"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
\set pguser `echo "$POSTGRES_USER"`
|
||||||
|
|
||||||
|
CREATE DATABASE _supabase WITH OWNER :pguser;
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
\set pguser `echo "$POSTGRES_USER"`
|
\set pguser `echo "$POSTGRES_USER"`
|
||||||
|
|
||||||
|
\c _supabase
|
||||||
create schema if not exists _analytics;
|
create schema if not exists _analytics;
|
||||||
alter schema _analytics owner to :pguser;
|
alter schema _analytics owner to :pguser;
|
||||||
|
\c postgres
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
\set pguser `echo "$POSTGRES_USER"`
|
||||||
|
|
||||||
|
\c _supabase
|
||||||
|
create schema if not exists _supavisor;
|
||||||
|
alter schema _supavisor owner to :pguser;
|
||||||
|
\c postgres
|
||||||
@@ -165,7 +165,9 @@ sinks:
|
|||||||
method: 'post'
|
method: 'post'
|
||||||
request:
|
request:
|
||||||
retry_max_duration_secs: 10
|
retry_max_duration_secs: 10
|
||||||
uri: 'http://analytics:4000/api/logs?source_name=gotrue.logs.prod&api_key=${LOGFLARE_API_KEY?LOGFLARE_API_KEY is required}'
|
headers:
|
||||||
|
x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required}
|
||||||
|
uri: 'http://analytics:4000/api/logs?source_name=gotrue.logs.prod'
|
||||||
logflare_realtime:
|
logflare_realtime:
|
||||||
type: 'http'
|
type: 'http'
|
||||||
inputs:
|
inputs:
|
||||||
@@ -175,7 +177,9 @@ sinks:
|
|||||||
method: 'post'
|
method: 'post'
|
||||||
request:
|
request:
|
||||||
retry_max_duration_secs: 10
|
retry_max_duration_secs: 10
|
||||||
uri: 'http://analytics:4000/api/logs?source_name=realtime.logs.prod&api_key=${LOGFLARE_API_KEY?LOGFLARE_API_KEY is required}'
|
headers:
|
||||||
|
x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required}
|
||||||
|
uri: 'http://analytics:4000/api/logs?source_name=realtime.logs.prod'
|
||||||
logflare_rest:
|
logflare_rest:
|
||||||
type: 'http'
|
type: 'http'
|
||||||
inputs:
|
inputs:
|
||||||
@@ -185,7 +189,9 @@ sinks:
|
|||||||
method: 'post'
|
method: 'post'
|
||||||
request:
|
request:
|
||||||
retry_max_duration_secs: 10
|
retry_max_duration_secs: 10
|
||||||
uri: 'http://analytics:4000/api/logs?source_name=postgREST.logs.prod&api_key=${LOGFLARE_API_KEY?LOGFLARE_API_KEY is required}'
|
headers:
|
||||||
|
x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required}
|
||||||
|
uri: 'http://analytics:4000/api/logs?source_name=postgREST.logs.prod'
|
||||||
logflare_db:
|
logflare_db:
|
||||||
type: 'http'
|
type: 'http'
|
||||||
inputs:
|
inputs:
|
||||||
@@ -195,10 +201,12 @@ sinks:
|
|||||||
method: 'post'
|
method: 'post'
|
||||||
request:
|
request:
|
||||||
retry_max_duration_secs: 10
|
retry_max_duration_secs: 10
|
||||||
|
headers:
|
||||||
|
x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required}
|
||||||
# We must route the sink through kong because ingesting logs before logflare is fully initialised will
|
# We must route the sink through kong because ingesting logs before logflare is fully initialised will
|
||||||
# lead to broken queries from studio. This works by the assumption that containers are started in the
|
# lead to broken queries from studio. This works by the assumption that containers are started in the
|
||||||
# following order: vector > db > logflare > kong
|
# following order: vector > db > logflare > kong
|
||||||
uri: 'http://kong:8000/analytics/v1/api/logs?source_name=postgres.logs&api_key=${LOGFLARE_API_KEY?LOGFLARE_API_KEY is required}'
|
uri: 'http://kong:8000/analytics/v1/api/logs?source_name=postgres.logs'
|
||||||
logflare_functions:
|
logflare_functions:
|
||||||
type: 'http'
|
type: 'http'
|
||||||
inputs:
|
inputs:
|
||||||
@@ -208,7 +216,9 @@ sinks:
|
|||||||
method: 'post'
|
method: 'post'
|
||||||
request:
|
request:
|
||||||
retry_max_duration_secs: 10
|
retry_max_duration_secs: 10
|
||||||
uri: 'http://analytics:4000/api/logs?source_name=deno-relay-logs&api_key=${LOGFLARE_API_KEY?LOGFLARE_API_KEY is required}'
|
headers:
|
||||||
|
x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required}
|
||||||
|
uri: 'http://analytics:4000/api/logs?source_name=deno-relay-logs'
|
||||||
logflare_storage:
|
logflare_storage:
|
||||||
type: 'http'
|
type: 'http'
|
||||||
inputs:
|
inputs:
|
||||||
@@ -218,7 +228,9 @@ sinks:
|
|||||||
method: 'post'
|
method: 'post'
|
||||||
request:
|
request:
|
||||||
retry_max_duration_secs: 10
|
retry_max_duration_secs: 10
|
||||||
uri: 'http://analytics:4000/api/logs?source_name=storage.logs.prod.2&api_key=${LOGFLARE_API_KEY?LOGFLARE_API_KEY is required}'
|
headers:
|
||||||
|
x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required}
|
||||||
|
uri: 'http://analytics:4000/api/logs?source_name=storage.logs.prod.2'
|
||||||
logflare_kong:
|
logflare_kong:
|
||||||
type: 'http'
|
type: 'http'
|
||||||
inputs:
|
inputs:
|
||||||
@@ -229,4 +241,6 @@ sinks:
|
|||||||
method: 'post'
|
method: 'post'
|
||||||
request:
|
request:
|
||||||
retry_max_duration_secs: 10
|
retry_max_duration_secs: 10
|
||||||
uri: 'http://analytics:4000/api/logs?source_name=cloudflare.logs.prod&api_key=${LOGFLARE_API_KEY?LOGFLARE_API_KEY is required}'
|
headers:
|
||||||
|
x-api-key: ${LOGFLARE_PUBLIC_ACCESS_TOKEN?LOGFLARE_PUBLIC_ACCESS_TOKEN is required}
|
||||||
|
uri: 'http://analytics:4000/api/logs?source_name=cloudflare.logs.prod'
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
{:ok, _} = Application.ensure_all_started(:supavisor)
|
||||||
|
|
||||||
|
{:ok, version} =
|
||||||
|
case Supavisor.Repo.query!("select version()") do
|
||||||
|
%{rows: [[ver]]} -> Supavisor.Helpers.parse_pg_version(ver)
|
||||||
|
_ -> nil
|
||||||
|
end
|
||||||
|
|
||||||
|
params = %{
|
||||||
|
"external_id" => System.get_env("POOLER_TENANT_ID"),
|
||||||
|
"db_host" => "db",
|
||||||
|
"db_port" => System.get_env("POSTGRES_PORT"),
|
||||||
|
"db_database" => System.get_env("POSTGRES_DB"),
|
||||||
|
"require_user" => false,
|
||||||
|
"auth_query" => "SELECT * FROM pgbouncer.get_auth($1)",
|
||||||
|
"default_max_clients" => System.get_env("POOLER_MAX_CLIENT_CONN"),
|
||||||
|
"default_pool_size" => System.get_env("POOLER_DEFAULT_POOL_SIZE"),
|
||||||
|
"default_parameter_status" => %{"server_version" => version},
|
||||||
|
"users" => [%{
|
||||||
|
"db_user" => "pgbouncer",
|
||||||
|
"db_password" => System.get_env("POSTGRES_PASSWORD"),
|
||||||
|
"mode_type" => System.get_env("POOLER_POOL_MODE"),
|
||||||
|
"pool_size" => System.get_env("POOLER_DEFAULT_POOL_SIZE"),
|
||||||
|
"is_manager" => true
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
|
||||||
|
if !Supavisor.Tenants.get_tenant_by_external_id(params["external_id"]) do
|
||||||
|
{:ok, _} = Supavisor.Tenants.create_tenant(params)
|
||||||
|
end
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import utils from "../utils.js";
|
||||||
|
|
||||||
|
await utils.cloneOrPullRepo({ repo: "https://github.com/supabase/supabase" });
|
||||||
|
await utils.copyDir("./repo/docker", "./code");
|
||||||
|
|
||||||
|
await utils.removeContainerNames("./code/docker-compose.yml");
|
||||||
|
await utils.removePorts("./code/docker-compose.yml");
|
||||||
|
|
||||||
|
await utils.searchReplace(
|
||||||
|
"./code/.env.example",
|
||||||
|
"SITE_URL=http://localhost:3000",
|
||||||
|
"SITE_URL=https://$(PRIMARY_DOMAIN)"
|
||||||
|
);
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
if [ ! -d "./repo" ]; then
|
|
||||||
git clone --depth 1 --branch master --single-branch https://github.com/supabase/supabase repo
|
|
||||||
else
|
|
||||||
cd repo
|
|
||||||
git pull
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
|
|
||||||
cp -r ./repo/docker/. ./code
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
# Twenty
|
|
||||||
|
|
||||||
- copied from https://github.com/twentyhq/twenty
|
|
||||||
- removed `ports`
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
TAG=latest
|
|
||||||
|
|
||||||
POSTGRES_ADMIN_PASSWORD=replace_me_with_a_strong_password
|
|
||||||
|
|
||||||
PG_DATABASE_HOST=db:5432
|
|
||||||
|
|
||||||
SERVER_URL=http://localhost:3000
|
|
||||||
# Uncoment if you are serving your front on another server than the API (eg. bucket)
|
|
||||||
# FRONT_BASE_URL=http://localhost:3000
|
|
||||||
|
|
||||||
# Use openssl rand -base64 32 for each secret
|
|
||||||
ACCESS_TOKEN_SECRET=replace_me_with_a_random_string_access
|
|
||||||
LOGIN_TOKEN_SECRET=replace_me_with_a_random_string_login
|
|
||||||
REFRESH_TOKEN_SECRET=replace_me_with_a_random_string_refresh
|
|
||||||
FILE_TOKEN_SECRET=replace_me_with_a_random_string_refresh
|
|
||||||
|
|
||||||
SIGN_IN_PREFILLED=true
|
|
||||||
|
|
||||||
STORAGE_TYPE=local
|
|
||||||
|
|
||||||
# STORAGE_S3_REGION=eu-west3
|
|
||||||
# STORAGE_S3_NAME=my-bucket
|
|
||||||
# STORAGE_S3_ENDPOINT=
|
|
||||||
|
|
||||||
MESSAGE_QUEUE_TYPE=pg-boss
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
dev-build:
|
|
||||||
@docker compose -f dev/docker-compose.yml down -v
|
|
||||||
@docker compose -f dev/docker-compose.yml build
|
|
||||||
|
|
||||||
dev-up:
|
|
||||||
@docker compose -f dev/docker-compose.yml up -d
|
|
||||||
|
|
||||||
dev-start:
|
|
||||||
@docker compose -f dev/docker-compose.yml start
|
|
||||||
|
|
||||||
dev-stop:
|
|
||||||
@docker compose -f dev/docker-compose.yml stop
|
|
||||||
|
|
||||||
dev-down:
|
|
||||||
@docker compose -f dev/docker-compose.yml down -v
|
|
||||||
|
|
||||||
dev-sh:
|
|
||||||
@docker compose -f dev/docker-compose.yml exec twenty-dev sh
|
|
||||||
|
|
||||||
dev-postgres-build:
|
|
||||||
@docker stop twenty_postgres || true
|
|
||||||
@docker rm twenty_postgres || true
|
|
||||||
@docker volume rm twenty_db_data || true
|
|
||||||
@docker compose -f dev/docker-compose.yml up --build postgres -d
|
|
||||||
|
|
||||||
prod-build:
|
|
||||||
@cd ../.. && docker build -f ./packages/twenty-docker/twenty/Dockerfile --tag twenty . && cd -
|
|
||||||
|
|
||||||
prod-run:
|
|
||||||
@docker run -d -p 3000:3000 --name twenty twenty
|
|
||||||
|
|
||||||
prod-postgres-build:
|
|
||||||
@cd ../.. && docker build -f ./packages/twenty-docker/twenty-postgres/Dockerfile --tag twenty-postgres . && cd -
|
|
||||||
|
|
||||||
prod-postgres-run:
|
|
||||||
@docker run -d -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres --name twenty-postgres twenty-postgres
|
|
||||||
|
|
||||||
prod-website-build:
|
|
||||||
@cd ../.. && docker build -f ./packages/twenty-docker/twenty-website/Dockerfile --tag twenty-website . && cd -
|
|
||||||
|
|
||||||
prod-website-run:
|
|
||||||
@docker run -d -p 3000:3000 --name twenty-website twenty-website
|
|
||||||
|
|
||||||
release-postgres:
|
|
||||||
@cd ../.. && docker buildx build \
|
|
||||||
--push \
|
|
||||||
--no-cache \
|
|
||||||
--platform linux/amd64,linux/arm64 \
|
|
||||||
-f ./packages/twenty-docker/twenty-postgres/Dockerfile -t twentycrm/twenty-postgres:$(version) -t twentycrm/twenty-postgres:latest . \
|
|
||||||
&& cd -
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
version: "3.9"
|
|
||||||
name: twenty
|
|
||||||
|
|
||||||
services:
|
|
||||||
change-vol-ownership:
|
|
||||||
image: ubuntu
|
|
||||||
user: root
|
|
||||||
volumes:
|
|
||||||
- server-local-data:/tmp/server-local-data
|
|
||||||
- docker-data:/tmp/docker-data
|
|
||||||
command: >
|
|
||||||
bash -c "
|
|
||||||
chown -R 1000:1000 /tmp/server-local-data
|
|
||||||
&& chown -R 1000:1000 /tmp/docker-data"
|
|
||||||
|
|
||||||
server:
|
|
||||||
image: twentycrm/twenty:${TAG}
|
|
||||||
volumes:
|
|
||||||
- server-local-data:/app/packages/twenty-server/${STORAGE_LOCAL_PATH:-.local-storage}
|
|
||||||
- docker-data:/app/docker-data
|
|
||||||
environment:
|
|
||||||
PORT: 3000
|
|
||||||
PG_DATABASE_URL: postgres://twenty:twenty@${PG_DATABASE_HOST}/default
|
|
||||||
SERVER_URL: ${SERVER_URL}
|
|
||||||
FRONT_BASE_URL: ${FRONT_BASE_URL:-$SERVER_URL}
|
|
||||||
MESSAGE_QUEUE_TYPE: ${MESSAGE_QUEUE_TYPE}
|
|
||||||
|
|
||||||
ENABLE_DB_MIGRATIONS: "true"
|
|
||||||
|
|
||||||
SIGN_IN_PREFILLED: ${SIGN_IN_PREFILLED}
|
|
||||||
STORAGE_TYPE: ${STORAGE_TYPE}
|
|
||||||
STORAGE_S3_REGION: ${STORAGE_S3_REGION}
|
|
||||||
STORAGE_S3_NAME: ${STORAGE_S3_NAME}
|
|
||||||
STORAGE_S3_ENDPOINT: ${STORAGE_S3_ENDPOINT}
|
|
||||||
ACCESS_TOKEN_SECRET: ${ACCESS_TOKEN_SECRET}
|
|
||||||
LOGIN_TOKEN_SECRET: ${LOGIN_TOKEN_SECRET}
|
|
||||||
REFRESH_TOKEN_SECRET: ${REFRESH_TOKEN_SECRET}
|
|
||||||
FILE_TOKEN_SECRET: ${FILE_TOKEN_SECRET}
|
|
||||||
depends_on:
|
|
||||||
change-vol-ownership:
|
|
||||||
condition: service_completed_successfully
|
|
||||||
db:
|
|
||||||
condition: service_healthy
|
|
||||||
healthcheck:
|
|
||||||
test: curl --fail http://localhost:3000/healthz
|
|
||||||
interval: 5s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 10
|
|
||||||
restart: always
|
|
||||||
|
|
||||||
worker:
|
|
||||||
image: twentycrm/twenty:${TAG}
|
|
||||||
command: ["yarn", "worker:prod"]
|
|
||||||
environment:
|
|
||||||
PG_DATABASE_URL: postgres://twenty:twenty@${PG_DATABASE_HOST}/default
|
|
||||||
SERVER_URL: ${SERVER_URL}
|
|
||||||
FRONT_BASE_URL: ${FRONT_BASE_URL:-$SERVER_URL}
|
|
||||||
MESSAGE_QUEUE_TYPE: ${MESSAGE_QUEUE_TYPE}
|
|
||||||
|
|
||||||
ENABLE_DB_MIGRATIONS: "false" # it already runs on the server
|
|
||||||
|
|
||||||
STORAGE_TYPE: ${STORAGE_TYPE}
|
|
||||||
STORAGE_S3_REGION: ${STORAGE_S3_REGION}
|
|
||||||
STORAGE_S3_NAME: ${STORAGE_S3_NAME}
|
|
||||||
STORAGE_S3_ENDPOINT: ${STORAGE_S3_ENDPOINT}
|
|
||||||
ACCESS_TOKEN_SECRET: ${ACCESS_TOKEN_SECRET}
|
|
||||||
LOGIN_TOKEN_SECRET: ${LOGIN_TOKEN_SECRET}
|
|
||||||
REFRESH_TOKEN_SECRET: ${REFRESH_TOKEN_SECRET}
|
|
||||||
FILE_TOKEN_SECRET: ${FILE_TOKEN_SECRET}
|
|
||||||
depends_on:
|
|
||||||
db:
|
|
||||||
condition: service_healthy
|
|
||||||
server:
|
|
||||||
condition: service_healthy
|
|
||||||
restart: always
|
|
||||||
|
|
||||||
db:
|
|
||||||
image: twentycrm/twenty-postgres:${TAG}
|
|
||||||
volumes:
|
|
||||||
- db-data:/bitnami/postgresql
|
|
||||||
environment:
|
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_ADMIN_PASSWORD}
|
|
||||||
healthcheck:
|
|
||||||
test: pg_isready -U twenty -d default
|
|
||||||
interval: 5s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 10
|
|
||||||
restart: always
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
docker-data:
|
|
||||||
db-data:
|
|
||||||
server-local-data:
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
# README
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
This repository contains Kubernetes manifests and Terraform files to help you deploy and manage the TwentyCRM application. The files are located in the `packages/twenty-docker/k8s` directory.
|
|
||||||
|
|
||||||
## Prerequisites
|
|
||||||
|
|
||||||
Before using these files, ensure you have the following installed and configured on your system:
|
|
||||||
|
|
||||||
- Kubernetes cluster (e.g., Minikube, EKS, GKE)
|
|
||||||
- kubectl
|
|
||||||
- Terraform
|
|
||||||
- Docker
|
|
||||||
|
|
||||||
## Setup Instructions
|
|
||||||
|
|
||||||
### Step 1: Clone the Repository
|
|
||||||
|
|
||||||
Clone the repository to your local machine:
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
git clone https://github.com/twentyhq/twenty.git
|
|
||||||
cd twentycrm/packages/twenty-docker/k8s
|
|
||||||
```
|
|
||||||
|
|
||||||
### Step 2: Customize the Manifests and Terraform Files
|
|
||||||
|
|
||||||
**Important:** These files require customization for your specific implementation. Update the placeholders and configurations according to your environment and requirements.
|
|
||||||
|
|
||||||
### Step 3: Deploy with Terraform
|
|
||||||
|
|
||||||
1. Navigate to the Terraform directory:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd terraform
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Initialize Terraform:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
terraform init
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Plan the deployment:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
terraform plan
|
|
||||||
```
|
|
||||||
|
|
||||||
4. Apply the deployment:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
terraform apply
|
|
||||||
```
|
|
||||||
|
|
||||||
## OR
|
|
||||||
|
|
||||||
### Step 3: Deploy with Kubernetes Manifests
|
|
||||||
|
|
||||||
1. Navigate to the Kubernetes manifests directory:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ../k8s
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Create Server Secret
|
|
||||||
|
|
||||||
``` bash
|
|
||||||
kubectl create secret generic -n twentycrm tokens --from-literal accessToken=changeme --from-literal loginToken="changeme" --from-literal refreshToken="changeme" --from-literal fileToken="changeme"
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Apply the manifests:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
kubectl apply -f .
|
|
||||||
```
|
|
||||||
|
|
||||||
## Customization
|
|
||||||
|
|
||||||
### Kubernetes Manifests
|
|
||||||
|
|
||||||
- **Namespace:** Update the `namespace` in the manifests as needed.
|
|
||||||
- **Resource Limits:** Adjust the resource limits and requests according to your application's requirements.
|
|
||||||
- **Environment Variables:** Configure server tokens in the `Secret` command above.
|
|
||||||
|
|
||||||
### Terraform Files
|
|
||||||
|
|
||||||
- **Variables:** Update the variables in the `variables.tf` file to match your environment.
|
|
||||||
- **Locals:** Update the locals in the `main.tf` file to match your environment.
|
|
||||||
- **Providers:** Ensure the provider configurations (e.g., AWS, GCP) are correct for your setup.
|
|
||||||
- **Resources:** Modify the resource definitions as needed to fit your infrastructure.
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Common Issues
|
|
||||||
|
|
||||||
- **Connectivity:** Ensure your Kubernetes cluster is accessible and configured correctly.
|
|
||||||
- **Permissions:** Verify that you have the necessary permissions to deploy resources in your cloud provider.
|
|
||||||
- **Resource Limits:** Adjust resource limits if you encounter issues related to insufficient resources.
|
|
||||||
|
|
||||||
### Logs and Debugging
|
|
||||||
|
|
||||||
- Use `kubectl logs` to check the logs of your Kubernetes pods.
|
|
||||||
- Use `terraform show` and `terraform state` to inspect your Terraform state and configurations.
|
|
||||||
|
|
||||||
## Conclusion
|
|
||||||
|
|
||||||
This setup provides a basic structure for deploying the TwentyCRM application using Kubernetes and Terraform. Ensure you thoroughly customize the manifests and Terraform files to suit your specific needs. For any issues or questions, please refer to the official documentation of Kubernetes and Terraform or seek support from your cloud provider.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Feel free to contribute and improve this repository by submitting pull requests or opening issues. Happy deploying!
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: twentycrm-db
|
|
||||||
name: twentycrm-db
|
|
||||||
namespace: twentycrm
|
|
||||||
spec:
|
|
||||||
progressDeadlineSeconds: 600
|
|
||||||
replicas: 1
|
|
||||||
strategy:
|
|
||||||
rollingUpdate:
|
|
||||||
maxSurge: 1
|
|
||||||
maxUnavailable: 1
|
|
||||||
type: RollingUpdate
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: twentycrm-db
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: twentycrm-db
|
|
||||||
spec:
|
|
||||||
volumes:
|
|
||||||
- name: twentycrm-db-data
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: twentycrm-db-pvc
|
|
||||||
containers:
|
|
||||||
- env:
|
|
||||||
- name: POSTGRES_PASSWORD
|
|
||||||
value: "twenty"
|
|
||||||
- name: BITNAMI_DEBUG
|
|
||||||
value: "true"
|
|
||||||
- image: twentycrm/twenty-postgres:latest
|
|
||||||
imagePullPolicy: Always
|
|
||||||
name: twentycrm
|
|
||||||
ports:
|
|
||||||
- containerPort: 5432
|
|
||||||
name: tcp
|
|
||||||
protocol: TCP
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "250m"
|
|
||||||
limits:
|
|
||||||
memory: "1024Mi"
|
|
||||||
cpu: "1000m"
|
|
||||||
stdin: true
|
|
||||||
tty: true
|
|
||||||
volumeMounts:
|
|
||||||
- mountPath: /bitnami/postgresql
|
|
||||||
name: twentycrm-db-data
|
|
||||||
dnsPolicy: ClusterFirst
|
|
||||||
restartPolicy: Always
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: twentycrm-server
|
|
||||||
name: twentycrm-server
|
|
||||||
namespace: twentycrm
|
|
||||||
spec:
|
|
||||||
progressDeadlineSeconds: 600
|
|
||||||
replicas: 1
|
|
||||||
strategy:
|
|
||||||
rollingUpdate:
|
|
||||||
maxSurge: 1
|
|
||||||
maxUnavailable: 1
|
|
||||||
type: RollingUpdate
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: twentycrm-server
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: twentycrm-server
|
|
||||||
spec:
|
|
||||||
volumes:
|
|
||||||
- name: twentycrm-server-data
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: twentycrm-server-pvc
|
|
||||||
containers:
|
|
||||||
- env:
|
|
||||||
- name: PORT
|
|
||||||
value: 3000
|
|
||||||
- name: SERVER_URL
|
|
||||||
value: "https://crm.example.com:443"
|
|
||||||
- name: FRONT_BASE_URL
|
|
||||||
value: "https://crm.example.com:443"
|
|
||||||
- name: PG_DATABASE_URL
|
|
||||||
value: "postgres://twenty:twenty@twenty-db.twentycrm.svc.cluster.local/default"
|
|
||||||
- name: ENABLE_DB_MIGRATIONS
|
|
||||||
value: "true"
|
|
||||||
- name: SIGN_IN_PREFILLED
|
|
||||||
value: "true"
|
|
||||||
- name: STORAGE_TYPE
|
|
||||||
value: "local"
|
|
||||||
- name: "MESSAGE_QUEUE_TYPE"
|
|
||||||
value: "pg-boss"
|
|
||||||
- name: ACCESS_TOKEN_SECRET
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: tokens
|
|
||||||
key: accessToken
|
|
||||||
- name: LOGIN_TOKEN_SECRET
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: tokens
|
|
||||||
key: loginToken
|
|
||||||
- name: REFRESH_TOKEN_SECRET
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: tokens
|
|
||||||
key: refreshToken
|
|
||||||
- name: FILE_TOKEN_SECRET
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: tokens
|
|
||||||
key: fileToken
|
|
||||||
- image: twentycrm/twenty:latest
|
|
||||||
imagePullPolicy: Always
|
|
||||||
name: twentycrm
|
|
||||||
ports:
|
|
||||||
- containerPort: 3000
|
|
||||||
name: http-tcp
|
|
||||||
protocol: TCP
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "250m"
|
|
||||||
limits:
|
|
||||||
memory: "1024Mi"
|
|
||||||
cpu: "1000m"
|
|
||||||
stdin: true
|
|
||||||
tty: true
|
|
||||||
volumeMounts:
|
|
||||||
- mountPath: /app/docker-data
|
|
||||||
name: twentycrm-server-data
|
|
||||||
- mountPath: /app/.local-storage
|
|
||||||
name: twentycrm-server-data
|
|
||||||
dnsPolicy: ClusterFirst
|
|
||||||
restartPolicy: Always
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: twentycrm-worker
|
|
||||||
name: twentycrm-worker
|
|
||||||
namespace: twentycrm
|
|
||||||
spec:
|
|
||||||
progressDeadlineSeconds: 600
|
|
||||||
replicas: 1
|
|
||||||
strategy:
|
|
||||||
rollingUpdate:
|
|
||||||
maxSurge: 1
|
|
||||||
maxUnavailable: 1
|
|
||||||
type: RollingUpdate
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
app: twentycrm-worker
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
labels:
|
|
||||||
app: twentycrm-worker
|
|
||||||
spec:
|
|
||||||
volumes:
|
|
||||||
- name: twentycrm-worker-data
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: twentycrm-worker-pvc
|
|
||||||
containers:
|
|
||||||
- env:
|
|
||||||
- name: SERVER_URL
|
|
||||||
value: "https://crm.example.com:443"
|
|
||||||
- name: FRONT_BASE_URL
|
|
||||||
value: "https://crm.example.com:443"
|
|
||||||
- name: PG_DATABASE_URL
|
|
||||||
value: "postgres://twenty:twenty@twenty-db.twentycrm.svc.cluster.local/default"
|
|
||||||
- name: ENABLE_DB_MIGRATIONS
|
|
||||||
value: "false" # it already runs on the server
|
|
||||||
- name: STORAGE_TYPE
|
|
||||||
value: "local"
|
|
||||||
- name: "MESSAGE_QUEUE_TYPE"
|
|
||||||
value: "pg-boss"
|
|
||||||
- name: ACCESS_TOKEN_SECRET
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: tokens
|
|
||||||
key: accessToken
|
|
||||||
- name: LOGIN_TOKEN_SECRET
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: tokens
|
|
||||||
key: loginToken
|
|
||||||
- name: REFRESH_TOKEN_SECRET
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: tokens
|
|
||||||
key: refreshToken
|
|
||||||
- name: FILE_TOKEN_SECRET
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: tokens
|
|
||||||
key: fileToken
|
|
||||||
- image: twentycrm/twenty:latest
|
|
||||||
imagePullPolicy: Always
|
|
||||||
name: twentycrm
|
|
||||||
command:
|
|
||||||
- yarn
|
|
||||||
- worker:prod
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
memory: "256Mi"
|
|
||||||
cpu: "250m"
|
|
||||||
limits:
|
|
||||||
memory: "1024Mi"
|
|
||||||
cpu: "1000m"
|
|
||||||
stdin: true
|
|
||||||
tty: true
|
|
||||||
dnsPolicy: ClusterFirst
|
|
||||||
restartPolicy: Always
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
apiVersion: networking.k8s.io/v1
|
|
||||||
kind: Ingress
|
|
||||||
metadata:
|
|
||||||
name: twentycrm
|
|
||||||
namespace: twentycrm
|
|
||||||
annotations:
|
|
||||||
nginx.ingress.kubernetes.io/configuration-snippet: |
|
|
||||||
more_set_headers "X-Forwarded-For $http_x_forwarded_for";
|
|
||||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
|
|
||||||
kubernetes.io/ingress.class: "nginx"
|
|
||||||
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
|
|
||||||
spec:
|
|
||||||
ingressClassName: nginx
|
|
||||||
rules:
|
|
||||||
- host: crm.example.com
|
|
||||||
http:
|
|
||||||
paths:
|
|
||||||
- path: /
|
|
||||||
pathType: Prefix
|
|
||||||
backend:
|
|
||||||
service:
|
|
||||||
name: twentycrm-server
|
|
||||||
port:
|
|
||||||
name: http-tcp
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: PersistentVolume
|
|
||||||
metadata:
|
|
||||||
name: twentycrm-db-pv
|
|
||||||
spec:
|
|
||||||
storageClassName: default
|
|
||||||
capacity:
|
|
||||||
storage: 10Gi
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce
|
|
||||||
persistentVolumeReclaimPolicy: Retain
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: PersistentVolume
|
|
||||||
metadata:
|
|
||||||
name: twentycrm-server-pv
|
|
||||||
namespace: twentycrm
|
|
||||||
spec:
|
|
||||||
storageClassName: default
|
|
||||||
capacity:
|
|
||||||
storage: 10Gi
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce
|
|
||||||
persistentVolumeReclaimPolicy: Retain
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: PersistentVolumeClaim
|
|
||||||
metadata:
|
|
||||||
name: twentycrm-db-pvc
|
|
||||||
namespace: twentycrm
|
|
||||||
spec:
|
|
||||||
storageClassName: default
|
|
||||||
volumeName: twentycrm-db-pv
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: 10Gi
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: PersistentVolumeClaim
|
|
||||||
metadata:
|
|
||||||
name: twentycrm-server-pvc
|
|
||||||
namespace: twentycrm
|
|
||||||
spec:
|
|
||||||
storageClassName: default
|
|
||||||
volumeName: twentycrm-server-pv
|
|
||||||
accessModes:
|
|
||||||
- ReadWriteOnce
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
storage: 10Gi
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: twentycrm-db
|
|
||||||
namespace: twentycrm
|
|
||||||
spec:
|
|
||||||
internalTrafficPolicy: Cluster
|
|
||||||
ports:
|
|
||||||
- port: 5432
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 5432
|
|
||||||
selector:
|
|
||||||
app: twentycrm-db
|
|
||||||
sessionAffinity: ClientIP
|
|
||||||
sessionAffinityConfig:
|
|
||||||
clientIP:
|
|
||||||
timeoutSeconds: 10800
|
|
||||||
type: ClusterIP
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: twentycrm-server
|
|
||||||
namespace: twentycrm
|
|
||||||
spec:
|
|
||||||
internalTrafficPolicy: Cluster
|
|
||||||
ports:
|
|
||||||
- name: http-tcp
|
|
||||||
port: 3000
|
|
||||||
protocol: TCP
|
|
||||||
targetPort: 3000
|
|
||||||
selector:
|
|
||||||
app: twentycrm-server
|
|
||||||
sessionAffinity: ClientIP
|
|
||||||
sessionAffinityConfig:
|
|
||||||
clientIP:
|
|
||||||
timeoutSeconds: 10800
|
|
||||||
type: ClusterIP
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
formatter: "markdown table" # this is required
|
|
||||||
|
|
||||||
version: ""
|
|
||||||
|
|
||||||
header-from: main.tf
|
|
||||||
|
|
||||||
recursive:
|
|
||||||
enabled: false
|
|
||||||
path: modules
|
|
||||||
|
|
||||||
output:
|
|
||||||
file: "README.md"
|
|
||||||
mode: inject
|
|
||||||
template: |-
|
|
||||||
<!-- BEGIN_TF_DOCS -->
|
|
||||||
# TwentyCRM Terraform Docs
|
|
||||||
|
|
||||||
This file was generated by [terraform-docs](https://terraform-docs.io/), for more information on how to install, configure and use visit their website.
|
|
||||||
|
|
||||||
To update this `README.md` after changes to the Terraform code in this folder, run: `terraform-docs .`
|
|
||||||
|
|
||||||
To make configuration changes to how this doc is generated, see `./.terraform-docs.yml`
|
|
||||||
|
|
||||||
{{ .Content }}
|
|
||||||
<!-- END_TF_DOCS -->
|
|
||||||
|
|
||||||
output-values:
|
|
||||||
enabled: false
|
|
||||||
from: "outputs.tf"
|
|
||||||
|
|
||||||
sort:
|
|
||||||
enabled: true
|
|
||||||
by: required
|
|
||||||
|
|
||||||
settings:
|
|
||||||
anchor: true
|
|
||||||
color: true
|
|
||||||
default: true
|
|
||||||
description: true
|
|
||||||
escape: true
|
|
||||||
hide-empty: true
|
|
||||||
html: true
|
|
||||||
indent: 2
|
|
||||||
lockfile: true
|
|
||||||
read-comments: true
|
|
||||||
required: true
|
|
||||||
sensitive: true
|
|
||||||
type: true
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
<!-- BEGIN_TF_DOCS -->
|
|
||||||
# TwentyCRM Terraform Docs
|
|
||||||
|
|
||||||
This file was generated by [terraform-docs](https://terraform-docs.io/), for more information on how to install, configure and use visit their website.
|
|
||||||
|
|
||||||
To update this `README.md` after changes to the Terraform code in this folder, run: `terraform-docs .`
|
|
||||||
|
|
||||||
To make configuration changes to how this doc is generated, see `./.terraform-docs.yml`
|
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
| Name | Version |
|
|
||||||
|------|---------|
|
|
||||||
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.9.2 |
|
|
||||||
| <a name="requirement_kubernetes"></a> [kubernetes](#requirement\_kubernetes) | >= 2.31.0 |
|
|
||||||
|
|
||||||
## Providers
|
|
||||||
|
|
||||||
| Name | Version |
|
|
||||||
|------|---------|
|
|
||||||
| <a name="provider_kubernetes"></a> [kubernetes](#provider\_kubernetes) | >= 2.31.0 |
|
|
||||||
|
|
||||||
## Resources
|
|
||||||
|
|
||||||
| Name | Type |
|
|
||||||
|------|------|
|
|
||||||
| [kubernetes_deployment.twentycrm_db](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/deployment) | resource |
|
|
||||||
| [kubernetes_deployment.twentycrm_server](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/deployment) | resource |
|
|
||||||
| [kubernetes_deployment.twentycrm_worker](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/deployment) | resource |
|
|
||||||
| [kubernetes_ingress.twentycrm](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/ingress) | resource |
|
|
||||||
| [kubernetes_namespace.twentycrm](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/namespace) | resource |
|
|
||||||
| [kubernetes_persistent_volume.db](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume) | resource |
|
|
||||||
| [kubernetes_persistent_volume.server](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume) | resource |
|
|
||||||
| [kubernetes_persistent_volume_claim.db](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume_claim) | resource |
|
|
||||||
| [kubernetes_persistent_volume_claim.server](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume_claim) | resource |
|
|
||||||
| [kubernetes_secret.twentycrm_tokens](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret) | resource |
|
|
||||||
| [kubernetes_service.twentycrm_db](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service) | resource |
|
|
||||||
| [kubernetes_service.twentycrm_server](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service) | resource |
|
|
||||||
|
|
||||||
## Inputs
|
|
||||||
|
|
||||||
| Name | Description | Type | Default | Required |
|
|
||||||
|------|-------------|------|---------|:--------:|
|
|
||||||
| <a name="input_twentycrm_app_hostname"></a> [twentycrm\_app\_hostname](#input\_twentycrm\_app\_hostname) | The protocol, DNS fully qualified hostname, and port used to access TwentyCRM in your environment. Ex: https://crm.example.com:443 | `string` | n/a | yes |
|
|
||||||
| <a name="input_twentycrm_pgdb_admin_password"></a> [twentycrm\_pgdb\_admin\_password](#input\_twentycrm\_pgdb\_admin\_password) | TwentyCRM password for postgres database. | `string` | n/a | yes |
|
|
||||||
| <a name="input_twentycrm_token_accessToken"></a> [twentycrm\_token\_accessToken](#input\_twentycrm\_token\_accessToken) | TwentyCRM access Token | `string` | n/a | yes |
|
|
||||||
| <a name="input_twentycrm_token_fileToken"></a> [twentycrm\_token\_fileToken](#input\_twentycrm\_token\_fileToken) | TwentyCRM file Token | `string` | n/a | yes |
|
|
||||||
| <a name="input_twentycrm_token_loginToken"></a> [twentycrm\_token\_loginToken](#input\_twentycrm\_token\_loginToken) | TwentyCRM login Token | `string` | n/a | yes |
|
|
||||||
| <a name="input_twentycrm_token_refreshToken"></a> [twentycrm\_token\_refreshToken](#input\_twentycrm\_token\_refreshToken) | TwentyCRM refresh Token | `string` | n/a | yes |
|
|
||||||
| <a name="input_twentycrm_app_name"></a> [twentycrm\_app\_name](#input\_twentycrm\_app\_name) | A friendly name prefix to use for every component deployed. | `string` | `"twentycrm"` | no |
|
|
||||||
| <a name="input_twentycrm_db_image"></a> [twentycrm\_db\_image](#input\_twentycrm\_db\_image) | TwentyCRM image for database deployment. This defaults to latest. | `string` | `"twentycrm/twenty-postgres:latest"` | no |
|
|
||||||
| <a name="input_twentycrm_db_pv_capacity"></a> [twentycrm\_db\_pv\_capacity](#input\_twentycrm\_db\_pv\_capacity) | Storage capacity provisioned for database persistent volume. | `string` | `"10Gi"` | no |
|
|
||||||
| <a name="input_twentycrm_db_pv_path"></a> [twentycrm\_db\_pv\_path](#input\_twentycrm\_db\_pv\_path) | Local path to use to store the physical volume if using local storage on nodes. | `string` | `""` | no |
|
|
||||||
| <a name="input_twentycrm_db_pvc_requests"></a> [twentycrm\_db\_pvc\_requests](#input\_twentycrm\_db\_pvc\_requests) | Storage capacity reservation for database persistent volume claim. | `string` | `"10Gi"` | no |
|
|
||||||
| <a name="input_twentycrm_db_replicas"></a> [twentycrm\_db\_replicas](#input\_twentycrm\_db\_replicas) | Number of replicas for the TwentyCRM database deployment. This defaults to 1. | `number` | `1` | no |
|
|
||||||
| <a name="input_twentycrm_namespace"></a> [twentycrm\_namespace](#input\_twentycrm\_namespace) | Namespace for all TwentyCRM resources | `string` | `"twentycrm"` | no |
|
|
||||||
| <a name="input_twentycrm_server_data_mount_path"></a> [twentycrm\_server\_data\_mount\_path](#input\_twentycrm\_server\_data\_mount\_path) | TwentyCRM mount path for servers application data. Defaults to '/app/docker-data'. | `string` | `"/app/docker-data"` | no |
|
|
||||||
| <a name="input_twentycrm_server_image"></a> [twentycrm\_server\_image](#input\_twentycrm\_server\_image) | TwentyCRM server image for the server deployment. This defaults to latest. This value is also used for the workers image. | `string` | `"twentycrm/twenty:latest"` | no |
|
|
||||||
| <a name="input_twentycrm_server_pv_capacity"></a> [twentycrm\_server\_pv\_capacity](#input\_twentycrm\_server\_pv\_capacity) | Storage capacity provisioned for server persistent volume. | `string` | `"10Gi"` | no |
|
|
||||||
| <a name="input_twentycrm_server_pv_path"></a> [twentycrm\_server\_pv\_path](#input\_twentycrm\_server\_pv\_path) | Local path to use to store the physical volume if using local storage on nodes. | `string` | `""` | no |
|
|
||||||
| <a name="input_twentycrm_server_pvc_requests"></a> [twentycrm\_server\_pvc\_requests](#input\_twentycrm\_server\_pvc\_requests) | Storage capacity reservation for server persistent volume claim. | `string` | `"10Gi"` | no |
|
|
||||||
| <a name="input_twentycrm_server_replicas"></a> [twentycrm\_server\_replicas](#input\_twentycrm\_server\_replicas) | Number of replicas for the TwentyCRM server deployment. This defaults to 1. | `number` | `1` | no |
|
|
||||||
| <a name="input_twentycrm_worker_replicas"></a> [twentycrm\_worker\_replicas](#input\_twentycrm\_worker\_replicas) | Number of replicas for the TwentyCRM worker deployment. This defaults to 1. | `number` | `1` | no |
|
|
||||||
<!-- END_TF_DOCS -->
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
resource "kubernetes_deployment" "twentycrm_db" {
|
|
||||||
metadata {
|
|
||||||
name = "${var.twentycrm_app_name}-db"
|
|
||||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
|
||||||
labels = {
|
|
||||||
app = "${var.twentycrm_app_name}-db"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spec {
|
|
||||||
replicas = var.twentycrm_db_replicas
|
|
||||||
selector {
|
|
||||||
match_labels = {
|
|
||||||
app = "${var.twentycrm_app_name}-db"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strategy {
|
|
||||||
type = "RollingUpdate"
|
|
||||||
rolling_update {
|
|
||||||
max_surge = "1"
|
|
||||||
max_unavailable = "1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template {
|
|
||||||
metadata {
|
|
||||||
labels = {
|
|
||||||
app = "${var.twentycrm_app_name}-db"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spec {
|
|
||||||
container {
|
|
||||||
image = var.twentycrm_db_image
|
|
||||||
name = var.twentycrm_app_name
|
|
||||||
stdin = true
|
|
||||||
tty = true
|
|
||||||
security_context {
|
|
||||||
allow_privilege_escalation = true
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "POSTGRES_PASSWORD"
|
|
||||||
value = var.twentycrm_pgdb_admin_password
|
|
||||||
}
|
|
||||||
env {
|
|
||||||
name = "BITNAMI_DEBUG"
|
|
||||||
value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
port {
|
|
||||||
container_port = 5432
|
|
||||||
protocol = "TCP"
|
|
||||||
}
|
|
||||||
|
|
||||||
resources {
|
|
||||||
requests = {
|
|
||||||
cpu = "250m"
|
|
||||||
memory = "256Mi"
|
|
||||||
}
|
|
||||||
limits = {
|
|
||||||
cpu = "1000m"
|
|
||||||
memory = "1024Mi"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
volume_mount {
|
|
||||||
name = "db-data"
|
|
||||||
mount_path = "/bitnami/postgresql"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
volume {
|
|
||||||
name = "db-data"
|
|
||||||
|
|
||||||
persistent_volume_claim {
|
|
||||||
claim_name = kubernetes_persistent_volume_claim.db.metadata.0.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dns_policy = "ClusterFirst"
|
|
||||||
restart_policy = "Always"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,167 +0,0 @@
|
|||||||
resource "kubernetes_deployment" "twentycrm_server" {
|
|
||||||
metadata {
|
|
||||||
name = "${var.twentycrm_app_name}-server"
|
|
||||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
|
||||||
labels = {
|
|
||||||
app = "${var.twentycrm_app_name}-server"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spec {
|
|
||||||
replicas = var.twentycrm_server_replicas
|
|
||||||
selector {
|
|
||||||
match_labels = {
|
|
||||||
app = "${var.twentycrm_app_name}-server"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strategy {
|
|
||||||
type = "RollingUpdate"
|
|
||||||
rolling_update {
|
|
||||||
max_surge = "1"
|
|
||||||
max_unavailable = "1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template {
|
|
||||||
metadata {
|
|
||||||
labels = {
|
|
||||||
app = "${var.twentycrm_app_name}-server"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spec {
|
|
||||||
container {
|
|
||||||
image = var.twentycrm_server_image
|
|
||||||
name = var.twentycrm_app_name
|
|
||||||
stdin = true
|
|
||||||
tty = true
|
|
||||||
|
|
||||||
security_context {
|
|
||||||
allow_privilege_escalation = true
|
|
||||||
privileged = true
|
|
||||||
run_as_user = 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "PORT"
|
|
||||||
value = "3000"
|
|
||||||
}
|
|
||||||
env {
|
|
||||||
name = "DEBUG_MODE"
|
|
||||||
value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "SERVER_URL"
|
|
||||||
value = var.twentycrm_app_hostname
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "FRONT_BASE_URL"
|
|
||||||
value = var.twentycrm_app_hostname
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "PG_DATABASE_URL"
|
|
||||||
value = "postgres://twenty:${var.twentycrm_pgdb_admin_password}@${var.twentycrm_app_name}-db.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local/default"
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "ENABLE_DB_MIGRATIONS"
|
|
||||||
value = "true"
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "SIGN_IN_PREFILLED"
|
|
||||||
value = "true"
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "STORAGE_TYPE"
|
|
||||||
value = "local"
|
|
||||||
}
|
|
||||||
env {
|
|
||||||
name = "MESSAGE_QUEUE_TYPE"
|
|
||||||
value = "pg-boss"
|
|
||||||
}
|
|
||||||
env {
|
|
||||||
name = "ACCESS_TOKEN_SECRET"
|
|
||||||
value_from {
|
|
||||||
secret_key_ref {
|
|
||||||
name = "tokens"
|
|
||||||
key = "accessToken"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "LOGIN_TOKEN_SECRET"
|
|
||||||
value_from {
|
|
||||||
secret_key_ref {
|
|
||||||
name = "tokens"
|
|
||||||
key = "loginToken"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "REFRESH_TOKEN_SECRET"
|
|
||||||
value_from {
|
|
||||||
secret_key_ref {
|
|
||||||
name = "tokens"
|
|
||||||
key = "refreshToken"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "FILE_TOKEN_SECRET"
|
|
||||||
value_from {
|
|
||||||
secret_key_ref {
|
|
||||||
name = "tokens"
|
|
||||||
key = "fileToken"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
port {
|
|
||||||
container_port = 3000
|
|
||||||
protocol = "TCP"
|
|
||||||
}
|
|
||||||
|
|
||||||
resources {
|
|
||||||
requests = {
|
|
||||||
cpu = "250m"
|
|
||||||
memory = "256Mi"
|
|
||||||
}
|
|
||||||
limits = {
|
|
||||||
cpu = "1000m"
|
|
||||||
memory = "1024Mi"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
volume_mount {
|
|
||||||
name = "server-data"
|
|
||||||
mount_path = var.twentycrm_server_data_mount_path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
volume {
|
|
||||||
name = "server-data"
|
|
||||||
|
|
||||||
persistent_volume_claim {
|
|
||||||
claim_name = kubernetes_persistent_volume_claim.server.metadata.0.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dns_policy = "ClusterFirst"
|
|
||||||
restart_policy = "Always"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
depends_on = [
|
|
||||||
kubernetes_deployment.twentycrm_db,
|
|
||||||
kubernetes_secret.twentycrm_tokens
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
resource "kubernetes_deployment" "twentycrm_worker" {
|
|
||||||
metadata {
|
|
||||||
name = "${var.twentycrm_app_name}-worker"
|
|
||||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
|
||||||
labels = {
|
|
||||||
app = "${var.twentycrm_app_name}-worker"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spec {
|
|
||||||
replicas = var.twentycrm_worker_replicas
|
|
||||||
selector {
|
|
||||||
match_labels = {
|
|
||||||
app = "${var.twentycrm_app_name}-worker"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strategy {
|
|
||||||
type = "RollingUpdate"
|
|
||||||
rolling_update {
|
|
||||||
max_surge = "1"
|
|
||||||
max_unavailable = "1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template {
|
|
||||||
metadata {
|
|
||||||
labels = {
|
|
||||||
app = "${var.twentycrm_app_name}-worker"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
spec {
|
|
||||||
container {
|
|
||||||
image = var.twentycrm_server_image
|
|
||||||
name = var.twentycrm_app_name
|
|
||||||
stdin = true
|
|
||||||
tty = true
|
|
||||||
command = ["yarn", "worker:prod"]
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "SERVER_URL"
|
|
||||||
value = var.twentycrm_app_hostname
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "FRONT_BASE_URL"
|
|
||||||
value = var.twentycrm_app_hostname
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "PG_DATABASE_URL"
|
|
||||||
value = "postgres://twenty:${var.twentycrm_pgdb_admin_password}@${var.twentycrm_app_name}-db.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local/default"
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "ENABLE_DB_MIGRATIONS"
|
|
||||||
value = "false" #it already runs on the server
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "STORAGE_TYPE"
|
|
||||||
value = "local"
|
|
||||||
}
|
|
||||||
env {
|
|
||||||
name = "MESSAGE_QUEUE_TYPE"
|
|
||||||
value = "pg-boss"
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "ACCESS_TOKEN_SECRET"
|
|
||||||
value_from {
|
|
||||||
secret_key_ref {
|
|
||||||
name = "tokens"
|
|
||||||
key = "accessToken"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "LOGIN_TOKEN_SECRET"
|
|
||||||
value_from {
|
|
||||||
secret_key_ref {
|
|
||||||
name = "tokens"
|
|
||||||
key = "loginToken"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "REFRESH_TOKEN_SECRET"
|
|
||||||
value_from {
|
|
||||||
secret_key_ref {
|
|
||||||
name = "tokens"
|
|
||||||
key = "refreshToken"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
|
||||||
name = "FILE_TOKEN_SECRET"
|
|
||||||
value_from {
|
|
||||||
secret_key_ref {
|
|
||||||
name = "tokens"
|
|
||||||
key = "fileToken"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resources {
|
|
||||||
requests = {
|
|
||||||
cpu = "250m"
|
|
||||||
memory = "256Mi"
|
|
||||||
}
|
|
||||||
limits = {
|
|
||||||
cpu = "1000m"
|
|
||||||
memory = "1024Mi"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dns_policy = "ClusterFirst"
|
|
||||||
restart_policy = "Always"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
depends_on = [
|
|
||||||
kubernetes_deployment.twentycrm_db,
|
|
||||||
kubernetes_secret.twentycrm_tokens
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
resource "kubernetes_ingress" "twentycrm" {
|
|
||||||
wait_for_load_balancer = true
|
|
||||||
metadata {
|
|
||||||
name = "${var.twentycrm_app_name}-ingress"
|
|
||||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
|
||||||
annotations = {
|
|
||||||
"kubernetes.io/ingress.class" = "nginx"
|
|
||||||
"nginx.ingress.kubernetes.io/configuration-snippet" = <<EOF
|
|
||||||
more_set_headers "X-Forwarded-For $http_x_forwarded_for";
|
|
||||||
EOF
|
|
||||||
"nginx.ingress.kubernetes.io/force-ssl-redirect" = "false"
|
|
||||||
"nginx.ingress.kubernetes.io/backend-protocol" = "HTTP"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
ingress_class_name = "nginx"
|
|
||||||
rule {
|
|
||||||
host = var.twentycrm_app_hostname
|
|
||||||
http {
|
|
||||||
path {
|
|
||||||
path = "/*"
|
|
||||||
backend {
|
|
||||||
service_name = kubernetes_service.twentycrm_server.metadata.0.name
|
|
||||||
service_port = kubernetes_service.twentycrm_server.spec.0.port.0.port
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#############
|
|
||||||
# Providers #
|
|
||||||
#############
|
|
||||||
provider "kubernetes" {
|
|
||||||
config_path = "~/.kube/config"
|
|
||||||
}
|
|
||||||
|
|
||||||
####################
|
|
||||||
# Terraform Config #
|
|
||||||
####################
|
|
||||||
terraform {
|
|
||||||
required_version = ">= 1.9.2"
|
|
||||||
required_providers {
|
|
||||||
kubernetes = {
|
|
||||||
source = "hashicorp/kubernetes"
|
|
||||||
version = ">= 2.31.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
resource "kubernetes_namespace" "twentycrm" {
|
|
||||||
metadata {
|
|
||||||
annotations = {
|
|
||||||
name = var.twentycrm_namespace
|
|
||||||
}
|
|
||||||
|
|
||||||
name = var.twentycrm_namespace
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
resource "kubernetes_persistent_volume" "db" {
|
|
||||||
metadata {
|
|
||||||
name = "${var.twentycrm_app_name}-db-pv"
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
storage_class_name = "default"
|
|
||||||
capacity = {
|
|
||||||
storage = var.twentycrm_db_pv_capacity
|
|
||||||
}
|
|
||||||
access_modes = ["ReadWriteOnce"]
|
|
||||||
# refer to Terraform Docs for your specific implementation requirements
|
|
||||||
# https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume
|
|
||||||
persistent_volume_source {
|
|
||||||
local {
|
|
||||||
path = var.twentycrm_db_pv_path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
resource "kubernetes_persistent_volume" "server" {
|
|
||||||
metadata {
|
|
||||||
name = "${var.twentycrm_app_name}-server-pv"
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
storage_class_name = "default"
|
|
||||||
capacity = {
|
|
||||||
storage = var.twentycrm_server_pv_capacity
|
|
||||||
}
|
|
||||||
access_modes = ["ReadWriteOnce"]
|
|
||||||
# refer to Terraform Docs for your specific implementation requirements
|
|
||||||
# https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume
|
|
||||||
persistent_volume_source {
|
|
||||||
local {
|
|
||||||
path = var.twentycrm_server_pv_path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
resource "kubernetes_persistent_volume_claim" "db" {
|
|
||||||
metadata {
|
|
||||||
name = "${var.twentycrm_app_name}-db-pvc"
|
|
||||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
access_modes = ["ReadWriteOnce"]
|
|
||||||
resources {
|
|
||||||
requests = {
|
|
||||||
storage = var.twentycrm_db_pvc_requests
|
|
||||||
}
|
|
||||||
}
|
|
||||||
volume_name = kubernetes_persistent_volume.db.metadata.0.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
resource "kubernetes_persistent_volume_claim" "server" {
|
|
||||||
metadata {
|
|
||||||
name = "${var.twentycrm_app_name}-server-pvc"
|
|
||||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
access_modes = ["ReadWriteOnce"]
|
|
||||||
resources {
|
|
||||||
requests = {
|
|
||||||
storage = var.twentycrm_server_pvc_requests
|
|
||||||
}
|
|
||||||
}
|
|
||||||
volume_name = kubernetes_persistent_volume.server.metadata.0.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
resource "kubernetes_secret" "twentycrm_tokens" {
|
|
||||||
metadata {
|
|
||||||
name = "tokens"
|
|
||||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
|
||||||
}
|
|
||||||
|
|
||||||
data = {
|
|
||||||
accessToken = var.twentycrm_token_accessToken
|
|
||||||
loginToken = var.twentycrm_token_loginToken
|
|
||||||
refreshToken = var.twentycrm_token_refreshToken
|
|
||||||
fileToken = var.twentycrm_token_fileToken
|
|
||||||
}
|
|
||||||
|
|
||||||
# type = "kubernetes.io/basic-auth"
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
resource "kubernetes_service" "twentycrm_db" {
|
|
||||||
metadata {
|
|
||||||
name = "${var.twentycrm_app_name}-db"
|
|
||||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
selector = {
|
|
||||||
app = "${var.twentycrm_app_name}-db"
|
|
||||||
}
|
|
||||||
session_affinity = "ClientIP"
|
|
||||||
port {
|
|
||||||
port = 5432
|
|
||||||
target_port = 5432
|
|
||||||
}
|
|
||||||
|
|
||||||
type = "ClusterIP"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
resource "kubernetes_service" "twentycrm_server" {
|
|
||||||
metadata {
|
|
||||||
name = "${var.twentycrm_app_name}-server"
|
|
||||||
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
|
||||||
}
|
|
||||||
spec {
|
|
||||||
selector = {
|
|
||||||
app = "${var.twentycrm_app_name}-server"
|
|
||||||
}
|
|
||||||
session_affinity = "ClientIP"
|
|
||||||
port {
|
|
||||||
name = "http-tcp"
|
|
||||||
port = 3000
|
|
||||||
target_port = 3000
|
|
||||||
}
|
|
||||||
|
|
||||||
type = "ClusterIP"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
######################
|
|
||||||
# Required Variables #
|
|
||||||
######################
|
|
||||||
variable "twentycrm_token_accessToken" {
|
|
||||||
type = string
|
|
||||||
description = "TwentyCRM access Token"
|
|
||||||
sensitive = true
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_token_loginToken" {
|
|
||||||
type = string
|
|
||||||
description = "TwentyCRM login Token"
|
|
||||||
sensitive = true
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_token_refreshToken" {
|
|
||||||
type = string
|
|
||||||
description = "TwentyCRM refresh Token"
|
|
||||||
sensitive = true
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_token_fileToken" {
|
|
||||||
type = string
|
|
||||||
description = "TwentyCRM file Token"
|
|
||||||
sensitive = true
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_pgdb_admin_password" {
|
|
||||||
type = string
|
|
||||||
description = "TwentyCRM password for postgres database."
|
|
||||||
sensitive = true
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_app_hostname" {
|
|
||||||
type = string
|
|
||||||
description = "The protocol, DNS fully qualified hostname, and port used to access TwentyCRM in your environment. Ex: https://crm.example.com:443"
|
|
||||||
}
|
|
||||||
|
|
||||||
######################
|
|
||||||
# Optional Variables #
|
|
||||||
######################
|
|
||||||
variable "twentycrm_app_name" {
|
|
||||||
type = string
|
|
||||||
default = "twentycrm"
|
|
||||||
description = "A friendly name prefix to use for every component deployed."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_server_image" {
|
|
||||||
type = string
|
|
||||||
default = "twentycrm/twenty:latest"
|
|
||||||
description = "TwentyCRM server image for the server deployment. This defaults to latest. This value is also used for the workers image."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_db_image" {
|
|
||||||
type = string
|
|
||||||
default = "twentycrm/twenty-postgres:latest"
|
|
||||||
description = "TwentyCRM image for database deployment. This defaults to latest."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_server_replicas" {
|
|
||||||
type = number
|
|
||||||
default = 1
|
|
||||||
description = "Number of replicas for the TwentyCRM server deployment. This defaults to 1."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_worker_replicas" {
|
|
||||||
type = number
|
|
||||||
default = 1
|
|
||||||
description = "Number of replicas for the TwentyCRM worker deployment. This defaults to 1."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_db_replicas" {
|
|
||||||
type = number
|
|
||||||
default = 1
|
|
||||||
description = "Number of replicas for the TwentyCRM database deployment. This defaults to 1."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_server_data_mount_path" {
|
|
||||||
type = string
|
|
||||||
default = "/app/docker-data"
|
|
||||||
description = "TwentyCRM mount path for servers application data. Defaults to '/app/docker-data'."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_db_pv_path" {
|
|
||||||
type = string
|
|
||||||
default = ""
|
|
||||||
description = "Local path to use to store the physical volume if using local storage on nodes."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_server_pv_path" {
|
|
||||||
type = string
|
|
||||||
default = ""
|
|
||||||
description = "Local path to use to store the physical volume if using local storage on nodes."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_db_pv_capacity" {
|
|
||||||
type = string
|
|
||||||
default = "10Gi"
|
|
||||||
description = "Storage capacity provisioned for database persistent volume."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_db_pvc_requests" {
|
|
||||||
type = string
|
|
||||||
default = "10Gi"
|
|
||||||
description = "Storage capacity reservation for database persistent volume claim."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_server_pv_capacity" {
|
|
||||||
type = string
|
|
||||||
default = "10Gi"
|
|
||||||
description = "Storage capacity provisioned for server persistent volume."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_server_pvc_requests" {
|
|
||||||
type = string
|
|
||||||
default = "10Gi"
|
|
||||||
description = "Storage capacity reservation for server persistent volume claim."
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "twentycrm_namespace" {
|
|
||||||
type = string
|
|
||||||
default = "twentycrm"
|
|
||||||
description = "Namespace for all TwentyCRM resources"
|
|
||||||
}
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
ARG POSTGRES_VERSION=15
|
|
||||||
ARG SPILO_VERSION=3.2-p1
|
|
||||||
ARG PG_GRAPHQL_VERSION=1.5.6
|
|
||||||
ARG WRAPPERS_VERSION=0.2.0
|
|
||||||
|
|
||||||
# Build the mysql_fdw extension
|
|
||||||
FROM debian:bookworm as build-mysql_fdw
|
|
||||||
ARG POSTGRES_VERSION
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND noninteractive
|
|
||||||
RUN apt update && \
|
|
||||||
apt install -y \
|
|
||||||
build-essential \
|
|
||||||
git \
|
|
||||||
postgresql-server-dev-${POSTGRES_VERSION} \
|
|
||||||
default-libmysqlclient-dev && \
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Install mysql_fdw
|
|
||||||
RUN git clone https://github.com/EnterpriseDB/mysql_fdw.git
|
|
||||||
WORKDIR mysql_fdw
|
|
||||||
RUN make USE_PGXS=1
|
|
||||||
|
|
||||||
|
|
||||||
# Build libssl for wrappers
|
|
||||||
FROM ubuntu:22.04 as build-libssl
|
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND noninteractive
|
|
||||||
RUN apt update && \
|
|
||||||
apt install -y \
|
|
||||||
build-essential \
|
|
||||||
git && \
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
WORKDIR /build
|
|
||||||
RUN git clone --branch OpenSSL_1_1_1-stable https://github.com/openssl/openssl.git
|
|
||||||
WORKDIR /build/openssl
|
|
||||||
RUN ./config && make && make install
|
|
||||||
|
|
||||||
|
|
||||||
# Extend the Spilo image with the pg_graphql and mysql_fdw extensions
|
|
||||||
FROM ghcr.io/zalando/spilo-${POSTGRES_VERSION}:${SPILO_VERSION}
|
|
||||||
ARG POSTGRES_VERSION
|
|
||||||
ARG PG_GRAPHQL_VERSION
|
|
||||||
ARG WRAPPERS_VERSION
|
|
||||||
ARG TARGETARCH
|
|
||||||
|
|
||||||
# Install precompiled supabase wrappers extensions
|
|
||||||
RUN set -eux; \
|
|
||||||
ARCH="$(dpkg --print-architecture)"; \
|
|
||||||
case "${ARCH}" in \
|
|
||||||
aarch64|arm64) TARGETARCH='arm64';; \
|
|
||||||
amd64|x86_64) TARGETARCH='amd64';; \
|
|
||||||
*) echo "Unsupported arch: ${ARCH}"; exit 1;; \
|
|
||||||
esac;
|
|
||||||
|
|
||||||
RUN apt update && apt install default-libmysqlclient-dev -y && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
RUN curl -L "https://github.com/supabase/wrappers/releases/download/v${WRAPPERS_VERSION}/wrappers-v${WRAPPERS_VERSION}-pg${POSTGRES_VERSION}-${TARGETARCH}-linux-gnu.deb" -o wrappers.deb && \
|
|
||||||
dpkg --install wrappers.deb && \
|
|
||||||
rm wrappers.deb
|
|
||||||
|
|
||||||
COPY --from=build-libssl /usr/local/lib/libssl* /usr/local/lib/libcrypto* /usr/lib/
|
|
||||||
COPY --from=build-libssl /usr/local/lib/engines-1.1 /usr/lib/engines-1.1
|
|
||||||
|
|
||||||
# Copy pg_graphql
|
|
||||||
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${POSTGRES_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql--${PG_GRAPHQL_VERSION}.sql \
|
|
||||||
/usr/share/postgresql/${POSTGRES_VERSION}/extension
|
|
||||||
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${POSTGRES_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql.control \
|
|
||||||
/usr/share/postgresql/${POSTGRES_VERSION}/extension
|
|
||||||
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${POSTGRES_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql.so \
|
|
||||||
/usr/lib/postgresql/${POSTGRES_VERSION}/lib/pg_graphql.so
|
|
||||||
|
|
||||||
# Copy mysql_fdw
|
|
||||||
COPY --from=build-mysql_fdw /mysql_fdw/mysql_fdw.so \
|
|
||||||
/usr/lib/postgresql/${POSTGRES_VERSION}/lib/mysql_fdw.so
|
|
||||||
COPY --from=build-mysql_fdw /mysql_fdw/mysql_fdw*.sql /mysql_fdw/mysql_fdw.control /mysql_fdw/mysql_fdw_pushdown.config \
|
|
||||||
/usr/share/postgresql/${POSTGRES_VERSION}/extension/
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
ARG IMAGE_TAG='15.5.0-debian-11-r15'
|
|
||||||
|
|
||||||
FROM bitnami/postgresql:${IMAGE_TAG}
|
|
||||||
|
|
||||||
ARG PG_MAIN_VERSION=15
|
|
||||||
ARG PG_GRAPHQL_VERSION=1.5.6
|
|
||||||
ARG WRAPPERS_VERSION=0.2.0
|
|
||||||
ARG TARGETARCH
|
|
||||||
|
|
||||||
USER root
|
|
||||||
|
|
||||||
RUN set -eux; \
|
|
||||||
ARCH="$(dpkg --print-architecture)"; \
|
|
||||||
case "${ARCH}" in \
|
|
||||||
aarch64|arm64) \
|
|
||||||
TARGETARCH='arm64'; \
|
|
||||||
;; \
|
|
||||||
amd64|x86_64) \
|
|
||||||
TARGETARCH='amd64'; \
|
|
||||||
;; \
|
|
||||||
*) \
|
|
||||||
echo "Unsupported arch: ${ARCH}"; \
|
|
||||||
exit 1; \
|
|
||||||
;; \
|
|
||||||
esac;
|
|
||||||
|
|
||||||
RUN apt update && apt install build-essential git curl default-libmysqlclient-dev -y
|
|
||||||
|
|
||||||
# Install precompiled pg_graphql extensions
|
|
||||||
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${PG_MAIN_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql--${PG_GRAPHQL_VERSION}.sql \
|
|
||||||
/opt/bitnami/postgresql/share/extension/
|
|
||||||
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${PG_MAIN_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql.control \
|
|
||||||
/opt/bitnami/postgresql/share/extension/
|
|
||||||
COPY ./packages/twenty-postgres/linux/${TARGETARCH}/${PG_MAIN_VERSION}/pg_graphql/${PG_GRAPHQL_VERSION}/pg_graphql.so \
|
|
||||||
/opt/bitnami/postgresql/lib/
|
|
||||||
|
|
||||||
# Install precompiled supabase wrappers extensions
|
|
||||||
RUN curl -L "https://github.com/supabase/wrappers/releases/download/v${WRAPPERS_VERSION}/wrappers-v${WRAPPERS_VERSION}-pg${PG_MAIN_VERSION}-${TARGETARCH}-linux-gnu.deb" -o wrappers.deb
|
|
||||||
RUN dpkg --install wrappers.deb
|
|
||||||
RUN cp /usr/share/postgresql/${PG_MAIN_VERSION}/extension/wrappers* /opt/bitnami/postgresql/share/extension/
|
|
||||||
RUN cp /usr/lib/postgresql/${PG_MAIN_VERSION}/lib/wrappers* /opt/bitnami/postgresql/lib/
|
|
||||||
|
|
||||||
RUN export PATH=/usr/local/pgsql/bin/:$PATH
|
|
||||||
RUN export PATH=/usr/local/mysql/bin/:$PATH
|
|
||||||
RUN git clone https://github.com/EnterpriseDB/mysql_fdw.git
|
|
||||||
WORKDIR mysql_fdw
|
|
||||||
RUN make USE_PGXS=1
|
|
||||||
RUN make USE_PGXS=1 install
|
|
||||||
|
|
||||||
COPY ./packages/twenty-docker/twenty-postgres/init.sql /docker-entrypoint-initdb.d/
|
|
||||||
|
|
||||||
USER 1001
|
|
||||||
ENTRYPOINT ["/opt/bitnami/scripts/postgresql/entrypoint.sh"]
|
|
||||||
CMD ["/opt/bitnami/scripts/postgresql/run.sh"]
|
|
||||||