# Optional OAuth 2.1 overlay for remote Streamable HTTP deployments. # # OAuth remains disabled by default. Enable it explicitly in .env, prepare the # state directory for the configured ServerFS UID/GID, then include this file: # # # Defaults shown; substitute the actual .env UID, GID and state path. # # Assigning ownership normally requires sudo; containers remain non-root. # sudo install -d -m 700 -o 10001 -g 10001 -- .serverfs-auth-state # # For matching current-user UID/GID, see docs/oauth.md for no-sudo setup. # docker compose --env-file .env \ # -f compose.yml -f compose.http.yml -f compose.oauth.yml up -d # # A reverse proxy should terminate public HTTPS for both the MCP resource URL # and SERVERFS_AUTH_PUBLIC_URL. The default host publications remain loopback. services: openai-tunnel: environment: # Tunnel OAuth discovery trusts the MCP origin by default. When the # Authorization Server uses a separate origin, list that public origin # here (one origin per line for multiple entries) so discovery can reach # it without broadening MCP forwarding or credential scope. MCP_OAUTH_TRUSTED_ORIGINS: ${MCP_OAUTH_TRUSTED_ORIGINS:-} serverfs-mcp: depends_on: serverfs-auth: condition: service_healthy environment: SERVERFS_OAUTH_ENABLED: ${SERVERFS_OAUTH_ENABLED:-false} SERVERFS_OAUTH_RESOURCE_URL: ${SERVERFS_OAUTH_RESOURCE_URL:-} SERVERFS_OAUTH_ISSUER_URL: ${SERVERFS_OAUTH_ISSUER_URL:-} SERVERFS_OAUTH_REQUIRED_SCOPES: ${SERVERFS_OAUTH_REQUIRED_SCOPES:-serverfs:access} SERVERFS_OAUTH_INTROSPECTION_URL: http://serverfs-auth:${SERVERFS_AUTH_PORT:-8082}/internal/introspect SERVERFS_OAUTH_INTROSPECTION_SECRET: ${SERVERFS_OAUTH_INTROSPECTION_SECRET:-} SERVERFS_OAUTH_INTROSPECTION_TIMEOUT_SECONDS: ${SERVERFS_OAUTH_INTROSPECTION_TIMEOUT_SECONDS:-2} networks: - serverfs_auth_internal serverfs-auth: image: ${SERVERFS_IMAGE:-ghcr.io/ntlx/serverfs_mcp:latest} command: ["serverfs-auth"] restart: unless-stopped user: "${SERVERFS_UID:-10001}:${SERVERFS_GID:-10001}" environment: TZ: ${TZ:-Asia/Shanghai} SERVERFS_LOG_LEVEL: ${SERVERFS_LOG_LEVEL:-INFO} SERVERFS_OAUTH_ENABLED: ${SERVERFS_OAUTH_ENABLED:-false} SERVERFS_OAUTH_RESOURCE_URL: ${SERVERFS_OAUTH_RESOURCE_URL:-} SERVERFS_OAUTH_ISSUER_URL: ${SERVERFS_OAUTH_ISSUER_URL:-} SERVERFS_OAUTH_INTROSPECTION_SECRET: ${SERVERFS_OAUTH_INTROSPECTION_SECRET:-} SERVERFS_AUTH_HOST: 0.0.0.0 SERVERFS_AUTH_PORT: ${SERVERFS_AUTH_PORT:-8082} SERVERFS_AUTH_PUBLIC_URL: ${SERVERFS_AUTH_PUBLIC_URL:-} SERVERFS_AUTH_STATE_DIR: /var/lib/serverfs-auth SERVERFS_AUTH_CLIENTS_FILE: ${SERVERFS_AUTH_CLIENTS_FILE:-} SERVERFS_AUTH_ALLOWED_PRINCIPALS: ${SERVERFS_AUTH_ALLOWED_PRINCIPALS:-} SERVERFS_AUTH_ACCESS_TOKEN_TTL_SECONDS: ${SERVERFS_AUTH_ACCESS_TOKEN_TTL_SECONDS:-3600} SERVERFS_AUTH_REFRESH_TOKEN_TTL_SECONDS: ${SERVERFS_AUTH_REFRESH_TOKEN_TTL_SECONDS:-2592000} SERVERFS_AUTH_DCR_ENABLED: ${SERVERFS_AUTH_DCR_ENABLED:-false} SERVERFS_AUTH_USE_PROXY: ${SERVERFS_AUTH_USE_PROXY:-false} SERVERFS_PROXY_HOST: ${SERVERFS_PROXY_HOST:-} SERVERFS_PROXY_PORT: ${SERVERFS_PROXY_PORT:-} SERVERFS_PROXY_USERNAME: ${SERVERFS_PROXY_USERNAME:-} SERVERFS_PROXY_PASSWORD: ${SERVERFS_PROXY_PASSWORD:-} SERVERFS_OAUTH_GITHUB_ENABLED: ${SERVERFS_OAUTH_GITHUB_ENABLED:-false} SERVERFS_OAUTH_GITHUB_CLIENT_ID: ${SERVERFS_OAUTH_GITHUB_CLIENT_ID:-} SERVERFS_OAUTH_GITHUB_CLIENT_SECRET: ${SERVERFS_OAUTH_GITHUB_CLIENT_SECRET:-} SERVERFS_OAUTH_DINGTALK_ENABLED: ${SERVERFS_OAUTH_DINGTALK_ENABLED:-false} SERVERFS_OAUTH_DINGTALK_CLIENT_ID: ${SERVERFS_OAUTH_DINGTALK_CLIENT_ID:-} SERVERFS_OAUTH_DINGTALK_CLIENT_SECRET: ${SERVERFS_OAUTH_DINGTALK_CLIENT_SECRET:-} SERVERFS_OAUTH_FEISHU_ENABLED: ${SERVERFS_OAUTH_FEISHU_ENABLED:-false} SERVERFS_OAUTH_FEISHU_CLIENT_ID: ${SERVERFS_OAUTH_FEISHU_CLIENT_ID:-} SERVERFS_OAUTH_FEISHU_CLIENT_SECRET: ${SERVERFS_OAUTH_FEISHU_CLIENT_SECRET:-} SERVERFS_OAUTH_WECHAT_ENABLED: ${SERVERFS_OAUTH_WECHAT_ENABLED:-false} SERVERFS_OAUTH_WECHAT_CLIENT_ID: ${SERVERFS_OAUTH_WECHAT_CLIENT_ID:-} SERVERFS_OAUTH_WECHAT_CLIENT_SECRET: ${SERVERFS_OAUTH_WECHAT_CLIENT_SECRET:-} volumes: - type: bind source: ${SERVERFS_AUTH_STATE_HOST_DIR:-./.serverfs-auth-state} target: /var/lib/serverfs-auth read_only: false bind: create_host_path: false expose: - "${SERVERFS_AUTH_PORT:-8082}" ports: - "${SERVERFS_AUTH_PUBLISH_HOST:-127.0.0.1}:${SERVERFS_AUTH_PUBLISH_PORT:-8082}:${SERVERFS_AUTH_PORT:-8082}" networks: - serverfs_auth_internal - oauth_egress read_only: true tmpfs: - /tmp cap_drop: - ALL security_opt: - no-new-privileges:true healthcheck: test: [ "CMD", ".venv/bin/python", "-c", "import os,urllib.request; p=os.environ.get('SERVERFS_AUTH_PORT','8082'); urllib.request.urlopen(f'http://127.0.0.1:{p}/healthz', timeout=2).read()", ] interval: 10s timeout: 3s retries: 5 start_period: 5s networks: serverfs_auth_internal: internal: true oauth_egress: