version: "3.9" # ThreeGate infrastructure skeleton # # Notes: # - This compose file is intentionally conservative and minimal. # - Images are placeholders; pin by digest in production. # - Network isolation is part of the security model; do not “simplify” it away. # - Egress must be enforced both here (networks) and on the host (DOCKER-USER chain). name: threegate services: # ------------------------------------------------------------ # CORE: analysis & writing (NO INTERNET) # ------------------------------------------------------------ core: image: threegate/core:0.1 container_name: threegate-core networks: - llmnet environment: - THREEGATE_ROLE=core - NO_PROXY=* volumes: # Policy is always read-only - ../policy:/srv/threegate/policy:ro # CORE workspace - ./volumes/core-workspace:/srv/threegate/core/workspace # One-way inbound: validated packets/results only (mounted ro into CORE) - ./volumes/handoff/inbound-to-core:/srv/threegate/handoff/inbound-to-core:ro # Optional outbound request drafts (CORE -> human -> fetch/tool-exec) - ./volumes/handoff/inbound-to-fetch:/srv/threegate/handoff/inbound-to-fetch - ./volumes/tool-exec/requests_in:/srv/threegate/tool-exec/requests_in # Optional manual PDF lane (read-only) - ./volumes/dropbox/pdfs_in:/srv/threegate/dropbox/pdfs_in:ro read_only: true tmpfs: - /tmp security_opt: - no-new-privileges:true cap_drop: - ALL restart: unless-stopped depends_on: - rolemesh # ------------------------------------------------------------ # FETCH: controlled retrieval (INTERNET ONLY VIA PROXY) # ------------------------------------------------------------ fetch: image: threegate/fetch:0.1 container_name: threegate-fetch networks: - llmnet - fetchnet environment: - THREEGATE_ROLE=fetch # Proxy is the only intended egress. Keep both set. - http_proxy=http://proxy:3128 - https_proxy=http://proxy:3128 - HTTP_PROXY=http://proxy:3128 - HTTPS_PROXY=http://proxy:3128 - NO_PROXY=localhost,127.0.0.1,rolemesh,core volumes: - ../policy:/srv/threegate/policy:ro - ./volumes/fetch-workspace:/srv/threegate/fetch/workspace # FETCH writes packets here; validator moves accepted packets to inbound-to-core - ./volumes/handoff/inbound-to-core:/srv/threegate/handoff/inbound-to-core - ./volumes/handoff/quarantine:/srv/threegate/handoff/quarantine - ./volumes/handoff/inbound-to-fetch:/srv/threegate/handoff/inbound-to-fetch:ro - ./volumes/tools:/srv/threegate/tools:ro read_only: true tmpfs: - /tmp security_opt: - no-new-privileges:true cap_drop: - ALL restart: unless-stopped depends_on: - proxy - rolemesh # ------------------------------------------------------------ # TOOL-EXEC: execution sandbox coordinator (ERA-backed) # Note: This service does NOT need network by default. # It orchestrates ERA runs and writes tool results to inbound-to-core. # ------------------------------------------------------------ tool-exec: image: threegate/tool-exec:0.1 container_name: threegate-tool-exec networks: - llmnet environment: - THREEGATE_ROLE=tool-exec - ERA_BACKEND=ERA # Default: forbid guest volumes unless explicitly enabled by operator policy - AGENT_ENABLE_GUEST_VOLUMES=0 - NO_PROXY=* volumes: - ../policy:/srv/threegate/policy:ro - ./volumes/tool-exec/requests_in:/srv/threegate/tool-exec/requests_in:ro - ./volumes/tool-exec/results_out:/srv/threegate/tool-exec/results_out - ./volumes/handoff/inbound-to-core:/srv/threegate/handoff/inbound-to-core - ./volumes/handoff/quarantine:/srv/threegate/handoff/quarantine - ./volumes/tools:/srv/threegate/tools:ro # ERA integration will usually require host resources (e.g., /dev/kvm) # Keep this commented until you implement TOOL-EXEC runner and review risks. # - /dev/kvm:/dev/kvm read_only: true tmpfs: - /tmp security_opt: - no-new-privileges:true cap_drop: - ALL restart: unless-stopped depends_on: - rolemesh # ------------------------------------------------------------ # PROXY: managed egress (sole internet exit for FETCH) # ------------------------------------------------------------ proxy: image: docker.io/library/squid:6 container_name: threegate-proxy networks: - fetchnet - egressnet volumes: - ./infra/proxy/squid.conf:/etc/squid/squid.conf:ro - ./volumes/proxy-cache:/var/spool/squid ports: # Expose to host only if you need to debug; otherwise keep internal-only. # - "3128:3128" restart: unless-stopped # ------------------------------------------------------------ # LLM Gateway: local / proxied LLM access (OpenAI-compatible) # Placeholder for RoleMesh-Gateway; replace with your actual gateway image/config. # ------------------------------------------------------------ rolemesh: image: threegate/rolemesh-gateway:0.1 container_name: threegate-rolemesh networks: - llmnet environment: - THREEGATE_ROLE=llm-gateway # Typically you will expose this only to other containers on llmnet. # ports: # - "8080:8080" read_only: true tmpfs: - /tmp security_opt: - no-new-privileges:true cap_drop: - ALL restart: unless-stopped networks: # Internal network: CORE/FETCH/TOOL-EXEC + gateway only llmnet: driver: bridge internal: true # Internal network between FETCH and proxy fetchnet: driver: bridge internal: true # Egress network for proxy only egressnet: driver: bridge internal: false