Compare commits
21 Commits
update-templates
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a1e50ecfdf | |||
| 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
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ _APP_OPTIONS_FUNCTIONS_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=localhost
|
||||||
|
_APP_CUSTOM_DOMAIN_DENY_LIST=example.com,test.com,app.example.com
|
||||||
_APP_DOMAIN_FUNCTIONS=functions.localhost
|
_APP_DOMAIN_FUNCTIONS=functions.localhost
|
||||||
_APP_DOMAIN_TARGET=localhost
|
_APP_DOMAIN_TARGET=localhost
|
||||||
_APP_CONSOLE_WHITELIST_ROOT=enabled
|
_APP_CONSOLE_WHITELIST_ROOT=enabled
|
||||||
@@ -13,7 +14,8 @@ _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 +27,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 +61,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,6 +79,7 @@ _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_FUNCTIONS_BUILD_SIZE_LIMIT=2000000000
|
||||||
_APP_FUNCTIONS_TIMEOUT=900
|
_APP_FUNCTIONS_TIMEOUT=900
|
||||||
_APP_FUNCTIONS_BUILD_TIMEOUT=900
|
_APP_FUNCTIONS_BUILD_TIMEOUT=900
|
||||||
_APP_FUNCTIONS_CONTAINERS=10
|
_APP_FUNCTIONS_CONTAINERS=10
|
||||||
@@ -104,6 +111,7 @@ _APP_MAINTENANCE_DELAY=0
|
|||||||
_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.6.2
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
@@ -61,8 +61,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
|
||||||
@@ -102,6 +104,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
|
||||||
@@ -126,7 +129,6 @@ services:
|
|||||||
- _APP_FUNCTIONS_RUNTIMES
|
- _APP_FUNCTIONS_RUNTIMES
|
||||||
- _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
|
||||||
@@ -134,6 +136,7 @@ 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
|
||||||
- _APP_SMS_PROVIDER
|
- _APP_SMS_PROVIDER
|
||||||
@@ -150,9 +153,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:5.2.58
|
||||||
|
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.6.2
|
||||||
entrypoint: realtime
|
entrypoint: realtime
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -191,11 +214,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.6.2
|
||||||
entrypoint: worker-audits
|
entrypoint: worker-audits
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -217,11 +239,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.6.2
|
||||||
entrypoint: worker-webhooks
|
entrypoint: worker-webhooks
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -245,11 +266,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.6.2
|
||||||
entrypoint: worker-deletes
|
entrypoint: worker-deletes
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -282,6 +302,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 +319,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.6.2
|
||||||
entrypoint: worker-databases
|
entrypoint: worker-databases
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -326,11 +352,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.6.2
|
||||||
entrypoint: worker-builds
|
entrypoint: worker-builds
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -357,7 +382,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_VCS_GITHUB_APP_NAME
|
- _APP_VCS_GITHUB_APP_NAME
|
||||||
- _APP_VCS_GITHUB_PRIVATE_KEY
|
- _APP_VCS_GITHUB_PRIVATE_KEY
|
||||||
@@ -375,6 +399,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
|
||||||
@@ -393,7 +418,7 @@ services:
|
|||||||
- _APP_STORAGE_WASABI_BUCKET
|
- _APP_STORAGE_WASABI_BUCKET
|
||||||
|
|
||||||
appwrite-worker-certificates:
|
appwrite-worker-certificates:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.6.2
|
||||||
entrypoint: worker-certificates
|
entrypoint: worker-certificates
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -422,11 +447,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.6.2
|
||||||
entrypoint: worker-functions
|
entrypoint: worker-functions
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -440,6 +464,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
|
||||||
@@ -459,10 +485,9 @@ services:
|
|||||||
- _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.6.2
|
||||||
entrypoint: worker-mails
|
entrypoint: worker-mails
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -490,11 +515,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.6.2
|
||||||
entrypoint: worker-messaging
|
entrypoint: worker-messaging
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -517,7 +543,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 +551,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,7 +570,7 @@ 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.6.2
|
||||||
entrypoint: worker-migrations
|
entrypoint: worker-migrations
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -568,13 +594,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.6.2
|
||||||
entrypoint: maintenance
|
entrypoint: maintenance
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -603,12 +628,43 @@ 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.6.2
|
||||||
entrypoint: worker-usage
|
entrypoint: stats-resources
|
||||||
|
<<: *x-logging
|
||||||
|
networks:
|
||||||
|
- appwrite
|
||||||
|
volumes:
|
||||||
|
- ./app:/usr/src/code/app
|
||||||
|
- ./src:/usr/src/code/src
|
||||||
|
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_DATABASE_SHARED_TABLES
|
||||||
|
- _APP_STATS_RESOURCES_INTERVAL
|
||||||
|
|
||||||
|
appwrite-worker-stats-resources:
|
||||||
|
image: appwrite/appwrite:1.6.2
|
||||||
|
entrypoint: worker-stats-resources
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
@@ -630,14 +686,14 @@ 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_STATS_RESOURCES_INTERVAL
|
||||||
|
|
||||||
appwrite-worker-usage-dump:
|
appwrite-worker-stats-usage:
|
||||||
image: appwrite/appwrite:1.5.10
|
image: appwrite/appwrite:1.6.2
|
||||||
entrypoint: worker-usage-dump
|
entrypoint: worker-stats-usage
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
|
restart: unless-stopped
|
||||||
networks:
|
networks:
|
||||||
- appwrite
|
- appwrite
|
||||||
depends_on:
|
depends_on:
|
||||||
@@ -657,12 +713,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.6.2
|
||||||
entrypoint: schedule-functions
|
entrypoint: schedule-functions
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -685,8 +740,32 @@ services:
|
|||||||
- _APP_DB_USER
|
- _APP_DB_USER
|
||||||
- _APP_DB_PASS
|
- _APP_DB_PASS
|
||||||
|
|
||||||
|
appwrite-task-scheduler-executions:
|
||||||
|
image: appwrite/appwrite:1.6.2
|
||||||
|
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.6.2
|
||||||
entrypoint: schedule-messages
|
entrypoint: schedule-messages
|
||||||
<<: *x-logging
|
<<: *x-logging
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@@ -723,7 +802,7 @@ services:
|
|||||||
<<: *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.6.11
|
||||||
networks:
|
networks:
|
||||||
- appwrite
|
- appwrite
|
||||||
- runtimes
|
- runtimes
|
||||||
@@ -743,13 +822,13 @@ services:
|
|||||||
- OPR_EXECUTOR_ENV=$_APP_ENV
|
- OPR_EXECUTOR_ENV=$_APP_ENV
|
||||||
- OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES
|
- OPR_EXECUTOR_RUNTIMES=$_APP_FUNCTIONS_RUNTIMES
|
||||||
- OPR_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET
|
- OPR_EXECUTOR_SECRET=$_APP_EXECUTOR_SECRET
|
||||||
- OPR_EXECUTOR_LOGGING_PROVIDER=$_APP_LOGGING_PROVIDER
|
|
||||||
- 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 +860,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
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
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");
|
||||||
+458
-76
@@ -39,6 +39,12 @@ APP_WEB_URL=
|
|||||||
# File preview or download Url prefix.
|
# File preview or download Url prefix.
|
||||||
# used to display File preview or download Url to the front-end or as Multi-model inputs;
|
# used to display File preview or download Url to the front-end or as Multi-model inputs;
|
||||||
# Url is signed and has expiration time.
|
# Url is signed and has expiration time.
|
||||||
|
# Setting FILES_URL is required for file processing plugins.
|
||||||
|
# - For https://example.com, use FILES_URL=https://example.com
|
||||||
|
# - For http://example.com, use FILES_URL=http://example.com
|
||||||
|
# Recommendation: use a dedicated domain (e.g., https://upload.example.com).
|
||||||
|
# Alternatively, use http://<your-ip>:5001 or http://api:5001,
|
||||||
|
# ensuring port 5001 is externally accessible (see docker-compose.yaml).
|
||||||
FILES_URL=
|
FILES_URL=
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
@@ -48,6 +54,16 @@ FILES_URL=
|
|||||||
# The log level for the application.
|
# The log level for the application.
|
||||||
# Supported values are `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`
|
# Supported values are `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL`
|
||||||
LOG_LEVEL=INFO
|
LOG_LEVEL=INFO
|
||||||
|
# Log file path
|
||||||
|
LOG_FILE=/app/logs/server.log
|
||||||
|
# Log file max size, the unit is MB
|
||||||
|
LOG_FILE_MAX_SIZE=20
|
||||||
|
# Log file max backup count
|
||||||
|
LOG_FILE_BACKUP_COUNT=5
|
||||||
|
# Log dateformat
|
||||||
|
LOG_DATEFORMAT=%Y-%m-%d %H:%M:%S
|
||||||
|
# Log Timezone
|
||||||
|
LOG_TZ=UTC
|
||||||
|
|
||||||
# Debug mode, default is false.
|
# Debug mode, default is false.
|
||||||
# It is recommended to turn on this configuration for local development
|
# It is recommended to turn on this configuration for local development
|
||||||
@@ -58,7 +74,11 @@ DEBUG=false
|
|||||||
# which is convenient for debugging.
|
# which is convenient for debugging.
|
||||||
FLASK_DEBUG=false
|
FLASK_DEBUG=false
|
||||||
|
|
||||||
# A secretkey that is used for securely signing the session cookie
|
# Enable request logging, which will log the request and response information.
|
||||||
|
# And the log level is DEBUG
|
||||||
|
ENABLE_REQUEST_LOGGING=False
|
||||||
|
|
||||||
|
# A secret key that is used for securely signing the session cookie
|
||||||
# and encrypting sensitive information on the database.
|
# and encrypting sensitive information on the database.
|
||||||
# You can generate a strong key using `openssl rand -base64 42`.
|
# You can generate a strong key using `openssl rand -base64 42`.
|
||||||
SECRET_KEY=sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U
|
SECRET_KEY=sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U
|
||||||
@@ -66,6 +86,7 @@ SECRET_KEY=sk-9f73s3ljTXVcMT3Blb3ljTqtsKiGHXVcMT3BlbkFJLK7U
|
|||||||
# Password for admin user initialization.
|
# Password for admin user initialization.
|
||||||
# If left unset, admin user will not be prompted for a password
|
# If left unset, admin user will not be prompted for a password
|
||||||
# when creating the initial admin account.
|
# when creating the initial admin account.
|
||||||
|
# The length of the password cannot exceed 30 characters.
|
||||||
INIT_PASSWORD=
|
INIT_PASSWORD=
|
||||||
|
|
||||||
# Deployment environment.
|
# Deployment environment.
|
||||||
@@ -75,7 +96,7 @@ INIT_PASSWORD=
|
|||||||
DEPLOY_ENV=PRODUCTION
|
DEPLOY_ENV=PRODUCTION
|
||||||
|
|
||||||
# Whether to enable the version check policy.
|
# Whether to enable the version check policy.
|
||||||
# If set to empty, https://updates.dify.ai will not be called for version check.
|
# If set to empty, https://updates.dify.ai will be called for version check.
|
||||||
CHECK_UPDATE_URL=https://updates.dify.ai
|
CHECK_UPDATE_URL=https://updates.dify.ai
|
||||||
|
|
||||||
# Used to change the OpenAI base address, default is https://api.openai.com/v1.
|
# Used to change the OpenAI base address, default is https://api.openai.com/v1.
|
||||||
@@ -91,8 +112,15 @@ MIGRATION_ENABLED=true
|
|||||||
# The default value is 300 seconds.
|
# The default value is 300 seconds.
|
||||||
FILES_ACCESS_TIMEOUT=300
|
FILES_ACCESS_TIMEOUT=300
|
||||||
|
|
||||||
|
# Access token expiration time in minutes
|
||||||
|
ACCESS_TOKEN_EXPIRE_MINUTES=60
|
||||||
|
|
||||||
|
# Refresh token expiration time in days
|
||||||
|
REFRESH_TOKEN_EXPIRE_DAYS=30
|
||||||
|
|
||||||
# The maximum number of active requests for the application, where 0 means unlimited, should be a non-negative integer.
|
# The maximum number of active requests for the application, where 0 means unlimited, should be a non-negative integer.
|
||||||
APP_MAX_ACTIVE_REQUESTS=0
|
APP_MAX_ACTIVE_REQUESTS=0
|
||||||
|
APP_MAX_EXECUTION_TIME=1200
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Container Startup Related Configuration
|
# Container Startup Related Configuration
|
||||||
@@ -105,15 +133,18 @@ DIFY_BIND_ADDRESS=0.0.0.0
|
|||||||
# API service binding port number, default 5001.
|
# API service binding port number, default 5001.
|
||||||
DIFY_PORT=5001
|
DIFY_PORT=5001
|
||||||
|
|
||||||
# The number of API server workers, i.e., the number of gevent workers.
|
# The number of API server workers, i.e., the number of workers.
|
||||||
# Formula: number of cpu cores x 2 + 1
|
# Formula: number of cpu cores x 2 + 1 for sync, 1 for Gevent
|
||||||
# Reference: https://docs.gunicorn.org/en/stable/design.html#how-many-workers
|
# Reference: https://docs.gunicorn.org/en/stable/design.html#how-many-workers
|
||||||
SERVER_WORKER_AMOUNT=
|
SERVER_WORKER_AMOUNT=1
|
||||||
|
|
||||||
# Defaults to gevent. If using windows, it can be switched to sync or solo.
|
# Defaults to gevent. If using windows, it can be switched to sync or solo.
|
||||||
SERVER_WORKER_CLASS=
|
SERVER_WORKER_CLASS=gevent
|
||||||
|
|
||||||
# Similar to SERVER_WORKER_CLASS. Default is gevent.
|
# Default number of worker connections, the default is 10.
|
||||||
|
SERVER_WORKER_CONNECTIONS=10
|
||||||
|
|
||||||
|
# Similar to SERVER_WORKER_CLASS.
|
||||||
# If using windows, it can be switched to sync or solo.
|
# If using windows, it can be switched to sync or solo.
|
||||||
CELERY_WORKER_CLASS=
|
CELERY_WORKER_CLASS=
|
||||||
|
|
||||||
@@ -153,6 +184,12 @@ CELERY_MIN_WORKERS=
|
|||||||
API_TOOL_DEFAULT_CONNECT_TIMEOUT=10
|
API_TOOL_DEFAULT_CONNECT_TIMEOUT=10
|
||||||
API_TOOL_DEFAULT_READ_TIMEOUT=60
|
API_TOOL_DEFAULT_READ_TIMEOUT=60
|
||||||
|
|
||||||
|
# -------------------------------
|
||||||
|
# Datasource Configuration
|
||||||
|
# --------------------------------
|
||||||
|
ENABLE_WEBSITE_JINAREADER=true
|
||||||
|
ENABLE_WEBSITE_FIRECRAWL=true
|
||||||
|
ENABLE_WEBSITE_WATERCRAWL=true
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Database Configuration
|
# Database Configuration
|
||||||
@@ -213,6 +250,25 @@ REDIS_PORT=6379
|
|||||||
REDIS_USERNAME=
|
REDIS_USERNAME=
|
||||||
REDIS_PASSWORD=difyai123456
|
REDIS_PASSWORD=difyai123456
|
||||||
REDIS_USE_SSL=false
|
REDIS_USE_SSL=false
|
||||||
|
REDIS_DB=0
|
||||||
|
|
||||||
|
# Whether to use Redis Sentinel mode.
|
||||||
|
# If set to true, the application will automatically discover and connect to the master node through Sentinel.
|
||||||
|
REDIS_USE_SENTINEL=false
|
||||||
|
|
||||||
|
# List of Redis Sentinel nodes. If Sentinel mode is enabled, provide at least one Sentinel IP and port.
|
||||||
|
# Format: `<sentinel1_ip>:<sentinel1_port>,<sentinel2_ip>:<sentinel2_port>,<sentinel3_ip>:<sentinel3_port>`
|
||||||
|
REDIS_SENTINELS=
|
||||||
|
REDIS_SENTINEL_SERVICE_NAME=
|
||||||
|
REDIS_SENTINEL_USERNAME=
|
||||||
|
REDIS_SENTINEL_PASSWORD=
|
||||||
|
REDIS_SENTINEL_SOCKET_TIMEOUT=0.1
|
||||||
|
|
||||||
|
# List of Redis Cluster nodes. If Cluster mode is enabled, provide at least one Cluster IP and port.
|
||||||
|
# Format: `<Cluster1_ip>:<Cluster1_port>,<Cluster2_ip>:<Cluster2_port>,<Cluster3_ip>:<Cluster3_port>`
|
||||||
|
REDIS_USE_CLUSTERS=false
|
||||||
|
REDIS_CLUSTERS=
|
||||||
|
REDIS_CLUSTERS_PASSWORD=
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Celery Configuration
|
# Celery Configuration
|
||||||
@@ -221,9 +277,16 @@ REDIS_USE_SSL=false
|
|||||||
# Use redis as the broker, and redis db 1 for celery broker.
|
# Use redis as the broker, and redis db 1 for celery broker.
|
||||||
# Format as follows: `redis://<redis_username>:<redis_password>@<redis_host>:<redis_port>/<redis_database>`
|
# Format as follows: `redis://<redis_username>:<redis_password>@<redis_host>:<redis_port>/<redis_database>`
|
||||||
# Example: redis://:difyai123456@redis:6379/1
|
# Example: redis://:difyai123456@redis:6379/1
|
||||||
|
# If use Redis Sentinel, format as follows: `sentinel://<sentinel_username>:<sentinel_password>@<sentinel_host>:<sentinel_port>/<redis_database>`
|
||||||
|
# Example: sentinel://localhost:26379/1;sentinel://localhost:26380/1;sentinel://localhost:26381/1
|
||||||
CELERY_BROKER_URL=redis://:difyai123456@redis:6379/1
|
CELERY_BROKER_URL=redis://:difyai123456@redis:6379/1
|
||||||
BROKER_USE_SSL=false
|
BROKER_USE_SSL=false
|
||||||
|
|
||||||
|
# If you are using Redis Sentinel for high availability, configure the following settings.
|
||||||
|
CELERY_USE_SENTINEL=false
|
||||||
|
CELERY_SENTINEL_MASTER_NAME=
|
||||||
|
CELERY_SENTINEL_SOCKET_TIMEOUT=0.1
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# CORS Configuration
|
# CORS Configuration
|
||||||
# Used to set the front-end cross-domain access policy.
|
# Used to set the front-end cross-domain access policy.
|
||||||
@@ -242,97 +305,123 @@ CONSOLE_CORS_ALLOW_ORIGINS=*
|
|||||||
# ------------------------------
|
# ------------------------------
|
||||||
|
|
||||||
# The type of storage to use for storing user files.
|
# The type of storage to use for storing user files.
|
||||||
# Supported values are `local` and `s3` and `azure-blob` and `google-storage` and `tencent-cos`,
|
STORAGE_TYPE=opendal
|
||||||
# Default: `local`
|
|
||||||
STORAGE_TYPE=local
|
# Apache OpenDAL Configuration
|
||||||
|
# The configuration for OpenDAL consists of the following format: OPENDAL_<SCHEME_NAME>_<CONFIG_NAME>.
|
||||||
|
# You can find all the service configurations (CONFIG_NAME) in the repository at: https://github.com/apache/opendal/tree/main/core/src/services.
|
||||||
|
# Dify will scan configurations starting with OPENDAL_<SCHEME_NAME> and automatically apply them.
|
||||||
|
# The scheme name for the OpenDAL storage.
|
||||||
|
OPENDAL_SCHEME=fs
|
||||||
|
# Configurations for OpenDAL Local File System.
|
||||||
|
OPENDAL_FS_ROOT=storage
|
||||||
|
|
||||||
# S3 Configuration
|
# S3 Configuration
|
||||||
|
#
|
||||||
|
S3_ENDPOINT=
|
||||||
|
S3_REGION=us-east-1
|
||||||
|
S3_BUCKET_NAME=difyai
|
||||||
|
S3_ACCESS_KEY=
|
||||||
|
S3_SECRET_KEY=
|
||||||
# Whether to use AWS managed IAM roles for authenticating with the S3 service.
|
# Whether to use AWS managed IAM roles for authenticating with the S3 service.
|
||||||
# If set to false, the access key and secret key must be provided.
|
# If set to false, the access key and secret key must be provided.
|
||||||
S3_USE_AWS_MANAGED_IAM=false
|
S3_USE_AWS_MANAGED_IAM=false
|
||||||
# The endpoint of the S3 service.
|
|
||||||
S3_ENDPOINT=
|
|
||||||
# The region of the S3 service.
|
|
||||||
S3_REGION=us-east-1
|
|
||||||
# The name of the S3 bucket to use for storing files.
|
|
||||||
S3_BUCKET_NAME=difyai
|
|
||||||
# The access key to use for authenticating with the S3 service.
|
|
||||||
S3_ACCESS_KEY=
|
|
||||||
# The secret key to use for authenticating with the S3 service.
|
|
||||||
S3_SECRET_KEY=
|
|
||||||
|
|
||||||
# Azure Blob Configuration
|
# Azure Blob Configuration
|
||||||
# The name of the Azure Blob Storage account to use for storing files.
|
#
|
||||||
AZURE_BLOB_ACCOUNT_NAME=difyai
|
AZURE_BLOB_ACCOUNT_NAME=difyai
|
||||||
# The access key to use for authenticating with the Azure Blob Storage account.
|
|
||||||
AZURE_BLOB_ACCOUNT_KEY=difyai
|
AZURE_BLOB_ACCOUNT_KEY=difyai
|
||||||
# The name of the Azure Blob Storage container to use for storing files.
|
|
||||||
AZURE_BLOB_CONTAINER_NAME=difyai-container
|
AZURE_BLOB_CONTAINER_NAME=difyai-container
|
||||||
# The URL of the Azure Blob Storage account.
|
|
||||||
AZURE_BLOB_ACCOUNT_URL=https://<your_account_name>.blob.core.windows.net
|
AZURE_BLOB_ACCOUNT_URL=https://<your_account_name>.blob.core.windows.net
|
||||||
|
|
||||||
# Google Storage Configuration
|
# Google Storage Configuration
|
||||||
# The name of the Google Storage bucket to use for storing files.
|
#
|
||||||
GOOGLE_STORAGE_BUCKET_NAME=your-bucket-name
|
GOOGLE_STORAGE_BUCKET_NAME=your-bucket-name
|
||||||
# The service account JSON key to use for authenticating with the Google Storage service.
|
GOOGLE_STORAGE_SERVICE_ACCOUNT_JSON_BASE64=
|
||||||
GOOGLE_STORAGE_SERVICE_ACCOUNT_JSON_BASE64=your-google-service-account-json-base64-string
|
|
||||||
|
|
||||||
# The Alibaba Cloud OSS configurations,
|
# The Alibaba Cloud OSS configurations,
|
||||||
# only available when STORAGE_TYPE is `aliyun-oss`
|
#
|
||||||
ALIYUN_OSS_BUCKET_NAME=your-bucket-name
|
ALIYUN_OSS_BUCKET_NAME=your-bucket-name
|
||||||
ALIYUN_OSS_ACCESS_KEY=your-access-key
|
ALIYUN_OSS_ACCESS_KEY=your-access-key
|
||||||
ALIYUN_OSS_SECRET_KEY=your-secret-key
|
ALIYUN_OSS_SECRET_KEY=your-secret-key
|
||||||
ALIYUN_OSS_ENDPOINT=https://oss-ap-southeast-1-internal.aliyuncs.com
|
ALIYUN_OSS_ENDPOINT=https://oss-ap-southeast-1-internal.aliyuncs.com
|
||||||
ALIYUN_OSS_REGION=ap-southeast-1
|
ALIYUN_OSS_REGION=ap-southeast-1
|
||||||
ALIYUN_OSS_AUTH_VERSION=v4
|
ALIYUN_OSS_AUTH_VERSION=v4
|
||||||
|
# Don't start with '/'. OSS doesn't support leading slash in object names.
|
||||||
|
ALIYUN_OSS_PATH=your-path
|
||||||
|
|
||||||
# Tencent COS Configuration
|
# Tencent COS Configuration
|
||||||
# The name of the Tencent COS bucket to use for storing files.
|
#
|
||||||
TENCENT_COS_BUCKET_NAME=your-bucket-name
|
TENCENT_COS_BUCKET_NAME=your-bucket-name
|
||||||
# The secret key to use for authenticating with the Tencent COS service.
|
|
||||||
TENCENT_COS_SECRET_KEY=your-secret-key
|
TENCENT_COS_SECRET_KEY=your-secret-key
|
||||||
# The secret id to use for authenticating with the Tencent COS service.
|
|
||||||
TENCENT_COS_SECRET_ID=your-secret-id
|
TENCENT_COS_SECRET_ID=your-secret-id
|
||||||
# The region of the Tencent COS service.
|
|
||||||
TENCENT_COS_REGION=your-region
|
TENCENT_COS_REGION=your-region
|
||||||
# The scheme of the Tencent COS service.
|
|
||||||
TENCENT_COS_SCHEME=your-scheme
|
TENCENT_COS_SCHEME=your-scheme
|
||||||
|
|
||||||
|
# Oracle Storage Configuration
|
||||||
|
#
|
||||||
|
OCI_ENDPOINT=https://your-object-storage-namespace.compat.objectstorage.us-ashburn-1.oraclecloud.com
|
||||||
|
OCI_BUCKET_NAME=your-bucket-name
|
||||||
|
OCI_ACCESS_KEY=your-access-key
|
||||||
|
OCI_SECRET_KEY=your-secret-key
|
||||||
|
OCI_REGION=us-ashburn-1
|
||||||
|
|
||||||
|
# Huawei OBS Configuration
|
||||||
|
#
|
||||||
|
HUAWEI_OBS_BUCKET_NAME=your-bucket-name
|
||||||
|
HUAWEI_OBS_SECRET_KEY=your-secret-key
|
||||||
|
HUAWEI_OBS_ACCESS_KEY=your-access-key
|
||||||
|
HUAWEI_OBS_SERVER=your-server-url
|
||||||
|
|
||||||
|
# Volcengine TOS Configuration
|
||||||
|
#
|
||||||
|
VOLCENGINE_TOS_BUCKET_NAME=your-bucket-name
|
||||||
|
VOLCENGINE_TOS_SECRET_KEY=your-secret-key
|
||||||
|
VOLCENGINE_TOS_ACCESS_KEY=your-access-key
|
||||||
|
VOLCENGINE_TOS_ENDPOINT=your-server-url
|
||||||
|
VOLCENGINE_TOS_REGION=your-region
|
||||||
|
|
||||||
|
# Baidu OBS Storage Configuration
|
||||||
|
#
|
||||||
|
BAIDU_OBS_BUCKET_NAME=your-bucket-name
|
||||||
|
BAIDU_OBS_SECRET_KEY=your-secret-key
|
||||||
|
BAIDU_OBS_ACCESS_KEY=your-access-key
|
||||||
|
BAIDU_OBS_ENDPOINT=your-server-url
|
||||||
|
|
||||||
|
# Supabase Storage Configuration
|
||||||
|
#
|
||||||
|
SUPABASE_BUCKET_NAME=your-bucket-name
|
||||||
|
SUPABASE_API_KEY=your-access-key
|
||||||
|
SUPABASE_URL=your-server-url
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Vector Database Configuration
|
# Vector Database Configuration
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
|
|
||||||
# The type of vector store to use.
|
# The type of vector store to use.
|
||||||
# Supported values are `weaviate`, `qdrant`, `milvus`, `myscale`, `relyt`, `pgvector`, `chroma`, `opensearch`, `tidb_vector`, `oracle`, `tencent`, `elasticsearch`.
|
# Supported values are `weaviate`, `qdrant`, `milvus`, `myscale`, `relyt`, `pgvector`, `pgvecto-rs`, `chroma`, `opensearch`, `oracle`, `tencent`, `elasticsearch`, `elasticsearch-ja`, `analyticdb`, `couchbase`, `vikingdb`, `oceanbase`, `opengauss`, `tablestore`,`vastbase`,`tidb`,`tidb_on_qdrant`,`baidu`,`lindorm`,`huawei_cloud`,`upstash`.
|
||||||
VECTOR_STORE=weaviate
|
VECTOR_STORE=weaviate
|
||||||
|
|
||||||
# The Weaviate endpoint URL. Only available when VECTOR_STORE is `weaviate`.
|
# The Weaviate endpoint URL. Only available when VECTOR_STORE is `weaviate`.
|
||||||
WEAVIATE_ENDPOINT=http://weaviate:8080
|
WEAVIATE_ENDPOINT=http://weaviate:8080
|
||||||
# The Weaviate API key.
|
|
||||||
WEAVIATE_API_KEY=WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih
|
WEAVIATE_API_KEY=WVF5YThaHlkYwhGUSmCRgsX3tD5ngdN8pkih
|
||||||
|
|
||||||
# The Qdrant endpoint URL. Only available when VECTOR_STORE is `qdrant`.
|
# The Qdrant endpoint URL. Only available when VECTOR_STORE is `qdrant`.
|
||||||
QDRANT_URL=http://qdrant:6333
|
QDRANT_URL=http://qdrant:6333
|
||||||
# The Qdrant API key.
|
|
||||||
QDRANT_API_KEY=difyai123456
|
QDRANT_API_KEY=difyai123456
|
||||||
# The Qdrant client timeout setting.
|
|
||||||
QDRANT_CLIENT_TIMEOUT=20
|
QDRANT_CLIENT_TIMEOUT=20
|
||||||
# The Qdrant client enable gRPC mode.
|
|
||||||
QDRANT_GRPC_ENABLED=false
|
QDRANT_GRPC_ENABLED=false
|
||||||
# The Qdrant server gRPC mode PORT.
|
|
||||||
QDRANT_GRPC_PORT=6334
|
QDRANT_GRPC_PORT=6334
|
||||||
|
|
||||||
# Milvus configuration Only available when VECTOR_STORE is `milvus`.
|
# Milvus configuration. Only available when VECTOR_STORE is `milvus`.
|
||||||
# The milvus host.
|
# The milvus uri.
|
||||||
MILVUS_HOST=127.0.0.1
|
MILVUS_URI=http://host.docker.internal:19530
|
||||||
# The milvus host.
|
MILVUS_DATABASE=
|
||||||
MILVUS_PORT=19530
|
MILVUS_TOKEN=
|
||||||
# The milvus username.
|
MILVUS_USER=
|
||||||
MILVUS_USER=root
|
MILVUS_PASSWORD=
|
||||||
# The milvus password.
|
MILVUS_ENABLE_HYBRID_SEARCH=False
|
||||||
MILVUS_PASSWORD=Milvus
|
MILVUS_ANALYZER_PARAMS=
|
||||||
# The milvus tls switch.
|
|
||||||
MILVUS_SECURE=false
|
|
||||||
|
|
||||||
# MyScale configuration, only available when VECTOR_STORE is `myscale`
|
# MyScale configuration, only available when VECTOR_STORE is `myscale`
|
||||||
# For multi-language support, please set MYSCALE_FTS_PARAMS with referring to:
|
# For multi-language support, please set MYSCALE_FTS_PARAMS with referring to:
|
||||||
@@ -344,34 +433,92 @@ MYSCALE_PASSWORD=
|
|||||||
MYSCALE_DATABASE=dify
|
MYSCALE_DATABASE=dify
|
||||||
MYSCALE_FTS_PARAMS=
|
MYSCALE_FTS_PARAMS=
|
||||||
|
|
||||||
# pgvector configurations, only available when VECTOR_STORE is `pgvecto-rs or pgvector`
|
# Couchbase configurations, only available when VECTOR_STORE is `couchbase`
|
||||||
|
# The connection string must include hostname defined in the docker-compose file (couchbase-server in this case)
|
||||||
|
COUCHBASE_CONNECTION_STRING=couchbase://couchbase-server
|
||||||
|
COUCHBASE_USER=Administrator
|
||||||
|
COUCHBASE_PASSWORD=password
|
||||||
|
COUCHBASE_BUCKET_NAME=Embeddings
|
||||||
|
COUCHBASE_SCOPE_NAME=_default
|
||||||
|
|
||||||
|
# pgvector configurations, only available when VECTOR_STORE is `pgvector`
|
||||||
PGVECTOR_HOST=pgvector
|
PGVECTOR_HOST=pgvector
|
||||||
PGVECTOR_PORT=5432
|
PGVECTOR_PORT=5432
|
||||||
PGVECTOR_USER=postgres
|
PGVECTOR_USER=postgres
|
||||||
PGVECTOR_PASSWORD=difyai123456
|
PGVECTOR_PASSWORD=difyai123456
|
||||||
PGVECTOR_DATABASE=dify
|
PGVECTOR_DATABASE=dify
|
||||||
|
PGVECTOR_MIN_CONNECTION=1
|
||||||
|
PGVECTOR_MAX_CONNECTION=5
|
||||||
|
PGVECTOR_PG_BIGM=false
|
||||||
|
PGVECTOR_PG_BIGM_VERSION=1.2-20240606
|
||||||
|
|
||||||
# TiDB vector configurations, only available when VECTOR_STORE is `tidb`
|
# vastbase configurations, only available when VECTOR_STORE is `vastbase`
|
||||||
|
VASTBASE_HOST=vastbase
|
||||||
|
VASTBASE_PORT=5432
|
||||||
|
VASTBASE_USER=dify
|
||||||
|
VASTBASE_PASSWORD=Difyai123456
|
||||||
|
VASTBASE_DATABASE=dify
|
||||||
|
VASTBASE_MIN_CONNECTION=1
|
||||||
|
VASTBASE_MAX_CONNECTION=5
|
||||||
|
|
||||||
|
# pgvecto-rs configurations, only available when VECTOR_STORE is `pgvecto-rs`
|
||||||
|
PGVECTO_RS_HOST=pgvecto-rs
|
||||||
|
PGVECTO_RS_PORT=5432
|
||||||
|
PGVECTO_RS_USER=postgres
|
||||||
|
PGVECTO_RS_PASSWORD=difyai123456
|
||||||
|
PGVECTO_RS_DATABASE=dify
|
||||||
|
|
||||||
|
# analyticdb configurations, only available when VECTOR_STORE is `analyticdb`
|
||||||
|
ANALYTICDB_KEY_ID=your-ak
|
||||||
|
ANALYTICDB_KEY_SECRET=your-sk
|
||||||
|
ANALYTICDB_REGION_ID=cn-hangzhou
|
||||||
|
ANALYTICDB_INSTANCE_ID=gp-ab123456
|
||||||
|
ANALYTICDB_ACCOUNT=testaccount
|
||||||
|
ANALYTICDB_PASSWORD=testpassword
|
||||||
|
ANALYTICDB_NAMESPACE=dify
|
||||||
|
ANALYTICDB_NAMESPACE_PASSWORD=difypassword
|
||||||
|
ANALYTICDB_HOST=gp-test.aliyuncs.com
|
||||||
|
ANALYTICDB_PORT=5432
|
||||||
|
ANALYTICDB_MIN_CONNECTION=1
|
||||||
|
ANALYTICDB_MAX_CONNECTION=5
|
||||||
|
|
||||||
|
# TiDB vector configurations, only available when VECTOR_STORE is `tidb_vector`
|
||||||
TIDB_VECTOR_HOST=tidb
|
TIDB_VECTOR_HOST=tidb
|
||||||
TIDB_VECTOR_PORT=4000
|
TIDB_VECTOR_PORT=4000
|
||||||
TIDB_VECTOR_USER=xxx.root
|
TIDB_VECTOR_USER=
|
||||||
TIDB_VECTOR_PASSWORD=xxxxxx
|
TIDB_VECTOR_PASSWORD=
|
||||||
TIDB_VECTOR_DATABASE=dify
|
TIDB_VECTOR_DATABASE=dify
|
||||||
|
|
||||||
|
# Tidb on qdrant configuration, only available when VECTOR_STORE is `tidb_on_qdrant`
|
||||||
|
TIDB_ON_QDRANT_URL=http://127.0.0.1
|
||||||
|
TIDB_ON_QDRANT_API_KEY=dify
|
||||||
|
TIDB_ON_QDRANT_CLIENT_TIMEOUT=20
|
||||||
|
TIDB_ON_QDRANT_GRPC_ENABLED=false
|
||||||
|
TIDB_ON_QDRANT_GRPC_PORT=6334
|
||||||
|
TIDB_PUBLIC_KEY=dify
|
||||||
|
TIDB_PRIVATE_KEY=dify
|
||||||
|
TIDB_API_URL=http://127.0.0.1
|
||||||
|
TIDB_IAM_API_URL=http://127.0.0.1
|
||||||
|
TIDB_REGION=regions/aws-us-east-1
|
||||||
|
TIDB_PROJECT_ID=dify
|
||||||
|
TIDB_SPEND_LIMIT=100
|
||||||
|
|
||||||
# Chroma configuration, only available when VECTOR_STORE is `chroma`
|
# Chroma configuration, only available when VECTOR_STORE is `chroma`
|
||||||
CHROMA_HOST=127.0.0.1
|
CHROMA_HOST=127.0.0.1
|
||||||
CHROMA_PORT=8000
|
CHROMA_PORT=8000
|
||||||
CHROMA_TENANT=default_tenant
|
CHROMA_TENANT=default_tenant
|
||||||
CHROMA_DATABASE=default_database
|
CHROMA_DATABASE=default_database
|
||||||
CHROMA_AUTH_PROVIDER=chromadb.auth.token_authn.TokenAuthClientProvider
|
CHROMA_AUTH_PROVIDER=chromadb.auth.token_authn.TokenAuthClientProvider
|
||||||
CHROMA_AUTH_CREDENTIALS=xxxxxx
|
CHROMA_AUTH_CREDENTIALS=
|
||||||
|
|
||||||
# Oracle configuration, only available when VECTOR_STORE is `oracle`
|
# Oracle configuration, only available when VECTOR_STORE is `oracle`
|
||||||
ORACLE_HOST=oracle
|
|
||||||
ORACLE_PORT=1521
|
|
||||||
ORACLE_USER=dify
|
ORACLE_USER=dify
|
||||||
ORACLE_PASSWORD=dify
|
ORACLE_PASSWORD=dify
|
||||||
ORACLE_DATABASE=FREEPDB1
|
ORACLE_DSN=oracle:1521/FREEPDB1
|
||||||
|
ORACLE_CONFIG_DIR=/app/api/storage/wallet
|
||||||
|
ORACLE_WALLET_LOCATION=/app/api/storage/wallet
|
||||||
|
ORACLE_WALLET_PASSWORD=dify
|
||||||
|
ORACLE_IS_AUTONOMOUS=false
|
||||||
|
|
||||||
# relyt configurations, only available when VECTOR_STORE is `relyt`
|
# relyt configurations, only available when VECTOR_STORE is `relyt`
|
||||||
RELYT_HOST=db
|
RELYT_HOST=db
|
||||||
@@ -383,9 +530,13 @@ RELYT_DATABASE=postgres
|
|||||||
# open search configuration, only available when VECTOR_STORE is `opensearch`
|
# open search configuration, only available when VECTOR_STORE is `opensearch`
|
||||||
OPENSEARCH_HOST=opensearch
|
OPENSEARCH_HOST=opensearch
|
||||||
OPENSEARCH_PORT=9200
|
OPENSEARCH_PORT=9200
|
||||||
|
OPENSEARCH_SECURE=true
|
||||||
|
OPENSEARCH_AUTH_METHOD=basic
|
||||||
OPENSEARCH_USER=admin
|
OPENSEARCH_USER=admin
|
||||||
OPENSEARCH_PASSWORD=admin
|
OPENSEARCH_PASSWORD=admin
|
||||||
OPENSEARCH_SECURE=true
|
# If using AWS managed IAM, e.g. Managed Cluster or OpenSearch Serverless
|
||||||
|
OPENSEARCH_AWS_REGION=ap-southeast-1
|
||||||
|
OPENSEARCH_AWS_SERVICE=aoss
|
||||||
|
|
||||||
# tencent vector configurations, only available when VECTOR_STORE is `tencent`
|
# tencent vector configurations, only available when VECTOR_STORE is `tencent`
|
||||||
TENCENT_VECTOR_DB_URL=http://127.0.0.1
|
TENCENT_VECTOR_DB_URL=http://127.0.0.1
|
||||||
@@ -395,12 +546,74 @@ TENCENT_VECTOR_DB_USERNAME=dify
|
|||||||
TENCENT_VECTOR_DB_DATABASE=dify
|
TENCENT_VECTOR_DB_DATABASE=dify
|
||||||
TENCENT_VECTOR_DB_SHARD=1
|
TENCENT_VECTOR_DB_SHARD=1
|
||||||
TENCENT_VECTOR_DB_REPLICAS=2
|
TENCENT_VECTOR_DB_REPLICAS=2
|
||||||
|
TENCENT_VECTOR_DB_ENABLE_HYBRID_SEARCH=false
|
||||||
|
|
||||||
# ElasticSearch configuration, only available when VECTOR_STORE is `elasticsearch`
|
# ElasticSearch configuration, only available when VECTOR_STORE is `elasticsearch`
|
||||||
ELASTICSEARCH_HOST=0.0.0.0
|
ELASTICSEARCH_HOST=0.0.0.0
|
||||||
ELASTICSEARCH_PORT=9200
|
ELASTICSEARCH_PORT=9200
|
||||||
ELASTICSEARCH_USERNAME=elastic
|
ELASTICSEARCH_USERNAME=elastic
|
||||||
ELASTICSEARCH_PASSWORD=elastic
|
ELASTICSEARCH_PASSWORD=elastic
|
||||||
|
KIBANA_PORT=5601
|
||||||
|
|
||||||
|
# baidu vector configurations, only available when VECTOR_STORE is `baidu`
|
||||||
|
BAIDU_VECTOR_DB_ENDPOINT=http://127.0.0.1:5287
|
||||||
|
BAIDU_VECTOR_DB_CONNECTION_TIMEOUT_MS=30000
|
||||||
|
BAIDU_VECTOR_DB_ACCOUNT=root
|
||||||
|
BAIDU_VECTOR_DB_API_KEY=dify
|
||||||
|
BAIDU_VECTOR_DB_DATABASE=dify
|
||||||
|
BAIDU_VECTOR_DB_SHARD=1
|
||||||
|
BAIDU_VECTOR_DB_REPLICAS=3
|
||||||
|
|
||||||
|
# VikingDB configurations, only available when VECTOR_STORE is `vikingdb`
|
||||||
|
VIKINGDB_ACCESS_KEY=your-ak
|
||||||
|
VIKINGDB_SECRET_KEY=your-sk
|
||||||
|
VIKINGDB_REGION=cn-shanghai
|
||||||
|
VIKINGDB_HOST=api-vikingdb.xxx.volces.com
|
||||||
|
VIKINGDB_SCHEMA=http
|
||||||
|
VIKINGDB_CONNECTION_TIMEOUT=30
|
||||||
|
VIKINGDB_SOCKET_TIMEOUT=30
|
||||||
|
|
||||||
|
# Lindorm configuration, only available when VECTOR_STORE is `lindorm`
|
||||||
|
LINDORM_URL=http://lindorm:30070
|
||||||
|
LINDORM_USERNAME=lindorm
|
||||||
|
LINDORM_PASSWORD=lindorm
|
||||||
|
LINDORM_QUERY_TIMEOUT=1
|
||||||
|
|
||||||
|
# OceanBase Vector configuration, only available when VECTOR_STORE is `oceanbase`
|
||||||
|
OCEANBASE_VECTOR_HOST=oceanbase
|
||||||
|
OCEANBASE_VECTOR_PORT=2881
|
||||||
|
OCEANBASE_VECTOR_USER=root@test
|
||||||
|
OCEANBASE_VECTOR_PASSWORD=difyai123456
|
||||||
|
OCEANBASE_VECTOR_DATABASE=test
|
||||||
|
OCEANBASE_CLUSTER_NAME=difyai
|
||||||
|
OCEANBASE_MEMORY_LIMIT=6G
|
||||||
|
OCEANBASE_ENABLE_HYBRID_SEARCH=false
|
||||||
|
|
||||||
|
# opengauss configurations, only available when VECTOR_STORE is `opengauss`
|
||||||
|
OPENGAUSS_HOST=opengauss
|
||||||
|
OPENGAUSS_PORT=6600
|
||||||
|
OPENGAUSS_USER=postgres
|
||||||
|
OPENGAUSS_PASSWORD=Dify@123
|
||||||
|
OPENGAUSS_DATABASE=dify
|
||||||
|
OPENGAUSS_MIN_CONNECTION=1
|
||||||
|
OPENGAUSS_MAX_CONNECTION=5
|
||||||
|
OPENGAUSS_ENABLE_PQ=false
|
||||||
|
|
||||||
|
# huawei cloud search service vector configurations, only available when VECTOR_STORE is `huawei_cloud`
|
||||||
|
HUAWEI_CLOUD_HOSTS=https://127.0.0.1:9200
|
||||||
|
HUAWEI_CLOUD_USER=admin
|
||||||
|
HUAWEI_CLOUD_PASSWORD=admin
|
||||||
|
|
||||||
|
# Upstash Vector configuration, only available when VECTOR_STORE is `upstash`
|
||||||
|
UPSTASH_VECTOR_URL=https://xxx-vector.upstash.io
|
||||||
|
UPSTASH_VECTOR_TOKEN=dify
|
||||||
|
|
||||||
|
# TableStore Vector configuration
|
||||||
|
# (only used when VECTOR_STORE is tablestore)
|
||||||
|
TABLESTORE_ENDPOINT=https://instance-name.cn-hangzhou.ots.aliyuncs.com
|
||||||
|
TABLESTORE_INSTANCE_NAME=instance-name
|
||||||
|
TABLESTORE_ACCESS_KEY_ID=xxx
|
||||||
|
TABLESTORE_ACCESS_KEY_SECRET=xxx
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Knowledge Configuration
|
# Knowledge Configuration
|
||||||
@@ -412,42 +625,68 @@ UPLOAD_FILE_SIZE_LIMIT=15
|
|||||||
# The maximum number of files that can be uploaded at a time, default 5.
|
# The maximum number of files that can be uploaded at a time, default 5.
|
||||||
UPLOAD_FILE_BATCH_LIMIT=5
|
UPLOAD_FILE_BATCH_LIMIT=5
|
||||||
|
|
||||||
# ETl type, support: `dify`, `Unstructured`
|
# ETL type, support: `dify`, `Unstructured`
|
||||||
# `dify` Dify's proprietary file extraction scheme
|
# `dify` Dify's proprietary file extraction scheme
|
||||||
# `Unstructured` Unstructured.io file extraction scheme
|
# `Unstructured` Unstructured.io file extraction scheme
|
||||||
ETL_TYPE=dify
|
ETL_TYPE=dify
|
||||||
|
|
||||||
# Unstructured API path, needs to be configured when ETL_TYPE is Unstructured.
|
# Unstructured API path and API key, needs to be configured when ETL_TYPE is Unstructured
|
||||||
|
# Or using Unstructured for document extractor node for pptx.
|
||||||
# For example: http://unstructured:8000/general/v0/general
|
# For example: http://unstructured:8000/general/v0/general
|
||||||
UNSTRUCTURED_API_URL=
|
UNSTRUCTURED_API_URL=
|
||||||
|
UNSTRUCTURED_API_KEY=
|
||||||
|
SCARF_NO_ANALYTICS=true
|
||||||
|
|
||||||
|
# ------------------------------
|
||||||
|
# Model Configuration
|
||||||
|
# ------------------------------
|
||||||
|
|
||||||
|
# The maximum number of tokens allowed for prompt generation.
|
||||||
|
# This setting controls the upper limit of tokens that can be used by the LLM
|
||||||
|
# when generating a prompt in the prompt generation tool.
|
||||||
|
# Default: 512 tokens.
|
||||||
|
PROMPT_GENERATION_MAX_TOKENS=512
|
||||||
|
|
||||||
|
# The maximum number of tokens allowed for code generation.
|
||||||
|
# This setting controls the upper limit of tokens that can be used by the LLM
|
||||||
|
# when generating code in the code generation tool.
|
||||||
|
# Default: 1024 tokens.
|
||||||
|
CODE_GENERATION_MAX_TOKENS=1024
|
||||||
|
|
||||||
|
# Enable or disable plugin based token counting. If disabled, token counting will return 0.
|
||||||
|
# This can improve performance by skipping token counting operations.
|
||||||
|
# Default: false (disabled).
|
||||||
|
PLUGIN_BASED_TOKEN_COUNTING_ENABLED=false
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Multi-modal Configuration
|
# Multi-modal Configuration
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
|
|
||||||
# The format of the image sent when the multi-modal model is input,
|
# The format of the image/video/audio/document sent when the multi-modal model is input,
|
||||||
# the default is base64, optional url.
|
# the default is base64, optional url.
|
||||||
# The delay of the call in url mode will be lower than that in base64 mode.
|
# The delay of the call in url mode will be lower than that in base64 mode.
|
||||||
# It is generally recommended to use the more compatible base64 mode.
|
# It is generally recommended to use the more compatible base64 mode.
|
||||||
# If configured as url, you need to configure FILES_URL as an externally accessible address so that the multi-modal model can access the image.
|
# If configured as url, you need to configure FILES_URL as an externally accessible address so that the multi-modal model can access the image/video/audio/document.
|
||||||
MULTIMODAL_SEND_IMAGE_FORMAT=base64
|
MULTIMODAL_SEND_FORMAT=base64
|
||||||
|
|
||||||
# Upload image file size limit, default 10M.
|
# Upload image file size limit, default 10M.
|
||||||
UPLOAD_IMAGE_FILE_SIZE_LIMIT=10
|
UPLOAD_IMAGE_FILE_SIZE_LIMIT=10
|
||||||
|
# Upload video file size limit, default 100M.
|
||||||
|
UPLOAD_VIDEO_FILE_SIZE_LIMIT=100
|
||||||
|
# Upload audio file size limit, default 50M.
|
||||||
|
UPLOAD_AUDIO_FILE_SIZE_LIMIT=50
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Sentry Configuration
|
# Sentry Configuration
|
||||||
# Used for application monitoring and error log tracking.
|
# Used for application monitoring and error log tracking.
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
|
SENTRY_DSN=
|
||||||
|
|
||||||
# API Service Sentry DSN address, default is empty, when empty,
|
# API Service Sentry DSN address, default is empty, when empty,
|
||||||
# all monitoring information is not reported to Sentry.
|
# all monitoring information is not reported to Sentry.
|
||||||
# If not set, Sentry error reporting will be disabled.
|
# If not set, Sentry error reporting will be disabled.
|
||||||
API_SENTRY_DSN=
|
API_SENTRY_DSN=
|
||||||
|
|
||||||
# API Service The reporting ratio of Sentry events, if it is 0.01, it is 1%.
|
# API Service The reporting ratio of Sentry events, if it is 0.01, it is 1%.
|
||||||
API_SENTRY_TRACES_SAMPLE_RATE=1.0
|
API_SENTRY_TRACES_SAMPLE_RATE=1.0
|
||||||
|
|
||||||
# API Service The reporting ratio of Sentry profiles, if it is 0.01, it is 1%.
|
# API Service The reporting ratio of Sentry profiles, if it is 0.01, it is 1%.
|
||||||
API_SENTRY_PROFILES_SAMPLE_RATE=1.0
|
API_SENTRY_PROFILES_SAMPLE_RATE=1.0
|
||||||
|
|
||||||
@@ -485,8 +724,10 @@ MAIL_TYPE=resend
|
|||||||
MAIL_DEFAULT_SEND_FROM=
|
MAIL_DEFAULT_SEND_FROM=
|
||||||
|
|
||||||
# API-Key for the Resend email provider, used when MAIL_TYPE is `resend`.
|
# API-Key for the Resend email provider, used when MAIL_TYPE is `resend`.
|
||||||
|
RESEND_API_URL=https://api.resend.com
|
||||||
RESEND_API_KEY=your-resend-api-key
|
RESEND_API_KEY=your-resend-api-key
|
||||||
|
|
||||||
|
|
||||||
# SMTP server configuration, used when MAIL_TYPE is `smtp`
|
# SMTP server configuration, used when MAIL_TYPE is `smtp`
|
||||||
SMTP_SERVER=
|
SMTP_SERVER=
|
||||||
SMTP_PORT=465
|
SMTP_PORT=465
|
||||||
@@ -500,33 +741,74 @@ SMTP_OPPORTUNISTIC_TLS=false
|
|||||||
# ------------------------------
|
# ------------------------------
|
||||||
|
|
||||||
# Maximum length of segmentation tokens for indexing
|
# Maximum length of segmentation tokens for indexing
|
||||||
INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH=1000
|
INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH=4000
|
||||||
|
|
||||||
# Member invitation link valid time (hours),
|
# Member invitation link valid time (hours),
|
||||||
# Default: 72.
|
# Default: 72.
|
||||||
INVITE_EXPIRY_HOURS=72
|
INVITE_EXPIRY_HOURS=72
|
||||||
|
|
||||||
# Reset password token valid time (hours),
|
# Reset password token valid time (minutes),
|
||||||
# Default: 24.
|
RESET_PASSWORD_TOKEN_EXPIRY_MINUTES=5
|
||||||
RESET_PASSWORD_TOKEN_EXPIRY_HOURS=24
|
|
||||||
|
|
||||||
# The sandbox service endpoint.
|
# The sandbox service endpoint.
|
||||||
CODE_EXECUTION_ENDPOINT=http://sandbox:8194
|
CODE_EXECUTION_ENDPOINT=http://sandbox:8194
|
||||||
|
CODE_EXECUTION_API_KEY=dify-sandbox
|
||||||
CODE_MAX_NUMBER=9223372036854775807
|
CODE_MAX_NUMBER=9223372036854775807
|
||||||
CODE_MIN_NUMBER=-9223372036854775808
|
CODE_MIN_NUMBER=-9223372036854775808
|
||||||
CODE_MAX_DEPTH=5
|
CODE_MAX_DEPTH=5
|
||||||
CODE_MAX_PRECISION=20
|
CODE_MAX_PRECISION=20
|
||||||
CODE_MAX_STRING_LENGTH=80000
|
CODE_MAX_STRING_LENGTH=80000
|
||||||
TEMPLATE_TRANSFORM_MAX_LENGTH=80000
|
|
||||||
CODE_MAX_STRING_ARRAY_LENGTH=30
|
CODE_MAX_STRING_ARRAY_LENGTH=30
|
||||||
CODE_MAX_OBJECT_ARRAY_LENGTH=30
|
CODE_MAX_OBJECT_ARRAY_LENGTH=30
|
||||||
CODE_MAX_NUMBER_ARRAY_LENGTH=1000
|
CODE_MAX_NUMBER_ARRAY_LENGTH=1000
|
||||||
|
CODE_EXECUTION_CONNECT_TIMEOUT=10
|
||||||
|
CODE_EXECUTION_READ_TIMEOUT=60
|
||||||
|
CODE_EXECUTION_WRITE_TIMEOUT=10
|
||||||
|
TEMPLATE_TRANSFORM_MAX_LENGTH=80000
|
||||||
|
|
||||||
|
# Workflow runtime configuration
|
||||||
|
WORKFLOW_MAX_EXECUTION_STEPS=500
|
||||||
|
WORKFLOW_MAX_EXECUTION_TIME=1200
|
||||||
|
WORKFLOW_CALL_MAX_DEPTH=5
|
||||||
|
MAX_VARIABLE_SIZE=204800
|
||||||
|
WORKFLOW_PARALLEL_DEPTH_LIMIT=3
|
||||||
|
WORKFLOW_FILE_UPLOAD_LIMIT=10
|
||||||
|
|
||||||
|
# Workflow storage configuration
|
||||||
|
# Options: rdbms, hybrid
|
||||||
|
# rdbms: Use only the relational database (default)
|
||||||
|
# hybrid: Save new data to object storage, read from both object storage and RDBMS
|
||||||
|
WORKFLOW_NODE_EXECUTION_STORAGE=rdbms
|
||||||
|
|
||||||
|
# HTTP request node in workflow configuration
|
||||||
|
HTTP_REQUEST_NODE_MAX_BINARY_SIZE=10485760
|
||||||
|
HTTP_REQUEST_NODE_MAX_TEXT_SIZE=1048576
|
||||||
|
HTTP_REQUEST_NODE_SSL_VERIFY=True
|
||||||
|
|
||||||
# SSRF Proxy server HTTP URL
|
# SSRF Proxy server HTTP URL
|
||||||
SSRF_PROXY_HTTP_URL=http://ssrf_proxy:3128
|
SSRF_PROXY_HTTP_URL=http://ssrf_proxy:3128
|
||||||
# SSRF Proxy server HTTPS URL
|
# SSRF Proxy server HTTPS URL
|
||||||
SSRF_PROXY_HTTPS_URL=http://ssrf_proxy:3128
|
SSRF_PROXY_HTTPS_URL=http://ssrf_proxy:3128
|
||||||
|
|
||||||
|
# Maximum loop count in the workflow
|
||||||
|
LOOP_NODE_MAX_COUNT=100
|
||||||
|
|
||||||
|
# The maximum number of tools that can be used in the agent.
|
||||||
|
MAX_TOOLS_NUM=10
|
||||||
|
|
||||||
|
# Maximum number of Parallelism branches in the workflow
|
||||||
|
MAX_PARALLEL_LIMIT=10
|
||||||
|
|
||||||
|
# The maximum number of iterations for agent setting
|
||||||
|
MAX_ITERATIONS_NUM=5
|
||||||
|
|
||||||
|
# ------------------------------
|
||||||
|
# Environment Variables for web Service
|
||||||
|
# ------------------------------
|
||||||
|
|
||||||
|
# The timeout for the text generation in millisecond
|
||||||
|
TEXT_GENERATION_TIMEOUT_MS=60000
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Environment Variables for db Service
|
# Environment Variables for db Service
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
@@ -562,7 +844,7 @@ SANDBOX_PORT=8194
|
|||||||
# Environment Variables for weaviate Service
|
# Environment Variables for weaviate Service
|
||||||
# (only used when VECTOR_STORE is weaviate)
|
# (only used when VECTOR_STORE is weaviate)
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
WEAVIATE_PERSISTENCE_DATA_PATH='/var/lib/weaviate'
|
WEAVIATE_PERSISTENCE_DATA_PATH=/var/lib/weaviate
|
||||||
WEAVIATE_QUERY_DEFAULTS_LIMIT=25
|
WEAVIATE_QUERY_DEFAULTS_LIMIT=25
|
||||||
WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED=true
|
WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED=true
|
||||||
WEAVIATE_DEFAULT_VECTORIZER_MODULE=none
|
WEAVIATE_DEFAULT_VECTORIZER_MODULE=none
|
||||||
@@ -587,7 +869,7 @@ CHROMA_IS_PERSISTENT=TRUE
|
|||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Environment Variables for Oracle Service
|
# Environment Variables for Oracle Service
|
||||||
# (only used when VECTOR_STORE is Oracle)
|
# (only used when VECTOR_STORE is oracle)
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
ORACLE_PWD=Dify123456
|
ORACLE_PWD=Dify123456
|
||||||
ORACLE_CHARACTERSET=AL32UTF8
|
ORACLE_CHARACTERSET=AL32UTF8
|
||||||
@@ -689,6 +971,10 @@ SSRF_HTTP_PORT=3128
|
|||||||
SSRF_COREDUMP_DIR=/var/spool/squid
|
SSRF_COREDUMP_DIR=/var/spool/squid
|
||||||
SSRF_REVERSE_PROXY_PORT=8194
|
SSRF_REVERSE_PROXY_PORT=8194
|
||||||
SSRF_SANDBOX_HOST=sandbox
|
SSRF_SANDBOX_HOST=sandbox
|
||||||
|
SSRF_DEFAULT_TIME_OUT=5
|
||||||
|
SSRF_DEFAULT_CONNECT_TIME_OUT=5
|
||||||
|
SSRF_DEFAULT_READ_TIME_OUT=5
|
||||||
|
SSRF_DEFAULT_WRITE_TIME_OUT=5
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# docker env var for specifying vector db type at startup
|
# docker env var for specifying vector db type at startup
|
||||||
@@ -721,4 +1007,100 @@ POSITION_TOOL_EXCLUDES=
|
|||||||
# Example: POSITION_PROVIDER_PINS=openai,openllm
|
# Example: POSITION_PROVIDER_PINS=openai,openllm
|
||||||
POSITION_PROVIDER_PINS=
|
POSITION_PROVIDER_PINS=
|
||||||
POSITION_PROVIDER_INCLUDES=
|
POSITION_PROVIDER_INCLUDES=
|
||||||
POSITION_PROVIDER_EXCLUDES=
|
POSITION_PROVIDER_EXCLUDES=
|
||||||
|
|
||||||
|
# CSP https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
|
||||||
|
CSP_WHITELIST=
|
||||||
|
|
||||||
|
# Enable or disable create tidb service job
|
||||||
|
CREATE_TIDB_SERVICE_JOB_ENABLED=false
|
||||||
|
|
||||||
|
# Maximum number of submitted thread count in a ThreadPool for parallel node execution
|
||||||
|
MAX_SUBMIT_COUNT=100
|
||||||
|
|
||||||
|
# The maximum number of top-k value for RAG.
|
||||||
|
TOP_K_MAX_VALUE=10
|
||||||
|
|
||||||
|
# ------------------------------
|
||||||
|
# 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://plugin_daemon:5002
|
||||||
|
PLUGIN_MAX_PACKAGE_SIZE=52428800
|
||||||
|
PLUGIN_PPROF_ENABLED=false
|
||||||
|
|
||||||
|
PLUGIN_DEBUGGING_HOST=0.0.0.0
|
||||||
|
PLUGIN_DEBUGGING_PORT=5003
|
||||||
|
EXPOSE_PLUGIN_DEBUGGING_HOST=localhost
|
||||||
|
EXPOSE_PLUGIN_DEBUGGING_PORT=5003
|
||||||
|
|
||||||
|
# If this key is changed, DIFY_INNER_API_KEY in plugin_daemon service must also be updated or agent node will fail.
|
||||||
|
PLUGIN_DIFY_INNER_API_KEY=QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1
|
||||||
|
PLUGIN_DIFY_INNER_API_URL=http://api:5001
|
||||||
|
|
||||||
|
ENDPOINT_URL_TEMPLATE=http://localhost/e/{hook_id}
|
||||||
|
|
||||||
|
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 aliyun_oss
|
||||||
|
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_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=
|
||||||
|
|
||||||
|
# ------------------------------
|
||||||
|
# OTLP Collector Configuration
|
||||||
|
# ------------------------------
|
||||||
|
ENABLE_OTEL=false
|
||||||
|
OTLP_BASE_ENDPOINT=http://localhost:4318
|
||||||
|
OTLP_API_KEY=
|
||||||
|
OTEL_EXPORTER_OTLP_PROTOCOL=
|
||||||
|
OTEL_EXPORTER_TYPE=otlp
|
||||||
|
OTEL_SAMPLING_RATE=0.1
|
||||||
|
OTEL_BATCH_EXPORT_SCHEDULE_DELAY=5000
|
||||||
|
OTEL_MAX_QUEUE_SIZE=2048
|
||||||
|
OTEL_MAX_EXPORT_BATCH_SIZE=512
|
||||||
|
OTEL_METRIC_EXPORT_INTERVAL=60000
|
||||||
|
OTEL_BATCH_EXPORT_TIMEOUT=10000
|
||||||
|
OTEL_METRIC_EXPORT_TIMEOUT=30000
|
||||||
|
|
||||||
|
# Prevent Clickjacking
|
||||||
|
ALLOW_EMBED=false
|
||||||
|
|||||||
+13
-6
@@ -14,7 +14,6 @@ Welcome to the new `docker` directory for deploying Dify using Docker Compose. T
|
|||||||
|
|
||||||
- **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`
|
||||||
|
|
||||||
@@ -27,7 +26,10 @@ Welcome to the new `docker` directory for deploying Dify using Docker Compose. T
|
|||||||
- 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**:
|
4. **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.
|
||||||
|
5. **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
|
||||||
|
|
||||||
@@ -36,7 +38,8 @@ Welcome to the new `docker` directory for deploying Dify using Docker Compose. T
|
|||||||
- 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**:
|
2. **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 -f docker-compose.middleware.yaml --profile weaviate -p dify up -d` to start the middleware services. (Change the profile to other vector database if you are not using weaviate)
|
||||||
|
|
||||||
### Migration for Existing Users
|
### Migration for Existing Users
|
||||||
|
|
||||||
@@ -54,7 +57,7 @@ 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
|
||||||
|
|
||||||
@@ -83,12 +86,16 @@ The `.env.example` file provided in the Docker setup is extensive and covers a w
|
|||||||
|
|
||||||
7. **Vector Database Configuration**:
|
7. **Vector Database Configuration**:
|
||||||
- `VECTOR_STORE`: Type of vector database (e.g., `weaviate`, `milvus`).
|
- `VECTOR_STORE`: Type of vector database (e.g., `weaviate`, `milvus`).
|
||||||
- Specific settings for each vector store like `WEAVIATE_ENDPOINT`, `MILVUS_HOST`.
|
- Specific settings for each vector store like `WEAVIATE_ENDPOINT`, `MILVUS_URI`.
|
||||||
|
|
||||||
8. **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**:
|
9. **OpenTelemetry Configuration**:
|
||||||
|
- `ENABLE_OTEL`: Enable OpenTelemetry collector in api.
|
||||||
|
- `OTLP_BASE_ENDPOINT`: Endpoint for your OTLP exporter.
|
||||||
|
|
||||||
|
10. **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`.
|
||||||
|
|
||||||
### Additional Information
|
### Additional Information
|
||||||
|
|||||||
+13
-13
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
## 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
|
||||||
|
|
||||||
@@ -18,21 +18,21 @@ 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.
|
2. 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)
|
||||||
@@ -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
|
||||||
Executable
+44
@@ -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,694 @@
|
|||||||
|
x-shared-env: &shared-api-worker-env
|
||||||
|
services:
|
||||||
|
# API service
|
||||||
|
api:
|
||||||
|
image: langgenius/dify-api:1.4.0
|
||||||
|
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}
|
||||||
|
INNER_API_KEY_FOR_PLUGIN: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1}
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
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 the queue.
|
||||||
|
worker:
|
||||||
|
image: langgenius/dify-api:1.4.0
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
# Use the shared environment variables.
|
||||||
|
<<: *shared-api-worker-env
|
||||||
|
# Startup mode, 'worker' starts the Celery worker for processing the queue.
|
||||||
|
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:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
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
|
||||||
|
|
||||||
|
# Frontend web application.
|
||||||
|
web:
|
||||||
|
image: langgenius/dify-web:1.4.0
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
CONSOLE_API_URL: ${CONSOLE_API_URL:-}
|
||||||
|
APP_API_URL: ${APP_API_URL:-}
|
||||||
|
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}
|
||||||
|
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:-5}
|
||||||
|
ENABLE_WEBSITE_JINAREADER: ${ENABLE_WEBSITE_JINAREADER:-true}
|
||||||
|
ENABLE_WEBSITE_FIRECRAWL: ${ENABLE_WEBSITE_FIRECRAWL:-true}
|
||||||
|
ENABLE_WEBSITE_WATERCRAWL: ${ENABLE_WEBSITE_WATERCRAWL:-true}
|
||||||
|
# The postgres database.
|
||||||
|
db:
|
||||||
|
image: postgres:15-alpine
|
||||||
|
restart: always
|
||||||
|
environment:
|
||||||
|
PGUSER: ${PGUSER:-postgres}
|
||||||
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-difyai123456}
|
||||||
|
POSTGRES_DB: ${POSTGRES_DB:-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}'
|
||||||
|
volumes:
|
||||||
|
- ./volumes/db/data:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: [ 'CMD', 'pg_isready', '-h', 'db', '-U', '${PGUSER:-postgres}', '-d', '${POSTGRES_DB:-dify}' ]
|
||||||
|
interval: 1s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 60
|
||||||
|
|
||||||
|
# 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', 'redis-cli', 'ping' ]
|
||||||
|
|
||||||
|
# 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.0.10-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}
|
||||||
|
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_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:-}
|
||||||
|
ports:
|
||||||
|
- "${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}:${PLUGIN_DEBUGGING_PORT:-5003}"
|
||||||
|
volumes:
|
||||||
|
- ./volumes/plugin_daemon:/app/storage
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
|
||||||
|
# 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.1 TLSv1.2 TLSv1.3}
|
||||||
|
NGINX_WORKER_PROCESSES: ${NGINX_WORKER_PROCESSES:-auto}
|
||||||
|
NGINX_CLIENT_MAX_BODY_SIZE: ${NGINX_CLIENT_MAX_BODY_SIZE:-15M}
|
||||||
|
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.19.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}
|
||||||
|
|
||||||
|
# Qdrant vector store.
|
||||||
|
# (if used, you need to set VECTOR_STORE to qdrant in the api & worker service.)
|
||||||
|
qdrant:
|
||||||
|
image: langgenius/qdrant:v1.7.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}
|
||||||
|
|
||||||
|
# OceanBase vector database
|
||||||
|
oceanbase:
|
||||||
|
image: oceanbase/oceanbase-ce:4.3.5.1-101000042025031818
|
||||||
|
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}
|
||||||
|
MODE: MINI
|
||||||
|
ports:
|
||||||
|
- "${OCEANBASE_VECTOR_PORT:-2881}:2881"
|
||||||
|
|
||||||
|
# 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.5.0-beta
|
||||||
|
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}
|
||||||
|
|
||||||
|
# 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:
|
||||||
@@ -16,26 +16,39 @@ services:
|
|||||||
-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}'
|
||||||
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" ]
|
||||||
|
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", "redis-cli", "ping" ]
|
||||||
|
|
||||||
# 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,14 +60,76 @@ 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.0.10-local
|
||||||
|
restart: always
|
||||||
|
env_file:
|
||||||
|
- ./middleware.env
|
||||||
|
environment:
|
||||||
|
# Use the shared environment variables.
|
||||||
|
DB_HOST: ${DB_HOST:-db}
|
||||||
|
DB_PORT: ${DB_PORT:-5432}
|
||||||
|
DB_USERNAME: ${DB_USER:-postgres}
|
||||||
|
DB_PASSWORD: ${DB_PASSWORD:-difyai123456}
|
||||||
|
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}
|
||||||
|
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}
|
||||||
|
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_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:-}
|
||||||
|
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
|
||||||
@@ -62,6 +137,8 @@ services:
|
|||||||
- ./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}
|
||||||
@@ -80,11 +157,12 @@ services:
|
|||||||
weaviate:
|
weaviate:
|
||||||
image: semitechnologies/weaviate:1.19.0
|
image: semitechnologies/weaviate:1.19.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:
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 170 KiB |
+662
-142
File diff suppressed because it is too large
Load Diff
Executable
+25
@@ -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
|
||||||
Executable
+112
@@ -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()
|
||||||
@@ -8,6 +8,7 @@ POSTGRES_PASSWORD=difyai123456
|
|||||||
POSTGRES_DB=dify
|
POSTGRES_DB=dify
|
||||||
# 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 +40,15 @@ 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
|
||||||
|
|
||||||
|
# -----------------------------
|
||||||
|
# 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 +56,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,6 +77,7 @@ 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_HOST_VOLUME=./volumes/weaviate
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# Docker Compose Service Expose Host Port Configurations
|
# Docker Compose Service Expose Host Port Configurations
|
||||||
@@ -79,3 +87,68 @@ 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://api: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_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=
|
||||||
|
|||||||
@@ -24,6 +24,17 @@ 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;
|
||||||
|
|||||||
@@ -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;'
|
||||||
|
|||||||
@@ -6,4 +6,4 @@ ssl_certificate_key ${SSL_CERTIFICATE_KEY_PATH};
|
|||||||
ssl_protocols ${NGINX_SSL_PROTOCOLS};
|
ssl_protocols ${NGINX_SSL_PROTOCOLS};
|
||||||
ssl_prefer_server_ciphers on;
|
ssl_prefer_server_ciphers on;
|
||||||
ssl_session_cache shared:SSL:10m;
|
ssl_session_cache shared:SSL:10m;
|
||||||
ssl_session_timeout 10m;
|
ssl_session_timeout 10m;
|
||||||
|
|||||||
@@ -31,4 +31,4 @@ http {
|
|||||||
client_max_body_size ${NGINX_CLIENT_MAX_BODY_SIZE};
|
client_max_body_size ${NGINX_CLIENT_MAX_BODY_SIZE};
|
||||||
|
|
||||||
include /etc/nginx/conf.d/*.conf;
|
include /etc/nginx/conf.d/*.conf;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Executable
+24
@@ -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
|
||||||
@@ -41,10 +44,13 @@ refresh_pattern . 0 20% 4320
|
|||||||
|
|
||||||
# cache_dir ufs /var/spool/squid 100 16 256
|
# cache_dir ufs /var/spool/squid 100 16 256
|
||||||
# upstream proxy, set to your own upstream proxy IP to avoid SSRF attacks
|
# upstream proxy, set to your own upstream proxy IP to avoid SSRF attacks
|
||||||
# cache_peer 172.1.1.1 parent 3128 0 no-query no-digest no-netdb-exchange default
|
# cache_peer 172.1.1.1 parent 3128 0 no-query no-digest no-netdb-exchange default
|
||||||
|
|
||||||
################################## Reverse Proxy To Sandbox ################################
|
################################## Reverse Proxy To Sandbox ################################
|
||||||
http_port ${REVERSE_PROXY_PORT} accel vhost
|
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
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
show pdbs;
|
show pdbs;
|
||||||
ALTER SYSTEM SET PROCESSES=500 SCOPE=SPFILE;
|
ALTER SYSTEM SET PROCESSES=500 SCOPE=SPFILE;
|
||||||
alter session set container= freepdb1;
|
alter session set container= freepdb1;
|
||||||
create user dify identified by dify DEFAULT TABLESPACE users quota unlimited on users;
|
create user dify identified by dify DEFAULT TABLESPACE users quota unlimited on users;
|
||||||
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,62 @@
|
|||||||
|
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:
|
||||||
|
- --config=/tiflash.toml
|
||||||
|
depends_on:
|
||||||
|
- "tikv"
|
||||||
|
- "tidb"
|
||||||
|
restart: on-failure
|
||||||
@@ -14,4 +14,4 @@
|
|||||||
<access_management>1</access_management>
|
<access_management>1</access_management>
|
||||||
</default>
|
</default>
|
||||||
</users>
|
</users>
|
||||||
</clickhouse>
|
</clickhouse>
|
||||||
|
|||||||
@@ -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,6 @@
|
|||||||
|
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");
|
||||||
Generated
+705
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
-5
@@ -5,13 +5,15 @@ 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
|
NGINX_PORT=80
|
||||||
WEB_URL=http://${APP_DOMAIN}
|
WEB_URL=http://${APP_DOMAIN}
|
||||||
DEBUG=0
|
DEBUG=0
|
||||||
SENTRY_DSN=
|
|
||||||
SENTRY_ENVIRONMENT=production
|
|
||||||
CORS_ALLOWED_ORIGINS=http://${APP_DOMAIN}
|
CORS_ALLOWED_ORIGINS=http://${APP_DOMAIN}
|
||||||
|
API_BASE_URL=http://api:8000
|
||||||
|
|
||||||
#DB SETTINGS
|
#DB SETTINGS
|
||||||
PGHOST=plane-db
|
PGHOST=plane-db
|
||||||
@@ -28,6 +30,14 @@ 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=
|
||||||
|
|
||||||
# Secret Key
|
# Secret Key
|
||||||
SECRET_KEY=60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5
|
SECRET_KEY=60gp0byfz2dvffa45cxl20p1scy9xbpf6d8c5y0geejgkyp1b5
|
||||||
|
|
||||||
@@ -38,9 +48,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 +56,8 @@ 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
|
||||||
|
|||||||
+137
-15
@@ -55,14 +55,26 @@ Installing plane is a very easy and minimal step process.
|
|||||||
- User context used must have access to docker services. In most cases, use sudo su to switch as root user
|
- 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
|
- Use the terminal (or gitbash) window to run all the future steps
|
||||||
|
|
||||||
### Downloading Latest Stable Release
|
### Downloading Latest Release
|
||||||
|
|
||||||
```
|
```
|
||||||
mkdir plane-selfhost
|
mkdir plane-selfhost
|
||||||
|
|
||||||
cd plane-selfhost
|
cd plane-selfhost
|
||||||
|
```
|
||||||
|
|
||||||
curl -fsSL -o setup.sh https://raw.githubusercontent.com/makeplane/plane/master/deploy/selfhost/install.sh
|
#### For *Docker Compose* based setup
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -fsSL -o setup.sh https://github.com/makeplane/plane/releases/latest/download/setup.sh
|
||||||
|
|
||||||
|
chmod +x setup.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
#### For *Docker Swarm* based setup
|
||||||
|
|
||||||
|
```
|
||||||
|
curl -fsSL -o setup.sh https://github.com/makeplane/plane/releases/latest/download/swarm.sh
|
||||||
|
|
||||||
chmod +x setup.sh
|
chmod +x setup.sh
|
||||||
```
|
```
|
||||||
@@ -77,8 +89,9 @@ Lets get started by running the `./setup.sh` command.
|
|||||||
|
|
||||||
This will prompt you with the below options.
|
This will prompt you with the below options.
|
||||||
|
|
||||||
|
#### Docker Compose
|
||||||
```bash
|
```bash
|
||||||
Select a Action you want to perform:
|
Select an Action you want to perform:
|
||||||
1) Install (x86_64)
|
1) Install (x86_64)
|
||||||
2) Start
|
2) Start
|
||||||
3) Stop
|
3) Stop
|
||||||
@@ -87,17 +100,42 @@ Select a Action you want to perform:
|
|||||||
6) View Logs
|
6) View Logs
|
||||||
7) Backup Data
|
7) Backup Data
|
||||||
8) Exit
|
8) Exit
|
||||||
|
|
||||||
Action [2]: 1
|
Action [2]: 1
|
||||||
```
|
```
|
||||||
|
|
||||||
For the 1st time setup, type "1" as action input.
|
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
|
This will create a folder `plane-app` and will download 2 files inside that
|
||||||
|
|
||||||
- `docker-compose.yaml`
|
- `docker-compose.yaml`
|
||||||
- `plane.env`
|
- `plane.env`
|
||||||
|
|
||||||
Again the `options [1-8]` will be popped up and this time hit `8` to exit.
|
Again the `options [1-8]` will be popped up, and this time hit `8` to exit.
|
||||||
|
|
||||||
|
#### Docker Swarm
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Select an Action you want to perform:
|
||||||
|
1) Deploy Stack
|
||||||
|
2) Remove Stack
|
||||||
|
3) View Stack Status
|
||||||
|
4) Redeploy Stack
|
||||||
|
5) Upgrade
|
||||||
|
6) View Logs
|
||||||
|
7) Exit
|
||||||
|
|
||||||
|
Action [3]: 1
|
||||||
|
```
|
||||||
|
|
||||||
|
For the 1st time setup, type "1" as action input.
|
||||||
|
|
||||||
|
This will create a create a folder `plane-app` and will download 2 files inside that
|
||||||
|
|
||||||
|
- `docker-compose.yaml`
|
||||||
|
- `plane.env`
|
||||||
|
|
||||||
|
Again the `options [1-7]` will be popped up, and this time hit `7` to exit.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -116,7 +154,7 @@ There are many other settings you can play with, but we suggest you configure `E
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Continue with setup - Start Server
|
### Continue with setup - Start Server (Docker Compose)
|
||||||
|
|
||||||
Lets again run the `./setup.sh` command. You will again be prompted with the below options. This time select `2` to start the sevices
|
Lets again run the `./setup.sh` command. You will again be prompted with the below options. This time select `2` to start the sevices
|
||||||
|
|
||||||
@@ -147,9 +185,11 @@ You have successfully self hosted `Plane` instance. Access the application by go
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Stopping the Server
|
### Stopping the Server / Remove Stack
|
||||||
|
|
||||||
In case you want to make changes to `.env` variables, we suggest you to stop the services before doing that.
|
In case you want to make changes to `plane.env` variables, we suggest you to stop the services before doing that.
|
||||||
|
|
||||||
|
#### Docker Compose
|
||||||
|
|
||||||
Lets again run the `./setup.sh` command. You will again be prompted with the below options. This time select `3` to stop the sevices
|
Lets again run the `./setup.sh` command. You will again be prompted with the below options. This time select `3` to stop the sevices
|
||||||
|
|
||||||
@@ -171,14 +211,34 @@ If all goes well, you must see something like this
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
#### Docker Swarm
|
||||||
|
|
||||||
|
Lets again run the `./setup.sh` command. You will again be prompted with the below options. This time select `2` to stop the sevices
|
||||||
|
|
||||||
|
```bash
|
||||||
|
Select an Action you want to perform:
|
||||||
|
1) Deploy Stack
|
||||||
|
2) Remove Stack
|
||||||
|
3) View Stack Status
|
||||||
|
4) Redeploy Stack
|
||||||
|
5) Upgrade
|
||||||
|
6) View Logs
|
||||||
|
7) Exit
|
||||||
|
|
||||||
|
Action [3]: 2
|
||||||
|
```
|
||||||
|
|
||||||
|
If all goes well, you will see the confirmation from docker cli
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Restarting the Server
|
### Restarting the Server / Redeploy Stack
|
||||||
|
|
||||||
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.
|
In case you want to make changes to `plane.env` variables, without stopping the server or you noticed some abnormalies in services, you can restart the services with `RESTART` / `REDEPLOY` 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
|
Lets again run the `./setup.sh` command. You will again be prompted with the below options. This time select `4` to restart the sevices
|
||||||
|
|
||||||
|
#### Docker Compose
|
||||||
```bash
|
```bash
|
||||||
Select a Action you want to perform:
|
Select a Action you want to perform:
|
||||||
1) Install (x86_64)
|
1) Install (x86_64)
|
||||||
@@ -197,14 +257,32 @@ If all goes well, you must see something like this
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
#### Docker Swarm
|
||||||
|
|
||||||
|
```bash
|
||||||
|
1) Deploy Stack
|
||||||
|
2) Remove Stack
|
||||||
|
3) View Stack Status
|
||||||
|
4) Redeploy Stack
|
||||||
|
5) Upgrade
|
||||||
|
6) View Logs
|
||||||
|
7) Exit
|
||||||
|
|
||||||
|
Action [3]: 4
|
||||||
|
```
|
||||||
|
|
||||||
|
If all goes well, you will see the confirmation from docker cli
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Upgrading Plane Version
|
### Upgrading Plane Version
|
||||||
|
|
||||||
It is always advised to keep Plane up to date with the latest release.
|
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.
|
Lets again run the `./setup.sh` command. You will again be prompted with the below options. This time select `5` to upgrade the release.
|
||||||
|
|
||||||
|
#### Docker Compose
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
Select a Action you want to perform:
|
Select a Action you want to perform:
|
||||||
1) Install (x86_64)
|
1) Install (x86_64)
|
||||||
@@ -231,13 +309,41 @@ Once done, choose `8` to exit from prompt.
|
|||||||
|
|
||||||
Once done with making changes in `plane.env` file, jump on to `Start Server`
|
Once done with making changes in `plane.env` file, jump on to `Start Server`
|
||||||
|
|
||||||
|
#### Docker Swarm
|
||||||
|
|
||||||
|
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
|
||||||
|
1) Deploy Stack
|
||||||
|
2) Remove Stack
|
||||||
|
3) View Stack Status
|
||||||
|
4) Redeploy Stack
|
||||||
|
5) Upgrade
|
||||||
|
6) View Logs
|
||||||
|
7) Exit
|
||||||
|
|
||||||
|
Action [3]: 5
|
||||||
|
```
|
||||||
|
|
||||||
|
By choosing this, it will stop the services and then will download the latest `docker-compose.yaml` and `plane.env`.
|
||||||
|
|
||||||
|
Once done, choose `7` 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 `Redeploy Stack`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### View Logs
|
### View Logs
|
||||||
|
|
||||||
There would a time when you might want to check what is happening inside the API, Worker or any other container.
|
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.
|
Lets again run the `./setup.sh` command. You will again be prompted with the below options.
|
||||||
|
|
||||||
|
This time select `6` to view logs.
|
||||||
|
|
||||||
|
#### Docker Compose
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
Select a Action you want to perform:
|
Select a Action you want to perform:
|
||||||
@@ -253,7 +359,22 @@ Select a Action you want to perform:
|
|||||||
Action [2]: 6
|
Action [2]: 6
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Docker Swarm
|
||||||
|
|
||||||
|
|
||||||
|
```bash
|
||||||
|
1) Deploy Stack
|
||||||
|
2) Remove Stack
|
||||||
|
3) View Stack Status
|
||||||
|
4) Redeploy Stack
|
||||||
|
5) Upgrade
|
||||||
|
6) View Logs
|
||||||
|
7) Exit
|
||||||
|
|
||||||
|
Action [3]: 6
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Service Menu Options for Logs
|
||||||
This will further open sub-menu with list of services
|
This will further open sub-menu with list of services
|
||||||
```bash
|
```bash
|
||||||
Select a Service you want to view the logs for:
|
Select a Service you want to view the logs for:
|
||||||
@@ -267,9 +388,10 @@ Select a Service you want to view the logs for:
|
|||||||
8) Redis
|
8) Redis
|
||||||
9) Postgres
|
9) Postgres
|
||||||
10) Minio
|
10) Minio
|
||||||
|
11) RabbitMQ
|
||||||
0) Back to Main Menu
|
0) Back to Main Menu
|
||||||
|
|
||||||
Service:
|
Service: 3
|
||||||
```
|
```
|
||||||
|
|
||||||
Select any of the service to view the logs e.g. `3`. Expect something similar to this
|
Select any of the service to view the logs e.g. `3`. Expect something similar to this
|
||||||
@@ -323,7 +445,7 @@ Similarly, you can view the logs of other services.
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Backup Data
|
### Backup Data (Docker Compose)
|
||||||
|
|
||||||
There would a time when you might want to backup your data from docker volumes to external storage like S3 or drives.
|
There would a time when you might want to backup your data from docker volumes to external storage like S3 or drives.
|
||||||
|
|
||||||
@@ -355,7 +477,7 @@ Backup completed successfully. Backup files are stored in /....../plane-app/back
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Restore Data
|
### Restore Data (Docker Compose)
|
||||||
|
|
||||||
When you want to restore the previously backed-up data, follow the instructions below.
|
When you want to restore the previously backed-up data, follow the instructions below.
|
||||||
|
|
||||||
|
|||||||
+141
-88
@@ -1,174 +1,226 @@
|
|||||||
|
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
|
||||||
|
NGINX_PORT: ${NGINX_PORT:-80}
|
||||||
|
BUCKET_NAME: ${AWS_S3_BUCKET_NAME:-uploads}
|
||||||
|
FILE_SIZE_LIMIT: ${FILE_SIZE_LIMIT:-5242880}
|
||||||
|
|
||||||
|
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}
|
||||||
|
|
||||||
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}
|
|
||||||
- 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:-stable}
|
||||||
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
|
command: node web/server.js web
|
||||||
deploy:
|
deploy:
|
||||||
replicas: ${WEB_REPLICAS:-1}
|
replicas: ${WEB_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
depends_on:
|
depends_on:
|
||||||
- api
|
- api
|
||||||
- worker
|
- worker
|
||||||
|
|
||||||
space:
|
space:
|
||||||
<<: *app-env
|
image: artifacts.plane.so/makeplane/plane-space:${APP_RELEASE:-stable}
|
||||||
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
|
command: node space/server.js space
|
||||||
deploy:
|
deploy:
|
||||||
replicas: ${SPACE_REPLICAS:-1}
|
replicas: ${SPACE_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
depends_on:
|
depends_on:
|
||||||
- api
|
- api
|
||||||
- worker
|
- worker
|
||||||
- web
|
- web
|
||||||
|
|
||||||
admin:
|
admin:
|
||||||
<<: *app-env
|
image: artifacts.plane.so/makeplane/plane-admin:${APP_RELEASE:-stable}
|
||||||
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
|
command: node admin/server.js admin
|
||||||
deploy:
|
deploy:
|
||||||
replicas: ${ADMIN_REPLICAS:-1}
|
replicas: ${ADMIN_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
depends_on:
|
||||||
|
- api
|
||||||
|
- web
|
||||||
|
|
||||||
|
live:
|
||||||
|
image: artifacts.plane.so/makeplane/plane-live:${APP_RELEASE:-stable}
|
||||||
|
command: node live/dist/server.js live
|
||||||
|
environment:
|
||||||
|
<<: [ *live-env ]
|
||||||
|
deploy:
|
||||||
|
replicas: ${LIVE_REPLICAS:-1}
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
depends_on:
|
depends_on:
|
||||||
- api
|
- api
|
||||||
- web
|
- web
|
||||||
|
|
||||||
api:
|
api:
|
||||||
<<: *app-env
|
image: artifacts.plane.so/makeplane/plane-backend:${APP_RELEASE:-stable}
|
||||||
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: on-failure
|
||||||
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:-stable}
|
||||||
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: on-failure
|
||||||
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:-stable}
|
||||||
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: on-failure
|
||||||
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:-stable}
|
||||||
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: on-failure
|
||||||
|
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.5-alpine
|
image: valkey/valkey:7.2.5-alpine
|
||||||
pull_policy: if_not_present
|
deploy:
|
||||||
restart: unless-stopped
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
volumes:
|
volumes:
|
||||||
- redisdata:/data
|
- redisdata:/data
|
||||||
|
|
||||||
|
plane-mq:
|
||||||
|
image: rabbitmq:3.13.6-management-alpine
|
||||||
|
deploy:
|
||||||
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
|
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: on-failure
|
||||||
|
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:-stable}
|
||||||
image: ${DOCKERHUB_USER:-makeplane}/plane-proxy:${APP_RELEASE:-stable}
|
environment:
|
||||||
platform: ${DOCKER_PLATFORM:-}
|
<<: *proxy-env
|
||||||
pull_policy: if_not_present
|
deploy:
|
||||||
restart: unless-stopped
|
replicas: 1
|
||||||
|
restart_policy:
|
||||||
|
condition: on-failure
|
||||||
depends_on:
|
depends_on:
|
||||||
- web
|
- web
|
||||||
- api
|
- api
|
||||||
@@ -182,3 +234,4 @@ volumes:
|
|||||||
logs_worker:
|
logs_worker:
|
||||||
logs_beat-worker:
|
logs_beat-worker:
|
||||||
logs_migrator:
|
logs_migrator:
|
||||||
|
rabbitmq_data:
|
||||||
|
|||||||
+153
-40
@@ -4,9 +4,12 @@ BRANCH=${BRANCH:-master}
|
|||||||
SCRIPT_DIR=$PWD
|
SCRIPT_DIR=$PWD
|
||||||
SERVICE_FOLDER=plane-app
|
SERVICE_FOLDER=plane-app
|
||||||
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/deploy/selfhost"
|
||||||
|
|
||||||
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 -s 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,7 +193,7 @@ 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/deploy/selfhost/build.yml" "$PLANE_TEMP_CODE_DIR/build.yml"
|
||||||
@@ -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 -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 -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 -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 -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
|
||||||
|
|
||||||
|
|||||||
@@ -66,8 +66,10 @@ function restoreData() {
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
local volume_suffix
|
||||||
|
volume_suffix="_pgdata|_redisdata|_uploads|_rabbitmq_data"
|
||||||
local volumes
|
local volumes
|
||||||
volumes=$(docker volume ls -f "name=plane-app" --format "{{.Name}}" | grep -E "_pgdata|_redisdata|_uploads")
|
volumes=$(docker volume ls -f "name=plane-app" --format "{{.Name}}" | grep -E "$volume_suffix")
|
||||||
# Check if there are any matching volumes
|
# Check if there are any matching volumes
|
||||||
if [ -z "$volumes" ]; then
|
if [ -z "$volumes" ]; then
|
||||||
echo ".....No volumes found starting with 'plane-app'"
|
echo ".....No volumes found starting with 'plane-app'"
|
||||||
@@ -87,7 +89,7 @@ function restoreData() {
|
|||||||
echo "Found $BACKUP_FILE"
|
echo "Found $BACKUP_FILE"
|
||||||
|
|
||||||
local docVol
|
local docVol
|
||||||
docVol=$(docker volume ls -f "name=$restoreVolName" --format "{{.Name}}" | grep -E "_pgdata|_redisdata|_uploads")
|
docVol=$(docker volume ls -f "name=$restoreVolName" --format "{{.Name}}" | grep -E "$volume_suffix")
|
||||||
|
|
||||||
if [ -z "$docVol" ]; then
|
if [ -z "$docVol" ]; then
|
||||||
echo "Skipping: No volume found with name $restoreVolName"
|
echo "Skipping: No volume found with name $restoreVolName"
|
||||||
|
|||||||
Executable
+612
@@ -0,0 +1,612 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
BRANCH=${BRANCH:-master}
|
||||||
|
SERVICE_FOLDER=plane-app
|
||||||
|
SCRIPT_DIR=$PWD
|
||||||
|
PLANE_INSTALL_DIR=$PWD/$SERVICE_FOLDER
|
||||||
|
export APP_RELEASE="stable"
|
||||||
|
export DOCKERHUB_USER=artifacts.plane.so/makeplane
|
||||||
|
|
||||||
|
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/deploy/selfhost"
|
||||||
|
|
||||||
|
OS_NAME=$(uname)
|
||||||
|
|
||||||
|
# Create necessary directories
|
||||||
|
mkdir -p $PLANE_INSTALL_DIR/archive
|
||||||
|
|
||||||
|
DOCKER_FILE_PATH=$PLANE_INSTALL_DIR/docker-compose.yml
|
||||||
|
DOCKER_ENV_PATH=$PLANE_INSTALL_DIR/plane.env
|
||||||
|
|
||||||
|
function print_header() {
|
||||||
|
clear
|
||||||
|
|
||||||
|
cat <<"EOF"
|
||||||
|
--------------------------------------------
|
||||||
|
____ _ /////////
|
||||||
|
| _ \| | __ _ _ __ ___ /////////
|
||||||
|
| |_) | |/ _` | '_ \ / _ \ ///// /////
|
||||||
|
| __/| | (_| | | | | __/ ///// /////
|
||||||
|
|_| |_|\__,_|_| |_|\___| ////
|
||||||
|
////
|
||||||
|
--------------------------------------------
|
||||||
|
Project management tool from the future
|
||||||
|
--------------------------------------------
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkLatestRelease(){
|
||||||
|
echo "Checking for the latest release..." >&2
|
||||||
|
local latest_release=$(curl -s 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 to read stack name from env file
|
||||||
|
function readStackName() {
|
||||||
|
if [ -f "$DOCKER_ENV_PATH" ]; then
|
||||||
|
local saved_stack_name=$(grep "^STACK_NAME=" "$DOCKER_ENV_PATH" | cut -d'=' -f2)
|
||||||
|
if [ -n "$saved_stack_name" ]; then
|
||||||
|
stack_name=$saved_stack_name
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to get stack name (either from env or user input)
|
||||||
|
function getStackName() {
|
||||||
|
read -p "Enter stack name [plane]: " input_stack_name
|
||||||
|
if [ -z "$input_stack_name" ]; then
|
||||||
|
input_stack_name="plane"
|
||||||
|
fi
|
||||||
|
stack_name=$input_stack_name
|
||||||
|
updateEnvFile "STACK_NAME" "$stack_name" "$DOCKER_ENV_PATH"
|
||||||
|
echo "Using stack name: $stack_name"
|
||||||
|
}
|
||||||
|
|
||||||
|
function syncEnvFile(){
|
||||||
|
echo "Syncing environment variables..." >&2
|
||||||
|
if [ -f "$PLANE_INSTALL_DIR/plane.env.bak" ]; then
|
||||||
|
# READ keys of plane.env and update the values from plane.env.bak
|
||||||
|
while IFS= read -r line
|
||||||
|
do
|
||||||
|
# ignore if the line is empty or starts with #
|
||||||
|
if [ -z "$line" ] || [[ $line == \#* ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
key=$(echo "$line" | cut -d'=' -f1)
|
||||||
|
value=$(getEnvValue "$key" "$PLANE_INSTALL_DIR/plane.env.bak")
|
||||||
|
if [ -n "$value" ]; then
|
||||||
|
updateEnvFile "$key" "$value" "$DOCKER_ENV_PATH"
|
||||||
|
fi
|
||||||
|
done < "$DOCKER_ENV_PATH"
|
||||||
|
|
||||||
|
value=$(getEnvValue "STACK_NAME" "$PLANE_INSTALL_DIR/plane.env.bak")
|
||||||
|
if [ -n "$value" ]; then
|
||||||
|
updateEnvFile "STACK_NAME" "$value" "$DOCKER_ENV_PATH"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "Environment variables synced successfully" >&2
|
||||||
|
rm -f $PLANE_INSTALL_DIR/plane.env.bak
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEnvValue() {
|
||||||
|
local key=$1
|
||||||
|
local file=$2
|
||||||
|
|
||||||
|
if [ -z "$key" ] || [ -z "$file" ]; then
|
||||||
|
echo "Invalid arguments supplied"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
grep -q "^$key=" "$file"
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
local value
|
||||||
|
value=$(grep "^$key=" "$file" | cut -d'=' -f2)
|
||||||
|
echo "$value"
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateEnvFile() {
|
||||||
|
local key=$1
|
||||||
|
local value=$2
|
||||||
|
local file=$3
|
||||||
|
|
||||||
|
if [ -z "$key" ] || [ -z "$value" ] || [ -z "$file" ]; then
|
||||||
|
echo "Invalid arguments supplied"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$file" ]; then
|
||||||
|
# check if key exists in the file
|
||||||
|
grep -q "^$key=" "$file"
|
||||||
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "$key=$value" >> "$file"
|
||||||
|
return
|
||||||
|
else
|
||||||
|
if [ "$OS_NAME" == "Darwin" ]; then
|
||||||
|
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
|
||||||
|
else
|
||||||
|
echo "File not found: $file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function download() {
|
||||||
|
cd $SCRIPT_DIR || exit 1
|
||||||
|
TS=$(date +%s)
|
||||||
|
if [ -f "$PLANE_INSTALL_DIR/docker-compose.yml" ]
|
||||||
|
then
|
||||||
|
mv $PLANE_INSTALL_DIR/docker-compose.yml $PLANE_INSTALL_DIR/archive/$TS.docker-compose.yml
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo $RELEASE_DOWNLOAD_URL
|
||||||
|
echo $FALLBACK_DOWNLOAD_URL
|
||||||
|
echo $APP_RELEASE
|
||||||
|
|
||||||
|
RESPONSE=$(curl -H 'Cache-Control: no-cache, no-store' -s -w "HTTPSTATUS:%{http_code}" "$RELEASE_DOWNLOAD_URL/$APP_RELEASE/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.yml
|
||||||
|
else
|
||||||
|
# Fallback to download from the raw github url
|
||||||
|
RESPONSE=$(curl -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.yml
|
||||||
|
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.yml $PLANE_INSTALL_DIR/docker-compose.yml
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
RESPONSE=$(curl -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 -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.yml $PLANE_INSTALL_DIR/docker-compose.yml
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$DOCKER_ENV_PATH" ];
|
||||||
|
then
|
||||||
|
cp "$DOCKER_ENV_PATH" "$PLANE_INSTALL_DIR/archive/$TS.env"
|
||||||
|
cp "$DOCKER_ENV_PATH" "$PLANE_INSTALL_DIR/plane.env.bak"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mv $PLANE_INSTALL_DIR/variables-upgrade.env $DOCKER_ENV_PATH
|
||||||
|
|
||||||
|
syncEnvFile
|
||||||
|
|
||||||
|
updateEnvFile "APP_RELEASE" "$APP_RELEASE" "$DOCKER_ENV_PATH"
|
||||||
|
|
||||||
|
}
|
||||||
|
function deployStack() {
|
||||||
|
# Check if docker compose file and env file exist
|
||||||
|
if [ ! -f "$DOCKER_FILE_PATH" ] || [ ! -f "$DOCKER_ENV_PATH" ]; then
|
||||||
|
echo "Configuration files not found"
|
||||||
|
echo "Downloading it now......"
|
||||||
|
APP_RELEASE=$(checkLatestRelease)
|
||||||
|
download
|
||||||
|
fi
|
||||||
|
if [ -z "$stack_name" ]; then
|
||||||
|
getStackName
|
||||||
|
fi
|
||||||
|
echo "Starting ${stack_name} stack..."
|
||||||
|
|
||||||
|
# Pull envs
|
||||||
|
if [ -f "$DOCKER_ENV_PATH" ]; then
|
||||||
|
set -o allexport; source $DOCKER_ENV_PATH; set +o allexport;
|
||||||
|
else
|
||||||
|
echo "Environment file not found: $DOCKER_ENV_PATH"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Deploy the stack
|
||||||
|
docker stack deploy -c $DOCKER_FILE_PATH $stack_name
|
||||||
|
|
||||||
|
echo "Waiting for services to be deployed..."
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# Check migrator service
|
||||||
|
local migrator_service=$(docker service ls --filter name=${stack_name}_migrator -q)
|
||||||
|
if [ -n "$migrator_service" ]; then
|
||||||
|
echo ">> Waiting for Data Migration to finish"
|
||||||
|
while docker service ls --filter name=${stack_name}_migrator | grep -q "running"; do
|
||||||
|
echo -n "."
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Get the most recent container for the migrator service
|
||||||
|
local migrator_container=$(docker ps -a --filter name=${stack_name}_migrator --latest -q)
|
||||||
|
|
||||||
|
if [ -n "$migrator_container" ]; then
|
||||||
|
# Get the exit code of the container
|
||||||
|
local exit_code=$(docker inspect --format='{{.State.ExitCode}}' $migrator_container)
|
||||||
|
|
||||||
|
if [ "$exit_code" != "0" ]; then
|
||||||
|
echo "Server failed to start ❌"
|
||||||
|
echo "Migration failed with exit code: $exit_code"
|
||||||
|
echo "Please check the logs for the 'migrator' service and resolve the issue(s)."
|
||||||
|
echo "Stop the services by running the command: ./swarm.sh stop"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo " Data Migration completed successfully ✅"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "Warning: Could not find migrator container to check exit status"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check API service
|
||||||
|
local api_service=$(docker service ls --filter name=${stack_name}_api -q)
|
||||||
|
while docker service ls --filter name=${stack_name}_api | grep -q "running"; do
|
||||||
|
local running_container=$(docker ps --filter "name=${stack_name}_api" --filter "status=running" -q)
|
||||||
|
if [ -n "$running_container" ]; then
|
||||||
|
if docker container logs $running_container 2>/dev/null | grep -q "Application Startup Complete"; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$api_service" ]; then
|
||||||
|
echo "Plane Server failed to start ❌"
|
||||||
|
echo "Please check the logs for the 'api' service and resolve the issue(s)."
|
||||||
|
echo "Stop the services by running the command: ./swarm.sh stop"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo " Plane Server started successfully ✅"
|
||||||
|
echo ""
|
||||||
|
echo " You can access the application at $WEB_URL"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeStack() {
|
||||||
|
if [ -z "$stack_name" ]; then
|
||||||
|
echo "Stack name not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Removing ${stack_name} stack..."
|
||||||
|
docker stack rm "$stack_name"
|
||||||
|
echo "Waiting for services to be removed..."
|
||||||
|
while docker stack ls | grep -q "$stack_name"; do
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
sleep 20
|
||||||
|
echo "Services stopped successfully ✅"
|
||||||
|
}
|
||||||
|
|
||||||
|
function viewStatus() {
|
||||||
|
echo "Checking status of ${stack_name} stack..."
|
||||||
|
if [ -z "$stack_name" ]; then
|
||||||
|
echo "Stack name not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
docker stack ps "$stack_name"
|
||||||
|
}
|
||||||
|
|
||||||
|
function redeployStack() {
|
||||||
|
removeStack
|
||||||
|
echo "ReDeploying ${stack_name} stack..."
|
||||||
|
deployStack
|
||||||
|
}
|
||||||
|
|
||||||
|
function upgrade() {
|
||||||
|
|
||||||
|
echo "Checking status of ${stack_name} stack..."
|
||||||
|
if [ -z "$stack_name" ]; then
|
||||||
|
echo "Stack name not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# check if stack exists
|
||||||
|
echo "Upgrading ${stack_name} stack..."
|
||||||
|
|
||||||
|
# check env file and take backup
|
||||||
|
if [ -f "$DOCKER_ENV_PATH" ]; then
|
||||||
|
cp "$DOCKER_ENV_PATH" "${DOCKER_ENV_PATH}.bak"
|
||||||
|
fi
|
||||||
|
|
||||||
|
download
|
||||||
|
redeployStack
|
||||||
|
}
|
||||||
|
|
||||||
|
function viewSpecificLogs() {
|
||||||
|
local service=$1
|
||||||
|
|
||||||
|
# Input validation
|
||||||
|
if [ -z "$service" ]; then
|
||||||
|
echo "Error: Please specify a service name"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Main loop for service logs
|
||||||
|
while true; do
|
||||||
|
# Get all running containers for the service
|
||||||
|
local running_containers=$(docker ps --filter "name=${stack_name}_${service}" --filter "status=running" -q)
|
||||||
|
|
||||||
|
# If no running containers found, try service logs
|
||||||
|
if [ -z "$running_containers" ]; then
|
||||||
|
echo "No running containers found for ${stack_name}_${service}, checking service logs..."
|
||||||
|
if docker service inspect ${stack_name}_${service} >/dev/null 2>&1; then
|
||||||
|
echo "Press Ctrl+C or 'q' to exit logs"
|
||||||
|
docker service logs ${stack_name}_${service} -f
|
||||||
|
break
|
||||||
|
else
|
||||||
|
echo "Error: No running containers or services found for ${stack_name}_${service}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If multiple containers are running, let user choose
|
||||||
|
if [ $(echo "$running_containers" | grep -v '^$' | wc -l) -gt 1 ]; then
|
||||||
|
clear
|
||||||
|
echo "Multiple containers found for ${stack_name}_${service}:"
|
||||||
|
local i=1
|
||||||
|
# Use regular arrays instead of associative arrays
|
||||||
|
container_ids=()
|
||||||
|
container_names=()
|
||||||
|
|
||||||
|
while read -r container_id; do
|
||||||
|
if [ -n "$container_id" ]; then
|
||||||
|
local container_name=$(docker inspect --format '{{.Name}}' "$container_id" | sed 's/\///')
|
||||||
|
container_ids[$i]=$container_id
|
||||||
|
container_names[$i]=$container_name
|
||||||
|
echo "[$i] ${container_names[$i]} (${container_ids[$i]})"
|
||||||
|
i=$((i+1))
|
||||||
|
fi
|
||||||
|
done <<< "$running_containers"
|
||||||
|
|
||||||
|
echo -e "\nPlease select a container number:"
|
||||||
|
read -r selection
|
||||||
|
|
||||||
|
if [[ "$selection" =~ ^[0-9]+$ ]] && [ -n "${container_ids[$selection]}" ]; then
|
||||||
|
local selected_container=${container_ids[$selection]}
|
||||||
|
clear
|
||||||
|
echo "Showing logs for container: ${container_names[$selection]}"
|
||||||
|
echo "Press Ctrl+C or 'q' to return to container selection"
|
||||||
|
|
||||||
|
# Start watching logs in the background
|
||||||
|
docker container logs -f "$selected_container" &
|
||||||
|
local log_pid=$!
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
read -r -n 1 input
|
||||||
|
if [[ $input == "q" ]]; then
|
||||||
|
kill $log_pid 2>/dev/null
|
||||||
|
wait $log_pid 2>/dev/null
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
clear
|
||||||
|
else
|
||||||
|
echo "Error: Invalid selection"
|
||||||
|
sleep 2
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Single container case
|
||||||
|
local container_name=$(docker inspect --format '{{.Name}}' "$running_containers" | sed 's/\///')
|
||||||
|
echo "Showing logs for container: $container_name"
|
||||||
|
echo "Press Ctrl+C or 'q' to exit logs"
|
||||||
|
docker container logs -f "$running_containers" &
|
||||||
|
local log_pid=$!
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
read -r -n 1 input
|
||||||
|
if [[ $input == "q" ]]; then
|
||||||
|
kill $log_pid 2>/dev/null
|
||||||
|
wait $log_pid 2>/dev/null
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function viewLogs(){
|
||||||
|
|
||||||
|
ARG_SERVICE_NAME=$2
|
||||||
|
if [ -z "$ARG_SERVICE_NAME" ];
|
||||||
|
then
|
||||||
|
echo
|
||||||
|
echo "Select a Service you want to view the logs for:"
|
||||||
|
echo " 1) Web"
|
||||||
|
echo " 2) Space"
|
||||||
|
echo " 3) API"
|
||||||
|
echo " 4) Worker"
|
||||||
|
echo " 5) Beat-Worker"
|
||||||
|
echo " 6) Migrator"
|
||||||
|
echo " 7) Proxy"
|
||||||
|
echo " 8) Redis"
|
||||||
|
echo " 9) Postgres"
|
||||||
|
echo " 10) Minio"
|
||||||
|
echo " 11) RabbitMQ"
|
||||||
|
echo " 0) Back to Main Menu"
|
||||||
|
echo
|
||||||
|
read -p "Service: " DOCKER_SERVICE_NAME
|
||||||
|
|
||||||
|
until (( DOCKER_SERVICE_NAME >= 0 && DOCKER_SERVICE_NAME <= 11 )); do
|
||||||
|
echo "Invalid selection. Please enter a number between 0 and 11."
|
||||||
|
read -p "Service: " DOCKER_SERVICE_NAME
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$DOCKER_SERVICE_NAME" ];
|
||||||
|
then
|
||||||
|
echo "INVALID SERVICE NAME SUPPLIED"
|
||||||
|
else
|
||||||
|
case $DOCKER_SERVICE_NAME in
|
||||||
|
1) viewSpecificLogs "web";;
|
||||||
|
2) viewSpecificLogs "space";;
|
||||||
|
3) viewSpecificLogs "api";;
|
||||||
|
4) viewSpecificLogs "worker";;
|
||||||
|
5) viewSpecificLogs "beat-worker";;
|
||||||
|
6) viewSpecificLogs "migrator";;
|
||||||
|
7) viewSpecificLogs "proxy";;
|
||||||
|
8) viewSpecificLogs "plane-redis";;
|
||||||
|
9) viewSpecificLogs "plane-db";;
|
||||||
|
10) viewSpecificLogs "plane-minio";;
|
||||||
|
11) viewSpecificLogs "plane-mq";;
|
||||||
|
0) askForAction;;
|
||||||
|
*) echo "INVALID SERVICE NAME SUPPLIED";;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
elif [ -n "$ARG_SERVICE_NAME" ];
|
||||||
|
then
|
||||||
|
ARG_SERVICE_NAME=$(echo "$ARG_SERVICE_NAME" | tr '[:upper:]' '[:lower:]')
|
||||||
|
case $ARG_SERVICE_NAME in
|
||||||
|
web) viewSpecificLogs "web";;
|
||||||
|
space) viewSpecificLogs "space";;
|
||||||
|
api) viewSpecificLogs "api";;
|
||||||
|
worker) viewSpecificLogs "worker";;
|
||||||
|
beat-worker) viewSpecificLogs "beat-worker";;
|
||||||
|
migrator) viewSpecificLogs "migrator";;
|
||||||
|
proxy) viewSpecificLogs "proxy";;
|
||||||
|
redis) viewSpecificLogs "plane-redis";;
|
||||||
|
postgres) viewSpecificLogs "plane-db";;
|
||||||
|
minio) viewSpecificLogs "plane-minio";;
|
||||||
|
rabbitmq) viewSpecificLogs "plane-mq";;
|
||||||
|
*) echo "INVALID SERVICE NAME SUPPLIED";;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
echo "INVALID SERVICE NAME SUPPLIED"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function askForAction() {
|
||||||
|
# Rest of askForAction remains the same but use $stack_name instead of $STACK_NAME
|
||||||
|
local DEFAULT_ACTION=$1
|
||||||
|
|
||||||
|
if [ -z "$DEFAULT_ACTION" ]; then
|
||||||
|
echo
|
||||||
|
echo "Select an Action you want to perform:"
|
||||||
|
echo " 1) Deploy Stack"
|
||||||
|
echo " 2) Remove Stack"
|
||||||
|
echo " 3) View Stack Status"
|
||||||
|
echo " 4) Redeploy Stack"
|
||||||
|
echo " 5) Upgrade"
|
||||||
|
echo " 6) View Logs"
|
||||||
|
echo " 7) Exit"
|
||||||
|
echo
|
||||||
|
read -p "Action [3]: " ACTION
|
||||||
|
until [[ -z "$ACTION" || "$ACTION" =~ ^[1-6]$ ]]; do
|
||||||
|
echo "$ACTION: invalid selection."
|
||||||
|
read -p "Action [3]: " ACTION
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$ACTION" ]; then
|
||||||
|
ACTION=3
|
||||||
|
fi
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$ACTION" == "1" ] || [ "$DEFAULT_ACTION" == "deploy" ]; then
|
||||||
|
deployStack
|
||||||
|
elif [ "$ACTION" == "2" ] || [ "$DEFAULT_ACTION" == "remove" ]; then
|
||||||
|
removeStack
|
||||||
|
elif [ "$ACTION" == "3" ] || [ "$DEFAULT_ACTION" == "status" ]; then
|
||||||
|
viewStatus
|
||||||
|
elif [ "$ACTION" == "4" ] || [ "$DEFAULT_ACTION" == "redeploy" ]; then
|
||||||
|
redeployStack
|
||||||
|
elif [ "$ACTION" == "5" ] || [ "$DEFAULT_ACTION" == "upgrade" ]; then
|
||||||
|
upgrade
|
||||||
|
elif [ "$ACTION" == "6" ] || [ "$DEFAULT_ACTION" == "logs" ]; then
|
||||||
|
viewLogs "$@"
|
||||||
|
elif [ "$ACTION" == "7" ] || [ "$DEFAULT_ACTION" == "exit" ]; then
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "INVALID ACTION SUPPLIED"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Initialize stack name at script start
|
||||||
|
|
||||||
|
if [ -z "$stack_name" ]; then
|
||||||
|
readStackName
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sync environment variables
|
||||||
|
if [ -f "$DOCKER_ENV_PATH" ]; then
|
||||||
|
DOCKERHUB_USER=$(getEnvValue "DOCKERHUB_USER" "$DOCKER_ENV_PATH")
|
||||||
|
APP_RELEASE=$(getEnvValue "APP_RELEASE" "$DOCKER_ENV_PATH")
|
||||||
|
|
||||||
|
if [ -z "$DOCKERHUB_USER" ]; then
|
||||||
|
DOCKERHUB_USER=artifacts.plane.so/makeplane
|
||||||
|
updateEnvFile "DOCKERHUB_USER" "$DOCKERHUB_USER" "$DOCKER_ENV_PATH"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$APP_RELEASE" ]; then
|
||||||
|
APP_RELEASE=stable
|
||||||
|
updateEnvFile "APP_RELEASE" "$APP_RELEASE" "$DOCKER_ENV_PATH"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Main execution
|
||||||
|
print_header
|
||||||
|
askForAction "$@"
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import utils from "../utils.js";
|
||||||
|
|
||||||
|
await utils.cloneOrPullRepo({
|
||||||
|
repo: "https://github.com/makeplane/plane.git",
|
||||||
|
path: "./repo",
|
||||||
|
branch: "preview",
|
||||||
|
});
|
||||||
|
|
||||||
|
await utils.copyDir("./repo/deploy/selfhost", "./code");
|
||||||
|
await utils.renameFile("./code/variables.env", "./code/.env.example");
|
||||||
|
|
||||||
|
await utils.removeContainerNames("./code/docker-compose.yml");
|
||||||
|
await utils.removePorts("./code/docker-compose.yml");
|
||||||
@@ -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,16 @@ POSTGRES_DB=postgres
|
|||||||
POSTGRES_PORT=5432
|
POSTGRES_PORT=5432
|
||||||
# default user is postgres
|
# default user is postgres
|
||||||
|
|
||||||
|
|
||||||
|
############
|
||||||
|
# Supavisor -- Database pooler
|
||||||
|
############
|
||||||
|
POOLER_PROXY_PORT_TRANSACTION=6543
|
||||||
|
POOLER_DEFAULT_POOL_SIZE=20
|
||||||
|
POOLER_MAX_CLIENT_CONN=100
|
||||||
|
POOLER_TENANT_ID=your-tenant-id
|
||||||
|
|
||||||
|
|
||||||
############
|
############
|
||||||
# API Proxy - Configuration for the Kong Reverse proxy.
|
# API Proxy - Configuration for the Kong Reverse proxy.
|
||||||
############
|
############
|
||||||
@@ -81,12 +94,17 @@ 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 Logflare
|
||||||
# Please refer to https://supabase.com/docs/reference/self-hosting-analytics/introduction
|
# Please refer to https://supabase.com/docs/reference/self-hosting-analytics/introduction
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
+185
-107
@@ -1,15 +1,16 @@
|
|||||||
# Usage
|
# Usage
|
||||||
# Start: docker compose up
|
# Start: docker compose up
|
||||||
# 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.05.19-sha-3487831
|
||||||
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}
|
||||||
@@ -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.172.1
|
||||||
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,17 +85,25 @@ 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
|
||||||
API_EXTERNAL_URL: ${API_EXTERNAL_URL}
|
API_EXTERNAL_URL: ${API_EXTERNAL_URL}
|
||||||
|
GOTRUE_EXTERNAL_GOOGLE_ENABLED: ${GOOGLE_ENABLED}
|
||||||
|
GOTRUE_EXTERNAL_GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
|
||||||
|
GOTRUE_EXTERNAL_GOOGLE_SECRET: ${GOOGLE_SECRET}
|
||||||
|
GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI: ${API_EXTERNAL_URL}/auth/v1/callback
|
||||||
GOTRUE_DB_DRIVER: postgres
|
GOTRUE_DB_DRIVER: postgres
|
||||||
GOTRUE_DB_DATABASE_URL: postgres://supabase_auth_admin:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
|
GOTRUE_DB_DATABASE_URL: postgres://supabase_auth_admin:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
|
||||||
|
|
||||||
@@ -113,6 +120,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 +139,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 +176,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 +199,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 +211,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.22.17
|
||||||
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 +236,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,13 +264,14 @@ 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
|
||||||
interval: 5s
|
interval: 5s
|
||||||
retries: 3
|
retries: 3
|
||||||
@@ -256,18 +280,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.89.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 +299,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,35 +314,30 @@ 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.12.0
|
||||||
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}
|
||||||
@@ -329,41 +348,17 @@ services:
|
|||||||
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
|
||||||
# GOOGLE_PROJECT_ID: ${GOOGLE_PROJECT_ID}
|
# GOOGLE_PROJECT_ID: ${GOOGLE_PROJECT_ID}
|
||||||
# GOOGLE_PROJECT_NUMBER: ${GOOGLE_PROJECT_NUMBER}
|
# GOOGLE_PROJECT_NUMBER: ${GOOGLE_PROJECT_NUMBER}
|
||||||
|
|
||||||
# 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 +369,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 +418,66 @@ 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_API_KEY: ${LOGFLARE_API_KEY}
|
||||||
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.1
|
||||||
|
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}@db:${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
|
||||||
|
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:
|
||||||
|
|||||||
Executable
+44
@@ -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
|
||||||
@@ -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,7 @@
|
|||||||
|
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");
|
||||||
@@ -1,25 +1,19 @@
|
|||||||
TAG=latest
|
TAG=latest
|
||||||
|
|
||||||
POSTGRES_ADMIN_PASSWORD=replace_me_with_a_strong_password
|
#PG_DATABASE_USER=postgres
|
||||||
|
#PG_DATABASE_PASSWORD=replace_me_with_a_strong_password_without_special_characters
|
||||||
|
#PG_DATABASE_HOST=db
|
||||||
|
#PG_DATABASE_PORT=5432
|
||||||
|
REDIS_URL=redis://redis:6379
|
||||||
|
|
||||||
PG_DATABASE_HOST=db:5432
|
SERVER_URL=https://$(PRIMARY_DOMAIN)
|
||||||
|
SIGN_IN_PREFILLED=false
|
||||||
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
|
# Use openssl rand -base64 32 for each secret
|
||||||
ACCESS_TOKEN_SECRET=replace_me_with_a_random_string_access
|
APP_SECRET=replace_me_with_a_random_string
|
||||||
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_TYPE=local
|
||||||
|
|
||||||
# STORAGE_S3_REGION=eu-west3
|
# STORAGE_S3_REGION=eu-west3
|
||||||
# STORAGE_S3_NAME=my-bucket
|
# STORAGE_S3_NAME=my-bucket
|
||||||
# STORAGE_S3_ENDPOINT=
|
# STORAGE_S3_ENDPOINT=
|
||||||
|
|
||||||
MESSAGE_QUEUE_TYPE=pg-boss
|
|
||||||
|
|||||||
+16
-39
@@ -1,50 +1,27 @@
|
|||||||
dev-build:
|
# Makefile for building Twenty CRM docker images.
|
||||||
@docker compose -f dev/docker-compose.yml down -v
|
# Set the tag and/or target build platform using make command-line variables assignments.
|
||||||
@docker compose -f dev/docker-compose.yml build
|
#
|
||||||
|
# Optional make variables:
|
||||||
|
# PLATFORM - defaults to 'linux/amd64'
|
||||||
|
# TAG - defaults to 'latest'
|
||||||
|
#
|
||||||
|
# Example: make
|
||||||
|
# Example: make PLATFORM=linux/aarch64 TAG=my-tag
|
||||||
|
|
||||||
dev-up:
|
PLATFORM ?= linux/amd64
|
||||||
@docker compose -f dev/docker-compose.yml up -d
|
TAG ?= latest
|
||||||
|
|
||||||
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:
|
prod-build:
|
||||||
@cd ../.. && docker build -f ./packages/twenty-docker/twenty/Dockerfile --tag twenty . && cd -
|
@cd ../.. && docker build -f ./packages/twenty-docker/twenty/Dockerfile --platform $(PLATFORM) --tag twenty:$(TAG) . && cd -
|
||||||
|
|
||||||
prod-run:
|
prod-run:
|
||||||
@docker run -d -p 3000:3000 --name twenty twenty
|
@docker run -d -p 3000:3000 --name twenty twenty:$(TAG)
|
||||||
|
|
||||||
prod-postgres-build:
|
|
||||||
@cd ../.. && docker build -f ./packages/twenty-docker/twenty-postgres/Dockerfile --tag twenty-postgres . && cd -
|
|
||||||
|
|
||||||
prod-postgres-run:
|
prod-postgres-run:
|
||||||
@docker run -d -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres --name twenty-postgres twenty-postgres
|
@docker run -d -p 5432:5432 -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres --name twenty-postgres twenty-postgres:$(TAG)
|
||||||
|
|
||||||
prod-website-build:
|
prod-website-build:
|
||||||
@cd ../.. && docker build -f ./packages/twenty-docker/twenty-website/Dockerfile --tag twenty-website . && cd -
|
@cd ../.. && docker build -f ./packages/twenty-docker/twenty-website/Dockerfile --platform $(PLATFORM) --tag twenty-website:$(TAG) . && cd -
|
||||||
|
|
||||||
prod-website-run:
|
prod-website-run:
|
||||||
@docker run -d -p 3000:3000 --name twenty-website twenty-website
|
@docker run -d -p 3000:3000 --name twenty-website twenty-website:$(TAG)
|
||||||
|
|
||||||
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,72 +1,97 @@
|
|||||||
version: "3.9"
|
|
||||||
name: twenty
|
name: twenty
|
||||||
|
|
||||||
services:
|
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:
|
server:
|
||||||
image: twentycrm/twenty:${TAG}
|
image: twentycrm/twenty:${TAG:-latest}
|
||||||
volumes:
|
volumes:
|
||||||
- server-local-data:/app/packages/twenty-server/${STORAGE_LOCAL_PATH:-.local-storage}
|
- server-local-data:/app/packages/twenty-server/.local-storage
|
||||||
- docker-data:/app/docker-data
|
|
||||||
environment:
|
environment:
|
||||||
PORT: 3000
|
NODE_PORT: 3000
|
||||||
PG_DATABASE_URL: postgres://twenty:twenty@${PG_DATABASE_HOST}/default
|
PG_DATABASE_URL: postgres://${PG_DATABASE_USER:-postgres}:${PG_DATABASE_PASSWORD:-postgres}@${PG_DATABASE_HOST:-db}:${PG_DATABASE_PORT:-5432}/default
|
||||||
SERVER_URL: ${SERVER_URL}
|
SERVER_URL: ${SERVER_URL}
|
||||||
FRONT_BASE_URL: ${FRONT_BASE_URL:-$SERVER_URL}
|
REDIS_URL: ${REDIS_URL:-redis://redis:6379}
|
||||||
MESSAGE_QUEUE_TYPE: ${MESSAGE_QUEUE_TYPE}
|
|
||||||
|
|
||||||
ENABLE_DB_MIGRATIONS: "true"
|
|
||||||
|
|
||||||
SIGN_IN_PREFILLED: ${SIGN_IN_PREFILLED}
|
|
||||||
STORAGE_TYPE: ${STORAGE_TYPE}
|
STORAGE_TYPE: ${STORAGE_TYPE}
|
||||||
STORAGE_S3_REGION: ${STORAGE_S3_REGION}
|
STORAGE_S3_REGION: ${STORAGE_S3_REGION}
|
||||||
STORAGE_S3_NAME: ${STORAGE_S3_NAME}
|
STORAGE_S3_NAME: ${STORAGE_S3_NAME}
|
||||||
STORAGE_S3_ENDPOINT: ${STORAGE_S3_ENDPOINT}
|
STORAGE_S3_ENDPOINT: ${STORAGE_S3_ENDPOINT}
|
||||||
ACCESS_TOKEN_SECRET: ${ACCESS_TOKEN_SECRET}
|
|
||||||
LOGIN_TOKEN_SECRET: ${LOGIN_TOKEN_SECRET}
|
APP_SECRET: ${APP_SECRET:-replace_me_with_a_random_string}
|
||||||
REFRESH_TOKEN_SECRET: ${REFRESH_TOKEN_SECRET}
|
# MESSAGING_PROVIDER_GMAIL_ENABLED: ${MESSAGING_PROVIDER_GMAIL_ENABLED}
|
||||||
FILE_TOKEN_SECRET: ${FILE_TOKEN_SECRET}
|
# CALENDAR_PROVIDER_GOOGLE_ENABLED: ${CALENDAR_PROVIDER_GOOGLE_ENABLED}
|
||||||
|
# AUTH_GOOGLE_CLIENT_ID: ${AUTH_GOOGLE_CLIENT_ID}
|
||||||
|
# AUTH_GOOGLE_CLIENT_SECRET: ${AUTH_GOOGLE_CLIENT_SECRET}
|
||||||
|
# AUTH_GOOGLE_CALLBACK_URL: ${AUTH_GOOGLE_CALLBACK_URL}
|
||||||
|
# AUTH_GOOGLE_APIS_CALLBACK_URL: ${AUTH_GOOGLE_APIS_CALLBACK_URL}
|
||||||
|
|
||||||
|
# CALENDAR_PROVIDER_MICROSOFT_ENABLED: ${CALENDAR_PROVIDER_MICROSOFT_ENABLED}
|
||||||
|
# MESSAGING_PROVIDER_MICROSOFT_ENABLED: ${MESSAGING_PROVIDER_MICROSOFT_ENABLED}
|
||||||
|
# AUTH_MICROSOFT_ENABLED: ${AUTH_MICROSOFT_ENABLED}
|
||||||
|
# AUTH_MICROSOFT_CLIENT_ID: ${AUTH_MICROSOFT_CLIENT_ID}
|
||||||
|
# AUTH_MICROSOFT_CLIENT_SECRET: ${AUTH_MICROSOFT_CLIENT_SECRET}
|
||||||
|
# AUTH_MICROSOFT_CALLBACK_URL: ${AUTH_MICROSOFT_CALLBACK_URL}
|
||||||
|
# AUTH_MICROSOFT_APIS_CALLBACK_URL: ${AUTH_MICROSOFT_APIS_CALLBACK_URL}
|
||||||
|
|
||||||
|
# EMAIL_FROM_ADDRESS: ${EMAIL_FROM_ADDRESS:-contact@yourdomain.com}
|
||||||
|
# EMAIL_FROM_NAME: ${EMAIL_FROM_NAME:-"John from YourDomain"}
|
||||||
|
# EMAIL_SYSTEM_ADDRESS: ${EMAIL_SYSTEM_ADDRESS:-system@yourdomain.com}
|
||||||
|
# EMAIL_DRIVER: ${EMAIL_DRIVER:-smtp}
|
||||||
|
# EMAIL_SMTP_HOST: ${EMAIL_SMTP_HOST:-smtp.gmail.com}
|
||||||
|
# EMAIL_SMTP_PORT: ${EMAIL_SMTP_PORT:-465}
|
||||||
|
# EMAIL_SMTP_USER: ${EMAIL_SMTP_USER:-}
|
||||||
|
# EMAIL_SMTP_PASSWORD: ${EMAIL_SMTP_PASSWORD:-}
|
||||||
|
|
||||||
depends_on:
|
depends_on:
|
||||||
change-vol-ownership:
|
|
||||||
condition: service_completed_successfully
|
|
||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: curl --fail http://localhost:3000/healthz
|
test: curl --fail http://localhost:3000/healthz
|
||||||
interval: 5s
|
interval: 5s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 10
|
retries: 20
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
worker:
|
worker:
|
||||||
image: twentycrm/twenty:${TAG}
|
image: twentycrm/twenty:${TAG:-latest}
|
||||||
command: ["yarn", "worker:prod"]
|
volumes:
|
||||||
|
- server-local-data:/app/packages/twenty-server/${STORAGE_LOCAL_PATH:-.local-storage}
|
||||||
|
command: [ "yarn", "worker:prod" ]
|
||||||
environment:
|
environment:
|
||||||
PG_DATABASE_URL: postgres://twenty:twenty@${PG_DATABASE_HOST}/default
|
PG_DATABASE_URL: postgres://${PG_DATABASE_USER:-postgres}:${PG_DATABASE_PASSWORD:-postgres}@${PG_DATABASE_HOST:-db}:${PG_DATABASE_PORT:-5432}/default
|
||||||
SERVER_URL: ${SERVER_URL}
|
SERVER_URL: ${SERVER_URL}
|
||||||
FRONT_BASE_URL: ${FRONT_BASE_URL:-$SERVER_URL}
|
REDIS_URL: ${REDIS_URL:-redis://redis:6379}
|
||||||
MESSAGE_QUEUE_TYPE: ${MESSAGE_QUEUE_TYPE}
|
DISABLE_DB_MIGRATIONS: "true" # it already runs on the server
|
||||||
|
|
||||||
ENABLE_DB_MIGRATIONS: "false" # it already runs on the server
|
|
||||||
|
|
||||||
STORAGE_TYPE: ${STORAGE_TYPE}
|
STORAGE_TYPE: ${STORAGE_TYPE}
|
||||||
STORAGE_S3_REGION: ${STORAGE_S3_REGION}
|
STORAGE_S3_REGION: ${STORAGE_S3_REGION}
|
||||||
STORAGE_S3_NAME: ${STORAGE_S3_NAME}
|
STORAGE_S3_NAME: ${STORAGE_S3_NAME}
|
||||||
STORAGE_S3_ENDPOINT: ${STORAGE_S3_ENDPOINT}
|
STORAGE_S3_ENDPOINT: ${STORAGE_S3_ENDPOINT}
|
||||||
ACCESS_TOKEN_SECRET: ${ACCESS_TOKEN_SECRET}
|
|
||||||
LOGIN_TOKEN_SECRET: ${LOGIN_TOKEN_SECRET}
|
APP_SECRET: ${APP_SECRET:-replace_me_with_a_random_string}
|
||||||
REFRESH_TOKEN_SECRET: ${REFRESH_TOKEN_SECRET}
|
# MESSAGING_PROVIDER_GMAIL_ENABLED: ${MESSAGING_PROVIDER_GMAIL_ENABLED}
|
||||||
FILE_TOKEN_SECRET: ${FILE_TOKEN_SECRET}
|
# CALENDAR_PROVIDER_GOOGLE_ENABLED: ${CALENDAR_PROVIDER_GOOGLE_ENABLED}
|
||||||
|
# AUTH_GOOGLE_CLIENT_ID: ${AUTH_GOOGLE_CLIENT_ID}
|
||||||
|
# AUTH_GOOGLE_CLIENT_SECRET: ${AUTH_GOOGLE_CLIENT_SECRET}
|
||||||
|
# AUTH_GOOGLE_CALLBACK_URL: ${AUTH_GOOGLE_CALLBACK_URL}
|
||||||
|
# AUTH_GOOGLE_APIS_CALLBACK_URL: ${AUTH_GOOGLE_APIS_CALLBACK_URL}
|
||||||
|
|
||||||
|
# CALENDAR_PROVIDER_MICROSOFT_ENABLED: ${CALENDAR_PROVIDER_MICROSOFT_ENABLED}
|
||||||
|
# MESSAGING_PROVIDER_MICROSOFT_ENABLED: ${MESSAGING_PROVIDER_MICROSOFT_ENABLED}
|
||||||
|
# AUTH_MICROSOFT_ENABLED: ${AUTH_MICROSOFT_ENABLED}
|
||||||
|
# AUTH_MICROSOFT_CLIENT_ID: ${AUTH_MICROSOFT_CLIENT_ID}
|
||||||
|
# AUTH_MICROSOFT_CLIENT_SECRET: ${AUTH_MICROSOFT_CLIENT_SECRET}
|
||||||
|
# AUTH_MICROSOFT_CALLBACK_URL: ${AUTH_MICROSOFT_CALLBACK_URL}
|
||||||
|
# AUTH_MICROSOFT_APIS_CALLBACK_URL: ${AUTH_MICROSOFT_APIS_CALLBACK_URL}
|
||||||
|
|
||||||
|
# EMAIL_FROM_ADDRESS: ${EMAIL_FROM_ADDRESS:-contact@yourdomain.com}
|
||||||
|
# EMAIL_FROM_NAME: ${EMAIL_FROM_NAME:-"John from YourDomain"}
|
||||||
|
# EMAIL_SYSTEM_ADDRESS: ${EMAIL_SYSTEM_ADDRESS:-system@yourdomain.com}
|
||||||
|
# EMAIL_DRIVER: ${EMAIL_DRIVER:-smtp}
|
||||||
|
# EMAIL_SMTP_HOST: ${EMAIL_SMTP_HOST:-smtp.gmail.com}
|
||||||
|
# EMAIL_SMTP_PORT: ${EMAIL_SMTP_PORT:-465}
|
||||||
|
# EMAIL_SMTP_USER: ${EMAIL_SMTP_USER:-}
|
||||||
|
# EMAIL_SMTP_PASSWORD: ${EMAIL_SMTP_PASSWORD:-}
|
||||||
|
|
||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
@@ -75,19 +100,24 @@ services:
|
|||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: twentycrm/twenty-postgres:${TAG}
|
image: postgres:16
|
||||||
volumes:
|
volumes:
|
||||||
- db-data:/bitnami/postgresql
|
- db-data:/var/lib/postgresql/data
|
||||||
environment:
|
environment:
|
||||||
POSTGRES_PASSWORD: ${POSTGRES_ADMIN_PASSWORD}
|
POSTGRES_USER: ${PG_DATABASE_USER:-postgres}
|
||||||
|
POSTGRES_PASSWORD: ${PG_DATABASE_PASSWORD:-postgres}
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: pg_isready -U twenty -d default
|
test: pg_isready -U ${PG_DATABASE_USER:-postgres} -h localhost -d postgres
|
||||||
interval: 5s
|
interval: 5s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 10
|
retries: 10
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
|
redis:
|
||||||
|
image: redis
|
||||||
|
restart: always
|
||||||
|
command: [ "--maxmemory-policy", "noeviction" ]
|
||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
docker-data:
|
|
||||||
db-data:
|
db-data:
|
||||||
server-local-data:
|
server-local-data:
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
# README
|
# README
|
||||||
|
DISCLAIMER: The k8s and podman deployments are not maintained by the core team.
|
||||||
|
These files are provided and maintained by the community. Twenty core team
|
||||||
|
maintains support for docker deployment.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
|
|||||||
@@ -22,33 +22,37 @@ spec:
|
|||||||
app: twentycrm-db
|
app: twentycrm-db
|
||||||
spec:
|
spec:
|
||||||
volumes:
|
volumes:
|
||||||
- name: twentycrm-db-data
|
- name: twentycrm-db-data
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: twentycrm-db-pvc
|
claimName: twentycrm-db-pvc
|
||||||
containers:
|
containers:
|
||||||
- env:
|
- name: twentycrm
|
||||||
- name: POSTGRES_PASSWORD
|
image: twentycrm/twenty-postgres-spilo:latest
|
||||||
value: "twenty"
|
imagePullPolicy: Always
|
||||||
- name: BITNAMI_DEBUG
|
env:
|
||||||
value: "true"
|
- name: PGUSER_SUPERUSER
|
||||||
- image: twentycrm/twenty-postgres:latest
|
value: "postgres"
|
||||||
imagePullPolicy: Always
|
- name: PGPASSWORD_SUPERUSER
|
||||||
name: twentycrm
|
value: "postgres"
|
||||||
ports:
|
- name: SPILO_PROVIDER
|
||||||
- containerPort: 5432
|
value: "local"
|
||||||
name: tcp
|
- name: ALLOW_NOSSL
|
||||||
protocol: TCP
|
value: "true"
|
||||||
resources:
|
ports:
|
||||||
requests:
|
- containerPort: 5432
|
||||||
memory: "256Mi"
|
name: tcp
|
||||||
cpu: "250m"
|
protocol: TCP
|
||||||
limits:
|
resources:
|
||||||
memory: "1024Mi"
|
requests:
|
||||||
cpu: "1000m"
|
memory: "256Mi"
|
||||||
stdin: true
|
cpu: "250m"
|
||||||
tty: true
|
limits:
|
||||||
volumeMounts:
|
memory: "1024Mi"
|
||||||
- mountPath: /bitnami/postgresql
|
cpu: "1000m"
|
||||||
name: twentycrm-db-data
|
stdin: true
|
||||||
|
tty: true
|
||||||
|
volumeMounts:
|
||||||
|
- mountPath: /home/postgres/pgdata
|
||||||
|
name: twentycrm-db-data
|
||||||
dnsPolicy: ClusterFirst
|
dnsPolicy: ClusterFirst
|
||||||
restartPolicy: Always
|
restartPolicy: Always
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: twentycrm-redis
|
||||||
|
name: twentycrm-redis
|
||||||
|
namespace: twentycrm
|
||||||
|
spec:
|
||||||
|
progressDeadlineSeconds: 600
|
||||||
|
replicas: 1
|
||||||
|
strategy:
|
||||||
|
rollingUpdate:
|
||||||
|
maxSurge: 1
|
||||||
|
maxUnavailable: 1
|
||||||
|
type: RollingUpdate
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: twentycrm-redis
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: twentycrm-redis
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: redis
|
||||||
|
image: redis/redis-stack-server:latest
|
||||||
|
imagePullPolicy: Always
|
||||||
|
args: ["--maxmemory-policy", "noeviction"]
|
||||||
|
env:
|
||||||
|
- name: PORT
|
||||||
|
value: "6379"
|
||||||
|
ports:
|
||||||
|
- containerPort: 6379
|
||||||
|
name: redis
|
||||||
|
protocol: TCP
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
memory: "1024Mi"
|
||||||
|
cpu: "250m"
|
||||||
|
limits:
|
||||||
|
memory: "2048Mi"
|
||||||
|
cpu: "500m"
|
||||||
|
|
||||||
|
dnsPolicy: ClusterFirst
|
||||||
|
restartPolicy: Always
|
||||||
@@ -22,67 +22,55 @@ spec:
|
|||||||
app: twentycrm-server
|
app: twentycrm-server
|
||||||
spec:
|
spec:
|
||||||
volumes:
|
volumes:
|
||||||
- name: twentycrm-server-data
|
- name: twentycrm-server-data
|
||||||
persistentVolumeClaim:
|
persistentVolumeClaim:
|
||||||
claimName: twentycrm-server-pvc
|
claimName: twentycrm-server-pvc
|
||||||
|
- name: twentycrm-docker-data
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: twentycrm-docker-data-pvc
|
||||||
containers:
|
containers:
|
||||||
- env:
|
- name: twentycrm
|
||||||
- name: PORT
|
image: twentycrm/twenty:latest
|
||||||
value: 3000
|
imagePullPolicy: Always
|
||||||
- name: SERVER_URL
|
env:
|
||||||
value: "https://crm.example.com:443"
|
- name: NODE_PORT
|
||||||
- name: FRONT_BASE_URL
|
value: 3000
|
||||||
value: "https://crm.example.com:443"
|
- name: SERVER_URL
|
||||||
- name: PG_DATABASE_URL
|
value: "https://crm.example.com:443"
|
||||||
value: "postgres://twenty:twenty@twenty-db.twentycrm.svc.cluster.local/default"
|
- name: "PG_DATABASE_URL"
|
||||||
- name: ENABLE_DB_MIGRATIONS
|
value: "postgres://postgres:postgres@twentycrm-db.twentycrm.svc.cluster.local/default"
|
||||||
value: "true"
|
- name: "REDIS_URL"
|
||||||
- name: SIGN_IN_PREFILLED
|
value: "redis://twentycrm-redis.twentycrm.svc.cluster.local:6379"
|
||||||
value: "true"
|
- name: SIGN_IN_PREFILLED
|
||||||
- name: STORAGE_TYPE
|
value: "false"
|
||||||
value: "local"
|
- name: STORAGE_TYPE
|
||||||
- name: "MESSAGE_QUEUE_TYPE"
|
value: "local"
|
||||||
value: "pg-boss"
|
- name: "ACCESS_TOKEN_EXPIRES_IN"
|
||||||
- name: ACCESS_TOKEN_SECRET
|
value: "7d"
|
||||||
valueFrom:
|
- name: "LOGIN_TOKEN_EXPIRES_IN"
|
||||||
secretKeyRef:
|
value: "1h"
|
||||||
name: tokens
|
- name: APP_SECRET
|
||||||
key: accessToken
|
valueFrom:
|
||||||
- name: LOGIN_TOKEN_SECRET
|
secretKeyRef:
|
||||||
valueFrom:
|
name: tokens
|
||||||
secretKeyRef:
|
key: accessToken
|
||||||
name: tokens
|
ports:
|
||||||
key: loginToken
|
- containerPort: 3000
|
||||||
- name: REFRESH_TOKEN_SECRET
|
name: http-tcp
|
||||||
valueFrom:
|
protocol: TCP
|
||||||
secretKeyRef:
|
resources:
|
||||||
name: tokens
|
requests:
|
||||||
key: refreshToken
|
memory: "256Mi"
|
||||||
- name: FILE_TOKEN_SECRET
|
cpu: "250m"
|
||||||
valueFrom:
|
limits:
|
||||||
secretKeyRef:
|
memory: "1024Mi"
|
||||||
name: tokens
|
cpu: "1000m"
|
||||||
key: fileToken
|
stdin: true
|
||||||
- image: twentycrm/twenty:latest
|
tty: true
|
||||||
imagePullPolicy: Always
|
volumeMounts:
|
||||||
name: twentycrm
|
- mountPath: /app/docker-data
|
||||||
ports:
|
name: twentycrm-docker-data
|
||||||
- containerPort: 3000
|
- mountPath: /app/packages/twenty-server/.local-storage
|
||||||
name: http-tcp
|
name: twentycrm-server-data
|
||||||
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
|
dnsPolicy: ClusterFirst
|
||||||
restartPolicy: Always
|
restartPolicy: Always
|
||||||
|
|||||||
@@ -21,58 +21,37 @@ spec:
|
|||||||
labels:
|
labels:
|
||||||
app: twentycrm-worker
|
app: twentycrm-worker
|
||||||
spec:
|
spec:
|
||||||
volumes:
|
|
||||||
- name: twentycrm-worker-data
|
|
||||||
persistentVolumeClaim:
|
|
||||||
claimName: twentycrm-worker-pvc
|
|
||||||
containers:
|
containers:
|
||||||
- env:
|
- name: twentycrm
|
||||||
- name: SERVER_URL
|
image: twentycrm/twenty:latest
|
||||||
value: "https://crm.example.com:443"
|
imagePullPolicy: Always
|
||||||
- name: FRONT_BASE_URL
|
env:
|
||||||
value: "https://crm.example.com:443"
|
- name: SERVER_URL
|
||||||
- name: PG_DATABASE_URL
|
value: "https://crm.example.com:443"
|
||||||
value: "postgres://twenty:twenty@twenty-db.twentycrm.svc.cluster.local/default"
|
- name: PG_DATABASE_URL
|
||||||
- name: ENABLE_DB_MIGRATIONS
|
value: "postgres://postgres:postgres@twentycrm-db.twentycrm.svc.cluster.local/default"
|
||||||
value: "false" # it already runs on the server
|
- name: DISABLE_DB_MIGRATIONS
|
||||||
- name: STORAGE_TYPE
|
value: "false" # it already runs on the server
|
||||||
value: "local"
|
- name: STORAGE_TYPE
|
||||||
- name: "MESSAGE_QUEUE_TYPE"
|
value: "local"
|
||||||
value: "pg-boss"
|
- name: "REDIS_URL"
|
||||||
- name: ACCESS_TOKEN_SECRET
|
value: "redis://twentycrm-redis.twentycrm.svc.cluster.local:6379"
|
||||||
valueFrom:
|
- name: APP_SECRET
|
||||||
secretKeyRef:
|
valueFrom:
|
||||||
name: tokens
|
secretKeyRef:
|
||||||
key: accessToken
|
name: tokens
|
||||||
- name: LOGIN_TOKEN_SECRET
|
key: accessToken
|
||||||
valueFrom:
|
command:
|
||||||
secretKeyRef:
|
- yarn
|
||||||
name: tokens
|
- worker:prod
|
||||||
key: loginToken
|
resources:
|
||||||
- name: REFRESH_TOKEN_SECRET
|
requests:
|
||||||
valueFrom:
|
memory: "1024Mi"
|
||||||
secretKeyRef:
|
cpu: "250m"
|
||||||
name: tokens
|
limits:
|
||||||
key: refreshToken
|
memory: "2048Mi"
|
||||||
- name: FILE_TOKEN_SECRET
|
cpu: "1000m"
|
||||||
valueFrom:
|
stdin: true
|
||||||
secretKeyRef:
|
tty: true
|
||||||
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
|
dnsPolicy: ClusterFirst
|
||||||
restartPolicy: Always
|
restartPolicy: Always
|
||||||
|
|||||||
@@ -4,21 +4,21 @@ metadata:
|
|||||||
name: twentycrm
|
name: twentycrm
|
||||||
namespace: twentycrm
|
namespace: twentycrm
|
||||||
annotations:
|
annotations:
|
||||||
nginx.ingress.kubernetes.io/configuration-snippet: |
|
nginx.ingress.kubernetes.io/configuration-snippet: |
|
||||||
more_set_headers "X-Forwarded-For $http_x_forwarded_for";
|
more_set_headers "X-Forwarded-For $http_x_forwarded_for";
|
||||||
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
|
nginx.ingress.kubernetes.io/force-ssl-redirect: "false"
|
||||||
kubernetes.io/ingress.class: "nginx"
|
kubernetes.io/ingress.class: "nginx"
|
||||||
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
|
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
|
||||||
spec:
|
spec:
|
||||||
ingressClassName: nginx
|
ingressClassName: nginx
|
||||||
rules:
|
rules:
|
||||||
- host: crm.example.com
|
- host: crm.example.com
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
- path: /
|
- path: /
|
||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
backend:
|
backend:
|
||||||
service:
|
service:
|
||||||
name: twentycrm-server
|
name: twentycrm-server
|
||||||
port:
|
port:
|
||||||
name: http-tcp
|
name: http-tcp
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolume
|
||||||
|
metadata:
|
||||||
|
name: twentycrm-docker-data-pv
|
||||||
|
spec:
|
||||||
|
storageClassName: default
|
||||||
|
capacity:
|
||||||
|
storage: 100Mi
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
persistentVolumeReclaimPolicy: Retain
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: twentycrm-docker-data-pvc
|
||||||
|
namespace: twentycrm
|
||||||
|
spec:
|
||||||
|
storageClassName: default
|
||||||
|
volumeName: twentycrm-docker-data-pv
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 100Mi
|
||||||
@@ -6,9 +6,9 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
internalTrafficPolicy: Cluster
|
internalTrafficPolicy: Cluster
|
||||||
ports:
|
ports:
|
||||||
- port: 5432
|
- port: 5432
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
targetPort: 5432
|
targetPort: 5432
|
||||||
selector:
|
selector:
|
||||||
app: twentycrm-db
|
app: twentycrm-db
|
||||||
sessionAffinity: ClientIP
|
sessionAffinity: ClientIP
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: twentycrm-redis
|
||||||
|
namespace: twentycrm
|
||||||
|
spec:
|
||||||
|
internalTrafficPolicy: Cluster
|
||||||
|
ports:
|
||||||
|
- port: 6379
|
||||||
|
protocol: TCP
|
||||||
|
targetPort: 6379
|
||||||
|
selector:
|
||||||
|
app: twentycrm-redis
|
||||||
|
sessionAffinity: ClientIP
|
||||||
|
sessionAffinityConfig:
|
||||||
|
clientIP:
|
||||||
|
timeoutSeconds: 10800
|
||||||
|
type: ClusterIP
|
||||||
@@ -6,10 +6,10 @@ metadata:
|
|||||||
spec:
|
spec:
|
||||||
internalTrafficPolicy: Cluster
|
internalTrafficPolicy: Cluster
|
||||||
ports:
|
ports:
|
||||||
- name: http-tcp
|
- name: http-tcp
|
||||||
port: 3000
|
port: 3000
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
targetPort: 3000
|
targetPort: 3000
|
||||||
selector:
|
selector:
|
||||||
app: twentycrm-server
|
app: twentycrm-server
|
||||||
sessionAffinity: ClientIP
|
sessionAffinity: ClientIP
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ output:
|
|||||||
<!-- BEGIN_TF_DOCS -->
|
<!-- BEGIN_TF_DOCS -->
|
||||||
# TwentyCRM Terraform 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.
|
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 update this `README.md` after changes to the Terraform code in this folder, run: `terraform-docs -c `./.terraform-docs.yml .`
|
||||||
|
|
||||||
To make configuration changes to how this doc is generated, see `./.terraform-docs.yml`
|
To make configuration changes to how this doc is generated, see `./.terraform-docs.yml`
|
||||||
|
|
||||||
{{ .Content }}
|
{{ .Content }}
|
||||||
<!-- END_TF_DOCS -->
|
<!-- END_TF_DOCS -->
|
||||||
|
|
||||||
@@ -45,4 +45,4 @@ settings:
|
|||||||
read-comments: true
|
read-comments: true
|
||||||
required: true
|
required: true
|
||||||
sensitive: true
|
sensitive: true
|
||||||
type: true
|
type: true
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<!-- BEGIN_TF_DOCS -->
|
<!-- BEGIN_TF_DOCS -->
|
||||||
# TwentyCRM Terraform 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.
|
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 update this `README.md` after changes to the Terraform code in this folder, run: `terraform-docs -c `./.terraform-docs.yml .`
|
||||||
|
|
||||||
To make configuration changes to how this doc is generated, see `./.terraform-docs.yml`
|
To make configuration changes to how this doc is generated, see `./.terraform-docs.yml`
|
||||||
|
|
||||||
@@ -12,30 +12,37 @@ To make configuration changes to how this doc is generated, see `./.terraform-do
|
|||||||
| Name | Version |
|
| Name | Version |
|
||||||
|------|---------|
|
|------|---------|
|
||||||
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.9.2 |
|
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.9.2 |
|
||||||
| <a name="requirement_kubernetes"></a> [kubernetes](#requirement\_kubernetes) | >= 2.31.0 |
|
| <a name="requirement_kubernetes"></a> [kubernetes](#requirement\_kubernetes) | >= 2.32.0 |
|
||||||
|
| <a name="requirement_random"></a> [random](#requirement\_random) | >= 3.6.3 |
|
||||||
|
|
||||||
## Providers
|
## Providers
|
||||||
|
|
||||||
| Name | Version |
|
| Name | Version |
|
||||||
|------|---------|
|
|------|---------|
|
||||||
| <a name="provider_kubernetes"></a> [kubernetes](#provider\_kubernetes) | >= 2.31.0 |
|
| <a name="provider_kubernetes"></a> [kubernetes](#provider\_kubernetes) | >= 2.32.0 |
|
||||||
|
| <a name="provider_random"></a> [random](#provider\_random) | >= 3.6.3 |
|
||||||
|
|
||||||
## Resources
|
## Resources
|
||||||
|
|
||||||
| Name | Type |
|
| Name | Type |
|
||||||
|------|------|
|
|------|------|
|
||||||
| [kubernetes_deployment.twentycrm_db](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/deployment) | resource |
|
| [kubernetes_deployment.twentycrm_db](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/deployment) | resource |
|
||||||
|
| [kubernetes_deployment.twentycrm_redis](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_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_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_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_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.db](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume) | resource |
|
||||||
|
| [kubernetes_persistent_volume.docker_data](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.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.db](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/persistent_volume_claim) | resource |
|
||||||
|
| [kubernetes_persistent_volume_claim.docker_data](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_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_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_db](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service) | resource |
|
||||||
|
| [kubernetes_service.twentycrm_redis](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 |
|
| [kubernetes_service.twentycrm_server](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/service) | resource |
|
||||||
|
| [random_bytes.this](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/bytes) | resource |
|
||||||
|
|
||||||
## Inputs
|
## Inputs
|
||||||
|
|
||||||
@@ -43,22 +50,24 @@ To make configuration changes to how this doc is generated, see `./.terraform-do
|
|||||||
|------|-------------|------|---------|:--------:|
|
|------|-------------|------|---------|:--------:|
|
||||||
| <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_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_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_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_image"></a> [twentycrm\_db\_image](#input\_twentycrm\_db\_image) | TwentyCRM image for database deployment. This defaults to latest. | `string` | `"twentycrm/twenty-postgres-spilo: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_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_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_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_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_docker_data_mount_path"></a> [twentycrm\_docker\_data\_mount\_path](#input\_twentycrm\_docker\_data\_mount\_path) | TwentyCRM mount path for servers application data. Defaults to '/app/docker-data'. | `string` | `"/app/docker-data"` | no |
|
||||||
|
| <a name="input_twentycrm_docker_data_pv_capacity"></a> [twentycrm\_docker\_data\_pv\_capacity](#input\_twentycrm\_docker\_data\_pv\_capacity) | Storage capacity provisioned for server persistent volume. | `string` | `"10Gi"` | no |
|
||||||
|
| <a name="input_twentycrm_docker_data_pv_path"></a> [twentycrm\_docker\_data\_pv\_path](#input\_twentycrm\_docker\_data\_pv\_path) | Local path to use to store the physical volume if using local storage on nodes. | `string` | `""` | no |
|
||||||
|
| <a name="input_twentycrm_docker_data_pvc_requests"></a> [twentycrm\_docker\_data\_pvc\_requests](#input\_twentycrm\_docker\_data\_pvc\_requests) | Storage capacity reservation for server persistent volume claim. | `string` | `"10Gi"` | no |
|
||||||
| <a name="input_twentycrm_namespace"></a> [twentycrm\_namespace](#input\_twentycrm\_namespace) | Namespace for all TwentyCRM resources | `string` | `"twentycrm"` | 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_redis_image"></a> [twentycrm\_redis\_image](#input\_twentycrm\_redis\_image) | TwentyCRM image for Redis deployment. This defaults to latest. | `string` | `"redis/redis-stack-server:latest"` | no |
|
||||||
|
| <a name="input_twentycrm_redis_replicas"></a> [twentycrm\_redis\_replicas](#input\_twentycrm\_redis\_replicas) | Number of replicas for the TwentyCRM Redis deployment. This defaults to 1. | `number` | `1` | 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/packages/twenty-server/.local-storage'. | `string` | `"/app/packages/twenty-server/.local-storage"` | 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_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_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_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_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_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 |
|
| <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 -->
|
<!-- END_TF_DOCS -->
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
resource "kubernetes_deployment" "twentycrm_redis" {
|
||||||
|
metadata {
|
||||||
|
name = "${var.twentycrm_app_name}-redis"
|
||||||
|
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
app = "${var.twentycrm_app_name}-redis"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spec {
|
||||||
|
replicas = var.twentycrm_redis_replicas
|
||||||
|
selector {
|
||||||
|
match_labels = {
|
||||||
|
app = "${var.twentycrm_app_name}-redis"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strategy {
|
||||||
|
type = "RollingUpdate"
|
||||||
|
rolling_update {
|
||||||
|
max_surge = "1"
|
||||||
|
max_unavailable = "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template {
|
||||||
|
metadata {
|
||||||
|
labels = {
|
||||||
|
app = "${var.twentycrm_app_name}-redis"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spec {
|
||||||
|
container {
|
||||||
|
image = var.twentycrm_redis_image
|
||||||
|
name = "redis"
|
||||||
|
|
||||||
|
port {
|
||||||
|
container_port = 6379
|
||||||
|
protocol = "TCP"
|
||||||
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
requests = {
|
||||||
|
cpu = "250m"
|
||||||
|
memory = "1024Mi"
|
||||||
|
}
|
||||||
|
limits = {
|
||||||
|
cpu = "500m"
|
||||||
|
memory = "2048Mi"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dns_policy = "ClusterFirst"
|
||||||
|
restart_policy = "Always"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,44 +37,27 @@ resource "kubernetes_deployment" "twentycrm_server" {
|
|||||||
stdin = true
|
stdin = true
|
||||||
tty = true
|
tty = true
|
||||||
|
|
||||||
security_context {
|
|
||||||
allow_privilege_escalation = true
|
|
||||||
privileged = true
|
|
||||||
run_as_user = 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
env {
|
||||||
name = "PORT"
|
name = "NODE_PORT"
|
||||||
value = "3000"
|
value = "3000"
|
||||||
}
|
}
|
||||||
env {
|
|
||||||
name = "DEBUG_MODE"
|
|
||||||
value = false
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
env {
|
||||||
name = "SERVER_URL"
|
name = "SERVER_URL"
|
||||||
value = var.twentycrm_app_hostname
|
value = var.twentycrm_app_hostname
|
||||||
}
|
}
|
||||||
|
|
||||||
env {
|
|
||||||
name = "FRONT_BASE_URL"
|
|
||||||
value = var.twentycrm_app_hostname
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
env {
|
||||||
name = "PG_DATABASE_URL"
|
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"
|
value = "postgres://twenty:${var.twentycrm_pgdb_admin_password}@${kubernetes_service.twentycrm_db.metadata.0.name}.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local/default"
|
||||||
}
|
}
|
||||||
|
|
||||||
env {
|
env {
|
||||||
name = "ENABLE_DB_MIGRATIONS"
|
name = "REDIS_URL"
|
||||||
value = "true"
|
value = "redis://${kubernetes_service.twentycrm_redis.metadata.0.name}.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local:6379"
|
||||||
}
|
}
|
||||||
|
|
||||||
env {
|
env {
|
||||||
name = "SIGN_IN_PREFILLED"
|
name = "DISABLE_DB_MIGRATIONS"
|
||||||
value = "true"
|
value = "false"
|
||||||
}
|
}
|
||||||
|
|
||||||
env {
|
env {
|
||||||
@@ -82,11 +65,15 @@ resource "kubernetes_deployment" "twentycrm_server" {
|
|||||||
value = "local"
|
value = "local"
|
||||||
}
|
}
|
||||||
env {
|
env {
|
||||||
name = "MESSAGE_QUEUE_TYPE"
|
name = "ACCESS_TOKEN_EXPIRES_IN"
|
||||||
value = "pg-boss"
|
value = "7d"
|
||||||
}
|
}
|
||||||
env {
|
env {
|
||||||
name = "ACCESS_TOKEN_SECRET"
|
name = "LOGIN_TOKEN_EXPIRES_IN"
|
||||||
|
value = "1h"
|
||||||
|
}
|
||||||
|
env {
|
||||||
|
name = "APP_SECRET"
|
||||||
value_from {
|
value_from {
|
||||||
secret_key_ref {
|
secret_key_ref {
|
||||||
name = "tokens"
|
name = "tokens"
|
||||||
@@ -95,36 +82,6 @@ resource "kubernetes_deployment" "twentycrm_server" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
port {
|
||||||
container_port = 3000
|
container_port = 3000
|
||||||
protocol = "TCP"
|
protocol = "TCP"
|
||||||
@@ -145,6 +102,11 @@ resource "kubernetes_deployment" "twentycrm_server" {
|
|||||||
name = "server-data"
|
name = "server-data"
|
||||||
mount_path = var.twentycrm_server_data_mount_path
|
mount_path = var.twentycrm_server_data_mount_path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volume_mount {
|
||||||
|
name = "docker-data"
|
||||||
|
mount_path = var.twentycrm_docker_data_mount_path
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
volume {
|
volume {
|
||||||
@@ -155,6 +117,14 @@ resource "kubernetes_deployment" "twentycrm_server" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volume {
|
||||||
|
name = "docker-data"
|
||||||
|
|
||||||
|
persistent_volume_claim {
|
||||||
|
claim_name = kubernetes_persistent_volume_claim.docker_data.metadata.0.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dns_policy = "ClusterFirst"
|
dns_policy = "ClusterFirst"
|
||||||
restart_policy = "Always"
|
restart_policy = "Always"
|
||||||
}
|
}
|
||||||
@@ -162,6 +132,7 @@ resource "kubernetes_deployment" "twentycrm_server" {
|
|||||||
}
|
}
|
||||||
depends_on = [
|
depends_on = [
|
||||||
kubernetes_deployment.twentycrm_db,
|
kubernetes_deployment.twentycrm_db,
|
||||||
|
kubernetes_deployment.twentycrm_redis,
|
||||||
kubernetes_secret.twentycrm_tokens
|
kubernetes_secret.twentycrm_tokens
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,32 +43,28 @@ resource "kubernetes_deployment" "twentycrm_worker" {
|
|||||||
value = var.twentycrm_app_hostname
|
value = var.twentycrm_app_hostname
|
||||||
}
|
}
|
||||||
|
|
||||||
env {
|
|
||||||
name = "FRONT_BASE_URL"
|
|
||||||
value = var.twentycrm_app_hostname
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
env {
|
||||||
name = "PG_DATABASE_URL"
|
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"
|
value = "postgres://twenty:${var.twentycrm_pgdb_admin_password}@${kubernetes_service.twentycrm_db.metadata.0.name}.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local/default"
|
||||||
}
|
}
|
||||||
|
|
||||||
env {
|
env {
|
||||||
name = "ENABLE_DB_MIGRATIONS"
|
name = "REDIS_URL"
|
||||||
value = "false" #it already runs on the server
|
value = "redis://${kubernetes_service.twentycrm_redis.metadata.0.name}.${kubernetes_namespace.twentycrm.metadata.0.name}.svc.cluster.local:6379"
|
||||||
|
}
|
||||||
|
|
||||||
|
env {
|
||||||
|
name = "DISABLE_DB_MIGRATIONS"
|
||||||
|
value = "true" #it already runs on the server
|
||||||
}
|
}
|
||||||
|
|
||||||
env {
|
env {
|
||||||
name = "STORAGE_TYPE"
|
name = "STORAGE_TYPE"
|
||||||
value = "local"
|
value = "local"
|
||||||
}
|
}
|
||||||
env {
|
|
||||||
name = "MESSAGE_QUEUE_TYPE"
|
|
||||||
value = "pg-boss"
|
|
||||||
}
|
|
||||||
|
|
||||||
env {
|
env {
|
||||||
name = "ACCESS_TOKEN_SECRET"
|
name = "APP_SECRET"
|
||||||
value_from {
|
value_from {
|
||||||
secret_key_ref {
|
secret_key_ref {
|
||||||
name = "tokens"
|
name = "tokens"
|
||||||
@@ -77,44 +73,14 @@ resource "kubernetes_deployment" "twentycrm_worker" {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
resources {
|
||||||
requests = {
|
requests = {
|
||||||
cpu = "250m"
|
cpu = "250m"
|
||||||
memory = "256Mi"
|
memory = "1024Mi"
|
||||||
}
|
}
|
||||||
limits = {
|
limits = {
|
||||||
cpu = "1000m"
|
cpu = "1000m"
|
||||||
memory = "1024Mi"
|
memory = "2048Mi"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,6 +92,8 @@ resource "kubernetes_deployment" "twentycrm_worker" {
|
|||||||
}
|
}
|
||||||
depends_on = [
|
depends_on = [
|
||||||
kubernetes_deployment.twentycrm_db,
|
kubernetes_deployment.twentycrm_db,
|
||||||
kubernetes_secret.twentycrm_tokens
|
kubernetes_deployment.twentycrm_redis,
|
||||||
|
kubernetes_deployment.twentycrm_server,
|
||||||
|
kubernetes_secret.twentycrm_tokens,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,11 @@ terraform {
|
|||||||
required_providers {
|
required_providers {
|
||||||
kubernetes = {
|
kubernetes = {
|
||||||
source = "hashicorp/kubernetes"
|
source = "hashicorp/kubernetes"
|
||||||
version = ">= 2.31.0"
|
version = ">= 2.32.0"
|
||||||
|
}
|
||||||
|
random = {
|
||||||
|
source = "hashicorp/random"
|
||||||
|
version = ">= 3.6.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
resource "kubernetes_persistent_volume" "docker_data" {
|
||||||
|
metadata {
|
||||||
|
name = "${var.twentycrm_app_name}-docker-data-pv"
|
||||||
|
}
|
||||||
|
spec {
|
||||||
|
storage_class_name = "default"
|
||||||
|
capacity = {
|
||||||
|
storage = var.twentycrm_docker_data_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_docker_data_pv_path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
resource "kubernetes_persistent_volume_claim" "docker_data" {
|
||||||
|
metadata {
|
||||||
|
name = "${var.twentycrm_app_name}-docker-data-pvc"
|
||||||
|
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
||||||
|
}
|
||||||
|
spec {
|
||||||
|
access_modes = ["ReadWriteOnce"]
|
||||||
|
resources {
|
||||||
|
requests = {
|
||||||
|
storage = var.twentycrm_docker_data_pvc_requests
|
||||||
|
}
|
||||||
|
}
|
||||||
|
volume_name = kubernetes_persistent_volume.docker_data.metadata.0.name
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,18 @@
|
|||||||
|
locals {
|
||||||
|
tokens = [
|
||||||
|
"accessToken",
|
||||||
|
"loginToken",
|
||||||
|
"refreshToken",
|
||||||
|
"fileToken"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "random_bytes" "this" {
|
||||||
|
for_each = toset(local.tokens)
|
||||||
|
|
||||||
|
length = 32
|
||||||
|
}
|
||||||
|
|
||||||
resource "kubernetes_secret" "twentycrm_tokens" {
|
resource "kubernetes_secret" "twentycrm_tokens" {
|
||||||
metadata {
|
metadata {
|
||||||
name = "tokens"
|
name = "tokens"
|
||||||
@@ -5,11 +20,9 @@ resource "kubernetes_secret" "twentycrm_tokens" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
accessToken = var.twentycrm_token_accessToken
|
accessToken = random_bytes.this["accessToken"].base64
|
||||||
loginToken = var.twentycrm_token_loginToken
|
loginToken = random_bytes.this["loginToken"].base64
|
||||||
refreshToken = var.twentycrm_token_refreshToken
|
refreshToken = random_bytes.this["refreshToken"].base64
|
||||||
fileToken = var.twentycrm_token_fileToken
|
fileToken = random_bytes.this["fileToken"].base64
|
||||||
}
|
}
|
||||||
|
|
||||||
# type = "kubernetes.io/basic-auth"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
resource "kubernetes_service" "twentycrm_redis" {
|
||||||
|
metadata {
|
||||||
|
name = "${var.twentycrm_app_name}-redis"
|
||||||
|
namespace = kubernetes_namespace.twentycrm.metadata.0.name
|
||||||
|
}
|
||||||
|
spec {
|
||||||
|
selector = {
|
||||||
|
app = "${var.twentycrm_app_name}-redis"
|
||||||
|
}
|
||||||
|
session_affinity = "ClientIP"
|
||||||
|
port {
|
||||||
|
port = 6379
|
||||||
|
target_port = 6379
|
||||||
|
}
|
||||||
|
|
||||||
|
type = "ClusterIP"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,30 +1,6 @@
|
|||||||
######################
|
######################
|
||||||
# Required Variables #
|
# 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" {
|
variable "twentycrm_pgdb_admin_password" {
|
||||||
type = string
|
type = string
|
||||||
description = "TwentyCRM password for postgres database."
|
description = "TwentyCRM password for postgres database."
|
||||||
@@ -53,7 +29,7 @@ variable "twentycrm_server_image" {
|
|||||||
|
|
||||||
variable "twentycrm_db_image" {
|
variable "twentycrm_db_image" {
|
||||||
type = string
|
type = string
|
||||||
default = "twentycrm/twenty-postgres:latest"
|
default = "twentycrm/twenty-postgres-spilo:latest"
|
||||||
description = "TwentyCRM image for database deployment. This defaults to latest."
|
description = "TwentyCRM image for database deployment. This defaults to latest."
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,8 +53,8 @@ variable "twentycrm_db_replicas" {
|
|||||||
|
|
||||||
variable "twentycrm_server_data_mount_path" {
|
variable "twentycrm_server_data_mount_path" {
|
||||||
type = string
|
type = string
|
||||||
default = "/app/docker-data"
|
default = "/app/packages/twenty-server/.local-storage"
|
||||||
description = "TwentyCRM mount path for servers application data. Defaults to '/app/docker-data'."
|
description = "TwentyCRM mount path for servers application data. Defaults to '/app/packages/twenty-server/.local-storage'."
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "twentycrm_db_pv_path" {
|
variable "twentycrm_db_pv_path" {
|
||||||
@@ -122,3 +98,39 @@ variable "twentycrm_namespace" {
|
|||||||
default = "twentycrm"
|
default = "twentycrm"
|
||||||
description = "Namespace for all TwentyCRM resources"
|
description = "Namespace for all TwentyCRM resources"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "twentycrm_redis_replicas" {
|
||||||
|
type = number
|
||||||
|
default = 1
|
||||||
|
description = "Number of replicas for the TwentyCRM Redis deployment. This defaults to 1."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "twentycrm_redis_image" {
|
||||||
|
type = string
|
||||||
|
default = "redis/redis-stack-server:latest"
|
||||||
|
description = "TwentyCRM image for Redis deployment. This defaults to latest."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "twentycrm_docker_data_mount_path" {
|
||||||
|
type = string
|
||||||
|
default = "/app/docker-data"
|
||||||
|
description = "TwentyCRM mount path for servers application data. Defaults to '/app/docker-data'."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "twentycrm_docker_data_pv_path" {
|
||||||
|
type = string
|
||||||
|
default = ""
|
||||||
|
description = "Local path to use to store the physical volume if using local storage on nodes."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "twentycrm_docker_data_pv_capacity" {
|
||||||
|
type = string
|
||||||
|
default = "100Mi"
|
||||||
|
description = "Storage capacity provisioned for server persistent volume."
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "twentycrm_docker_data_pvc_requests" {
|
||||||
|
type = string
|
||||||
|
default = "100Mi"
|
||||||
|
description = "Storage capacity reservation for server persistent volume claim."
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# How to deploy twenty on podman
|
||||||
|
|
||||||
|
DISCLAIMER: The k8s and podman deployments are not maintained by the core team.
|
||||||
|
These files are provided and maintained by the community. Twenty core team
|
||||||
|
maintains support for docker deployment.
|
||||||
|
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
1. Edit `.env` file. At the minimum set `POSTGRES_PASSWORD`, `SERVER_URL`, and `APP_SECRET`.
|
||||||
|
2. Start twenty by running `podman-compose up -d`.
|
||||||
|
|
||||||
|
If you need to stop twenty, you can do so by running `podman-compose down`.
|
||||||
|
|
||||||
|
|
||||||
|
### Install systemd service (optional)
|
||||||
|
|
||||||
|
If you want to install a systemd service to run twenty, you can use the provided systemd service.
|
||||||
|
|
||||||
|
Edit `twentycrm.service` and change these two variables:
|
||||||
|
|
||||||
|
|
||||||
|
WorkingDirectory=/opt/apps/twenty
|
||||||
|
EnvironmentFile=/opt/apps/twenty/.env
|
||||||
|
|
||||||
|
`WorkingDirectory` should be changed to the path in which `podman-compose.yml` is located.
|
||||||
|
|
||||||
|
`EnvironmentFile` should be changed to the path in which your `.env`file is located.
|
||||||
|
|
||||||
|
You can run the script `install-systemd-user-service` to install the systemd service under the current user.
|
||||||
|
|
||||||
|
|
||||||
|
./install-systemd-user-service
|
||||||
|
|
||||||
|
Note: this script will enable the service and also start it. So it will assume that twenty is not currently running.
|
||||||
|
If you started it previously, bring it down using:
|
||||||
|
|
||||||
|
podman-compose down
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
These files should be compatible with podman 4.3+.
|
||||||
|
|
||||||
|
I have tested this on Debian GNU/Linux 12 (bookworm) and with the podman that is distributed with the official Debian stable mirrors (podman v4.3.1+ds1-8+deb12u1, podman-compose v1.0.3-3).
|
||||||
|
|
||||||
|
|
||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
mkdir -p ~/.config/systemd/user
|
||||||
|
[ -f twentycrm.service ] || { echo "Error: twentycrm.service not found"; exit 1; }
|
||||||
|
cp twentycrm.service ~/.config/systemd/user
|
||||||
|
|
||||||
|
|
||||||
|
systemctl --user daemon-reload
|
||||||
|
systemctl --user enable twentycrm.service
|
||||||
|
systemctl --user start twentycrm.service
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
if [ ! -f "$(dirname "$0")/.env" ]; then
|
||||||
|
echo "Error: .env file not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
source "$(dirname "$0")/.env"
|
||||||
|
|
||||||
|
## steps to cleanup and start over from scratch - useful when testing
|
||||||
|
#podman pod stop twenty-pod
|
||||||
|
#podman pod rm twenty-pod
|
||||||
|
#podman volume rm twenty-db-data twenty-server-data twenty-redis-data
|
||||||
|
# end of cleanup
|
||||||
|
|
||||||
|
podman volume create twenty-db-data
|
||||||
|
podman volume create twenty-server-data
|
||||||
|
podman volume create twenty-redis-data
|
||||||
|
|
||||||
|
podman pod create --name twenty-pod -p 127.0.0.1:8080:3000
|
||||||
|
|
||||||
|
podman run -d --pod twenty-pod --name twenty-db \
|
||||||
|
-e POSTGRES_DB=twenty \
|
||||||
|
-e POSTGRES_USER=twenty \
|
||||||
|
-e POSTGRES_PASSWORD="$POSTGRES_PASSWORD" \
|
||||||
|
-v twenty-db-data:/var/lib/postgresql/data:Z \
|
||||||
|
docker.io/library/postgres:16
|
||||||
|
|
||||||
|
podman run -d --pod twenty-pod --name twenty-redis \
|
||||||
|
-v twenty-redis-data:/data:Z \
|
||||||
|
docker.io/library/redis:latest
|
||||||
|
|
||||||
|
podman run -d --pod twenty-pod --name twenty-server \
|
||||||
|
-e NODE_PORT=3000 \
|
||||||
|
-e SERVER_URL="$SERVER_URL" \
|
||||||
|
-e PG_DATABASE_URL="postgresql://twenty:$POSTGRES_PASSWORD@twenty-db:5432/twenty" \
|
||||||
|
-e REDIS_URL="redis://twenty-redis:6379" \
|
||||||
|
-e APP_SECRET="$APP_SECRET" \
|
||||||
|
-e NODE_ENV=production \
|
||||||
|
-e LOG_LEVEL=info \
|
||||||
|
-v twenty-server-data:/app/docker-data:Z \
|
||||||
|
docker.io/twentycrm/twenty:latest
|
||||||
|
|
||||||
|
podman run -d --pod twenty-pod --name twenty-worker \
|
||||||
|
--init \
|
||||||
|
-e SERVER_URL="$SERVER_URL" \
|
||||||
|
-e PG_DATABASE_URL="postgresql://twenty:$POSTGRES_PASSWORD@twenty-db:5432/twenty" \
|
||||||
|
-e REDIS_URL="redis://twenty-redis:6379" \
|
||||||
|
-e APP_SECRET="$APP_SECRET" \
|
||||||
|
-e DISABLE_DB_MIGRATIONS=true \
|
||||||
|
-e NODE_ENV=production \
|
||||||
|
-e LOG_LEVEL=info \
|
||||||
|
-v twenty-server-data:/app/docker-data:Z \
|
||||||
|
docker.io/twentycrm/twenty:latest \
|
||||||
|
yarn worker:prod
|
||||||
|
|
||||||
|
# wait some time, check status
|
||||||
|
sleep 30
|
||||||
|
podman ps --pod -f name=twenty-pod
|
||||||
|
|
||||||
|
|
||||||
|
mkdir -p ~/.config/systemd/user
|
||||||
|
if [ ! -f "twentycrm.service" ]; then
|
||||||
|
echo "Error: twentycrm.service file not found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
cp twentycrm.service ~/.config/systemd/user
|
||||||
|
|
||||||
|
systemctl --user daemon-reload
|
||||||
|
systemctl --user enable twentycrm.service
|
||||||
|
systemctl --user start twentycrm.service
|
||||||
|
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
version: "3.8"
|
||||||
|
|
||||||
|
services:
|
||||||
|
db:
|
||||||
|
container_name: twenty-db
|
||||||
|
image: postgres:16
|
||||||
|
environment:
|
||||||
|
POSTGRES_DB: twenty
|
||||||
|
POSTGRES_USER: twenty
|
||||||
|
POSTGRES_PASSWORD: ${PG_DATABASE_PASSWORD}
|
||||||
|
volumes:
|
||||||
|
- twenty-db-data:/var/lib/postgresql/data:Z
|
||||||
|
|
||||||
|
redis:
|
||||||
|
container_name: twenty-redis
|
||||||
|
image: redis:latest
|
||||||
|
command: ["--maxmemory-policy", "noeviction"]
|
||||||
|
volumes:
|
||||||
|
- twenty-redis-data:/data:Z
|
||||||
|
|
||||||
|
server:
|
||||||
|
container_name: twenty-server
|
||||||
|
image: twentycrm/twenty:latest
|
||||||
|
environment:
|
||||||
|
NODE_PORT: "3000"
|
||||||
|
SERVER_URL: ${SERVER_URL}
|
||||||
|
PG_DATABASE_URL: "postgresql://twenty:${PG_DATABASE_PASSWORD}@twenty-db:5432/twenty"
|
||||||
|
REDIS_URL: "redis://twenty-redis:6379"
|
||||||
|
APP_SECRET: ${APP_SECRET}
|
||||||
|
NODE_ENV: production
|
||||||
|
LOG_LEVEL: info
|
||||||
|
volumes:
|
||||||
|
- twenty-server-data:/app/docker-data:Z
|
||||||
|
ports:
|
||||||
|
- 127.0.0.1:8080:3000
|
||||||
|
|
||||||
|
worker:
|
||||||
|
container_name: twenty-worker
|
||||||
|
image: twentycrm/twenty:latest
|
||||||
|
command: yarn worker:prod
|
||||||
|
environment:
|
||||||
|
SERVER_URL: ${SERVER_URL}
|
||||||
|
PG_DATABASE_URL: "postgresql://twenty:${PG_DATABASE_PASSWORD}@twenty-db:5432/twenty"
|
||||||
|
REDIS_URL: "redis://twenty-redis:6379"
|
||||||
|
APP_SECRET: ${APP_SECRET}
|
||||||
|
DISABLE_DB_MIGRATIONS: "true"
|
||||||
|
NODE_ENV: production
|
||||||
|
LOG_LEVEL: info
|
||||||
|
volumes:
|
||||||
|
- twenty-server-data:/app/docker-data:Z
|
||||||
|
init: true
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
twenty-db-data:
|
||||||
|
twenty-server-data:
|
||||||
|
twenty-redis-data:
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=TwentyCRM Container Stack via Podman-Compose
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
WorkingDirectory=/opt/apps/twenty
|
||||||
|
EnvironmentFile=/opt/apps/twenty/.env
|
||||||
|
ExecStart=/usr/bin/podman-compose -f podman-compose.yml up -d
|
||||||
|
ExecStop=/usr/bin/podman-compose -f podman-compose.yml down
|
||||||
|
RemainAfterExit=yes
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=default.target
|
||||||
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
pull_version=${VERSION:-$(curl -s https://api.github.com/repos/twentyhq/twenty/tags | grep '"name":' | head -n 1 | cut -d '"' -f 4)}
|
||||||
|
|
||||||
|
if [[ -z "$pull_version" ]]; then
|
||||||
|
echo "Error: Unable to fetch the latest version tag. Please check your network connection or the GitHub API response."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
pull_branch=${BRANCH:-$pull_version}
|
||||||
|
|
||||||
|
version_num=${pull_version#v}
|
||||||
|
target_version="0.32.4"
|
||||||
|
|
||||||
|
# We moved the install script to a different location in v0.32.4
|
||||||
|
if [[ -n "$BRANCH" ]] || [[ "$(printf '%s\n' "$target_version" "$version_num" | sort -V | head -n1)" != "$version_num" ]]; then
|
||||||
|
curl -sL "https://raw.githubusercontent.com/twentyhq/twenty/$pull_branch/packages/twenty-docker/scripts/install.sh" -o twenty_install.sh
|
||||||
|
else
|
||||||
|
curl -sL "https://raw.githubusercontent.com/twentyhq/twenty/$pull_branch/install.sh" -o twenty_install.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
chmod +x twenty_install.sh
|
||||||
|
VERSION="$VERSION" BRANCH="$BRANCH" ./twenty_install.sh
|
||||||
|
|
||||||
|
rm twenty_install.sh
|
||||||
Executable
+167
@@ -0,0 +1,167 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
echo "🔧 Checking dependencies..."
|
||||||
|
if ! command -v docker &>/dev/null; then
|
||||||
|
echo -e "\t❌ Docker is not installed or not in PATH. Please install Docker first.\n\t\tSee https://docs.docker.com/get-docker/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Check if docker compose plugin is installed
|
||||||
|
if ! docker compose version &>/dev/null; then
|
||||||
|
echo -e "\t❌ Docker Compose is not installed or not in PATH (n.b. docker-compose is deprecated)\n\t\tUpdate docker or install docker-compose-plugin\n\t\tOn Linux: sudo apt-get install docker-compose-plugin\n\t\tSee https://docs.docker.com/compose/install/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Check if docker is started
|
||||||
|
if ! docker info &>/dev/null; then
|
||||||
|
echo -e "\t❌ Docker is not running.\n\t\tPlease start Docker Desktop, Docker or check documentation at https://docs.docker.com/config/daemon/start/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if ! command -v curl &>/dev/null; then
|
||||||
|
echo -e "\t❌ Curl is not installed or not in PATH.\n\t\tOn macOS: brew install curl\n\t\tOn Linux: sudo apt install curl"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if docker compose version is >= 2
|
||||||
|
if [ "$(docker compose version --short | cut -d' ' -f3 | cut -d'.' -f1)" -lt 2 ]; then
|
||||||
|
echo -e "\t❌ Docker Compose is outdated. Please update Docker Compose to version 2 or higher.\n\t\tSee https://docs.docker.com/compose/install/linux/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# Check if docker-compose is installed, if so issue a warning if version is < 2
|
||||||
|
if command -v docker-compose &>/dev/null; then
|
||||||
|
if [ "$(docker-compose version --short | cut -d' ' -f3 | cut -d'.' -f1)" -lt 2 ]; then
|
||||||
|
echo -e "\n\t⚠️ 'docker-compose' is installed but outdated. Make sure to use 'docker compose' or to upgrade 'docker-compose' to version 2.\n\t\tSee https://docs.docker.com/compose/install/standalone/\n"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Catch errors
|
||||||
|
set -e
|
||||||
|
function on_exit {
|
||||||
|
# $? is the exit status of the last command executed
|
||||||
|
local exit_status=$?
|
||||||
|
if [ $exit_status -ne 0 ]; then
|
||||||
|
echo "❌ Something went wrong, exiting: $exit_status"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
trap on_exit EXIT
|
||||||
|
|
||||||
|
# Use environment variables VERSION and BRANCH, with defaults if not set
|
||||||
|
version=${VERSION:-$(curl -s "https://hub.docker.com/v2/repositories/twentycrm/twenty/tags" | grep -o '"name":"[^"]*"' | grep -v 'latest' | cut -d'"' -f4 | sort -V | tail -n1)}
|
||||||
|
branch=${BRANCH:-$(curl -s https://api.github.com/repos/twentyhq/twenty/tags | grep '"name":' | head -n 1 | cut -d '"' -f 4)}
|
||||||
|
|
||||||
|
echo "🚀 Using docker version $version and Github branch $branch"
|
||||||
|
|
||||||
|
dir_name="twenty"
|
||||||
|
function ask_directory {
|
||||||
|
read -p "📁 Enter the directory name to setup the project (default: $dir_name): " answer
|
||||||
|
if [ -n "$answer" ]; then
|
||||||
|
dir_name=$answer
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ask_directory
|
||||||
|
|
||||||
|
while [ -d "$dir_name" ]; do
|
||||||
|
read -p "🚫 Directory '$dir_name' already exists. Do you want to overwrite it? (y/N) " answer
|
||||||
|
if [ "$answer" = "y" ]; then
|
||||||
|
break
|
||||||
|
else
|
||||||
|
ask_directory
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Create a directory named twenty
|
||||||
|
echo "📁 Creating directory '$dir_name'"
|
||||||
|
mkdir -p "$dir_name" && cd "$dir_name" || { echo "❌ Failed to create/access directory '$dir_name'"; exit 1; }
|
||||||
|
|
||||||
|
# Copy twenty/packages/twenty-docker/docker-compose.yml in it
|
||||||
|
echo -e "\t• Copying docker-compose.yml"
|
||||||
|
curl -sLo docker-compose.yml https://raw.githubusercontent.com/twentyhq/twenty/$branch/packages/twenty-docker/docker-compose.yml
|
||||||
|
|
||||||
|
# Copy twenty/packages/twenty-docker/.env.example to .env
|
||||||
|
echo -e "\t• Setting up .env file"
|
||||||
|
curl -sLo .env https://raw.githubusercontent.com/twentyhq/twenty/$branch/packages/twenty-docker/.env.example
|
||||||
|
|
||||||
|
# Replace TAG=latest by TAG=<latest_release or version input>
|
||||||
|
if [[ $(uname) == "Darwin" ]]; then
|
||||||
|
# Running on macOS
|
||||||
|
sed -i '' "s/TAG=latest/TAG=$version/g" .env
|
||||||
|
else
|
||||||
|
# Assuming Linux
|
||||||
|
sed -i'' "s/TAG=latest/TAG=$version/g" .env
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate random strings for secrets
|
||||||
|
echo "# === Randomly generated secret ===" >> .env
|
||||||
|
echo "APP_SECRET=$(openssl rand -base64 32)" >> .env
|
||||||
|
|
||||||
|
echo "" >> .env
|
||||||
|
echo "PG_DATABASE_PASSWORD=$(openssl rand -hex 16)" >> .env
|
||||||
|
|
||||||
|
echo -e "\t• .env configuration completed"
|
||||||
|
|
||||||
|
port=3000
|
||||||
|
# Check if command nc is available
|
||||||
|
if command -v nc &> /dev/null; then
|
||||||
|
# Check if port 3000 is already in use, propose to change it
|
||||||
|
while nc -zv localhost $port &>/dev/null; do
|
||||||
|
read -p "🚫 Port $port is already in use. Do you want to use another port? (Y/n) " answer
|
||||||
|
if [ "$answer" = "n" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
read -p "Enter a new port number: " new_port
|
||||||
|
if [[ $(uname) == "Darwin" ]]; then
|
||||||
|
sed -i '' "s/$port:$port/$new_port:$port/g" docker-compose.yml
|
||||||
|
sed -E -i '' "s|^SERVER_URL=http://localhost:[0-9]+|SERVER_URL=http://localhost:$new_port|g" .env
|
||||||
|
else
|
||||||
|
sed -i'' "s/$port:$port/$new_port:$port/g" docker-compose.yml
|
||||||
|
sed -E -i'' "s|^SERVER_URL=http://localhost:[0-9]+|SERVER_URL=http://localhost:$new_port|g" .env
|
||||||
|
fi
|
||||||
|
port=$new_port
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ask user if they want to start the project
|
||||||
|
read -p "🚀 Do you want to start the project now? (Y/n) " answer
|
||||||
|
if [ "$answer" = "n" ]; then
|
||||||
|
echo "✅ Project setup completed. Run 'docker compose up -d' to start."
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo "🐳 Starting Docker containers..."
|
||||||
|
docker compose up -d
|
||||||
|
# Check if port is listening
|
||||||
|
echo "Waiting for server to be healthy, it might take a few minutes while we initialize the database..."
|
||||||
|
# Tail logs of the server until it's ready
|
||||||
|
docker compose logs -f server &
|
||||||
|
pid=$!
|
||||||
|
while [ ! $(docker inspect --format='{{.State.Health.Status}}' twenty-server-1) = "healthy" ]; do
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
kill $pid
|
||||||
|
echo ""
|
||||||
|
echo "✅ Server is up and running"
|
||||||
|
fi
|
||||||
|
|
||||||
|
function ask_open_browser {
|
||||||
|
read -p "🌐 Do you want to open the project in your browser? (Y/n) " answer
|
||||||
|
if [ "$answer" = "n" ]; then
|
||||||
|
echo "✅ Setup completed. Access your project at http://localhost:$port"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ask user if they want to open the project
|
||||||
|
# Running on macOS
|
||||||
|
if [[ $(uname) == "Darwin" ]]; then
|
||||||
|
ask_open_browser
|
||||||
|
|
||||||
|
open "http://localhost:$port"
|
||||||
|
# Assuming Linux
|
||||||
|
else
|
||||||
|
# xdg-open is not installed, we could be running in a non gui environment
|
||||||
|
if command -v xdg-open >/dev/null 2>&1; then
|
||||||
|
ask_open_browser
|
||||||
|
|
||||||
|
xdg-open "http://localhost:$port"
|
||||||
|
else
|
||||||
|
echo "✅ Setup completed. Your project is available at http://localhost:$port"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
@@ -1,13 +1,12 @@
|
|||||||
ARG POSTGRES_VERSION=15
|
ARG POSTGRES_VERSION=15
|
||||||
ARG SPILO_VERSION=3.2-p1
|
ARG SPILO_VERSION=3.2-p1
|
||||||
ARG PG_GRAPHQL_VERSION=1.5.6
|
|
||||||
ARG WRAPPERS_VERSION=0.2.0
|
ARG WRAPPERS_VERSION=0.2.0
|
||||||
|
|
||||||
# Build the mysql_fdw extension
|
# Build the mysql_fdw extension
|
||||||
FROM debian:bookworm as build-mysql_fdw
|
FROM debian:bookworm AS build-mysql_fdw
|
||||||
ARG POSTGRES_VERSION
|
ARG POSTGRES_VERSION
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
RUN apt update && \
|
RUN apt update && \
|
||||||
apt install -y \
|
apt install -y \
|
||||||
build-essential \
|
build-essential \
|
||||||
@@ -18,14 +17,14 @@ RUN apt update && \
|
|||||||
|
|
||||||
# Install mysql_fdw
|
# Install mysql_fdw
|
||||||
RUN git clone https://github.com/EnterpriseDB/mysql_fdw.git
|
RUN git clone https://github.com/EnterpriseDB/mysql_fdw.git
|
||||||
WORKDIR mysql_fdw
|
WORKDIR /mysql_fdw
|
||||||
RUN make USE_PGXS=1
|
RUN make USE_PGXS=1
|
||||||
|
|
||||||
|
|
||||||
# Build libssl for wrappers
|
# Build libssl for wrappers
|
||||||
FROM ubuntu:22.04 as build-libssl
|
FROM ubuntu:22.04 AS build-libssl
|
||||||
|
|
||||||
ENV DEBIAN_FRONTEND noninteractive
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
RUN apt update && \
|
RUN apt update && \
|
||||||
apt install -y \
|
apt install -y \
|
||||||
build-essential \
|
build-essential \
|
||||||
@@ -38,10 +37,9 @@ WORKDIR /build/openssl
|
|||||||
RUN ./config && make && make install
|
RUN ./config && make && make install
|
||||||
|
|
||||||
|
|
||||||
# Extend the Spilo image with the pg_graphql and mysql_fdw extensions
|
# Extend the Spilo image with the mysql_fdw extensions
|
||||||
FROM ghcr.io/zalando/spilo-${POSTGRES_VERSION}:${SPILO_VERSION}
|
FROM ghcr.io/zalando/spilo-${POSTGRES_VERSION}:${SPILO_VERSION}
|
||||||
ARG POSTGRES_VERSION
|
ARG POSTGRES_VERSION
|
||||||
ARG PG_GRAPHQL_VERSION
|
|
||||||
ARG WRAPPERS_VERSION
|
ARG WRAPPERS_VERSION
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
|
|
||||||
@@ -63,14 +61,6 @@ RUN curl -L "https://github.com/supabase/wrappers/releases/download/v${WRAPPERS_
|
|||||||
COPY --from=build-libssl /usr/local/lib/libssl* /usr/local/lib/libcrypto* /usr/lib/
|
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 --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 mysql_fdw
|
||||||
COPY --from=build-mysql_fdw /mysql_fdw/mysql_fdw.so \
|
COPY --from=build-mysql_fdw /mysql_fdw/mysql_fdw.so \
|
||||||
/usr/lib/postgresql/${POSTGRES_VERSION}/lib/mysql_fdw.so
|
/usr/lib/postgresql/${POSTGRES_VERSION}/lib/mysql_fdw.so
|
||||||
|
|||||||
@@ -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"]
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
CREATE DATABASE "default";
|
|
||||||
CREATE DATABASE "test";
|
|
||||||
CREATE USER twenty PASSWORD 'twenty';
|
|
||||||
ALTER ROLE twenty superuser;
|
|
||||||
@@ -8,10 +8,18 @@ COPY ./yarn.lock .
|
|||||||
COPY ./.yarnrc.yml .
|
COPY ./.yarnrc.yml .
|
||||||
COPY ./.yarn/releases /app/.yarn/releases
|
COPY ./.yarn/releases /app/.yarn/releases
|
||||||
COPY ./tools/eslint-rules /app/tools/eslint-rules
|
COPY ./tools/eslint-rules /app/tools/eslint-rules
|
||||||
|
COPY ./packages/twenty-ui/package.json /app/packages/twenty-ui/
|
||||||
|
COPY ./packages/twenty-shared/package.json /app/packages/twenty-shared/
|
||||||
COPY ./packages/twenty-website/package.json /app/packages/twenty-website/package.json
|
COPY ./packages/twenty-website/package.json /app/packages/twenty-website/package.json
|
||||||
|
|
||||||
RUN yarn
|
RUN yarn
|
||||||
|
|
||||||
|
ENV KEYSTATIC_GITHUB_CLIENT_ID="<fake build value>"
|
||||||
|
ENV KEYSTATIC_GITHUB_CLIENT_SECRET="<fake build value>"
|
||||||
|
ENV KEYSTATIC_SECRET="<fake build value>"
|
||||||
|
ENV NEXT_PUBLIC_KEYSTATIC_GITHUB_APP_SLUG="<fake build value>"
|
||||||
|
|
||||||
|
COPY ./packages/twenty-ui /app/packages/twenty-ui
|
||||||
COPY ./packages/twenty-website /app/packages/twenty-website
|
COPY ./packages/twenty-website /app/packages/twenty-website
|
||||||
RUN npx nx build twenty-website
|
RUN npx nx build twenty-website
|
||||||
|
|
||||||
@@ -26,4 +34,9 @@ WORKDIR /app/packages/twenty-website
|
|||||||
LABEL org.opencontainers.image.source=https://github.com/twentyhq/twenty
|
LABEL org.opencontainers.image.source=https://github.com/twentyhq/twenty
|
||||||
LABEL org.opencontainers.image.description="This image provides a consistent and reproducible environment for the website."
|
LABEL org.opencontainers.image.description="This image provides a consistent and reproducible environment for the website."
|
||||||
|
|
||||||
|
RUN chown -R 1000 /app
|
||||||
|
|
||||||
|
# Use non root user with uid 1000
|
||||||
|
USER 1000
|
||||||
|
|
||||||
CMD ["/bin/sh", "-c", "npx nx start"]
|
CMD ["/bin/sh", "-c", "npx nx start"]
|
||||||
@@ -7,10 +7,12 @@ WORKDIR /app
|
|||||||
COPY ./package.json ./yarn.lock ./.yarnrc.yml ./tsconfig.base.json ./nx.json /app/
|
COPY ./package.json ./yarn.lock ./.yarnrc.yml ./tsconfig.base.json ./nx.json /app/
|
||||||
COPY ./.yarn/releases /app/.yarn/releases
|
COPY ./.yarn/releases /app/.yarn/releases
|
||||||
|
|
||||||
|
COPY ./.prettierrc /app/
|
||||||
COPY ./packages/twenty-emails/package.json /app/packages/twenty-emails/
|
COPY ./packages/twenty-emails/package.json /app/packages/twenty-emails/
|
||||||
COPY ./packages/twenty-server/package.json /app/packages/twenty-server/
|
COPY ./packages/twenty-server/package.json /app/packages/twenty-server/
|
||||||
COPY ./packages/twenty-server/patches /app/packages/twenty-server/patches
|
COPY ./packages/twenty-server/patches /app/packages/twenty-server/patches
|
||||||
COPY ./packages/twenty-ui/package.json /app/packages/twenty-ui/
|
COPY ./packages/twenty-ui/package.json /app/packages/twenty-ui/
|
||||||
|
COPY ./packages/twenty-shared/package.json /app/packages/twenty-shared/
|
||||||
COPY ./packages/twenty-front/package.json /app/packages/twenty-front/
|
COPY ./packages/twenty-front/package.json /app/packages/twenty-front/
|
||||||
|
|
||||||
# Install all dependencies
|
# Install all dependencies
|
||||||
@@ -22,6 +24,7 @@ FROM common-deps as twenty-server-build
|
|||||||
|
|
||||||
# Copy sourcecode after installing dependences to accelerate subsequents builds
|
# Copy sourcecode after installing dependences to accelerate subsequents builds
|
||||||
COPY ./packages/twenty-emails /app/packages/twenty-emails
|
COPY ./packages/twenty-emails /app/packages/twenty-emails
|
||||||
|
COPY ./packages/twenty-shared /app/packages/twenty-shared
|
||||||
COPY ./packages/twenty-server /app/packages/twenty-server
|
COPY ./packages/twenty-server /app/packages/twenty-server
|
||||||
|
|
||||||
RUN npx nx run twenty-server:build
|
RUN npx nx run twenty-server:build
|
||||||
@@ -31,7 +34,7 @@ RUN mv /app/packages/twenty-server/dist/package.json /app/packages/twenty-server
|
|||||||
RUN rm -rf /app/packages/twenty-server/dist
|
RUN rm -rf /app/packages/twenty-server/dist
|
||||||
RUN mv /app/packages/twenty-server/build /app/packages/twenty-server/dist
|
RUN mv /app/packages/twenty-server/build /app/packages/twenty-server/dist
|
||||||
|
|
||||||
RUN yarn workspaces focus --production twenty-emails twenty-server
|
RUN yarn workspaces focus --production twenty-emails twenty-shared twenty-server
|
||||||
|
|
||||||
|
|
||||||
# Build the front
|
# Build the front
|
||||||
@@ -41,6 +44,7 @@ ARG REACT_APP_SERVER_BASE_URL
|
|||||||
|
|
||||||
COPY ./packages/twenty-front /app/packages/twenty-front
|
COPY ./packages/twenty-front /app/packages/twenty-front
|
||||||
COPY ./packages/twenty-ui /app/packages/twenty-ui
|
COPY ./packages/twenty-ui /app/packages/twenty-ui
|
||||||
|
COPY ./packages/twenty-shared /app/packages/twenty-shared
|
||||||
RUN npx nx build twenty-front
|
RUN npx nx build twenty-front
|
||||||
|
|
||||||
|
|
||||||
@@ -50,15 +54,19 @@ FROM node:18.17.1-alpine as twenty
|
|||||||
# Used to run healthcheck in docker
|
# Used to run healthcheck in docker
|
||||||
RUN apk add --no-cache curl jq
|
RUN apk add --no-cache curl jq
|
||||||
|
|
||||||
|
RUN npm install -g tsx
|
||||||
|
|
||||||
|
RUN apk add --no-cache postgresql-client
|
||||||
|
|
||||||
COPY ./packages/twenty-docker/twenty/entrypoint.sh /app/entrypoint.sh
|
COPY ./packages/twenty-docker/twenty/entrypoint.sh /app/entrypoint.sh
|
||||||
RUN chmod +x /app/entrypoint.sh
|
RUN chmod +x /app/entrypoint.sh
|
||||||
|
|
||||||
WORKDIR /app/packages/twenty-server
|
WORKDIR /app/packages/twenty-server
|
||||||
|
|
||||||
ARG REACT_APP_SERVER_BASE_URL
|
ARG REACT_APP_SERVER_BASE_URL
|
||||||
ENV REACT_APP_SERVER_BASE_URL $REACT_APP_SERVER_BASE_URL
|
ENV REACT_APP_SERVER_BASE_URL $REACT_APP_SERVER_BASE_URL
|
||||||
ARG SENTRY_RELEASE
|
|
||||||
ENV SENTRY_RELEASE $SENTRY_RELEASE
|
ARG APP_VERSION
|
||||||
|
ENV APP_VERSION $APP_VERSION
|
||||||
|
|
||||||
# Copy built applications from previous stages
|
# Copy built applications from previous stages
|
||||||
COPY --chown=1000 --from=twenty-server-build /app /app
|
COPY --chown=1000 --from=twenty-server-build /app /app
|
||||||
@@ -69,8 +77,8 @@ COPY --chown=1000 --from=twenty-front-build /app/packages/twenty-front/build /ap
|
|||||||
LABEL org.opencontainers.image.source=https://github.com/twentyhq/twenty
|
LABEL org.opencontainers.image.source=https://github.com/twentyhq/twenty
|
||||||
LABEL org.opencontainers.image.description="This image provides a consistent and reproducible environment for the backend and frontend, ensuring it deploys faster and runs the same way regardless of the deployment environment."
|
LABEL org.opencontainers.image.description="This image provides a consistent and reproducible environment for the backend and frontend, ensuring it deploys faster and runs the same way regardless of the deployment environment."
|
||||||
|
|
||||||
RUN mkdir /app/.local-storage
|
RUN mkdir -p /app/.local-storage /app/packages/twenty-server/.local-storage && \
|
||||||
RUN chown -R 1000 /app
|
chown -R 1000:1000 /app
|
||||||
|
|
||||||
# Use non root user with uid 1000
|
# Use non root user with uid 1000
|
||||||
USER 1000
|
USER 1000
|
||||||
|
|||||||
@@ -1,17 +1,33 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
setup_and_migrate_db() {
|
||||||
|
if [ "${DISABLE_DB_MIGRATIONS}" = "true" ]; then
|
||||||
|
echo "Database setup and migrations are disabled, skipping..."
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
# Check if the initialization has already been done and that we enabled automatic migration
|
|
||||||
if [ "${ENABLE_DB_MIGRATIONS}" = "true" ] && [ ! -f /app/docker-data/db_status ]; then
|
|
||||||
echo "Running database setup and migrations..."
|
echo "Running database setup and migrations..."
|
||||||
|
PGUSER=$(echo $PG_DATABASE_URL | awk -F '//' '{print $2}' | awk -F ':' '{print $1}')
|
||||||
|
PGPASS=$(echo $PG_DATABASE_URL | awk -F ':' '{print $3}' | awk -F '@' '{print $1}')
|
||||||
|
PGHOST=$(echo $PG_DATABASE_URL | awk -F '@' '{print $2}' | awk -F ':' '{print $1}')
|
||||||
|
PGPORT=$(echo $PG_DATABASE_URL | awk -F ':' '{print $4}' | awk -F '/' '{print $1}')
|
||||||
|
PGDATABASE=$(echo $PG_DATABASE_URL | awk -F ':' '{print $4}' | awk -F '/' '{print $2}')
|
||||||
|
|
||||||
# Run setup and migration scripts
|
# Creating the database if it doesn't exist
|
||||||
NODE_OPTIONS="--max-old-space-size=1500" npx ts-node ./scripts/setup-db.ts
|
db_count=$(PGPASSWORD=${PGPASS} psql -h ${PGHOST} -p ${PGPORT} -U ${PGUSER} -d postgres -tAc "SELECT COUNT(*) FROM pg_database WHERE datname = '${PGDATABASE}'")
|
||||||
yarn database:migrate:prod
|
if [ "$db_count" = "0" ]; then
|
||||||
|
echo "Database ${PGDATABASE} does not exist, creating..."
|
||||||
|
PGPASSWORD=${PGPASS} psql -h ${PGHOST} -p ${PGPORT} -U ${PGUSER} -d postgres -c "CREATE DATABASE \"${PGDATABASE}\""
|
||||||
|
|
||||||
# Mark initialization as done
|
# Run setup and migration scripts
|
||||||
echo "Successfuly migrated DB!"
|
NODE_OPTIONS="--max-old-space-size=1500" tsx ./scripts/setup-db.ts
|
||||||
touch /app/docker-data/db_status
|
fi
|
||||||
fi
|
|
||||||
|
yarn command:prod upgrade
|
||||||
|
echo "Successfully migrated DB!"
|
||||||
|
}
|
||||||
|
setup_and_migrate_db
|
||||||
|
|
||||||
# Continue with the original Docker command
|
# Continue with the original Docker command
|
||||||
exec "$@"
|
exec "$@"
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import utils from "../utils.js";
|
||||||
|
|
||||||
|
await utils.cloneOrPullRepo({ repo: "git@github.com:twentyhq/twenty.git" });
|
||||||
|
await utils.copyDir("./repo/packages/twenty-docker", "./code");
|
||||||
|
|
||||||
|
await utils.removeContainerNames("./code/docker-compose.yml");
|
||||||
|
await utils.removePorts("./code/docker-compose.yml");
|
||||||
|
|
||||||
|
await utils.searchReplace(
|
||||||
|
"./code/.env.example",
|
||||||
|
"#REDIS_URL=redis://redis:6379",
|
||||||
|
"REDIS_URL=redis://redis:6379"
|
||||||
|
);
|
||||||
|
|
||||||
|
await utils.searchReplace(
|
||||||
|
"./code/.env.example",
|
||||||
|
"SERVER_URL=http://localhost:3000",
|
||||||
|
"SERVER_URL=https://$(PRIMARY_DOMAIN)"
|
||||||
|
);
|
||||||
|
|
||||||
|
await utils.searchReplace(
|
||||||
|
"./code/.env.example",
|
||||||
|
"# APP_SECRET=replace_me_with_a_random_string",
|
||||||
|
"APP_SECRET=replace_me_with_a_random_string"
|
||||||
|
);
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import { execa } from "execa";
|
||||||
|
import { glob } from "glob";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
const files = await glob("*/update.js", { absolute: true });
|
||||||
|
|
||||||
|
for (const file of files) {
|
||||||
|
console.log(`Executing ${file}`);
|
||||||
|
|
||||||
|
await execa("node", ["update.js"], {
|
||||||
|
stdio: "inherit",
|
||||||
|
cwd: path.dirname(file),
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`--------------------------------`);
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import { execa } from "execa";
|
||||||
|
import fs from "fs";
|
||||||
|
import yaml from "yaml";
|
||||||
|
|
||||||
|
async function cloneOrPullRepo({
|
||||||
|
repo,
|
||||||
|
path = "./repo",
|
||||||
|
branch = "main",
|
||||||
|
depth = 1,
|
||||||
|
}) {
|
||||||
|
if (!fs.existsSync(path)) {
|
||||||
|
console.log(`Cloning ${repo} into ${path}`);
|
||||||
|
await execa(
|
||||||
|
"git",
|
||||||
|
[
|
||||||
|
"clone",
|
||||||
|
["--depth", depth],
|
||||||
|
["--branch", branch],
|
||||||
|
"--single-branch",
|
||||||
|
repo,
|
||||||
|
path,
|
||||||
|
].flat()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.log(`Pulling ${repo} into ${path}`);
|
||||||
|
await execa("git", ["pull"], { cwd: path });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removeContainerNames(path) {
|
||||||
|
console.log(`Removing container names from ${path}`);
|
||||||
|
|
||||||
|
const file = await fs.promises.readFile(path, "utf8");
|
||||||
|
const document = yaml.parseDocument(file);
|
||||||
|
|
||||||
|
document.get("services").items.forEach((item) => {
|
||||||
|
item.value.delete("container_name");
|
||||||
|
});
|
||||||
|
|
||||||
|
await fs.promises.writeFile(path, document.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removePorts(path) {
|
||||||
|
console.log(`Removing ports from ${path}`);
|
||||||
|
|
||||||
|
const file = await fs.promises.readFile(path, "utf8");
|
||||||
|
const document = yaml.parseDocument(file);
|
||||||
|
|
||||||
|
document.get("services").items.forEach((item) => {
|
||||||
|
item.value.delete("ports");
|
||||||
|
});
|
||||||
|
|
||||||
|
await fs.promises.writeFile(path, document.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
async function copyDir(src, dest) {
|
||||||
|
console.log(`Copying ${src} to ${dest}`);
|
||||||
|
|
||||||
|
await execa("rm", ["-rf", dest]);
|
||||||
|
await execa("cp", ["-r", src, dest]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function downloadFile(url, dest) {
|
||||||
|
console.log(`Downloading ${url} to ${dest}`);
|
||||||
|
|
||||||
|
await execa("curl", ["-s", url, "-o", dest]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function renameFile(src, dest) {
|
||||||
|
console.log(`Renaming ${src} to ${dest}`);
|
||||||
|
|
||||||
|
await execa("mv", [src, dest]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function searchReplace(path, search, replace) {
|
||||||
|
console.log(`Searching and replacing ${search} with ${replace} in ${path}`);
|
||||||
|
|
||||||
|
const file = await fs.promises.readFile(path, "utf8");
|
||||||
|
const newFile = file.replaceAll(search, replace);
|
||||||
|
|
||||||
|
await fs.promises.writeFile(path, newFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
cloneOrPullRepo,
|
||||||
|
removeContainerNames,
|
||||||
|
removePorts,
|
||||||
|
copyDir,
|
||||||
|
downloadFile,
|
||||||
|
renameFile,
|
||||||
|
searchReplace,
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user