Headless gateway and Docker
docker pull ghcr.io/btsouth/toolport-gateway:latest
mkdir -p data
cp data/registry.json.example data/registry.json
cp docker-compose.example.yml docker-compose.yml
# create .env with at least TOOLPORT_HTTP_TOKEN=...
docker compose up -dImage defaults: TOOLPORT_HTTP_HOST=0.0.0.0, TOOLPORT_REGISTRY=/data/registry.json, port 8765, volume /data. The image runs as user toolport (uid 10001).
export TOOLPORT_HTTP_HOST=0.0.0.0
export TOOLPORT_HTTP_TOKEN="$(openssl rand -hex 24)"
export TOOLPORT_REGISTRY=/path/to/registry.json
toolport-gateway --http 8765From source, compiling inside Docker:
docker build -f Dockerfile.source -t toolport-gateway .Or build the binary on the host, then the runtime image:
cargo build --release --bin toolport-gateway --manifest-path src-tauri/Cargo.toml --no-default-features
cp src-tauri/target/release/toolport-gateway toolport-gateway-bin
docker build -t toolport-gateway .Point an MCP client at http://host:8765/mcp, or Open WebUI at http://host:8765 with the token as its API key.
Secrets without a keychain#
Put secrets in .env with the TOOLPORT_SECRET_ prefix:
TOOLPORT_HTTP_TOKEN=replace-me
TOOLPORT_SECRET_STRIPE_SECRET_KEY=sk_live_...Or set TOOLPORT_SECRET_KEY and use the encrypted secrets.enc vault. The full order is in Configuration.
Stdio servers need their runtimes (node/npx, uv) in the image. Remote MCP servers need nothing extra.
Production checklist#
Network and auth
- Bearer token with at least 24 bytes of entropy, or scoped
httpClients[]. - Firewall the port; do not publish
:8765to the internet without a reverse proxy. - Terminate TLS in front: the gateway speaks plain HTTP.
- The gateway allows 10 seconds for headers and 30 for the body, then returns 408. Keep proxy deadlines at least as strict.
Secrets and registry
- Use
TOOLPORT_SECRET_KEYwithsecrets.enc, orTOOLPORT_SECRET_<KEY>env vars. - Keep
.envat mode600and never commit it. - Persist
/data/registry.jsonon a volume and back it up before upgrades. A corrupt file is quarantined, not wiped. - Set
humanApproval: false: without the desktop approval broker, gated tools fail closed.
Runtime
- Browser OAuth needs the desktop app. Use API keys or pre-vaulted secrets.
- The first
npx/uvxconnect can take up to about 2 minutes while the package downloads. - Pin the image by digest or version tag in production.