networks: internal: driver: bridge volumes: caddy-data: caddy-config: secrets: deribit_credentials: file: ./secrets/deribit.json hyperliquid_wallet: file: ./secrets/hyperliquid.json bybit_credentials: file: ./secrets/bybit.json alpaca_credentials: file: ./secrets/alpaca.json macro_credentials: file: ./secrets/macro.json sentiment_credentials: file: ./secrets/sentiment.json core_token: file: ./secrets/core.token observer_token: file: ./secrets/observer.token x-common-security: &common-security cap_drop: [ALL] security_opt: - no-new-privileges:true restart: unless-stopped networks: [internal] services: # ======================================================== # GATEWAY — unica porta host, reverse proxy + landing page # ======================================================== gateway: image: caddy:2-alpine restart: unless-stopped networks: [internal] security_opt: - no-new-privileges:true ports: ["${GATEWAY_PORT:-8080}:8080"] volumes: - ./gateway/Caddyfile:/etc/caddy/Caddyfile:ro - ./gateway/public:/srv:ro - caddy-data:/data - caddy-config:/config depends_on: mcp-deribit: { condition: service_healthy } mcp-hyperliquid: { condition: service_healthy } mcp-bybit: { condition: service_healthy } mcp-alpaca: { condition: service_healthy } mcp-macro: { condition: service_healthy } mcp-sentiment: { condition: service_healthy } healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/"] interval: 30s timeout: 5s retries: 3 # ======================================================== # MCP — accessibili solo via gateway (nessuna porta host) # ======================================================== mcp-deribit: image: cerbero-mcp-deribit:dev build: context: . dockerfile: docker/mcp-deribit.Dockerfile <<: *common-security user: "1000:1000" read_only: true tmpfs: - /tmp:rw,size=64M,mode=1777 secrets: [deribit_credentials, core_token, observer_token] environment: CREDENTIALS_FILE: /run/secrets/deribit_credentials CORE_TOKEN_FILE: /run/secrets/core_token OBSERVER_TOKEN_FILE: /run/secrets/observer_token DERIBIT_TESTNET: "true" # override secrets/deribit.json testnet flag ROOT_PATH: /mcp-deribit mcp-hyperliquid: image: cerbero-mcp-hyperliquid:dev build: context: . dockerfile: docker/mcp-hyperliquid.Dockerfile <<: *common-security user: "1000:1000" read_only: true tmpfs: - /tmp:rw,size=64M,mode=1777 secrets: [hyperliquid_wallet, core_token, observer_token] environment: HYPERLIQUID_WALLET_FILE: /run/secrets/hyperliquid_wallet CORE_TOKEN_FILE: /run/secrets/core_token OBSERVER_TOKEN_FILE: /run/secrets/observer_token ROOT_PATH: /mcp-hyperliquid mcp-bybit: image: cerbero-mcp-bybit:dev build: context: . dockerfile: docker/mcp-bybit.Dockerfile <<: *common-security user: "1000:1000" read_only: true tmpfs: - /tmp:rw,size=64M,mode=1777 secrets: [bybit_credentials, core_token, observer_token] environment: BYBIT_CREDENTIALS_FILE: /run/secrets/bybit_credentials CORE_TOKEN_FILE: /run/secrets/core_token OBSERVER_TOKEN_FILE: /run/secrets/observer_token BYBIT_TESTNET: "true" # override secrets/bybit.json testnet flag ROOT_PATH: /mcp-bybit PORT: "9019" mcp-alpaca: image: cerbero-mcp-alpaca:dev build: context: . dockerfile: docker/mcp-alpaca.Dockerfile <<: *common-security user: "1000:1000" read_only: true tmpfs: - /tmp:rw,size=64M,mode=1777 secrets: [alpaca_credentials, core_token, observer_token] environment: ALPACA_CREDENTIALS_FILE: /run/secrets/alpaca_credentials CORE_TOKEN_FILE: /run/secrets/core_token OBSERVER_TOKEN_FILE: /run/secrets/observer_token ALPACA_PAPER: "true" ROOT_PATH: /mcp-alpaca PORT: "9020" mcp-macro: image: cerbero-mcp-macro:dev build: context: . dockerfile: docker/mcp-macro.Dockerfile <<: *common-security user: "1000:1000" read_only: true tmpfs: - /tmp:rw,size=64M,mode=1777 secrets: [macro_credentials, core_token, observer_token] environment: MACRO_CREDENTIALS_FILE: /run/secrets/macro_credentials CORE_TOKEN_FILE: /run/secrets/core_token OBSERVER_TOKEN_FILE: /run/secrets/observer_token ROOT_PATH: /mcp-macro mcp-sentiment: image: cerbero-mcp-sentiment:dev build: context: . dockerfile: docker/mcp-sentiment.Dockerfile <<: *common-security user: "1000:1000" read_only: true tmpfs: - /tmp:rw,size=64M,mode=1777 secrets: [sentiment_credentials, core_token, observer_token] environment: SENTIMENT_CREDENTIALS_FILE: /run/secrets/sentiment_credentials CORE_TOKEN_FILE: /run/secrets/core_token OBSERVER_TOKEN_FILE: /run/secrets/observer_token ROOT_PATH: /mcp-sentiment