# A single hushgate in front of your applications. # # docker compose up --build # # The port is published on loopback only. hushgate holds the mapping from # placeholders back to real personal data, so exposing it to the network is a # decision to be taken deliberately — and then only with tenants defined. services: hushgate: build: . # Built from this checkout, so the tag names no release. Retag it for your # registry before deploying it anywhere else. image: hushgate:local restart: unless-stopped ports: - '127.0.0.1:8787:8787' environment: # Credentials belong in the environment, never in the config file. OPENAI_API_KEY: ${OPENAI_API_KEY:-} ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY:-} HUSHGATE_HMAC_KEY: ${HUSHGATE_HMAC_KEY:-} # Overrides limits.idleTimeoutMs in the config file: how long a # connection may sit silent between bytes before it is closed. Left # commented because the config file should stay the single reviewed # source for limits — uncomment only to stretch it for clients that # hold requests open a long while before streaming. An idle connection # costs nearly nothing in memory, but it does hold a file descriptor, # and the reaper closes stalled connections on its own schedule; check # the container's nofile limit before pushing this far past its # default of sixty seconds. # HUSHGATE_IDLE_TIMEOUT_MS: '600000' volumes: # Your policy, read-only: the container has no business rewriting it. - ./hushgate.config.json:/app/hushgate.config.json:ro # The audit trail has to outlive the container. - hushgate-audit:/var/lib/hushgate read_only: true tmpfs: - /tmp cap_drop: - ALL security_opt: - no-new-privileges:true healthcheck: test: ['CMD', 'node', '-e', "fetch('http://127.0.0.1:8787/healthz').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"] interval: 30s timeout: 3s retries: 3 start_period: 5s volumes: hushgate-audit: