Configuration
Configure Docker Compose, environment variables, and connector secrets for self-hosted ctx|.
Configuration is environment-driven. Set only the values your deployment needs, but treat the required auth, database, model, and public-origin values as production secrets.
Runtime requirements
- A supported deployment path: Docker Compose, the repository Terraform stack (Railway + Neon), or AWS CDK
- PostgreSQL 17; the reference Compose image is pgvector on Postgres 17
- A graph database; FalkorDB is included in the reference Compose stack
- An SMTP provider for transactional email
- An OpenRouter, Azure, Bedrock, or OpenAI-compatible model provider
- A public HTTPS origin for production auth callbacks, webhooks, MCP, and Forge remotes
Docker Compose
Clone the repository and copy the example environment file:
git clone https://github.com/ctxpipe-ai/ctxpipe.git
cd ctxpipe
cp docker-compose.env.example .envEdit .env with your values. The full production-style stack is the Compose
deploy profile:
pnpm startThe deploy profile starts Postgres, FalkorDB, migrator, backend, worker, UI,
and codesearch. It does not start an OpenTelemetry collector. The backend
listens on the public app port and proxies the UI.
Required variables
| Variable | Description |
|---|---|
DATABASE_URL | PostgreSQL connection string, for example postgresql://user:pass@host:5432/db |
AUTH_SECRET | Random 32+ character string for session signing. Generate with openssl rand -hex 32. |
AUTH_BASE_URL | Public URL of your ctx| instance, for example https://ctx.example.com |
CTXPIPE_PUBLIC_APP_URL | Public backend URL baked into the UI image. Usually the same value as AUTH_BASE_URL. |
MODEL_PROVIDER_API_KEY | API key for your configured model provider |
| Variable | Description |
|---|---|
SMTP_CONNECTION_URL | SMTP connection URL, for example smtps://user:[email protected]:465 |
EMAIL_FROM_ADDRESS | From address for transactional email, for example [email protected] |
Social sign-in
All social providers are optional. Omit the variables to disable that provider.
| Variable | Description |
|---|---|
GITHUB_CLIENT_ID | GitHub OAuth app client ID |
GITHUB_CLIENT_SECRET | GitHub OAuth app client secret |
GOOGLE_CLIENT_ID | Google OAuth client ID |
GOOGLE_CLIENT_SECRET | Google OAuth client secret |
MICROSOFT_CLIENT_ID | Microsoft Entra application client ID |
MICROSOFT_CLIENT_SECRET | Microsoft Entra client secret |
See Authentication for OAuth and session behavior.
Models and embeddings
| Variable | Description |
|---|---|
MODEL_PROVIDER | Optional. openai-like default, openrouter, azure, or bedrock. |
MODEL_PROVIDER_API_KEY | API key for OpenAI-compatible providers. Omit for native Bedrock IAM. |
MODEL_PROVIDER_URL | Optional for openai-like and openrouter; required for Azure; not used by native Bedrock. |
MODEL_BEDROCK_AWS_REGION | Optional explicit region for native Bedrock; otherwise use the AWS runtime region. |
MODEL_FAST_NAME, MODEL_MEDIUM_NAME, MODEL_HIGH_NAME | Optional model names per tier. |
MODEL_EMBEDDING_NAME | Optional embedding model ID. |
See Model configuration for provider-specific examples and embedding requirements.
Graph database
| Variable | Description |
|---|---|
GRAPH_DB_PROVIDER | Optional. Selects graph provider strategy. |
GRAPH_DB_URI | FalkorDB Redis URI or Bolt URI for another supported graph database. |
GRAPH_DB_USER, GRAPH_DB_PASSWORD | Optional credentials for providers that require them. |
See Graph databases for provider support and tenancy behavior.
GitHub App connector
Repository connectors use a deployment-owned GitHub App. The in-product wizard stores its ID, PEM private key, and webhook secret encrypted for the connection.
| Variable | Description |
|---|---|
GITHUB_APP_ID | Optional after migrations. GitHub App numeric ID. |
GITHUB_PRIVATE_KEY | Optional after migrations. PEM private key for the App. |
GITHUB_WEBHOOK_SECRET | Optional after migrations. Also used for the legacy webhook route. |
GITHUB_APP_SLUG | Optional. Public app slug used for default install URLs. |
CONNECTION_SECRETS_ENCRYPTION_KEY | Optional 64-character hex key. When unset, encryption derives from AUTH_SECRET. |
The wizard reserves the connection-specific webhook URL and provides the exact value to paste into GitHub.
OAuth sign-in is separate
GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET are for signing in with GitHub.
GitHub App credentials are for repository installation and webhook access.
See GitHub for App registration, permissions, events, credentials, installation, and end-to-end verification.
Atlassian and Confluence
Self-hosted Confluence uses the same product wizard as fully managed ctx|, but your deployment or organization must provide Atlassian and Forge settings first.
| Variable | Description |
|---|---|
ATLASSIAN_CLIENT_ID, ATLASSIAN_CLIENT_SECRET | Optional global Atlassian 3LO app for account linking. If unset, each Forge connection can store its own 3LO credentials through the wizard. |
CONFLUENCE_FORGE_INSTALL_URL | Optional deployment-wide Forge install URL fallback when a Forge connection has no install URL in connections.config. |
See Confluence & Atlassian for the full operator flow.
Slack
Self-hosted Slack uses one deployment-owned Slack app. Organizations authorize that app; they do not create per-tenant Slack apps or Event Subscription URLs.
| Variable | Description |
|---|---|
SLACK_CLIENT_ID, SLACK_CLIENT_SECRET | Slack app OAuth credentials. Required to enable the Slack connector. |
SLACK_SIGNING_SECRET | Verifies Event Subscription requests (X-Slack-Signature). |
SLACK_REDIRECT_URI | Optional. Override when the public OAuth callback differs from {AUTH_BASE_URL}/api/v1/connectors/slack/oauth/callback. |
Set the client ID, client secret, and signing secret together, then restart or
redeploy backend. Backend and worker must share the same AUTH_SECRET and, when
configured, CONNECTION_SECRETS_ENCRYPTION_KEY so encrypted Slack bot tokens
remain usable by background capture jobs.
Set the Slack Event Subscriptions Request URL to:
https://<public-origin>/api/v1/webhook/slackSee Slack for scopes, app_mention Events, and
intent-based thread capture.
Linear
Linear can store the OAuth application and webhook signing secret on the
connection (Register in the product UI). LINEAR_* is an optional
deployment-wide fallback.
| Variable | Description |
|---|---|
LINEAR_CLIENT_ID, LINEAR_CLIENT_SECRET | Optional shared Linear OAuth application credentials. When both are set, the wizard skips Register. |
LINEAR_REDIRECT_URI | Optional exact callback override. Defaults to {AUTH_BASE_URL}/api/v1/integrations/linear/callback. |
LINEAR_WEBHOOK_SECRET | Optional shared signing secret for /api/v1/webhook/linear. Per-connection secrets are stored on the row. |
See Linear for application registration, webhook subscriptions, preview limitations, and troubleshooting.
Notion
Notion uses one deployment-owned public integration and one deployment webhook subscription.
| Variable | Description |
|---|---|
NOTION_CLIENT_ID, NOTION_CLIENT_SECRET | Public integration OAuth credentials. Both are required to enable the connector. |
NOTION_REDIRECT_URI | Optional exact callback override. Defaults to {AUTH_BASE_URL}/api/v1/connectors/notion/oauth/callback. |
NOTION_WEBHOOK_SECRET | Verification token shown by Notion after the first webhook delivery. Required for signed updates. |
Put the OAuth credentials on every service that performs token refresh or connector work, then register the single deployment webhook. See Notion for provisioning and verification.
PagerDuty
PagerDuty can use a deployment-owned OAuth application. After a user authorizes an account, ctx| creates the signed webhook subscription. These variables are an optional hosted-style shortcut; self-host can save the app on the connection in the setup wizard instead.
| Variable | Description |
|---|---|
PAGERDUTY_CLIENT_ID, PAGERDUTY_CLIENT_SECRET | Optional shared PagerDuty OAuth application. When unset, save client id and secret on the connection in the wizard. |
PAGERDUTY_REDIRECT_URI | Optional exact callback override. Defaults to {AUTH_BASE_URL}/api/v1/integrations/pagerduty/callback. |
There is no PAGERDUTY_WEBHOOK_SECRET. Per-subscription signing secrets are
stored encrypted on the connection.
See PagerDuty for application registration and verification.
Observability
Telemetry is off until you set it. ctx| does not ship a collector, Langfuse, or
ClickStack in the Compose deploy profile or in @ctxpipe/aws-cdk. Unset
values keep logs on stdout and do not start trace or metric export. Empty
values are treated as unset.
Point the signal URLs at your own OTLP/HTTP backend. Export starts from these variables. Include the signal path on each URL.
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT=https://otel.example.com/v1/traces
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT=https://otel.example.com/v1/logs
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT=https://otel.example.com/v1/metrics
OTEL_EXPORTER_OTLP_HEADERS=Authorization=Bearer xxx| Variable | Description |
|---|---|
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT | Traces URL, including /v1/traces. Trace export stays off when this is unset. |
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT | Logs URL, including /v1/logs. Unset keeps logs on stdout. |
OTEL_EXPORTER_OTLP_METRICS_ENDPOINT | Metrics URL, including /v1/metrics. |
OTEL_EXPORTER_OTLP_HEADERS | Optional headers, for example Authorization=Bearer xxx. |
OTEL_SERVICE_NAME | Resource service.name. Compose and CDK set backend, openworkflow, ui, and codesearch per container. Compose does not apply a shared name from the root .env. |
OTEL_RESOURCE_ATTRIBUTES | Extra resource attributes, for example deployment.environment=production. |
deployment.environment on backend traces, metrics, and logs, the Langfuse
environment tag, codesearch, and the UI relay is RAILWAY_ENVIRONMENT_NAME
when that is set, otherwise deployment.environment from
OTEL_RESOURCE_ATTRIBUTES, otherwise production when NODE_ENV=production,
otherwise development. Backend and codesearch also set
service.namespace=ctxpipe. Codesearch always exports service.name
codesearch.
LLM spans are OpenTelemetry spans. The apps do not read LANGFUSE_PUBLIC_KEY,
LANGFUSE_SECRET_KEY, or LANGFUSE_HOST. A Langfuse project accepts traces at
https://<your-langfuse>/api/public/otel/v1/traces with
Authorization=Basic <base64(publicKey:secretKey)> in
OTEL_EXPORTER_OTLP_HEADERS. @ctxpipe/aws-cdk takes one base otel.endpoint
and appends /v1/traces, /v1/logs, and /v1/metrics; see
AWS.
Browser telemetry
The UI enables browser telemetry only when
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT is set on the UI server. The browser posts
traces to the same origin at /.otel/v1/traces. The relay also accepts
/.otel/v1/logs, but the SDK does not use it: replay is off, and console
capture is emitted as spans. The UI server forwards traces to
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT and logs to
OTEL_EXPORTER_OTLP_LOGS_ENDPOINT, using OTEL_EXPORTER_OTLP_HEADERS. When
the traces endpoint is unset, the browser SDK does not start. A signal whose
endpoint is unset returns 204.
Advanced
| Variable | Description |
|---|---|
AUTH_ISSUER | Override the OAuth issuer claim. Defaults to AUTH_BASE_URL. |
AUTH_ALLOWED_ORIGINS | Comma-separated list of allowed CORS origins for auth endpoints. |
CODESEARCH_URL | URL of the codesearch service when running separately. |
OPENWORKFLOW_CONCURRENCY | In-flight OpenWorkflow runs per worker process. Default 4 when unset. CDK/Railway/Compose inject size-based values. |
CODESEARCH_INDEXER_CONCURRENCY | Max concurrent Zoekt/SCIP child processes on codesearch, and SCIP HTTP batch size on the worker. Default 2. |
CODESEARCH_INDEX_PIPELINE_CONCURRENCY | Max distinct repos with in-flight OpenWorkflow index-phase HTTP (clone included). Default 2. Codesearch returns 429 when full. |
Railway
ctx| can be deployed on Railway with prebuilt images from GitHub Container Registry. A typical flow is:
- Build and push service images from CI:
ghcr.io/ctxpipe-ai/backend:<sha>ghcr.io/ctxpipe-ai/worker:<sha>ghcr.io/ctxpipe-ai/ui:<sha>ghcr.io/ctxpipe-ai/codesearch:<sha>
- Configure Railway services to use image sources.
- Set environment variables and secrets in Railway.
- Roll production by changing service image tags to the intended commit SHA.