feat(sandbox): add SSH agentbox provider for middleware and docker deployments

This commit is contained in:
Harry
2026-02-09 16:37:01 +08:00
parent b014e91740
commit 3c0b50ee77
19 changed files with 750 additions and 145 deletions

View File

@@ -998,8 +998,13 @@ EMAIL_REGISTER_TOKEN_EXPIRY_MINUTES=5
CHANGE_EMAIL_TOKEN_EXPIRY_MINUTES=5
OWNER_TRANSFER_TOKEN_EXPIRY_MINUTES=5
# Sandbox Dify CLI configuration
# Directory containing dify CLI binaries (dify-cli-<os>-<arch>). Defaults to api/bin when unset.
SANDBOX_DIFY_CLI_ROOT=
# CLI API URL for sandbox (dify-sandbox or e2b) to call back to Dify API.
# This URL must be accessible from the sandbox environment.
# For local development: use http://localhost:5001 or http://127.0.0.1:5001
# For Docker deployment: use http://api:5001 (internal Docker network)
# For external sandbox (e.g., e2b): use a publicly accessible URL
CLI_API_URL=http://api:5001
@@ -1190,6 +1195,21 @@ SANDBOX_HTTPS_PROXY=http://ssrf_proxy:3128
# The port on which the sandbox service runs
SANDBOX_PORT=8194
# ------------------------------
# Environment Variables for agentbox Service
# ------------------------------
# SSH username used by the agentbox service
AGENTBOX_SSH_USERNAME=agentbox
# SSH password used by the agentbox service
AGENTBOX_SSH_PASSWORD=agentbox
# SSH port exposed inside the docker network
AGENTBOX_SSH_PORT=22
# socat target host for localhost forwarding inside agentbox
AGENTBOX_SOCAT_TARGET_HOST=api
# socat target port for localhost forwarding inside agentbox
AGENTBOX_SOCAT_TARGET_PORT=5001
# ------------------------------
# Environment Variables for weaviate Service
# (only used when VECTOR_STORE is weaviate)

View File

@@ -21,7 +21,7 @@ services:
# API service
api:
image: langgenius/dify-api:1.12.1
image: langgenius/dify-api:deploy-agent-dev
restart: always
environment:
# Use the shared environment variables.
@@ -63,7 +63,7 @@ services:
# worker service
# The Celery worker for processing all queues (dataset, workflow, mail, etc.)
worker:
image: langgenius/dify-api:1.12.1
image: langgenius/dify-api:deploy-agent-dev
restart: always
environment:
# Use the shared environment variables.
@@ -102,7 +102,7 @@ services:
# worker_beat service
# Celery beat for scheduling periodic tasks.
worker_beat:
image: langgenius/dify-api:1.12.1
image: langgenius/dify-api:deploy-agent-dev
restart: always
environment:
# Use the shared environment variables.
@@ -132,7 +132,7 @@ services:
# Frontend web application.
web:
image: langgenius/dify-web:1.12.1
image: langgenius/dify-web:deploy-agent-dev
restart: always
environment:
CONSOLE_API_URL: ${CONSOLE_API_URL:-}
@@ -269,6 +269,41 @@ services:
networks:
- ssrf_proxy_network
# SSH sandbox runtime for agent execution.
agentbox:
image: langgenius/dify-agentbox:latest
user: "0:0"
restart: always
environment:
AGENTBOX_SSH_USERNAME: ${AGENTBOX_SSH_USERNAME:-agentbox}
AGENTBOX_SSH_PASSWORD: ${AGENTBOX_SSH_PASSWORD:-agentbox}
AGENTBOX_SSH_PORT: ${AGENTBOX_SSH_PORT:-22}
AGENTBOX_SOCAT_TARGET_HOST: ${AGENTBOX_SOCAT_TARGET_HOST:-api}
AGENTBOX_SOCAT_TARGET_PORT: ${AGENTBOX_SOCAT_TARGET_PORT:-5001}
command: >
sh -c "
set -e;
if ! command -v sshd >/dev/null 2>&1; then
apt-get update;
DEBIAN_FRONTEND=noninteractive apt-get install -y openssh-server;
rm -rf /var/lib/apt/lists/*;
fi;
mkdir -p /run/sshd;
ssh-keygen -A;
if [ \"$${AGENTBOX_SSH_USERNAME}\" = \"root\" ]; then
echo \"root:$${AGENTBOX_SSH_PASSWORD}\" | chpasswd;
grep -q '^PermitRootLogin' /etc/ssh/sshd_config && sed -i 's/^PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config || echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config;
else
id -u \"$${AGENTBOX_SSH_USERNAME}\" >/dev/null 2>&1 || useradd -m -s /bin/bash \"$${AGENTBOX_SSH_USERNAME}\";
echo \"$${AGENTBOX_SSH_USERNAME}:$${AGENTBOX_SSH_PASSWORD}\" | chpasswd;
fi;
grep -q '^PasswordAuthentication' /etc/ssh/sshd_config && sed -i 's/^PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config || echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config;
nohup socat TCP-LISTEN:$${AGENTBOX_SOCAT_TARGET_PORT},bind=127.0.0.1,fork,reuseaddr TCP:$${AGENTBOX_SOCAT_TARGET_HOST}:$${AGENTBOX_SOCAT_TARGET_PORT} >/tmp/socat.log 2>&1 &
exec /usr/sbin/sshd -D -p $${AGENTBOX_SSH_PORT}
"
depends_on:
- api
# plugin daemon
plugin_daemon:
image: langgenius/dify-plugin-daemon:0.5.3-local

View File

@@ -121,6 +121,45 @@ services:
networks:
- ssrf_proxy_network
# SSH sandbox runtime for agent execution.
agentbox:
image: langgenius/dify-agentbox:latest
user: "0:0"
restart: always
env_file:
- ./middleware.env
environment:
AGENTBOX_SSH_USERNAME: ${AGENTBOX_SSH_USERNAME:-agentbox}
AGENTBOX_SSH_PASSWORD: ${AGENTBOX_SSH_PASSWORD:-agentbox}
AGENTBOX_SSH_PORT: ${AGENTBOX_SSH_PORT:-22}
AGENTBOX_SOCAT_TARGET_HOST: ${AGENTBOX_SOCAT_TARGET_HOST:-host.docker.internal}
AGENTBOX_SOCAT_TARGET_PORT: ${AGENTBOX_SOCAT_TARGET_PORT:-5001}
command: >
sh -c "
set -e;
if ! command -v sshd >/dev/null 2>&1; then
apt-get update;
DEBIAN_FRONTEND=noninteractive apt-get install -y openssh-server;
rm -rf /var/lib/apt/lists/*;
fi;
mkdir -p /run/sshd;
ssh-keygen -A;
if [ \"$${AGENTBOX_SSH_USERNAME}\" = \"root\" ]; then
echo \"root:$${AGENTBOX_SSH_PASSWORD}\" | chpasswd;
grep -q '^PermitRootLogin' /etc/ssh/sshd_config && sed -i 's/^PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config || echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config;
else
id -u \"$${AGENTBOX_SSH_USERNAME}\" >/dev/null 2>&1 || useradd -m -s /bin/bash \"$${AGENTBOX_SSH_USERNAME}\";
echo \"$${AGENTBOX_SSH_USERNAME}:$${AGENTBOX_SSH_PASSWORD}\" | chpasswd;
fi;
grep -q '^PasswordAuthentication' /etc/ssh/sshd_config && sed -i 's/^PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config || echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config;
nohup socat TCP-LISTEN:$${AGENTBOX_SOCAT_TARGET_PORT},bind=127.0.0.1,fork,reuseaddr TCP:$${AGENTBOX_SOCAT_TARGET_HOST}:$${AGENTBOX_SOCAT_TARGET_PORT} >/tmp/socat.log 2>&1 &
exec /usr/sbin/sshd -D -p $${AGENTBOX_SSH_PORT}
"
ports:
- "${EXPOSE_AGENTBOX_SSH_PORT:-2222}:${AGENTBOX_SSH_PORT:-22}"
networks:
- default
# plugin daemon
plugin_daemon:
image: langgenius/dify-plugin-daemon:0.5.3-local

View File

@@ -435,6 +435,8 @@ x-shared-env: &shared-api-worker-env
EMAIL_REGISTER_TOKEN_EXPIRY_MINUTES: ${EMAIL_REGISTER_TOKEN_EXPIRY_MINUTES:-5}
CHANGE_EMAIL_TOKEN_EXPIRY_MINUTES: ${CHANGE_EMAIL_TOKEN_EXPIRY_MINUTES:-5}
OWNER_TRANSFER_TOKEN_EXPIRY_MINUTES: ${OWNER_TRANSFER_TOKEN_EXPIRY_MINUTES:-5}
SANDBOX_DIFY_CLI_ROOT: ${SANDBOX_DIFY_CLI_ROOT:-}
CLI_API_URL: ${CLI_API_URL:-http://api:5001}
CODE_EXECUTION_ENDPOINT: ${CODE_EXECUTION_ENDPOINT:-http://sandbox:8194}
CODE_EXECUTION_API_KEY: ${CODE_EXECUTION_API_KEY:-dify-sandbox}
CODE_EXECUTION_SSL_VERIFY: ${CODE_EXECUTION_SSL_VERIFY:-True}
@@ -505,6 +507,11 @@ x-shared-env: &shared-api-worker-env
SANDBOX_HTTP_PROXY: ${SANDBOX_HTTP_PROXY:-http://ssrf_proxy:3128}
SANDBOX_HTTPS_PROXY: ${SANDBOX_HTTPS_PROXY:-http://ssrf_proxy:3128}
SANDBOX_PORT: ${SANDBOX_PORT:-8194}
AGENTBOX_SSH_USERNAME: ${AGENTBOX_SSH_USERNAME:-agentbox}
AGENTBOX_SSH_PASSWORD: ${AGENTBOX_SSH_PASSWORD:-agentbox}
AGENTBOX_SSH_PORT: ${AGENTBOX_SSH_PORT:-22}
AGENTBOX_SOCAT_TARGET_HOST: ${AGENTBOX_SOCAT_TARGET_HOST:-api}
AGENTBOX_SOCAT_TARGET_PORT: ${AGENTBOX_SOCAT_TARGET_PORT:-5001}
WEAVIATE_PERSISTENCE_DATA_PATH: ${WEAVIATE_PERSISTENCE_DATA_PATH:-/var/lib/weaviate}
WEAVIATE_QUERY_DEFAULTS_LIMIT: ${WEAVIATE_QUERY_DEFAULTS_LIMIT:-25}
WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: ${WEAVIATE_AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED:-true}
@@ -709,7 +716,7 @@ services:
# API service
api:
image: langgenius/dify-api:1.12.1
image: langgenius/dify-api:deploy-agent-dev
restart: always
environment:
# Use the shared environment variables.
@@ -751,7 +758,7 @@ services:
# worker service
# The Celery worker for processing all queues (dataset, workflow, mail, etc.)
worker:
image: langgenius/dify-api:1.12.1
image: langgenius/dify-api:deploy-agent-dev
restart: always
environment:
# Use the shared environment variables.
@@ -790,7 +797,7 @@ services:
# worker_beat service
# Celery beat for scheduling periodic tasks.
worker_beat:
image: langgenius/dify-api:1.12.1
image: langgenius/dify-api:deploy-agent-dev
restart: always
environment:
# Use the shared environment variables.
@@ -820,7 +827,7 @@ services:
# Frontend web application.
web:
image: langgenius/dify-web:1.12.1
image: langgenius/dify-web:deploy-agent-dev
restart: always
environment:
CONSOLE_API_URL: ${CONSOLE_API_URL:-}
@@ -957,6 +964,41 @@ services:
networks:
- ssrf_proxy_network
# SSH sandbox runtime for agent execution.
agentbox:
image: langgenius/dify-agentbox:latest
user: "0:0"
restart: always
environment:
AGENTBOX_SSH_USERNAME: ${AGENTBOX_SSH_USERNAME:-agentbox}
AGENTBOX_SSH_PASSWORD: ${AGENTBOX_SSH_PASSWORD:-agentbox}
AGENTBOX_SSH_PORT: ${AGENTBOX_SSH_PORT:-22}
AGENTBOX_SOCAT_TARGET_HOST: ${AGENTBOX_SOCAT_TARGET_HOST:-api}
AGENTBOX_SOCAT_TARGET_PORT: ${AGENTBOX_SOCAT_TARGET_PORT:-5001}
command: >
sh -c "
set -e;
if ! command -v sshd >/dev/null 2>&1; then
apt-get update;
DEBIAN_FRONTEND=noninteractive apt-get install -y openssh-server;
rm -rf /var/lib/apt/lists/*;
fi;
mkdir -p /run/sshd;
ssh-keygen -A;
if [ \"$${AGENTBOX_SSH_USERNAME}\" = \"root\" ]; then
echo \"root:$${AGENTBOX_SSH_PASSWORD}\" | chpasswd;
grep -q '^PermitRootLogin' /etc/ssh/sshd_config && sed -i 's/^PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config || echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config;
else
id -u \"$${AGENTBOX_SSH_USERNAME}\" >/dev/null 2>&1 || useradd -m -s /bin/bash \"$${AGENTBOX_SSH_USERNAME}\";
echo \"$${AGENTBOX_SSH_USERNAME}:$${AGENTBOX_SSH_PASSWORD}\" | chpasswd;
fi;
grep -q '^PasswordAuthentication' /etc/ssh/sshd_config && sed -i 's/^PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config || echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config;
nohup socat TCP-LISTEN:$${AGENTBOX_SOCAT_TARGET_PORT},bind=127.0.0.1,fork,reuseaddr TCP:$${AGENTBOX_SOCAT_TARGET_HOST}:$${AGENTBOX_SOCAT_TARGET_PORT} >/tmp/socat.log 2>&1 &
exec /usr/sbin/sshd -D -p $${AGENTBOX_SSH_PORT}
"
depends_on:
- api
# plugin daemon
plugin_daemon:
image: langgenius/dify-plugin-daemon:0.5.3-local

View File

@@ -103,6 +103,15 @@ SANDBOX_HTTP_PROXY=http://ssrf_proxy:3128
SANDBOX_HTTPS_PROXY=http://ssrf_proxy:3128
SANDBOX_PORT=8194
# ------------------------------
# Environment Variables for agentbox Service
# ------------------------------
AGENTBOX_SSH_USERNAME=agentbox
AGENTBOX_SSH_PASSWORD=agentbox
AGENTBOX_SSH_PORT=22
AGENTBOX_SOCAT_TARGET_HOST=host.docker.internal
AGENTBOX_SOCAT_TARGET_PORT=5001
# ------------------------------
# Environment Variables for ssrf_proxy Service
# ------------------------------
@@ -140,6 +149,7 @@ EXPOSE_POSTGRES_PORT=5432
EXPOSE_MYSQL_PORT=3306
EXPOSE_REDIS_PORT=6379
EXPOSE_SANDBOX_PORT=8194
EXPOSE_AGENTBOX_SSH_PORT=2222
EXPOSE_SSRF_PROXY_PORT=3128
EXPOSE_WEAVIATE_PORT=8080
@@ -237,4 +247,4 @@ LOGSTORE_DUAL_READ_ENABLED=true
# Control flag for whether to write the `graph` field to LogStore.
# If LOGSTORE_ENABLE_PUT_GRAPH_FIELD is "true", write the full `graph` field;
# otherwise write an empty {} instead. Defaults to writing the `graph` field.
LOGSTORE_ENABLE_PUT_GRAPH_FIELD=true
LOGSTORE_ENABLE_PUT_GRAPH_FIELD=true