Personal mode is npx octoport up --open on a laptop. This document covers
the organization shape: one octoport for a team, behind TLS, with SSO.
employees' MCP clients ──▶ https://mcp.company.internal (TLS proxy)
│
octoport container
│─ /data volume (config, tokens, OAuth grants, call log)
└─▶ downstream MCP servers
octoport never terminates TLS. Put Caddy (deploy/Caddyfile), nginx, or your
load balancer in front, and run the container bound to loopback-published
ports only (127.0.0.1:6286:6286 as in deploy/docker-compose.yml).
cd deploy
# edit docker-compose.yml: replace mcp.company.internal with your hostname
docker compose up -d
docker compose exec octoport node dist/cli.js token # initial admin token + dashboard URLFlags that matter for a central deployment:
| Flag | Why |
|---|---|
--host 0.0.0.0 |
containers must bind all interfaces |
--allow-host <hostname> |
the exact Host employees use — DNS-rebinding guard |
--behind-proxy |
acknowledgement that TLS terminates upstream |
--public-url https://… |
snippets, dashboard display, and OAuth callbacks use the external URL |
GET /healthz— token-exempt liveness/readiness (wire it to your proxy or orchestrator).GET /metrics— Prometheus text format; scrape with an admin-scope bearer token.- Call log: SQLite at
/data/calls.sqlite; retention vialogRetentionDaysin config;octoport logs --jsonlor the dashboard export for SIEM ingestion. - Payloads: set
"logPayloads": falseglobally (or per server) to keep the audit metadata-only.
Keep credentials out of config.json: any env/header/oauth value that is
exactly a reference resolves at connect time —
file:// pairs with Docker/Kubernetes secrets mounts; vault:// reads
HashiCorp KV v2 using $VAULT_ADDR + $VAULT_TOKEN (the standard Vault
agent/sidecar contract), cached for 5 minutes. ${VAR} expansion still works.
- OIDC: see idp.md. Employees authenticate with company access
tokens; profiles map IdP groups to servers/tools. Non-admin identities
opening the hub in a browser land on the
/myportal (their per-user server authorizations); the admin dashboard and API stay admin-scope. - Local tokens remain for CI/service accounts and break-glass. In org mode
create them hashed (
hashed: true) with an expiry (expiresDays) and themcpscope only; keep exactly one full-admin token in a password manager.
Everything durable lives in the /data volume:
config.json— servers, tokens (hashes + any plaintext ones), profiles, OIDC settingsoauth/*.json— downstream OAuth grants (shared and per-user)calls.sqlite— the audit log
Backup = snapshot the volume (the config write path is atomic; SQLite is
WAL — prefer stopping the container or using sqlite3 .backup for consistency).
Treat backups as secret material.
Upgrade: pull/build the new image, docker compose up -d. Schema changes
migrate forward automatically (additive ALTER TABLEs). Rollback: run the
previous image against the same volume — older versions ignore newer optional
config fields, and the call-log schema is additive, so this is safe within one
minor-version step. Take a volume snapshot before major upgrades.
One octoport process serves a small-to-mid team comfortably (calls are I/O-bound relays). It is intentionally single-node: SQLite + in-process state. If you outgrow it, that is the Postgres/HA milestone on the roadmap — tell us before you need it.