Self-hosting
Run Gatehouse in your own network with Docker or Kubernetes, manage the master key, and take backups.
Gatehouse is one Node.js process with one SQLite database on a volume. There's no other service to run. It works fully air-gapped.
What Gatehouse connects to
Gatehouse makes no outbound calls except to what you configure:
- the MCP servers you add,
- your identity providers (for SSO),
- your SMTP server (for invites and resets),
- Slack (for approvals), if you turn it on,
- your audit streaming destination.
There is no telemetry, license check or phone-home.
Docker Compose
openssl rand -base64 32 > deploy/master.key && chmod 600 deploy/master.key
docker build -t gatehouse .
Edit deploy/docker-compose.yml and set at least GATEHOUSE_BASE_URL to the address people and agents will use. Then:
cd deploy && docker compose up -d
docker compose logs gatehouse | grep "setup code"
Open <base url>/setup, enter the code and create the owner account.
The compose file:
- listens on port 8787,
- stores data on a named volume mounted at /data,
- reads the master key from a Docker secret via
GATEHOUSE_MASTER_KEY_FILE, - runs with a read-only root filesystem and
no-new-privileges.
The image runs as the unprivileged node user, sets HOST=0.0.0.0 and GATEHOUSE_ENV=production, and has a health check on /healthz.
Kubernetes with Helm
The chart is in deploy/helm/gatehouse.
kubectl create secret generic gatehouse-key --from-file=master.key=./master.key
helm install gatehouse deploy/helm/gatehouse \
--set baseUrl=https://gatehouse.example.com \
--set masterKey.existingSecret=gatehouse-key
Useful values:
| Value | Purpose |
|---|---|
baseUrl |
Public URL. The MCP endpoint is <baseUrl>/mcp. |
orgName |
Shown in the console and emails. |
masterKey.existingSecret |
A Secret with key master.key. Recommended. |
masterKey.command |
Fetch the key from your KMS or vault at startup instead. |
extraEnv, extraEnvFrom |
SMTP, Slack and other settings. Use extraEnvFrom for secrets. |
persistence.size |
Volume size, 10Gi by default. |
ingress.* |
Expose Gatehouse through your ingress controller. |
Run exactly one replica. The database is SQLite on a volume, so the chart uses the Recreate deployment strategy. Expect a short gap during upgrades.
Put TLS in front
Gatehouse serves plain HTTP. Terminate TLS at your load balancer, ingress or reverse proxy, and use an https:// base URL. OAuth for agents and SSO callbacks rely on it.
Behind a proxy, set GATEHOUSE_TRUST_PROXY so audit entries and the IP allow-list see real client addresses. Use the proxy's address range (for example 10.0.0.0/8). Use 1 only if nothing but the proxy can reach Gatehouse, since any client that reaches it directly could otherwise fake its address. In Kubernetes, set trustProxy in the chart values; the chart's NetworkPolicy (on by default) lets only your ingress controller in.
For a single cloud server with HTTPS and backups set up for you, see Deploy on AWS Lightsail. Backups are covered in Backups and restore, and license keys in Licensing.
For a locked-down install, set GATEHOUSE_STDIO_COMMANDS to the programs you allow (like npx,uvx), or GATEHOUSE_DISABLE_STDIO=true to allow remote MCP servers only. See Configuration.
The master key
The master key encrypts every stored credential: server tokens, SSO client secrets and the audit stream secret. It's 32 random bytes, base64-encoded:
openssl rand -base64 32
Gatehouse reads it from the first of these that's set:
GATEHOUSE_MASTER_KEY_COMMAND: a command that prints the key. The key never touches disk.- AWS KMS:
aws kms decrypt --ciphertext-blob fileb:///kms/key.enc --query Plaintext --output text - Vault:
vault kv get -field=key secret/gatehouse
- AWS KMS:
GATEHOUSE_MASTER_KEY_FILE: a file with the key, for Docker and Kubernetes secrets.GATEHOUSE_MASTER_KEY: the key itself.
With GATEHOUSE_ENV=production, the default in the image, Gatehouse refuses to start without one of these. Outside production it generates data/master.key for convenience.
Keep a safe copy of the key. Without it, stored credentials can't be decrypted. People, policies and the audit log stay readable, but you'd need to re-enter every server credential.
Backups
npm run cli -- backup /data/backups/gatehouse-$(date +%F).db
This uses SQLite's VACUUM INTO to write a consistent copy, and it's safe while Gatehouse is running. In Docker:
docker compose exec gatehouse npm run cli -- backup /data/backups/gatehouse-$(date +%F).db
Copy backups off the volume and store the master key separately. To restore, stop Gatehouse, put the backup file in place of /data/gatehouse.db, and start it with the same master key.
Upgrades
Build or pull the new image and restart. Gatehouse updates its database schema on start. Take a backup first.
Email and Slack
Set SMTP_* to send invites and password resets. Without SMTP, admins copy links by hand. Set SLACK_* for Slack approvals. Slack uses Socket Mode, so no inbound connection is needed. See Configuration.