services: serverfs-mcp: build: context: . # `image` doubles as the tag `docker compose build` writes to, so a bare # build under a pinned production .env (SERVERFS_IMAGE=...:) would # point that release tag at locally built code. Build under a scratch tag # instead: `SERVERFS_IMAGE=serverfs-mcp:dev docker compose build`. image: ${SERVERFS_IMAGE:-ghcr.io/ntlx/serverfs_mcp:latest} restart: unless-stopped user: "${SERVERFS_UID:-10001}:${SERVERFS_GID:-10001}" environment: TZ: ${TZ:-Asia/Shanghai} SERVERFS_LOG_LEVEL: ${SERVERFS_LOG_LEVEL:-INFO} SERVERFS_HTTP_HOST: ${SERVERFS_HTTP_HOST:-0.0.0.0} SERVERFS_HTTP_PORT: ${SERVERFS_HTTP_PORT:-8000} SERVERFS_HTTP_PATH: ${SERVERFS_HTTP_PATH:-/mcp} SERVERFS_HTTP_ALLOWED_HOSTS: ${SERVERFS_HTTP_ALLOWED_HOSTS:-} SERVERFS_HTTP_ALLOWED_ORIGINS: ${SERVERFS_HTTP_ALLOWED_ORIGINS:-} SERVERFS_HTTP_API_KEY: ${SERVERFS_HTTP_API_KEY:-} SERVERFS_MAX_READ_BYTES: ${SERVERFS_MAX_READ_BYTES:-524288} SERVERFS_MAX_READ_LINES: ${SERVERFS_MAX_READ_LINES:-500} SERVERFS_DEFAULT_LIST_LIMIT: ${SERVERFS_DEFAULT_LIST_LIMIT:-100} SERVERFS_MAX_LIST_ENTRIES: ${SERVERFS_MAX_LIST_ENTRIES:-500} SERVERFS_DEFAULT_SEARCH_RESULTS: ${SERVERFS_DEFAULT_SEARCH_RESULTS:-50} SERVERFS_MAX_SEARCH_RESULTS: ${SERVERFS_MAX_SEARCH_RESULTS:-100} SERVERFS_MAX_WALK_ENTRIES: ${SERVERFS_MAX_WALK_ENTRIES:-200000} SERVERFS_SEARCH_TIMEOUT_SECONDS: ${SERVERFS_SEARCH_TIMEOUT_SECONDS:-15} SERVERFS_SEARCH_MAX_FILE_BYTES: ${SERVERFS_SEARCH_MAX_FILE_BYTES:-52428800} SERVERFS_ALLOW_HIDDEN: ${SERVERFS_ALLOW_HIDDEN:-false} SERVERFS_EXTRA_DENY_GLOBS: ${SERVERFS_EXTRA_DENY_GLOBS:-} SERVERFS_DISABLE_DEFAULT_DENY: ${SERVERFS_DISABLE_DEFAULT_DENY:-false} SERVERFS_MAX_WRITE_BYTES: ${SERVERFS_MAX_WRITE_BYTES:-1048576} SERVERFS_MAX_EDITS_PER_CALL: ${SERVERFS_MAX_EDITS_PER_CALL:-50} SERVERFS_BINARY_TRANSFER_ENABLED: ${SERVERFS_BINARY_TRANSFER_ENABLED:-false} SERVERFS_MAX_BINARY_TRANSFER_BYTES: ${SERVERFS_MAX_BINARY_TRANSFER_BYTES:-8388608} SERVERFS_FILE_INGRESS_ENABLED: ${SERVERFS_FILE_INGRESS_ENABLED:-false} SERVERFS_FILE_INGRESS_TIMEOUT_SECONDS: ${SERVERFS_FILE_INGRESS_TIMEOUT_SECONDS:-30} WORKDIR_01_ALIAS: ${WORKDIR_01_ALIAS:-} WORKDIR_01_DESCRIPTION: ${WORKDIR_01_DESCRIPTION:-} WORKDIR_01_READ_ONLY: ${WORKDIR_01_READ_ONLY:-true} WORKDIR_01_ALLOW_HIDDEN: ${WORKDIR_01_ALLOW_HIDDEN:-} WORKDIR_01_DISABLE_DEFAULT_DENY: ${WORKDIR_01_DISABLE_DEFAULT_DENY:-} WORKDIR_01_EXTRA_DENY_GLOBS: ${WORKDIR_01_EXTRA_DENY_GLOBS:-} WORKDIR_01_MAX_READ_BYTES: ${WORKDIR_01_MAX_READ_BYTES:-} WORKDIR_01_MAX_READ_LINES: ${WORKDIR_01_MAX_READ_LINES:-} WORKDIR_01_MAX_WRITE_BYTES: ${WORKDIR_01_MAX_WRITE_BYTES:-} WORKDIR_01_BINARY_TRANSFER_ENABLED: ${WORKDIR_01_BINARY_TRANSFER_ENABLED:-} WORKDIR_01_MAX_BINARY_TRANSFER_BYTES: ${WORKDIR_01_MAX_BINARY_TRANSFER_BYTES:-} WORKDIR_02_ALIAS: ${WORKDIR_02_ALIAS:-} WORKDIR_02_DESCRIPTION: ${WORKDIR_02_DESCRIPTION:-} WORKDIR_02_READ_ONLY: ${WORKDIR_02_READ_ONLY:-true} WORKDIR_02_ALLOW_HIDDEN: ${WORKDIR_02_ALLOW_HIDDEN:-} WORKDIR_02_DISABLE_DEFAULT_DENY: ${WORKDIR_02_DISABLE_DEFAULT_DENY:-} WORKDIR_02_EXTRA_DENY_GLOBS: ${WORKDIR_02_EXTRA_DENY_GLOBS:-} WORKDIR_02_MAX_READ_BYTES: ${WORKDIR_02_MAX_READ_BYTES:-} WORKDIR_02_MAX_READ_LINES: ${WORKDIR_02_MAX_READ_LINES:-} WORKDIR_02_MAX_WRITE_BYTES: ${WORKDIR_02_MAX_WRITE_BYTES:-} WORKDIR_02_BINARY_TRANSFER_ENABLED: ${WORKDIR_02_BINARY_TRANSFER_ENABLED:-} WORKDIR_02_MAX_BINARY_TRANSFER_BYTES: ${WORKDIR_02_MAX_BINARY_TRANSFER_BYTES:-} WORKDIR_03_ALIAS: ${WORKDIR_03_ALIAS:-} WORKDIR_03_DESCRIPTION: ${WORKDIR_03_DESCRIPTION:-} WORKDIR_03_READ_ONLY: ${WORKDIR_03_READ_ONLY:-true} WORKDIR_03_ALLOW_HIDDEN: ${WORKDIR_03_ALLOW_HIDDEN:-} WORKDIR_03_DISABLE_DEFAULT_DENY: ${WORKDIR_03_DISABLE_DEFAULT_DENY:-} WORKDIR_03_EXTRA_DENY_GLOBS: ${WORKDIR_03_EXTRA_DENY_GLOBS:-} WORKDIR_03_MAX_READ_BYTES: ${WORKDIR_03_MAX_READ_BYTES:-} WORKDIR_03_MAX_READ_LINES: ${WORKDIR_03_MAX_READ_LINES:-} WORKDIR_03_MAX_WRITE_BYTES: ${WORKDIR_03_MAX_WRITE_BYTES:-} WORKDIR_03_BINARY_TRANSFER_ENABLED: ${WORKDIR_03_BINARY_TRANSFER_ENABLED:-} WORKDIR_03_MAX_BINARY_TRANSFER_BYTES: ${WORKDIR_03_MAX_BINARY_TRANSFER_BYTES:-} WORKDIR_04_ALIAS: ${WORKDIR_04_ALIAS:-} WORKDIR_04_DESCRIPTION: ${WORKDIR_04_DESCRIPTION:-} WORKDIR_04_READ_ONLY: ${WORKDIR_04_READ_ONLY:-true} WORKDIR_04_ALLOW_HIDDEN: ${WORKDIR_04_ALLOW_HIDDEN:-} WORKDIR_04_DISABLE_DEFAULT_DENY: ${WORKDIR_04_DISABLE_DEFAULT_DENY:-} WORKDIR_04_EXTRA_DENY_GLOBS: ${WORKDIR_04_EXTRA_DENY_GLOBS:-} WORKDIR_04_MAX_READ_BYTES: ${WORKDIR_04_MAX_READ_BYTES:-} WORKDIR_04_MAX_READ_LINES: ${WORKDIR_04_MAX_READ_LINES:-} WORKDIR_04_MAX_WRITE_BYTES: ${WORKDIR_04_MAX_WRITE_BYTES:-} WORKDIR_04_BINARY_TRANSFER_ENABLED: ${WORKDIR_04_BINARY_TRANSFER_ENABLED:-} WORKDIR_04_MAX_BINARY_TRANSFER_BYTES: ${WORKDIR_04_MAX_BINARY_TRANSFER_BYTES:-} WORKDIR_05_ALIAS: ${WORKDIR_05_ALIAS:-} WORKDIR_05_DESCRIPTION: ${WORKDIR_05_DESCRIPTION:-} WORKDIR_05_READ_ONLY: ${WORKDIR_05_READ_ONLY:-true} WORKDIR_05_ALLOW_HIDDEN: ${WORKDIR_05_ALLOW_HIDDEN:-} WORKDIR_05_DISABLE_DEFAULT_DENY: ${WORKDIR_05_DISABLE_DEFAULT_DENY:-} WORKDIR_05_EXTRA_DENY_GLOBS: ${WORKDIR_05_EXTRA_DENY_GLOBS:-} WORKDIR_05_MAX_READ_BYTES: ${WORKDIR_05_MAX_READ_BYTES:-} WORKDIR_05_MAX_READ_LINES: ${WORKDIR_05_MAX_READ_LINES:-} WORKDIR_05_MAX_WRITE_BYTES: ${WORKDIR_05_MAX_WRITE_BYTES:-} WORKDIR_05_BINARY_TRANSFER_ENABLED: ${WORKDIR_05_BINARY_TRANSFER_ENABLED:-} WORKDIR_05_MAX_BINARY_TRANSFER_BYTES: ${WORKDIR_05_MAX_BINARY_TRANSFER_BYTES:-} WORKDIR_06_ALIAS: ${WORKDIR_06_ALIAS:-} WORKDIR_06_DESCRIPTION: ${WORKDIR_06_DESCRIPTION:-} WORKDIR_06_READ_ONLY: ${WORKDIR_06_READ_ONLY:-true} WORKDIR_06_ALLOW_HIDDEN: ${WORKDIR_06_ALLOW_HIDDEN:-} WORKDIR_06_DISABLE_DEFAULT_DENY: ${WORKDIR_06_DISABLE_DEFAULT_DENY:-} WORKDIR_06_EXTRA_DENY_GLOBS: ${WORKDIR_06_EXTRA_DENY_GLOBS:-} WORKDIR_06_MAX_READ_BYTES: ${WORKDIR_06_MAX_READ_BYTES:-} WORKDIR_06_MAX_READ_LINES: ${WORKDIR_06_MAX_READ_LINES:-} WORKDIR_06_MAX_WRITE_BYTES: ${WORKDIR_06_MAX_WRITE_BYTES:-} WORKDIR_06_BINARY_TRANSFER_ENABLED: ${WORKDIR_06_BINARY_TRANSFER_ENABLED:-} WORKDIR_06_MAX_BINARY_TRANSFER_BYTES: ${WORKDIR_06_MAX_BINARY_TRANSFER_BYTES:-} WORKDIR_07_ALIAS: ${WORKDIR_07_ALIAS:-} WORKDIR_07_DESCRIPTION: ${WORKDIR_07_DESCRIPTION:-} WORKDIR_07_READ_ONLY: ${WORKDIR_07_READ_ONLY:-true} WORKDIR_07_ALLOW_HIDDEN: ${WORKDIR_07_ALLOW_HIDDEN:-} WORKDIR_07_DISABLE_DEFAULT_DENY: ${WORKDIR_07_DISABLE_DEFAULT_DENY:-} WORKDIR_07_EXTRA_DENY_GLOBS: ${WORKDIR_07_EXTRA_DENY_GLOBS:-} WORKDIR_07_MAX_READ_BYTES: ${WORKDIR_07_MAX_READ_BYTES:-} WORKDIR_07_MAX_READ_LINES: ${WORKDIR_07_MAX_READ_LINES:-} WORKDIR_07_MAX_WRITE_BYTES: ${WORKDIR_07_MAX_WRITE_BYTES:-} WORKDIR_07_BINARY_TRANSFER_ENABLED: ${WORKDIR_07_BINARY_TRANSFER_ENABLED:-} WORKDIR_07_MAX_BINARY_TRANSFER_BYTES: ${WORKDIR_07_MAX_BINARY_TRANSFER_BYTES:-} WORKDIR_08_ALIAS: ${WORKDIR_08_ALIAS:-} WORKDIR_08_DESCRIPTION: ${WORKDIR_08_DESCRIPTION:-} WORKDIR_08_READ_ONLY: ${WORKDIR_08_READ_ONLY:-true} WORKDIR_08_ALLOW_HIDDEN: ${WORKDIR_08_ALLOW_HIDDEN:-} WORKDIR_08_DISABLE_DEFAULT_DENY: ${WORKDIR_08_DISABLE_DEFAULT_DENY:-} WORKDIR_08_EXTRA_DENY_GLOBS: ${WORKDIR_08_EXTRA_DENY_GLOBS:-} WORKDIR_08_MAX_READ_BYTES: ${WORKDIR_08_MAX_READ_BYTES:-} WORKDIR_08_MAX_READ_LINES: ${WORKDIR_08_MAX_READ_LINES:-} WORKDIR_08_MAX_WRITE_BYTES: ${WORKDIR_08_MAX_WRITE_BYTES:-} WORKDIR_08_BINARY_TRANSFER_ENABLED: ${WORKDIR_08_BINARY_TRANSFER_ENABLED:-} WORKDIR_08_MAX_BINARY_TRANSFER_BYTES: ${WORKDIR_08_MAX_BINARY_TRANSFER_BYTES:-} WORKDIR_09_ALIAS: ${WORKDIR_09_ALIAS:-} WORKDIR_09_DESCRIPTION: ${WORKDIR_09_DESCRIPTION:-} WORKDIR_09_READ_ONLY: ${WORKDIR_09_READ_ONLY:-true} WORKDIR_09_ALLOW_HIDDEN: ${WORKDIR_09_ALLOW_HIDDEN:-} WORKDIR_09_DISABLE_DEFAULT_DENY: ${WORKDIR_09_DISABLE_DEFAULT_DENY:-} WORKDIR_09_EXTRA_DENY_GLOBS: ${WORKDIR_09_EXTRA_DENY_GLOBS:-} WORKDIR_09_MAX_READ_BYTES: ${WORKDIR_09_MAX_READ_BYTES:-} WORKDIR_09_MAX_READ_LINES: ${WORKDIR_09_MAX_READ_LINES:-} WORKDIR_09_MAX_WRITE_BYTES: ${WORKDIR_09_MAX_WRITE_BYTES:-} WORKDIR_09_BINARY_TRANSFER_ENABLED: ${WORKDIR_09_BINARY_TRANSFER_ENABLED:-} WORKDIR_09_MAX_BINARY_TRANSFER_BYTES: ${WORKDIR_09_MAX_BINARY_TRANSFER_BYTES:-} WORKDIR_10_ALIAS: ${WORKDIR_10_ALIAS:-} WORKDIR_10_DESCRIPTION: ${WORKDIR_10_DESCRIPTION:-} WORKDIR_10_READ_ONLY: ${WORKDIR_10_READ_ONLY:-true} WORKDIR_10_ALLOW_HIDDEN: ${WORKDIR_10_ALLOW_HIDDEN:-} WORKDIR_10_DISABLE_DEFAULT_DENY: ${WORKDIR_10_DISABLE_DEFAULT_DENY:-} WORKDIR_10_EXTRA_DENY_GLOBS: ${WORKDIR_10_EXTRA_DENY_GLOBS:-} WORKDIR_10_MAX_READ_BYTES: ${WORKDIR_10_MAX_READ_BYTES:-} WORKDIR_10_MAX_READ_LINES: ${WORKDIR_10_MAX_READ_LINES:-} WORKDIR_10_MAX_WRITE_BYTES: ${WORKDIR_10_MAX_WRITE_BYTES:-} WORKDIR_10_BINARY_TRANSFER_ENABLED: ${WORKDIR_10_BINARY_TRANSFER_ENABLED:-} WORKDIR_10_MAX_BINARY_TRANSFER_BYTES: ${WORKDIR_10_MAX_BINARY_TRANSFER_BYTES:-} WORKDIR_11_ALIAS: ${WORKDIR_11_ALIAS:-} WORKDIR_11_DESCRIPTION: ${WORKDIR_11_DESCRIPTION:-} WORKDIR_11_READ_ONLY: ${WORKDIR_11_READ_ONLY:-true} WORKDIR_11_ALLOW_HIDDEN: ${WORKDIR_11_ALLOW_HIDDEN:-} WORKDIR_11_DISABLE_DEFAULT_DENY: ${WORKDIR_11_DISABLE_DEFAULT_DENY:-} WORKDIR_11_EXTRA_DENY_GLOBS: ${WORKDIR_11_EXTRA_DENY_GLOBS:-} WORKDIR_11_MAX_READ_BYTES: ${WORKDIR_11_MAX_READ_BYTES:-} WORKDIR_11_MAX_READ_LINES: ${WORKDIR_11_MAX_READ_LINES:-} WORKDIR_11_MAX_WRITE_BYTES: ${WORKDIR_11_MAX_WRITE_BYTES:-} WORKDIR_11_BINARY_TRANSFER_ENABLED: ${WORKDIR_11_BINARY_TRANSFER_ENABLED:-} WORKDIR_11_MAX_BINARY_TRANSFER_BYTES: ${WORKDIR_11_MAX_BINARY_TRANSFER_BYTES:-} WORKDIR_12_ALIAS: ${WORKDIR_12_ALIAS:-} WORKDIR_12_DESCRIPTION: ${WORKDIR_12_DESCRIPTION:-} WORKDIR_12_READ_ONLY: ${WORKDIR_12_READ_ONLY:-true} WORKDIR_12_ALLOW_HIDDEN: ${WORKDIR_12_ALLOW_HIDDEN:-} WORKDIR_12_DISABLE_DEFAULT_DENY: ${WORKDIR_12_DISABLE_DEFAULT_DENY:-} WORKDIR_12_EXTRA_DENY_GLOBS: ${WORKDIR_12_EXTRA_DENY_GLOBS:-} WORKDIR_12_MAX_READ_BYTES: ${WORKDIR_12_MAX_READ_BYTES:-} WORKDIR_12_MAX_READ_LINES: ${WORKDIR_12_MAX_READ_LINES:-} WORKDIR_12_MAX_WRITE_BYTES: ${WORKDIR_12_MAX_WRITE_BYTES:-} WORKDIR_12_BINARY_TRANSFER_ENABLED: ${WORKDIR_12_BINARY_TRANSFER_ENABLED:-} WORKDIR_12_MAX_BINARY_TRANSFER_BYTES: ${WORKDIR_12_MAX_BINARY_TRANSFER_BYTES:-} WORKDIR_13_ALIAS: ${WORKDIR_13_ALIAS:-} WORKDIR_13_DESCRIPTION: ${WORKDIR_13_DESCRIPTION:-} WORKDIR_13_READ_ONLY: ${WORKDIR_13_READ_ONLY:-true} WORKDIR_13_ALLOW_HIDDEN: ${WORKDIR_13_ALLOW_HIDDEN:-} WORKDIR_13_DISABLE_DEFAULT_DENY: ${WORKDIR_13_DISABLE_DEFAULT_DENY:-} WORKDIR_13_EXTRA_DENY_GLOBS: ${WORKDIR_13_EXTRA_DENY_GLOBS:-} WORKDIR_13_MAX_READ_BYTES: ${WORKDIR_13_MAX_READ_BYTES:-} WORKDIR_13_MAX_READ_LINES: ${WORKDIR_13_MAX_READ_LINES:-} WORKDIR_13_MAX_WRITE_BYTES: ${WORKDIR_13_MAX_WRITE_BYTES:-} WORKDIR_13_BINARY_TRANSFER_ENABLED: ${WORKDIR_13_BINARY_TRANSFER_ENABLED:-} WORKDIR_13_MAX_BINARY_TRANSFER_BYTES: ${WORKDIR_13_MAX_BINARY_TRANSFER_BYTES:-} WORKDIR_14_ALIAS: ${WORKDIR_14_ALIAS:-} WORKDIR_14_DESCRIPTION: ${WORKDIR_14_DESCRIPTION:-} WORKDIR_14_READ_ONLY: ${WORKDIR_14_READ_ONLY:-true} WORKDIR_14_ALLOW_HIDDEN: ${WORKDIR_14_ALLOW_HIDDEN:-} WORKDIR_14_DISABLE_DEFAULT_DENY: ${WORKDIR_14_DISABLE_DEFAULT_DENY:-} WORKDIR_14_EXTRA_DENY_GLOBS: ${WORKDIR_14_EXTRA_DENY_GLOBS:-} WORKDIR_14_MAX_READ_BYTES: ${WORKDIR_14_MAX_READ_BYTES:-} WORKDIR_14_MAX_READ_LINES: ${WORKDIR_14_MAX_READ_LINES:-} WORKDIR_14_MAX_WRITE_BYTES: ${WORKDIR_14_MAX_WRITE_BYTES:-} WORKDIR_14_BINARY_TRANSFER_ENABLED: ${WORKDIR_14_BINARY_TRANSFER_ENABLED:-} WORKDIR_14_MAX_BINARY_TRANSFER_BYTES: ${WORKDIR_14_MAX_BINARY_TRANSFER_BYTES:-} WORKDIR_15_ALIAS: ${WORKDIR_15_ALIAS:-} WORKDIR_15_DESCRIPTION: ${WORKDIR_15_DESCRIPTION:-} WORKDIR_15_READ_ONLY: ${WORKDIR_15_READ_ONLY:-true} WORKDIR_15_ALLOW_HIDDEN: ${WORKDIR_15_ALLOW_HIDDEN:-} WORKDIR_15_DISABLE_DEFAULT_DENY: ${WORKDIR_15_DISABLE_DEFAULT_DENY:-} WORKDIR_15_EXTRA_DENY_GLOBS: ${WORKDIR_15_EXTRA_DENY_GLOBS:-} WORKDIR_15_MAX_READ_BYTES: ${WORKDIR_15_MAX_READ_BYTES:-} WORKDIR_15_MAX_READ_LINES: ${WORKDIR_15_MAX_READ_LINES:-} WORKDIR_15_MAX_WRITE_BYTES: ${WORKDIR_15_MAX_WRITE_BYTES:-} WORKDIR_15_BINARY_TRANSFER_ENABLED: ${WORKDIR_15_BINARY_TRANSFER_ENABLED:-} WORKDIR_15_MAX_BINARY_TRANSFER_BYTES: ${WORKDIR_15_MAX_BINARY_TRANSFER_BYTES:-} WORKDIR_16_ALIAS: ${WORKDIR_16_ALIAS:-} WORKDIR_16_DESCRIPTION: ${WORKDIR_16_DESCRIPTION:-} WORKDIR_16_READ_ONLY: ${WORKDIR_16_READ_ONLY:-true} WORKDIR_16_ALLOW_HIDDEN: ${WORKDIR_16_ALLOW_HIDDEN:-} WORKDIR_16_DISABLE_DEFAULT_DENY: ${WORKDIR_16_DISABLE_DEFAULT_DENY:-} WORKDIR_16_EXTRA_DENY_GLOBS: ${WORKDIR_16_EXTRA_DENY_GLOBS:-} WORKDIR_16_MAX_READ_BYTES: ${WORKDIR_16_MAX_READ_BYTES:-} WORKDIR_16_MAX_READ_LINES: ${WORKDIR_16_MAX_READ_LINES:-} WORKDIR_16_MAX_WRITE_BYTES: ${WORKDIR_16_MAX_WRITE_BYTES:-} WORKDIR_16_BINARY_TRANSFER_ENABLED: ${WORKDIR_16_BINARY_TRANSFER_ENABLED:-} WORKDIR_16_MAX_BINARY_TRANSFER_BYTES: ${WORKDIR_16_MAX_BINARY_TRANSFER_BYTES:-} volumes: - type: bind source: ${WORKDIR_01_PATH:-./.empty} target: /workdirs/01 read_only: ${WORKDIR_01_READ_ONLY:-true} bind: create_host_path: false - type: bind source: ${WORKDIR_02_PATH:-./.empty} target: /workdirs/02 read_only: ${WORKDIR_02_READ_ONLY:-true} bind: create_host_path: false - type: bind source: ${WORKDIR_03_PATH:-./.empty} target: /workdirs/03 read_only: ${WORKDIR_03_READ_ONLY:-true} bind: create_host_path: false - type: bind source: ${WORKDIR_04_PATH:-./.empty} target: /workdirs/04 read_only: ${WORKDIR_04_READ_ONLY:-true} bind: create_host_path: false - type: bind source: ${WORKDIR_05_PATH:-./.empty} target: /workdirs/05 read_only: ${WORKDIR_05_READ_ONLY:-true} bind: create_host_path: false - type: bind source: ${WORKDIR_06_PATH:-./.empty} target: /workdirs/06 read_only: ${WORKDIR_06_READ_ONLY:-true} bind: create_host_path: false - type: bind source: ${WORKDIR_07_PATH:-./.empty} target: /workdirs/07 read_only: ${WORKDIR_07_READ_ONLY:-true} bind: create_host_path: false - type: bind source: ${WORKDIR_08_PATH:-./.empty} target: /workdirs/08 read_only: ${WORKDIR_08_READ_ONLY:-true} bind: create_host_path: false - type: bind source: ${WORKDIR_09_PATH:-./.empty} target: /workdirs/09 read_only: ${WORKDIR_09_READ_ONLY:-true} bind: create_host_path: false - type: bind source: ${WORKDIR_10_PATH:-./.empty} target: /workdirs/10 read_only: ${WORKDIR_10_READ_ONLY:-true} bind: create_host_path: false - type: bind source: ${WORKDIR_11_PATH:-./.empty} target: /workdirs/11 read_only: ${WORKDIR_11_READ_ONLY:-true} bind: create_host_path: false - type: bind source: ${WORKDIR_12_PATH:-./.empty} target: /workdirs/12 read_only: ${WORKDIR_12_READ_ONLY:-true} bind: create_host_path: false - type: bind source: ${WORKDIR_13_PATH:-./.empty} target: /workdirs/13 read_only: ${WORKDIR_13_READ_ONLY:-true} bind: create_host_path: false - type: bind source: ${WORKDIR_14_PATH:-./.empty} target: /workdirs/14 read_only: ${WORKDIR_14_READ_ONLY:-true} bind: create_host_path: false - type: bind source: ${WORKDIR_15_PATH:-./.empty} target: /workdirs/15 read_only: ${WORKDIR_15_READ_ONLY:-true} bind: create_host_path: false - type: bind source: ${WORKDIR_16_PATH:-./.empty} target: /workdirs/16 read_only: ${WORKDIR_16_READ_ONLY:-true} bind: create_host_path: false expose: - "${SERVERFS_HTTP_PORT:-8000}" networks: - serverfs_internal - serverfs_file_ingress read_only: true tmpfs: - /tmp cap_drop: - ALL security_opt: - no-new-privileges:true healthcheck: test: [ "CMD", ".venv/bin/python", "-c", "import os,socket; socket.create_connection(('127.0.0.1', int(os.environ.get('SERVERFS_HTTP_PORT', '8000'))), timeout=2).close()", ] interval: 10s timeout: 3s retries: 5 start_period: 5s serverfs-file-ingress: profiles: ["file-ingress"] image: ${SERVERFS_IMAGE:-ghcr.io/ntlx/serverfs_mcp:latest} command: ["python", "-m", "serverfs_mcp.file_ingress"] restart: unless-stopped user: "${SERVERFS_UID:-10001}:${SERVERFS_GID:-10001}" environment: TZ: ${TZ:-Asia/Shanghai} SERVERFS_FILE_INGRESS_ALLOWED_HOSTS: ${SERVERFS_FILE_INGRESS_ALLOWED_HOSTS:-} SERVERFS_FILE_INGRESS_ALLOW_OPENAI_BLOB_HOSTS: ${SERVERFS_FILE_INGRESS_ALLOW_OPENAI_BLOB_HOSTS:-false} SERVERFS_MAX_BINARY_TRANSFER_BYTES: ${SERVERFS_MAX_BINARY_TRANSFER_BYTES:-} SERVERFS_FILE_INGRESS_MAX_BYTES: ${SERVERFS_FILE_INGRESS_MAX_BYTES:-} SERVERFS_FILE_INGRESS_FETCH_TIMEOUT_SECONDS: ${SERVERFS_FILE_INGRESS_FETCH_TIMEOUT_SECONDS:-30} SERVERFS_FILE_INGRESS_MAX_REDIRECTS: ${SERVERFS_FILE_INGRESS_MAX_REDIRECTS:-3} SERVERFS_FILE_INGRESS_PORT: 8081 expose: - "8081" networks: - serverfs_file_ingress - file_ingress_egress read_only: true tmpfs: - /tmp cap_drop: - ALL security_opt: - no-new-privileges:true healthcheck: test: [ "CMD", ".venv/bin/python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8081/healthz', timeout=2).read()", ] interval: 10s timeout: 3s retries: 5 start_period: 5s openai-tunnel: image: ${OPENAI_TUNNEL_IMAGE:-ghcr.io/openai/tunnel-client:v0.0.17} restart: unless-stopped depends_on: serverfs-mcp: condition: service_healthy environment: CONTROL_PLANE_API_KEY: ${CONTROL_PLANE_API_KEY} CONTROL_PLANE_TUNNEL_ID: ${CONTROL_PLANE_TUNNEL_ID} CONTROL_PLANE_BASE_URL: ${CONTROL_PLANE_BASE_URL:-https://api.openai.com} SERVERFS_OPENAI_TUNNEL_USE_PROXY: ${SERVERFS_OPENAI_TUNNEL_USE_PROXY-__serverfs_unset__} SERVERFS_PROXY_HOST: ${SERVERFS_PROXY_HOST:-} SERVERFS_PROXY_PORT: ${SERVERFS_PROXY_PORT:-} SERVERFS_PROXY_USERNAME: ${SERVERFS_PROXY_USERNAME:-} SERVERFS_PROXY_PASSWORD: ${SERVERFS_PROXY_PASSWORD:-} MCP_SERVER_URL: http://serverfs-mcp:${SERVERFS_HTTP_PORT:-8000}${SERVERFS_HTTP_PATH:-/mcp} MCP_STARTUP_WAIT_TIMEOUT: ${MCP_STARTUP_WAIT_TIMEOUT:-60s} LOG_LEVEL: ${TUNNEL_LOG_LEVEL:-info} LOG_FORMAT: ${TUNNEL_LOG_FORMAT:-json} HEALTH_LISTEN_ADDR: ${HEALTH_LISTEN_ADDR:-:8080} entrypoint: ["/bin/sh", "/opt/serverfs/tunnel-launcher.sh"] volumes: - ./deployment/tunnel/tunnel-launcher.sh:/opt/serverfs/tunnel-launcher.sh:ro expose: - "8080" healthcheck: test: [ "CMD-SHELL", "port=$${HEALTH_LISTEN_ADDR##*:}; /usr/bin/tunnel-client health --port \"$${port}\" --require-control-plane-poll", ] interval: 10s timeout: 5s retries: 5 start_period: 10s networks: - serverfs_internal - tunnel_egress cap_drop: - ALL security_opt: - no-new-privileges:true networks: serverfs_internal: internal: true serverfs_file_ingress: internal: true tunnel_egress: file_ingress_egress: