Getting started

Architecture

Service topology and request flow for self-hosted ctxpipe.

Self-hosted ctxpipe uses the same product architecture as hosted ctxpipe, but the operator owns the runtime, network boundary, secrets, and stateful services. Keep the browser, REST API, auth callbacks, and MCP endpoint on the same public backend origin.

Request flow

  1. The browser opens your public AUTH_BASE_URL.
  2. The backend serves API, auth, webhook, and MCP routes from that origin.
  3. The backend proxies UI requests to the ui service.
  4. Auth sessions, repository records, connections, and workflow state live in Postgres.
  5. Repository ingestion calls codesearch, which clones repositories and maintains Zoekt indexes. Codesearch is a single replica: Zoekt shards, git clone cache, and SCIP artifacts live on one process and one volume. Extra worker replicas do not raise ingest throughput unless codesearch memory (and OPENWORKFLOW_CONCURRENCY / indexer caps) also grow.
  6. The worker runs durable jobs for ingestion, connector setup, scoped source mirrors, Slack thread capture, and Forge provisioning.
  7. Extracted claims and relationships are projected into the configured graph database.
  8. Chat and MCP tools retrieve from Postgres, codesearch, and the graph database before calling your configured model provider.

Services

ServiceDefault portStatefulPurpose
backend3000NoPublic API, auth, MCP, callbacks, UI proxy
ui3002NoProduct web app, proxied by backend
workerinternalNoBackground workflows and connector jobs
codesearch3001YesRepository clone cache and Zoekt index. Stay at one replica.
postgres5432 internal (no host port in the deploy profile)YesPrimary relational state
falkordb6379 Redis, 7687 Bolt, internalYesDefault graph database
dind (Docker Compose)2376 internalNoDocker daemon for Workspace chat sandboxes

Chat sandbox network policy

The same policy holds on Docker Compose and AWS:

  • A chat sandbox holds no credential. It has no GitHub token, no model proxy credential, and no tool bridge token in its environment, files, or Git configuration. Agent Vault (open source) runs next to the sandboxes and adds each credential to the requests that need it.
  • Sandboxes reach the network only through the Agent Vault proxy. On Compose, rules in the dind service enforce this; on AWS, DOCKER-USER rules on the sandbox host do. HTTP and HTTPS stay open: agents can clone, fetch, push, call the GitHub CLI, install packages, and read documentation on the internet. The proxy forwards hosts that have no credential rule as they are.
  • All other traffic from a sandbox is blocked: a direct connection that does not use the proxy, any non-HTTP protocol (SSH, raw TCP, UDP), and DNS. Sandboxes do not resolve names; the proxy resolves them.
  • Private addresses through the proxy: on Compose, only the backend's fixed address on the sandbox network. On AWS, only the backend's subnets; the host also rejects traffic from Agent Vault to the host itself. Agent Vault never reaches its own management API. Data stores are never exposed to sandboxes: Compose never publishes Postgres or FalkorDB, and AWS admits only the app's security group to them.
  • Sandboxes cannot reach cloud instance metadata (169.254.169.254).
  • Each agent port needs a password, and sandboxes cannot reach each other over the Docker bridge.
  • Each chat turn gets its own Agent Vault vault and proxy session. The backend deletes the vault when the turn ends, and the session stops with it. The backend also revokes the turn's GitHub token.
  • If Agent Vault does not answer, Docker chat fails closed with a clear error. The backend never gives a sandbox a credential instead.

The deployment generates the Agent Vault passwords. You do not set them. On Compose, the master password is on a volume that only Agent Vault mounts, and the owner password is on a volume that only the backend and the worker mount. On AWS, the stack keeps both in Secrets Manager; only the host reads the master password.

Agent Vault owner password

The backend registers the owner password on its first login to an Agent Vault with no owner. After that, Agent Vault refuses another password, and Docker chat fails closed with an error that names this section. To change the password, change it in Agent Vault first (agent-vault account change-password, or its web UI on port 14321 inside the deployment), then give the backend the new value. To start over, remove Agent Vault's data (Compose: the agent_vault_data volume; AWS: replace the sandbox host). Run vaults are temporary, so no data is lost.

Tools in a sandbox must use the standard proxy variables (HTTPS_PROXY, HTTP_PROXY) and trust the proxy's certificate authority. The sandbox environment sets both. A tool that ignores the proxy variables cannot reach the network.

Chat sandboxes on Docker Compose

Compose runs each Workspace conversation's agent in its own container inside dind, a stock Docker-in-Docker service. dind, agent-vault, backend, and worker share a separate sandbox network (172.30.99.0/24):

ComponentPortReached byPurpose
Docker API (mutual TLS)2376backend, workerCreate, stop, resume, and remove sandboxes
Sandbox agent ports (password per conversation)32768–60999 on dindbackendThe backend talks to the agent in each sandbox
Agent Vault API14321backend, workerOne vault per chat turn
Agent Vault proxy14322Sandboxes (the only address they reach)Adds credentials and forwards HTTP(S)
Backend model proxy and tool bridges3000 and per-run ports on backend.sandbox.ctxpipe.internalAgent Vault, for sandboxesModel calls and tool calls go back to the backend

See Docker: Chat sandboxes.

Chat sandbox host on AWS

On AWS, @ctxpipe/aws-cdk adds one EC2 Docker host next to the Fargate services. Each Workspace conversation's agent runs in its own container there.

ComponentPortReached byPurpose
Docker API (mutual TLS)2376backend, workerCreate, stop, resume, and remove sandboxes
Sandbox agent ports (password per conversation)32768–60999backendThe backend talks to the agent in each sandbox
Agent Vault API14321backend, workerOne vault per chat turn
Agent Vault proxy14322 (on the host)Sandboxes (the only address they reach)Adds credentials and forwards HTTP(S)
Backend model proxy and tool bridges3000, 32768–60999Agent Vault, for sandboxesModel calls and tool calls go back to the backend task that runs the turn, at its VPC DNS name

DOCKER-USER rules on the host let sandboxes reach only the Agent Vault proxy. Agent Vault reaches the internet through NAT and may dial private addresses only in the VPC. Security groups keep Postgres, Neptune, EFS, codesearch, the UI, and the worker away from the host. The host also blocks sandboxes from the host itself. See AWS: Chat sandbox host.

Public surface

Expose the backend origin publicly. Keep internal services private unless you have a specific operational need.

Route or endpointPublic?Notes
/YesBackend proxies UI requests
/.auth/*YesBetter Auth routes and provider callbacks
/api/v1/*YesREST API and connector callbacks
/:orgSlug/api/v1/*YesOrganization-scoped REST API
/mcpYesStreamable HTTP MCP endpoint. Tool calls name the organization in org
/.statusOptionalBasic backend status endpoint
ui:3002NoInternal service behind backend. Docker Compose binds it to 127.0.0.1 only.
codesearch:3001NoInternal service called by backend and workflows. Docker Compose binds it to 127.0.0.1 only.
postgres, falkordbNoStateful infrastructure. Never published.

Stateful data

Back up anything you cannot rebuild quickly.

DataLocationRecovery note
App databasePostgres. On Compose, an anonymous volume unless you mount a named one (see Docker).Required. Contains users, sessions, repositories, connections, workflow state, and encrypted connector metadata.
Graph dataFalkorDB or another graph database. On Compose, the writable layer of the falkordb container unless you mount a named volume (see Docker).Back up for fast recovery. Some graph data may be regenerated by reindexing, but that can be slow and may not cover all operational state.
Repository cacherepo_cache volume in Compose, EFS /data on AWS CDK, a Railway volume on TerraformRebuildable by recloning, but useful to retain.
Zoekt indexzoekt_index_deploy volume in Compose, EFS /data on AWS CDK, a Railway volume on TerraformRebuildable by reindexing, but can be expensive for large repositories.
Chat sandboxessandbox_docker volume in Compose, Docker volume on the AWS sandbox hostNo backup needed. Conversations keep their work in their git branch, and a lost sandbox is created again from it.
SecretsDeployment secret store or .env filesRequired to decrypt sessions and connector credentials. Protect and version changes carefully.