Dify
Dify is an open-source LLM app development platform. Build AI workflows, RAG pipelines, agents and chatbots with a visual interface and publish them as APIs or web apps.
Configuration
# Dify - open-source LLM app development platform
# Adapted from the official docker/docker-compose.yaml (tag 1.15.0).
# Minimal functional stack: api + worker + worker_beat + web + postgres
# (pgvector, reused as the vector store) + redis + sandbox + ssrf_proxy
# + plugin_daemon, fronted by a lightweight internal nginx gateway that
# mirrors the upstream path routing (TLS terminates at Traefik).
x-shared-api-env: &shared-api-env
LOG_LEVEL: INFO
DEPLOY_ENV: PRODUCTION
SECRET_KEY: ${SECRET_KEY}
MIGRATION_ENABLED: "true"
# Public URLs - a single domain, path-routed like the upstream nginx
CONSOLE_API_URL: https://${DIFY_DOMAIN}
CONSOLE_WEB_URL: https://${DIFY_DOMAIN}
SERVICE_API_URL: https://${DIFY_DOMAIN}
APP_API_URL: https://${DIFY_DOMAIN}
APP_WEB_URL: https://${DIFY_DOMAIN}
FILES_URL: https://${DIFY_DOMAIN}
INTERNAL_FILES_URL: http://api:5001
TRIGGER_URL: https://${DIFY_DOMAIN}
ENDPOINT_URL_TEMPLATE: https://${DIFY_DOMAIN}/e/{hook_id}
# The dedicated api_websocket collaboration service is not deployed
ENABLE_COLLABORATION_MODE: "false"
WEB_API_CORS_ALLOW_ORIGINS: "*"
CONSOLE_CORS_ALLOW_ORIGINS: "*"
# PostgreSQL
DB_USERNAME: postgres
DB_PASSWORD: ${POSTGRES_PASSWORD}
DB_HOST: db
DB_PORT: "5432"
DB_DATABASE: dify
# Redis / Celery
REDIS_HOST: redis
REDIS_PORT: "6379"
REDIS_PASSWORD: ${REDIS_PASSWORD}
REDIS_DB: "0"
CELERY_BROKER_URL: redis://:${REDIS_PASSWORD}@redis:6379/1
# File storage on a local volume
STORAGE_TYPE: opendal
OPENDAL_SCHEME: fs
OPENDAL_FS_ROOT: storage
# Vector store: pgvector, reusing the same PostgreSQL instance
VECTOR_STORE: pgvector
PGVECTOR_HOST: db
PGVECTOR_PORT: "5432"
PGVECTOR_USER: postgres
PGVECTOR_PASSWORD: ${POSTGRES_PASSWORD}
PGVECTOR_DATABASE: dify
PGVECTOR_MIN_CONNECTION: "1"
PGVECTOR_MAX_CONNECTION: "5"
# Code execution sandbox
CODE_EXECUTION_ENDPOINT: http://sandbox:8194
CODE_EXECUTION_API_KEY: ${SANDBOX_API_KEY}
# SSRF proxy (squid) for user-triggered outbound requests
SSRF_PROXY_HTTP_URL: http://ssrf_proxy:3128
SSRF_PROXY_HTTPS_URL: http://ssrf_proxy:3128
# Plugin daemon (model providers / tools are plugins since Dify 1.0)
PLUGIN_DAEMON_URL: http://plugin_daemon:5002
PLUGIN_DAEMON_KEY: ${PLUGIN_DAEMON_KEY}
INNER_API_KEY_FOR_PLUGIN: ${PLUGIN_INNER_API_KEY}
PLUGIN_MAX_PACKAGE_SIZE: "52428800"
PLUGIN_REMOTE_INSTALL_HOST: localhost
PLUGIN_REMOTE_INSTALL_PORT: "5003"
MARKETPLACE_ENABLED: "true"
MARKETPLACE_API_URL: https://marketplace.dify.ai
services:
nginx:
image: nginx:1.27-alpine
restart: always
volumes:
- ../files/dify-nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
api:
condition: service_healthy
web:
condition: service_started
plugin_daemon:
condition: service_started
# The dify-api image runs as the non-root user 1001, so the shared
# storage volume has to be handed over to it once (same trick as the
# upstream init_permissions container).
init_permissions:
image: busybox:1.36
command:
- sh
- -c
- |
FLAG_FILE="/app/api/storage/.init_permissions"
if [ -f "$$FLAG_FILE" ]; then
echo "Permissions already initialized."
exit 0
fi
echo "Initializing permissions for /app/api/storage"
chown -R 1001:1001 /app/api/storage && touch "$$FLAG_FILE"
volumes:
- dify-app-storage:/app/api/storage
restart: "no"
api:
image: langgenius/dify-api:1.15.0
restart: always
environment:
<<: *shared-api-env
MODE: api
depends_on:
init_permissions:
condition: service_completed_successfully
db:
condition: service_healthy
redis:
condition: service_healthy
volumes:
- dify-app-storage:/app/api/storage
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5001/health"]
interval: 15s
timeout: 5s
retries: 20
start_period: 120s
worker:
image: langgenius/dify-api:1.15.0
restart: always
environment:
<<: *shared-api-env
MODE: worker
depends_on:
init_permissions:
condition: service_completed_successfully
db:
condition: service_healthy
redis:
condition: service_healthy
volumes:
- dify-app-storage:/app/api/storage
worker_beat:
image: langgenius/dify-api:1.15.0
restart: always
environment:
<<: *shared-api-env
MODE: beat
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
web:
image: langgenius/dify-web:1.15.0
restart: always
environment:
CONSOLE_API_URL: https://${DIFY_DOMAIN}
APP_API_URL: https://${DIFY_DOMAIN}
SERVER_CONSOLE_API_URL: http://api:5001
ENABLE_COLLABORATION_MODE: "false"
MARKETPLACE_API_URL: https://marketplace.dify.ai
MARKETPLACE_URL: https://marketplace.dify.ai
NEXT_TELEMETRY_DISABLED: "1"
db:
image: pgvector/pgvector:pg16
restart: always
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: dify
PGDATA: /var/lib/postgresql/data/pgdata
volumes:
- dify-db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d dify"]
interval: 5s
timeout: 3s
retries: 30
redis:
image: redis:6-alpine
restart: always
environment:
REDISCLI_AUTH: ${REDIS_PASSWORD}
command: redis-server --requirepass ${REDIS_PASSWORD}
volumes:
- dify-redis-data:/data
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep -q PONG"]
interval: 5s
timeout: 3s
retries: 30
sandbox:
image: langgenius/dify-sandbox:0.2.15
restart: always
environment:
API_KEY: ${SANDBOX_API_KEY}
GIN_MODE: release
WORKER_TIMEOUT: "15"
ENABLE_NETWORK: "true"
HTTP_PROXY: http://ssrf_proxy:3128
HTTPS_PROXY: http://ssrf_proxy:3128
SANDBOX_PORT: "8194"
volumes:
- dify-sandbox-deps:/dependencies
ssrf_proxy:
image: ubuntu/squid:latest
restart: always
volumes:
- ../files/dify-squid.conf:/etc/squid/squid.conf:ro
plugin_daemon:
image: langgenius/dify-plugin-daemon:0.6.3-local
restart: always
environment:
DB_HOST: db
DB_PORT: "5432"
DB_USERNAME: postgres
DB_PASSWORD: ${POSTGRES_PASSWORD}
DB_DATABASE: dify_plugin
DB_SSL_MODE: disable
REDIS_HOST: redis
REDIS_PORT: "6379"
REDIS_PASSWORD: ${REDIS_PASSWORD}
SERVER_PORT: "5002"
SERVER_KEY: ${PLUGIN_DAEMON_KEY}
MAX_PLUGIN_PACKAGE_SIZE: "52428800"
DIFY_INNER_API_URL: http://api:5001
DIFY_INNER_API_KEY: ${PLUGIN_INNER_API_KEY}
PLUGIN_REMOTE_INSTALLING_HOST: 0.0.0.0
PLUGIN_REMOTE_INSTALLING_PORT: "5003"
PLUGIN_WORKING_PATH: /app/storage/cwd
FORCE_VERIFYING_SIGNATURE: "true"
PYTHON_ENV_INIT_TIMEOUT: "120"
PLUGIN_MAX_EXECUTION_TIMEOUT: "600"
PLUGIN_STORAGE_TYPE: local
PLUGIN_STORAGE_LOCAL_ROOT: /app/storage
PLUGIN_INSTALLED_PATH: plugin
PLUGIN_PACKAGE_CACHE_PATH: plugin_packages
PLUGIN_MEDIA_CACHE_PATH: assets
volumes:
- dify-plugin-storage:/app/storage
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
volumes:
dify-app-storage:
dify-db-data:
dify-redis-data:
dify-sandbox-deps:
dify-plugin-storage:[variables]
main_domain = "${domain}"
secret_key = "${base64:42}"
postgres_password = "${password:32}"
redis_password = "${password:32}"
sandbox_api_key = "${password:32}"
plugin_daemon_key = "${base64:42}"
plugin_inner_api_key = "${base64:42}"
[config]
env = [
"DIFY_DOMAIN=${main_domain}",
"SECRET_KEY=${secret_key}",
"POSTGRES_PASSWORD=${postgres_password}",
"REDIS_PASSWORD=${redis_password}",
"SANDBOX_API_KEY=${sandbox_api_key}",
"PLUGIN_DAEMON_KEY=${plugin_daemon_key}",
"PLUGIN_INNER_API_KEY=${plugin_inner_api_key}",
]
[[config.domains]]
serviceName = "nginx"
port = 80
host = "${main_domain}"
# Internal nginx gateway replicating the upstream Dify nginx routing
# (TLS terminates at Traefik, which forwards everything to this nginx).
[[config.mounts]]
filePath = "dify-nginx.conf"
content = '''
map $http_x_forwarded_proto $dify_forwarded_proto {
default $http_x_forwarded_proto;
"" $scheme;
}
server {
listen 80;
server_name _;
client_max_body_size 100M;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $dify_forwarded_proto;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
location /console/api { proxy_pass http://api:5001; }
location /api { proxy_pass http://api:5001; }
location /v1 { proxy_pass http://api:5001; }
location /openapi { proxy_pass http://api:5001; }
location /files { proxy_pass http://api:5001; }
location /mcp { proxy_pass http://api:5001; }
location /triggers { proxy_pass http://api:5001; }
location /explore { proxy_pass http://web:3000; }
location /e/ {
proxy_pass http://plugin_daemon:5002;
# nginx drops inherited proxy_set_header directives as soon as a
# location defines its own, so the shared ones are repeated here.
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $dify_forwarded_proto;
proxy_set_header Connection "";
proxy_set_header Dify-Hook-Url $dify_forwarded_proto://$host$request_uri;
}
location / { proxy_pass http://web:3000; }
}
'''
# Squid SSRF proxy configuration, rendered from the upstream
# docker/ssrf_proxy/squid.conf.template with its default values.
[[config.mounts]]
filePath = "dify-squid.conf"
content = '''
acl client_localnet src 0.0.0.1-0.255.255.255
acl client_localnet src 10.0.0.0/8
acl client_localnet src 100.64.0.0/10
acl client_localnet src 169.254.0.0/16
acl client_localnet src 172.16.0.0/12
acl client_localnet src 192.168.0.0/16
acl client_localnet src fc00::/7
acl client_localnet src fe80::/10
acl to_private_networks dst 0.0.0.0/8
acl to_private_networks dst 10.0.0.0/8
acl to_private_networks dst 100.64.0.0/10
acl to_private_networks dst 127.0.0.0/8
acl to_private_networks dst 169.254.0.0/16
acl to_private_networks dst 172.16.0.0/12
acl to_private_networks dst 192.168.0.0/16
acl to_private_networks dst 224.0.0.0/4
acl to_private_networks dst 240.0.0.0/4
acl to_private_networks dst ::/128
acl to_private_networks dst ::1/128
acl to_private_networks dst ::ffff:0:0/96
acl to_private_networks dst ::/96
acl to_private_networks dst fc00::/7
acl to_private_networks dst fe80::/10
acl SSL_ports port 443
acl Safe_ports port 80
acl Safe_ports port 21
acl Safe_ports port 443
acl Safe_ports port 70
acl Safe_ports port 210
acl Safe_ports port 1025-65535
acl Safe_ports port 280
acl Safe_ports port 488
acl Safe_ports port 591
acl Safe_ports port 777
acl CONNECT method CONNECT
acl allowed_domains dstdomain .marketplace.dify.ai
http_port 3128
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localhost manager
http_access deny manager
http_access deny to_private_networks
http_access allow allowed_domains
http_access allow client_localnet
http_access allow localhost
http_access deny all
tcp_outgoing_address 0.0.0.0
coredump_dir /var/spool/squid
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern . 0 20% 4320
client_request_buffer_max_size 100 MB
max_filedescriptors 65536
connect_timeout 30 seconds
request_timeout 2 minutes
read_timeout 2 minutes
client_lifetime 5 minutes
shutdown_lifetime 30 seconds
server_persistent_connections on
client_persistent_connections on
persistent_request_timeout 30 seconds
pconn_timeout 1 minute
client_db on
server_idle_pconn_timeout 2 minutes
client_idle_pconn_timeout 2 minutes
quick_abort_min 16 KB
quick_abort_max 16 MB
quick_abort_pct 95
memory_cache_mode disk
cache_mem 256 MB
maximum_object_size_in_memory 512 KB
dns_timeout 30 seconds
dns_retransmit_interval 5 seconds
logformat dify_log %ts.%03tu %6tr %>a %Ss/%03>Hs %<st %rm %ru %[un %Sh/%<a %mt
access_log daemon:/var/log/squid/access.log dify_log
logfile_rotate 10
'''Base64
To import this template in Dokploy: create a Compose service → Advanced → Base64 import and paste the content below:
ewogICJjb21wb3NlIjogIiMgRGlmeSAtIG9wZW4tc291cmNlIExMTSBhcHAgZGV2ZWxvcG1lbnQgcGxhdGZvcm1cbiMgQWRhcHRlZCBmcm9tIHRoZSBvZmZpY2lhbCBkb2NrZXIvZG9ja2VyLWNvbXBvc2UueWFtbCAodGFnIDEuMTUuMCkuXG4jIE1pbmltYWwgZnVuY3Rpb25hbCBzdGFjazogYXBpICsgd29ya2VyICsgd29ya2VyX2JlYXQgKyB3ZWIgKyBwb3N0Z3Jlc1xuIyAocGd2ZWN0b3IsIHJldXNlZCBhcyB0aGUgdmVjdG9yIHN0b3JlKSArIHJlZGlzICsgc2FuZGJveCArIHNzcmZfcHJveHlcbiMgKyBwbHVnaW5fZGFlbW9uLCBmcm9udGVkIGJ5IGEgbGlnaHR3ZWlnaHQgaW50ZXJuYWwgbmdpbnggZ2F0ZXdheSB0aGF0XG4jIG1pcnJvcnMgdGhlIHVwc3RyZWFtIHBhdGggcm91dGluZyAoVExTIHRlcm1pbmF0ZXMgYXQgVHJhZWZpaykuXG5cbngtc2hhcmVkLWFwaS1lbnY6ICZzaGFyZWQtYXBpLWVudlxuICBMT0dfTEVWRUw6IElORk9cbiAgREVQTE9ZX0VOVjogUFJPRFVDVElPTlxuICBTRUNSRVRfS0VZOiAke1NFQ1JFVF9LRVl9XG4gIE1JR1JBVElPTl9FTkFCTEVEOiBcInRydWVcIlxuICAjIFB1YmxpYyBVUkxzIC0gYSBzaW5nbGUgZG9tYWluLCBwYXRoLXJvdXRlZCBsaWtlIHRoZSB1cHN0cmVhbSBuZ2lueFxuICBDT05TT0xFX0FQSV9VUkw6IGh0dHBzOi8vJHtESUZZX0RPTUFJTn1cbiAgQ09OU09MRV9XRUJfVVJMOiBodHRwczovLyR7RElGWV9ET01BSU59XG4gIFNFUlZJQ0VfQVBJX1VSTDogaHR0cHM6Ly8ke0RJRllfRE9NQUlOfVxuICBBUFBfQVBJX1VSTDogaHR0cHM6Ly8ke0RJRllfRE9NQUlOfVxuICBBUFBfV0VCX1VSTDogaHR0cHM6Ly8ke0RJRllfRE9NQUlOfVxuICBGSUxFU19VUkw6IGh0dHBzOi8vJHtESUZZX0RPTUFJTn1cbiAgSU5URVJOQUxfRklMRVNfVVJMOiBodHRwOi8vYXBpOjUwMDFcbiAgVFJJR0dFUl9VUkw6IGh0dHBzOi8vJHtESUZZX0RPTUFJTn1cbiAgRU5EUE9JTlRfVVJMX1RFTVBMQVRFOiBodHRwczovLyR7RElGWV9ET01BSU59L2Uve2hvb2tfaWR9XG4gICMgVGhlIGRlZGljYXRlZCBhcGlfd2Vic29ja2V0IGNvbGxhYm9yYXRpb24gc2VydmljZSBpcyBub3QgZGVwbG95ZWRcbiAgRU5BQkxFX0NPTExBQk9SQVRJT05fTU9ERTogXCJmYWxzZVwiXG4gIFdFQl9BUElfQ09SU19BTExPV19PUklHSU5TOiBcIipcIlxuICBDT05TT0xFX0NPUlNfQUxMT1dfT1JJR0lOUzogXCIqXCJcbiAgIyBQb3N0Z3JlU1FMXG4gIERCX1VTRVJOQU1FOiBwb3N0Z3Jlc1xuICBEQl9QQVNTV09SRDogJHtQT1NUR1JFU19QQVNTV09SRH1cbiAgREJfSE9TVDogZGJcbiAgREJfUE9SVDogXCI1NDMyXCJcbiAgREJfREFUQUJBU0U6IGRpZnlcbiAgIyBSZWRpcyAvIENlbGVyeVxuICBSRURJU19IT1NUOiByZWRpc1xuICBSRURJU19QT1JUOiBcIjYzNzlcIlxuICBSRURJU19QQVNTV09SRDogJHtSRURJU19QQVNTV09SRH1cbiAgUkVESVNfREI6IFwiMFwiXG4gIENFTEVSWV9CUk9LRVJfVVJMOiByZWRpczovLzoke1JFRElTX1BBU1NXT1JEfUByZWRpczo2Mzc5LzFcbiAgIyBGaWxlIHN0b3JhZ2Ugb24gYSBsb2NhbCB2b2x1bWVcbiAgU1RPUkFHRV9UWVBFOiBvcGVuZGFsXG4gIE9QRU5EQUxfU0NIRU1FOiBmc1xuICBPUEVOREFMX0ZTX1JPT1Q6IHN0b3JhZ2VcbiAgIyBWZWN0b3Igc3RvcmU6IHBndmVjdG9yLCByZXVzaW5nIHRoZSBzYW1lIFBvc3RncmVTUUwgaW5zdGFuY2VcbiAgVkVDVE9SX1NUT1JFOiBwZ3ZlY3RvclxuICBQR1ZFQ1RPUl9IT1NUOiBkYlxuICBQR1ZFQ1RPUl9QT1JUOiBcIjU0MzJcIlxuICBQR1ZFQ1RPUl9VU0VSOiBwb3N0Z3Jlc1xuICBQR1ZFQ1RPUl9QQVNTV09SRDogJHtQT1NUR1JFU19QQVNTV09SRH1cbiAgUEdWRUNUT1JfREFUQUJBU0U6IGRpZnlcbiAgUEdWRUNUT1JfTUlOX0NPTk5FQ1RJT046IFwiMVwiXG4gIFBHVkVDVE9SX01BWF9DT05ORUNUSU9OOiBcIjVcIlxuICAjIENvZGUgZXhlY3V0aW9uIHNhbmRib3hcbiAgQ09ERV9FWEVDVVRJT05fRU5EUE9JTlQ6IGh0dHA6Ly9zYW5kYm94OjgxOTRcbiAgQ09ERV9FWEVDVVRJT05fQVBJX0tFWTogJHtTQU5EQk9YX0FQSV9LRVl9XG4gICMgU1NSRiBwcm94eSAoc3F1aWQpIGZvciB1c2VyLXRyaWdnZXJlZCBvdXRib3VuZCByZXF1ZXN0c1xuICBTU1JGX1BST1hZX0hUVFBfVVJMOiBodHRwOi8vc3NyZl9wcm94eTozMTI4XG4gIFNTUkZfUFJPWFlfSFRUUFNfVVJMOiBodHRwOi8vc3NyZl9wcm94eTozMTI4XG4gICMgUGx1Z2luIGRhZW1vbiAobW9kZWwgcHJvdmlkZXJzIC8gdG9vbHMgYXJlIHBsdWdpbnMgc2luY2UgRGlmeSAxLjApXG4gIFBMVUdJTl9EQUVNT05fVVJMOiBodHRwOi8vcGx1Z2luX2RhZW1vbjo1MDAyXG4gIFBMVUdJTl9EQUVNT05fS0VZOiAke1BMVUdJTl9EQUVNT05fS0VZfVxuICBJTk5FUl9BUElfS0VZX0ZPUl9QTFVHSU46ICR7UExVR0lOX0lOTkVSX0FQSV9LRVl9XG4gIFBMVUdJTl9NQVhfUEFDS0FHRV9TSVpFOiBcIjUyNDI4ODAwXCJcbiAgUExVR0lOX1JFTU9URV9JTlNUQUxMX0hPU1Q6IGxvY2FsaG9zdFxuICBQTFVHSU5fUkVNT1RFX0lOU1RBTExfUE9SVDogXCI1MDAzXCJcbiAgTUFSS0VUUExBQ0VfRU5BQkxFRDogXCJ0cnVlXCJcbiAgTUFSS0VUUExBQ0VfQVBJX1VSTDogaHR0cHM6Ly9tYXJrZXRwbGFjZS5kaWZ5LmFpXG5cbnNlcnZpY2VzOlxuICBuZ2lueDpcbiAgICBpbWFnZTogbmdpbng6MS4yNy1hbHBpbmVcbiAgICByZXN0YXJ0OiBhbHdheXNcbiAgICB2b2x1bWVzOlxuICAgICAgLSAuLi9maWxlcy9kaWZ5LW5naW54LmNvbmY6L2V0Yy9uZ2lueC9jb25mLmQvZGVmYXVsdC5jb25mOnJvXG4gICAgZGVwZW5kc19vbjpcbiAgICAgIGFwaTpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICAgIHdlYjpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWRcbiAgICAgIHBsdWdpbl9kYWVtb246XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9zdGFydGVkXG5cbiAgIyBUaGUgZGlmeS1hcGkgaW1hZ2UgcnVucyBhcyB0aGUgbm9uLXJvb3QgdXNlciAxMDAxLCBzbyB0aGUgc2hhcmVkXG4gICMgc3RvcmFnZSB2b2x1bWUgaGFzIHRvIGJlIGhhbmRlZCBvdmVyIHRvIGl0IG9uY2UgKHNhbWUgdHJpY2sgYXMgdGhlXG4gICMgdXBzdHJlYW0gaW5pdF9wZXJtaXNzaW9ucyBjb250YWluZXIpLlxuICBpbml0X3Blcm1pc3Npb25zOlxuICAgIGltYWdlOiBidXN5Ym94OjEuMzZcbiAgICBjb21tYW5kOlxuICAgICAgLSBzaFxuICAgICAgLSAtY1xuICAgICAgLSB8XG4gICAgICAgIEZMQUdfRklMRT1cIi9hcHAvYXBpL3N0b3JhZ2UvLmluaXRfcGVybWlzc2lvbnNcIlxuICAgICAgICBpZiBbIC1mIFwiJCRGTEFHX0ZJTEVcIiBdOyB0aGVuXG4gICAgICAgICAgZWNobyBcIlBlcm1pc3Npb25zIGFscmVhZHkgaW5pdGlhbGl6ZWQuXCJcbiAgICAgICAgICBleGl0IDBcbiAgICAgICAgZmlcbiAgICAgICAgZWNobyBcIkluaXRpYWxpemluZyBwZXJtaXNzaW9ucyBmb3IgL2FwcC9hcGkvc3RvcmFnZVwiXG4gICAgICAgIGNob3duIC1SIDEwMDE6MTAwMSAvYXBwL2FwaS9zdG9yYWdlICYmIHRvdWNoIFwiJCRGTEFHX0ZJTEVcIlxuICAgIHZvbHVtZXM6XG4gICAgICAtIGRpZnktYXBwLXN0b3JhZ2U6L2FwcC9hcGkvc3RvcmFnZVxuICAgIHJlc3RhcnQ6IFwibm9cIlxuXG4gIGFwaTpcbiAgICBpbWFnZTogbGFuZ2dlbml1cy9kaWZ5LWFwaToxLjE1LjBcbiAgICByZXN0YXJ0OiBhbHdheXNcbiAgICBlbnZpcm9ubWVudDpcbiAgICAgIDw8OiAqc2hhcmVkLWFwaS1lbnZcbiAgICAgIE1PREU6IGFwaVxuICAgIGRlcGVuZHNfb246XG4gICAgICBpbml0X3Blcm1pc3Npb25zOlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfY29tcGxldGVkX3N1Y2Nlc3NmdWxseVxuICAgICAgZGI6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5XG4gICAgICByZWRpczpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICB2b2x1bWVzOlxuICAgICAgLSBkaWZ5LWFwcC1zdG9yYWdlOi9hcHAvYXBpL3N0b3JhZ2VcbiAgICBoZWFsdGhjaGVjazpcbiAgICAgIHRlc3Q6IFtcIkNNRFwiLCBcImN1cmxcIiwgXCItZlwiLCBcImh0dHA6Ly9sb2NhbGhvc3Q6NTAwMS9oZWFsdGhcIl1cbiAgICAgIGludGVydmFsOiAxNXNcbiAgICAgIHRpbWVvdXQ6IDVzXG4gICAgICByZXRyaWVzOiAyMFxuICAgICAgc3RhcnRfcGVyaW9kOiAxMjBzXG5cbiAgd29ya2VyOlxuICAgIGltYWdlOiBsYW5nZ2VuaXVzL2RpZnktYXBpOjEuMTUuMFxuICAgIHJlc3RhcnQ6IGFsd2F5c1xuICAgIGVudmlyb25tZW50OlxuICAgICAgPDw6ICpzaGFyZWQtYXBpLWVudlxuICAgICAgTU9ERTogd29ya2VyXG4gICAgZGVwZW5kc19vbjpcbiAgICAgIGluaXRfcGVybWlzc2lvbnM6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9jb21wbGV0ZWRfc3VjY2Vzc2Z1bGx5XG4gICAgICBkYjpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICAgIHJlZGlzOlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeVxuICAgIHZvbHVtZXM6XG4gICAgICAtIGRpZnktYXBwLXN0b3JhZ2U6L2FwcC9hcGkvc3RvcmFnZVxuXG4gIHdvcmtlcl9iZWF0OlxuICAgIGltYWdlOiBsYW5nZ2VuaXVzL2RpZnktYXBpOjEuMTUuMFxuICAgIHJlc3RhcnQ6IGFsd2F5c1xuICAgIGVudmlyb25tZW50OlxuICAgICAgPDw6ICpzaGFyZWQtYXBpLWVudlxuICAgICAgTU9ERTogYmVhdFxuICAgIGRlcGVuZHNfb246XG4gICAgICBkYjpcbiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHlcbiAgICAgIHJlZGlzOlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeVxuXG4gIHdlYjpcbiAgICBpbWFnZTogbGFuZ2dlbml1cy9kaWZ5LXdlYjoxLjE1LjBcbiAgICByZXN0YXJ0OiBhbHdheXNcbiAgICBlbnZpcm9ubWVudDpcbiAgICAgIENPTlNPTEVfQVBJX1VSTDogaHR0cHM6Ly8ke0RJRllfRE9NQUlOfVxuICAgICAgQVBQX0FQSV9VUkw6IGh0dHBzOi8vJHtESUZZX0RPTUFJTn1cbiAgICAgIFNFUlZFUl9DT05TT0xFX0FQSV9VUkw6IGh0dHA6Ly9hcGk6NTAwMVxuICAgICAgRU5BQkxFX0NPTExBQk9SQVRJT05fTU9ERTogXCJmYWxzZVwiXG4gICAgICBNQVJLRVRQTEFDRV9BUElfVVJMOiBodHRwczovL21hcmtldHBsYWNlLmRpZnkuYWlcbiAgICAgIE1BUktFVFBMQUNFX1VSTDogaHR0cHM6Ly9tYXJrZXRwbGFjZS5kaWZ5LmFpXG4gICAgICBORVhUX1RFTEVNRVRSWV9ESVNBQkxFRDogXCIxXCJcblxuICBkYjpcbiAgICBpbWFnZTogcGd2ZWN0b3IvcGd2ZWN0b3I6cGcxNlxuICAgIHJlc3RhcnQ6IGFsd2F5c1xuICAgIGVudmlyb25tZW50OlxuICAgICAgUE9TVEdSRVNfVVNFUjogcG9zdGdyZXNcbiAgICAgIFBPU1RHUkVTX1BBU1NXT1JEOiAke1BPU1RHUkVTX1BBU1NXT1JEfVxuICAgICAgUE9TVEdSRVNfREI6IGRpZnlcbiAgICAgIFBHREFUQTogL3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhL3BnZGF0YVxuICAgIHZvbHVtZXM6XG4gICAgICAtIGRpZnktZGItZGF0YTovdmFyL2xpYi9wb3N0Z3Jlc3FsL2RhdGFcbiAgICBoZWFsdGhjaGVjazpcbiAgICAgIHRlc3Q6IFtcIkNNRC1TSEVMTFwiLCBcInBnX2lzcmVhZHkgLVUgcG9zdGdyZXMgLWQgZGlmeVwiXVxuICAgICAgaW50ZXJ2YWw6IDVzXG4gICAgICB0aW1lb3V0OiAzc1xuICAgICAgcmV0cmllczogMzBcblxuICByZWRpczpcbiAgICBpbWFnZTogcmVkaXM6Ni1hbHBpbmVcbiAgICByZXN0YXJ0OiBhbHdheXNcbiAgICBlbnZpcm9ubWVudDpcbiAgICAgIFJFRElTQ0xJX0FVVEg6ICR7UkVESVNfUEFTU1dPUkR9XG4gICAgY29tbWFuZDogcmVkaXMtc2VydmVyIC0tcmVxdWlyZXBhc3MgJHtSRURJU19QQVNTV09SRH1cbiAgICB2b2x1bWVzOlxuICAgICAgLSBkaWZ5LXJlZGlzLWRhdGE6L2RhdGFcbiAgICBoZWFsdGhjaGVjazpcbiAgICAgIHRlc3Q6IFtcIkNNRC1TSEVMTFwiLCBcInJlZGlzLWNsaSBwaW5nIHwgZ3JlcCAtcSBQT05HXCJdXG4gICAgICBpbnRlcnZhbDogNXNcbiAgICAgIHRpbWVvdXQ6IDNzXG4gICAgICByZXRyaWVzOiAzMFxuXG4gIHNhbmRib3g6XG4gICAgaW1hZ2U6IGxhbmdnZW5pdXMvZGlmeS1zYW5kYm94OjAuMi4xNVxuICAgIHJlc3RhcnQ6IGFsd2F5c1xuICAgIGVudmlyb25tZW50OlxuICAgICAgQVBJX0tFWTogJHtTQU5EQk9YX0FQSV9LRVl9XG4gICAgICBHSU5fTU9ERTogcmVsZWFzZVxuICAgICAgV09SS0VSX1RJTUVPVVQ6IFwiMTVcIlxuICAgICAgRU5BQkxFX05FVFdPUks6IFwidHJ1ZVwiXG4gICAgICBIVFRQX1BST1hZOiBodHRwOi8vc3NyZl9wcm94eTozMTI4XG4gICAgICBIVFRQU19QUk9YWTogaHR0cDovL3NzcmZfcHJveHk6MzEyOFxuICAgICAgU0FOREJPWF9QT1JUOiBcIjgxOTRcIlxuICAgIHZvbHVtZXM6XG4gICAgICAtIGRpZnktc2FuZGJveC1kZXBzOi9kZXBlbmRlbmNpZXNcblxuICBzc3JmX3Byb3h5OlxuICAgIGltYWdlOiB1YnVudHUvc3F1aWQ6bGF0ZXN0XG4gICAgcmVzdGFydDogYWx3YXlzXG4gICAgdm9sdW1lczpcbiAgICAgIC0gLi4vZmlsZXMvZGlmeS1zcXVpZC5jb25mOi9ldGMvc3F1aWQvc3F1aWQuY29uZjpyb1xuXG4gIHBsdWdpbl9kYWVtb246XG4gICAgaW1hZ2U6IGxhbmdnZW5pdXMvZGlmeS1wbHVnaW4tZGFlbW9uOjAuNi4zLWxvY2FsXG4gICAgcmVzdGFydDogYWx3YXlzXG4gICAgZW52aXJvbm1lbnQ6XG4gICAgICBEQl9IT1NUOiBkYlxuICAgICAgREJfUE9SVDogXCI1NDMyXCJcbiAgICAgIERCX1VTRVJOQU1FOiBwb3N0Z3Jlc1xuICAgICAgREJfUEFTU1dPUkQ6ICR7UE9TVEdSRVNfUEFTU1dPUkR9XG4gICAgICBEQl9EQVRBQkFTRTogZGlmeV9wbHVnaW5cbiAgICAgIERCX1NTTF9NT0RFOiBkaXNhYmxlXG4gICAgICBSRURJU19IT1NUOiByZWRpc1xuICAgICAgUkVESVNfUE9SVDogXCI2Mzc5XCJcbiAgICAgIFJFRElTX1BBU1NXT1JEOiAke1JFRElTX1BBU1NXT1JEfVxuICAgICAgU0VSVkVSX1BPUlQ6IFwiNTAwMlwiXG4gICAgICBTRVJWRVJfS0VZOiAke1BMVUdJTl9EQUVNT05fS0VZfVxuICAgICAgTUFYX1BMVUdJTl9QQUNLQUdFX1NJWkU6IFwiNTI0Mjg4MDBcIlxuICAgICAgRElGWV9JTk5FUl9BUElfVVJMOiBodHRwOi8vYXBpOjUwMDFcbiAgICAgIERJRllfSU5ORVJfQVBJX0tFWTogJHtQTFVHSU5fSU5ORVJfQVBJX0tFWX1cbiAgICAgIFBMVUdJTl9SRU1PVEVfSU5TVEFMTElOR19IT1NUOiAwLjAuMC4wXG4gICAgICBQTFVHSU5fUkVNT1RFX0lOU1RBTExJTkdfUE9SVDogXCI1MDAzXCJcbiAgICAgIFBMVUdJTl9XT1JLSU5HX1BBVEg6IC9hcHAvc3RvcmFnZS9jd2RcbiAgICAgIEZPUkNFX1ZFUklGWUlOR19TSUdOQVRVUkU6IFwidHJ1ZVwiXG4gICAgICBQWVRIT05fRU5WX0lOSVRfVElNRU9VVDogXCIxMjBcIlxuICAgICAgUExVR0lOX01BWF9FWEVDVVRJT05fVElNRU9VVDogXCI2MDBcIlxuICAgICAgUExVR0lOX1NUT1JBR0VfVFlQRTogbG9jYWxcbiAgICAgIFBMVUdJTl9TVE9SQUdFX0xPQ0FMX1JPT1Q6IC9hcHAvc3RvcmFnZVxuICAgICAgUExVR0lOX0lOU1RBTExFRF9QQVRIOiBwbHVnaW5cbiAgICAgIFBMVUdJTl9QQUNLQUdFX0NBQ0hFX1BBVEg6IHBsdWdpbl9wYWNrYWdlc1xuICAgICAgUExVR0lOX01FRElBX0NBQ0hFX1BBVEg6IGFzc2V0c1xuICAgIHZvbHVtZXM6XG4gICAgICAtIGRpZnktcGx1Z2luLXN0b3JhZ2U6L2FwcC9zdG9yYWdlXG4gICAgZGVwZW5kc19vbjpcbiAgICAgIGRiOlxuICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeVxuICAgICAgcmVkaXM6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5XG5cbnZvbHVtZXM6XG4gIGRpZnktYXBwLXN0b3JhZ2U6XG4gIGRpZnktZGItZGF0YTpcbiAgZGlmeS1yZWRpcy1kYXRhOlxuICBkaWZ5LXNhbmRib3gtZGVwczpcbiAgZGlmeS1wbHVnaW4tc3RvcmFnZTpcbiIsCiAgImNvbmZpZyI6ICJbdmFyaWFibGVzXVxubWFpbl9kb21haW4gPSBcIiR7ZG9tYWlufVwiXG5zZWNyZXRfa2V5ID0gXCIke2Jhc2U2NDo0Mn1cIlxucG9zdGdyZXNfcGFzc3dvcmQgPSBcIiR7cGFzc3dvcmQ6MzJ9XCJcbnJlZGlzX3Bhc3N3b3JkID0gXCIke3Bhc3N3b3JkOjMyfVwiXG5zYW5kYm94X2FwaV9rZXkgPSBcIiR7cGFzc3dvcmQ6MzJ9XCJcbnBsdWdpbl9kYWVtb25fa2V5ID0gXCIke2Jhc2U2NDo0Mn1cIlxucGx1Z2luX2lubmVyX2FwaV9rZXkgPSBcIiR7YmFzZTY0OjQyfVwiXG5cbltjb25maWddXG5lbnYgPSBbXG4gIFwiRElGWV9ET01BSU49JHttYWluX2RvbWFpbn1cIixcbiAgXCJTRUNSRVRfS0VZPSR7c2VjcmV0X2tleX1cIixcbiAgXCJQT1NUR1JFU19QQVNTV09SRD0ke3Bvc3RncmVzX3Bhc3N3b3JkfVwiLFxuICBcIlJFRElTX1BBU1NXT1JEPSR7cmVkaXNfcGFzc3dvcmR9XCIsXG4gIFwiU0FOREJPWF9BUElfS0VZPSR7c2FuZGJveF9hcGlfa2V5fVwiLFxuICBcIlBMVUdJTl9EQUVNT05fS0VZPSR7cGx1Z2luX2RhZW1vbl9rZXl9XCIsXG4gIFwiUExVR0lOX0lOTkVSX0FQSV9LRVk9JHtwbHVnaW5faW5uZXJfYXBpX2tleX1cIixcbl1cblxuW1tjb25maWcuZG9tYWluc11dXG5zZXJ2aWNlTmFtZSA9IFwibmdpbnhcIlxucG9ydCA9IDgwXG5ob3N0ID0gXCIke21haW5fZG9tYWlufVwiXG5cbiMgSW50ZXJuYWwgbmdpbnggZ2F0ZXdheSByZXBsaWNhdGluZyB0aGUgdXBzdHJlYW0gRGlmeSBuZ2lueCByb3V0aW5nXG4jIChUTFMgdGVybWluYXRlcyBhdCBUcmFlZmlrLCB3aGljaCBmb3J3YXJkcyBldmVyeXRoaW5nIHRvIHRoaXMgbmdpbngpLlxuW1tjb25maWcubW91bnRzXV1cbmZpbGVQYXRoID0gXCJkaWZ5LW5naW54LmNvbmZcIlxuY29udGVudCA9ICcnJ1xubWFwICRodHRwX3hfZm9yd2FyZGVkX3Byb3RvICRkaWZ5X2ZvcndhcmRlZF9wcm90byB7XG4gICAgZGVmYXVsdCAkaHR0cF94X2ZvcndhcmRlZF9wcm90bztcbiAgICBcIlwiICAgICAgJHNjaGVtZTtcbn1cblxuc2VydmVyIHtcbiAgICBsaXN0ZW4gODA7XG4gICAgc2VydmVyX25hbWUgXztcblxuICAgIGNsaWVudF9tYXhfYm9keV9zaXplIDEwME07XG5cbiAgICBwcm94eV9zZXRfaGVhZGVyIEhvc3QgJGhvc3Q7XG4gICAgcHJveHlfc2V0X2hlYWRlciBYLUZvcndhcmRlZC1Gb3IgJHByb3h5X2FkZF94X2ZvcndhcmRlZF9mb3I7XG4gICAgcHJveHlfc2V0X2hlYWRlciBYLUZvcndhcmRlZC1Qcm90byAkZGlmeV9mb3J3YXJkZWRfcHJvdG87XG4gICAgcHJveHlfaHR0cF92ZXJzaW9uIDEuMTtcbiAgICBwcm94eV9zZXRfaGVhZGVyIENvbm5lY3Rpb24gXCJcIjtcbiAgICBwcm94eV9idWZmZXJpbmcgb2ZmO1xuICAgIHByb3h5X3JlYWRfdGltZW91dCAzNjAwcztcbiAgICBwcm94eV9zZW5kX3RpbWVvdXQgMzYwMHM7XG5cbiAgICBsb2NhdGlvbiAvY29uc29sZS9hcGkgeyBwcm94eV9wYXNzIGh0dHA6Ly9hcGk6NTAwMTsgfVxuICAgIGxvY2F0aW9uIC9hcGkgICAgICAgICB7IHByb3h5X3Bhc3MgaHR0cDovL2FwaTo1MDAxOyB9XG4gICAgbG9jYXRpb24gL3YxICAgICAgICAgIHsgcHJveHlfcGFzcyBodHRwOi8vYXBpOjUwMDE7IH1cbiAgICBsb2NhdGlvbiAvb3BlbmFwaSAgICAgeyBwcm94eV9wYXNzIGh0dHA6Ly9hcGk6NTAwMTsgfVxuICAgIGxvY2F0aW9uIC9maWxlcyAgICAgICB7IHByb3h5X3Bhc3MgaHR0cDovL2FwaTo1MDAxOyB9XG4gICAgbG9jYXRpb24gL21jcCAgICAgICAgIHsgcHJveHlfcGFzcyBodHRwOi8vYXBpOjUwMDE7IH1cbiAgICBsb2NhdGlvbiAvdHJpZ2dlcnMgICAgeyBwcm94eV9wYXNzIGh0dHA6Ly9hcGk6NTAwMTsgfVxuICAgIGxvY2F0aW9uIC9leHBsb3JlICAgICB7IHByb3h5X3Bhc3MgaHR0cDovL3dlYjozMDAwOyB9XG5cbiAgICBsb2NhdGlvbiAvZS8ge1xuICAgICAgICBwcm94eV9wYXNzIGh0dHA6Ly9wbHVnaW5fZGFlbW9uOjUwMDI7XG4gICAgICAgICMgbmdpbnggZHJvcHMgaW5oZXJpdGVkIHByb3h5X3NldF9oZWFkZXIgZGlyZWN0aXZlcyBhcyBzb29uIGFzIGFcbiAgICAgICAgIyBsb2NhdGlvbiBkZWZpbmVzIGl0cyBvd24sIHNvIHRoZSBzaGFyZWQgb25lcyBhcmUgcmVwZWF0ZWQgaGVyZS5cbiAgICAgICAgcHJveHlfc2V0X2hlYWRlciBIb3N0ICRob3N0O1xuICAgICAgICBwcm94eV9zZXRfaGVhZGVyIFgtRm9yd2FyZGVkLUZvciAkcHJveHlfYWRkX3hfZm9yd2FyZGVkX2ZvcjtcbiAgICAgICAgcHJveHlfc2V0X2hlYWRlciBYLUZvcndhcmRlZC1Qcm90byAkZGlmeV9mb3J3YXJkZWRfcHJvdG87XG4gICAgICAgIHByb3h5X3NldF9oZWFkZXIgQ29ubmVjdGlvbiBcIlwiO1xuICAgICAgICBwcm94eV9zZXRfaGVhZGVyIERpZnktSG9vay1VcmwgJGRpZnlfZm9yd2FyZGVkX3Byb3RvOi8vJGhvc3QkcmVxdWVzdF91cmk7XG4gICAgfVxuXG4gICAgbG9jYXRpb24gLyB7IHByb3h5X3Bhc3MgaHR0cDovL3dlYjozMDAwOyB9XG59XG4nJydcblxuIyBTcXVpZCBTU1JGIHByb3h5IGNvbmZpZ3VyYXRpb24sIHJlbmRlcmVkIGZyb20gdGhlIHVwc3RyZWFtXG4jIGRvY2tlci9zc3JmX3Byb3h5L3NxdWlkLmNvbmYudGVtcGxhdGUgd2l0aCBpdHMgZGVmYXVsdCB2YWx1ZXMuXG5bW2NvbmZpZy5tb3VudHNdXVxuZmlsZVBhdGggPSBcImRpZnktc3F1aWQuY29uZlwiXG5jb250ZW50ID0gJycnXG5hY2wgY2xpZW50X2xvY2FsbmV0IHNyYyAwLjAuMC4xLTAuMjU1LjI1NS4yNTVcbmFjbCBjbGllbnRfbG9jYWxuZXQgc3JjIDEwLjAuMC4wLzhcbmFjbCBjbGllbnRfbG9jYWxuZXQgc3JjIDEwMC42NC4wLjAvMTBcbmFjbCBjbGllbnRfbG9jYWxuZXQgc3JjIDE2OS4yNTQuMC4wLzE2XG5hY2wgY2xpZW50X2xvY2FsbmV0IHNyYyAxNzIuMTYuMC4wLzEyXG5hY2wgY2xpZW50X2xvY2FsbmV0IHNyYyAxOTIuMTY4LjAuMC8xNlxuYWNsIGNsaWVudF9sb2NhbG5ldCBzcmMgZmMwMDo6LzdcbmFjbCBjbGllbnRfbG9jYWxuZXQgc3JjIGZlODA6Oi8xMFxuYWNsIHRvX3ByaXZhdGVfbmV0d29ya3MgZHN0IDAuMC4wLjAvOFxuYWNsIHRvX3ByaXZhdGVfbmV0d29ya3MgZHN0IDEwLjAuMC4wLzhcbmFjbCB0b19wcml2YXRlX25ldHdvcmtzIGRzdCAxMDAuNjQuMC4wLzEwXG5hY2wgdG9fcHJpdmF0ZV9uZXR3b3JrcyBkc3QgMTI3LjAuMC4wLzhcbmFjbCB0b19wcml2YXRlX25ldHdvcmtzIGRzdCAxNjkuMjU0LjAuMC8xNlxuYWNsIHRvX3ByaXZhdGVfbmV0d29ya3MgZHN0IDE3Mi4xNi4wLjAvMTJcbmFjbCB0b19wcml2YXRlX25ldHdvcmtzIGRzdCAxOTIuMTY4LjAuMC8xNlxuYWNsIHRvX3ByaXZhdGVfbmV0d29ya3MgZHN0IDIyNC4wLjAuMC80XG5hY2wgdG9fcHJpdmF0ZV9uZXR3b3JrcyBkc3QgMjQwLjAuMC4wLzRcbmFjbCB0b19wcml2YXRlX25ldHdvcmtzIGRzdCA6Oi8xMjhcbmFjbCB0b19wcml2YXRlX25ldHdvcmtzIGRzdCA6OjEvMTI4XG5hY2wgdG9fcHJpdmF0ZV9uZXR3b3JrcyBkc3QgOjpmZmZmOjA6MC85NlxuYWNsIHRvX3ByaXZhdGVfbmV0d29ya3MgZHN0IDo6Lzk2XG5hY2wgdG9fcHJpdmF0ZV9uZXR3b3JrcyBkc3QgZmMwMDo6LzdcbmFjbCB0b19wcml2YXRlX25ldHdvcmtzIGRzdCBmZTgwOjovMTBcbmFjbCBTU0xfcG9ydHMgcG9ydCA0NDNcbmFjbCBTYWZlX3BvcnRzIHBvcnQgODBcbmFjbCBTYWZlX3BvcnRzIHBvcnQgMjFcbmFjbCBTYWZlX3BvcnRzIHBvcnQgNDQzXG5hY2wgU2FmZV9wb3J0cyBwb3J0IDcwXG5hY2wgU2FmZV9wb3J0cyBwb3J0IDIxMFxuYWNsIFNhZmVfcG9ydHMgcG9ydCAxMDI1LTY1NTM1XG5hY2wgU2FmZV9wb3J0cyBwb3J0IDI4MFxuYWNsIFNhZmVfcG9ydHMgcG9ydCA0ODhcbmFjbCBTYWZlX3BvcnRzIHBvcnQgNTkxXG5hY2wgU2FmZV9wb3J0cyBwb3J0IDc3N1xuYWNsIENPTk5FQ1QgbWV0aG9kIENPTk5FQ1RcbmFjbCBhbGxvd2VkX2RvbWFpbnMgZHN0ZG9tYWluIC5tYXJrZXRwbGFjZS5kaWZ5LmFpXG5cbmh0dHBfcG9ydCAzMTI4XG5cbmh0dHBfYWNjZXNzIGRlbnkgIVNhZmVfcG9ydHNcbmh0dHBfYWNjZXNzIGRlbnkgQ09OTkVDVCAhU1NMX3BvcnRzXG5odHRwX2FjY2VzcyBhbGxvdyBsb2NhbGhvc3QgbWFuYWdlclxuaHR0cF9hY2Nlc3MgZGVueSBtYW5hZ2VyXG5odHRwX2FjY2VzcyBkZW55IHRvX3ByaXZhdGVfbmV0d29ya3Ncbmh0dHBfYWNjZXNzIGFsbG93IGFsbG93ZWRfZG9tYWluc1xuaHR0cF9hY2Nlc3MgYWxsb3cgY2xpZW50X2xvY2FsbmV0XG5odHRwX2FjY2VzcyBhbGxvdyBsb2NhbGhvc3Rcbmh0dHBfYWNjZXNzIGRlbnkgYWxsXG50Y3Bfb3V0Z29pbmdfYWRkcmVzcyAwLjAuMC4wXG5cbmNvcmVkdW1wX2RpciAvdmFyL3Nwb29sL3NxdWlkXG5yZWZyZXNoX3BhdHRlcm4gXmZ0cDogMTQ0MCAyMCUgMTAwODBcbnJlZnJlc2hfcGF0dGVybiBeZ29waGVyOiAxNDQwIDAlIDE0NDBcbnJlZnJlc2hfcGF0dGVybiAtaSAoL2NnaS1iaW4vfFxcPykgMCAwJSAwXG5yZWZyZXNoX3BhdHRlcm4gLiAwIDIwJSA0MzIwXG5cbmNsaWVudF9yZXF1ZXN0X2J1ZmZlcl9tYXhfc2l6ZSAxMDAgTUJcbm1heF9maWxlZGVzY3JpcHRvcnMgNjU1MzZcblxuY29ubmVjdF90aW1lb3V0IDMwIHNlY29uZHNcbnJlcXVlc3RfdGltZW91dCAyIG1pbnV0ZXNcbnJlYWRfdGltZW91dCAyIG1pbnV0ZXNcbmNsaWVudF9saWZldGltZSA1IG1pbnV0ZXNcbnNodXRkb3duX2xpZmV0aW1lIDMwIHNlY29uZHNcblxuc2VydmVyX3BlcnNpc3RlbnRfY29ubmVjdGlvbnMgb25cbmNsaWVudF9wZXJzaXN0ZW50X2Nvbm5lY3Rpb25zIG9uXG5wZXJzaXN0ZW50X3JlcXVlc3RfdGltZW91dCAzMCBzZWNvbmRzXG5wY29ubl90aW1lb3V0IDEgbWludXRlXG5cbmNsaWVudF9kYiBvblxuc2VydmVyX2lkbGVfcGNvbm5fdGltZW91dCAyIG1pbnV0ZXNcbmNsaWVudF9pZGxlX3Bjb25uX3RpbWVvdXQgMiBtaW51dGVzXG5cbnF1aWNrX2Fib3J0X21pbiAxNiBLQlxucXVpY2tfYWJvcnRfbWF4IDE2IE1CXG5xdWlja19hYm9ydF9wY3QgOTVcblxubWVtb3J5X2NhY2hlX21vZGUgZGlza1xuY2FjaGVfbWVtIDI1NiBNQlxubWF4aW11bV9vYmplY3Rfc2l6ZV9pbl9tZW1vcnkgNTEyIEtCXG5cbmRuc190aW1lb3V0IDMwIHNlY29uZHNcbmRuc19yZXRyYW5zbWl0X2ludGVydmFsIDUgc2Vjb25kc1xuXG5sb2dmb3JtYXQgZGlmeV9sb2cgJXRzLiUwM3R1ICU2dHIgJT5hICVTcy8lMDM+SHMgJTxzdCAlcm0gJXJ1ICVbdW4gJVNoLyU8YSAlbXRcbmFjY2Vzc19sb2cgZGFlbW9uOi92YXIvbG9nL3NxdWlkL2FjY2Vzcy5sb2cgZGlmeV9sb2dcbmxvZ2ZpbGVfcm90YXRlIDEwXG4nJydcbiIKfQ==Instructions
Instructions
First setup
- The first boot runs the database migrations, so it can take 2-4 minutes before the application responds.
- Open your domain: you will be redirected to
/install, where you create the admin (workspace owner) account. - After signing in, go to Settings -> Model Provider and install a model provider plugin (OpenAI, Anthropic, Ollama, etc.) from the marketplace, then configure your API keys.
Notes
-
HTTPS is required for the console login: Dify issues
__Host-/Securesession cookies, so make sure the domain has a certificate (e.g. Let's Encrypt in the domain settings). Over plain HTTP the browser will drop the session cookies and login will not persist. -
The vector store is pgvector, running inside the bundled PostgreSQL instance (no separate Weaviate/Qdrant container needed).
-
All routing (
/console/api,/api,/v1,/files,/e/, ...) is handled by the bundled internal nginx gateway, mirroring the upstream deployment, so the Dify service API is available athttps://<your-domain>/v1. -
Code execution runs in the isolated
sandboxservice, and user-triggered outbound HTTP requests go through thessrf_proxy(squid) service, like in the official deployment.
Links
Tags
ai, llm, rag
Version: 1.15.0