Confluence Connector - Configuration
13 min read
Configuration Overview
The Confluence Connector uses a YAML-based tenant configuration file for all settings. The configuration file path is specified via the TENANT_CONFIG_PATH_PATTERN environment variable.
Environment Variables
The following environment variables control application-level behavior. They are set outside the tenant configuration YAML (typically in Helm connector.env).
Variable | Default | Description |
|---|---|---|
|
| Environment mode ( |
|
| HTTP port the application binds to |
|
| Log verbosity: |
|
| Controls whether diagnostic data (emails, usernames, IDs) is logged in full ( |
| -- (required; Helm chart sets | Glob pattern to tenant configuration YAML files |
| -- | OpenTelemetry metrics exporter (e.g., |
| -- | Prometheus exporter bind host |
| -- | Prometheus exporter bind port |
| -- | Path to a PEM file containing additional CA certificates for TLS verification if the pod's trust store doesn't have them |
|
| Node.js V8 max old space size in MB |
|
| Number of recent sync runs kept per tenant in the sliding window for health evaluation. See Health Endpoint |
|
| Per-tenant failure ratio (0--1) across the window that marks the service unhealthy when exceeded. See Health Endpoint |
|
| Timeout in milliseconds for each reachability ping used by the health endpoint. See Health Endpoint |
The following environment variables are typically loaded from Kubernetes Secrets:
Variable | Description |
|---|---|
| OAuth 2.0 client secret (used when |
| Personal Access Token (used when |
| Zitadel client secret (required when |
| Proxy password (required when proxy |
Secret values in tenant YAML files are referenced via the os.environ/ prefix (e.g., os.environ/CONFLUENCE_CLIENT_SECRET). The conventional environment variable names are listed above, but operators can use any variable name as long as the os.environ/ reference in the tenant YAML matches. See Authentication -- Secret Resolution for the full resolution mechanism, supported fields, and Kubernetes integration.
Tenant Configuration File
File Naming and Loading
Tenant configuration files must follow the naming convention {tenant-name}-tenant-config.yaml. The tenant name is extracted from the filename by removing the -tenant-config.yaml suffix and must match the pattern ^[a-z0-9]+(-[a-z0-9]+)*$ (lowercase alphanumeric with hyphens). Duplicate tenant names cause a startup failure.
The connector loads all files matching the TENANT_CONFIG_PATH_PATTERN glob at startup. At least one file must match the pattern, and at least one tenant must have active or deleted status. For details on how tenants are isolated at runtime, see Architecture -- Multi-Tenancy Support.
Tenant Status
Each tenant configuration file can include a top-level status field:
Status | Default | Behavior |
|---|---|---|
| Yes | Tenant is loaded and sync jobs are scheduled |
| -- | Tenant config is validated but no sync jobs run |
| -- | Ingested content is deleted from the Unique knowledge base and sync is stopped |
Complete Example (Cloud + External Auth)
confluence:
instanceType: cloud
baseUrl: https://your-domain.atlassian.net
cloudId: your-cloud-id
auth:
mode: oauth_2lo
clientId: your-oauth-client-id
clientSecret: os.environ/CONFLUENCE_CLIENT_SECRET
apiRateLimitPerMinute: 100
ingestSingleLabel: ai-ingest
ingestAllLabel: ai-ingest-all
unique:
serviceAuthMode: external
zitadelOauthTokenUrl: https://auth.your-unique-instance.com/oauth/v2/token
zitadelProjectId: your-zitadel-project-id
zitadelClientId: confluence-connector
zitadelClientSecret: os.environ/ZITADEL_CLIENT_SECRET
ingestionServiceBaseUrl: https://ingestion.your-unique-instance.com
scopeManagementServiceBaseUrl: https://scope-management.your-unique-instance.com
apiRateLimitPerMinute: 100
processing:
concurrency: 1
scanIntervalCron: "*/15 * * * *"
ingestion:
ingestionMode: flat
scopeId: your-scope-id
storeInternally: enabledComplete Example (Data Center + Cluster-Local Auth)
confluence:
instanceType: data-center
baseUrl: https://confluence.your-company.com
auth:
mode: oauth_2lo
clientId: your-confluence-app-client-id
clientSecret: os.environ/CONFLUENCE_CLIENT_SECRET
apiRateLimitPerMinute: 50
ingestSingleLabel: ai-ingest
ingestAllLabel: ai-ingest-all
unique:
serviceAuthMode: cluster_local
serviceExtraHeaders:
x-company-id: your-company-id
x-user-id: your-user-id
ingestionServiceBaseUrl: http://node-ingestion.<namespace>:8091
scopeManagementServiceBaseUrl: http://node-scope-management.<namespace>:8094
apiRateLimitPerMinute: 100
processing:
concurrency: 1
scanIntervalCron: "0 */2 * * *"
ingestion:
ingestionMode: flat
scopeId: your-scope-id
storeInternally: enabledConfluence Connection Settings
The confluence section configures how the connector connects to the Confluence instance:
confluence:
instanceType: cloud
baseUrl: https://your-domain.atlassian.net
cloudId: your-cloud-id
auth:
mode: oauth_2lo
clientId: your-oauth-client-id
clientSecret: os.environ/CONFLUENCE_CLIENT_SECRET
apiRateLimitPerMinute: 100
ingestSingleLabel: ai-ingest
ingestAllLabel: ai-ingest-allField | Required | Default | Description |
|---|---|---|---|
| Yes | -- |
|
| Yes | -- | Base URL of the Confluence instance (e.g., |
| Yes (Cloud only) | -- | Atlassian Cloud ID (UUID) for the Confluence site |
| Yes | -- | Authentication configuration (see Authentication) |
| Yes | -- | Number of Confluence API requests allowed per minute |
| Yes | -- | Confluence label that marks individual pages for synchronization (e.g., |
| Yes | -- | Confluence label that marks a page and all its descendants for synchronization (e.g., |
Important:ingestSingleLabel and ingestAllLabel are required fields with no schema default. Operators must explicitly configure them.
Important:apiRateLimitPerMinute is a required field with no schema default. Atlassian recommends Data Center admins allow at least 20 requests/second (1200 RPM). Cloud uses a points-based quota -- consult the Atlassian REST API rate limiting documentation for details.
Authentication
For full details on authentication setup, credential management, secret resolution, and token flows, see Authentication.
Space Scanning
The connector discovers pages via Confluence Query Language (CQL) label searches. Only pages in the following space types are scanned:
Instance Type | Space Types Scanned |
|---|---|
Cloud |
|
Data Center |
|
Unique Platform Settings
The unique section configures how the connector communicates with the Unique platform. The field for selecting the auth mode is serviceAuthMode (not authMode).
Note: The Helm chart
values.yamlusesunique.authMode, which the Helm template maps toserviceAuthModein the generated tenant config YAML. See Authentication -- Helm Chart Field Mapping.
unique:
serviceAuthMode: cluster_local
ingestionServiceBaseUrl: http://node-ingestion.<namespace>:8091
scopeManagementServiceBaseUrl: http://node-scope-management.<namespace>:8094
apiRateLimitPerMinute: 100
serviceExtraHeaders:
x-company-id: "company-id"
x-user-id: "service-user-id"Field | Required | Default | Description |
|---|---|---|---|
| Yes | -- |
|
| Yes | -- | Base URL for the Unique ingestion service. Must not end with a trailing slash |
| Yes | -- | Base URL for the Unique scope management service. Must not end with a trailing slash |
| No |
| Number of Unique API requests allowed per minute |
The additional fields required for each auth mode (serviceExtraHeaders for cluster_local, Zitadel credentials for external) are documented in the Authentication Guide -- Unique Platform Authentication Methods, which also covers setup instructions and token flows.
Proxy Configuration
The connector supports HTTP/HTTPS forward proxies for environments where outbound internet access is only available through a proxy. Proxy settings are configured via environment variables (managed by the Helm chart's proxyConfig section).
Mode | Description |
|---|---|
| Proxy disabled (default) |
| Proxy enabled without authentication |
| Basic authentication proxy |
| TLS client certificate proxy |
Common options (required for no_auth, username_password, and ssl_tls modes):
Variable | Description |
|---|---|
| Proxy server hostname |
| Proxy server port |
|
|
| (Optional) Path to CA bundle for verifying proxy TLS certificate |
| (Optional) JSON string of custom headers for CONNECT request |
username_password mode adds:
Variable | Description |
|---|---|
| Proxy username |
| Proxy password (loaded from secret) |
ssl_tls mode adds:
Variable | Description |
|---|---|
| Path to TLS client certificate |
| Path to TLS client key |
Traffic Routing
When the proxy is enabled, traffic is routed as follows:
Target | Routing |
|---|---|
Confluence API (Cloud or Data Center) | Always through the proxy |
Atlassian or Data Center OAuth token endpoint | Always through the proxy |
Unique Ingestion and Scope Management services | Through the proxy only when |
Attachment and content uploads to Unique | Same routing as Unique API calls above |
Ingestion Settings
The ingestion section configures how content is organized and stored in the Unique knowledge base:
ingestion:
ingestionMode: flat
scopeId: your-scope-id
storeInternally: enabled
useV1KeyFormat: disabled
attachments:
mode: enabled
allowedMimeTypes:
- application/pdf
- application/vnd.openxmlformats-officedocument.wordprocessingml.document
- application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
- application/vnd.openxmlformats-officedocument.presentationml.presentation
- text/plain
- text/csv
- text/html
- image/png
- image/jpeg
maxFileSizeMb: 200
imageOcr: enabledField | Required | Default | Description |
|---|---|---|---|
| No |
| Ingestion traversal mode. Currently only |
| Yes | -- | Root scope ID in the Unique platform. The scope must exist before the connector starts (see Authentication -- Create the Root Scope in Unique) |
| No |
| Whether to store content internally in Unique ( |
| No |
| Use v1-compatible ingestion key format ( |
| No | (see sub-fields) | Configuration for file attachment ingestion |
Attachment Configuration
The attachments sub-section controls ingestion of file attachments from Confluence pages:
Field | Required | Default | Description |
|---|---|---|---|
| No |
| Whether to ingest file attachments ( |
| No | MIME types to include when ingesting attachments. Matched against the | |
| No |
| Maximum file size in megabytes. Attachments larger than this are skipped |
| No |
| Whether the connector should request OCR-based ingestion for image attachments by attaching |
Default Allowed MIME Types
- application/pdf
- application/vnd.openxmlformats-officedocument.wordprocessingml.document # DOCX
- application/vnd.openxmlformats-officedocument.spreadsheetml.sheet # XLSX
- application/vnd.openxmlformats-officedocument.presentationml.presentation # PPTX
- text/plain
- text/csv
- text/html
- image/png
- image/jpegThese are matched against the mediaType reported by the Confluence API. Operators can override the list via ingestion.attachments.allowedMimeTypes. Note that the Unique ingestion service ultimately decides which types it can chunk; configuring a MIME type here that the ingestion service does not accept will result in upload errors at runtime.
Image Attachments
Images embedded in Confluence pages (drag/drop, paste, or "Insert image") are stored as regular page attachments by Confluence and are ingested through this same configuration when image/png or image/jpeg is in allowedMimeTypes. Both formats are in the default list, so enabling attachment ingestion is sufficient to ingest embedded images out of the box.
For images to produce searchable chunks, the Unique ingestion worker must run them through Document Intelligence (jpgReadMode = DOC_INTELLIGENCE_DEFAULT). The connector handles this automatically: with attachments.imageOcr = enabled (the default), each image content registration is sent with ingestionConfig.jpgReadMode = DOC_INTELLIGENCE_DEFAULT, which overrides the scope-level default (NO_INGESTION). Set attachments.imageOcr = disabled to leave the decision to the destination scope's own ingestionConfig.
Images inserted as external URLs (rather than uploaded to Confluence) are stored as plain URL references in the page body, not as attachments, and are therefore not ingested.
Other image formats (GIF, WebP, SVG, HEIC, BMP, TIFF) are not currently supported by the Unique ingestion service. Adding them to allowedMimeTypes will cause uploads to be rejected with HTTP 400.
Processing Settings
The processing section controls sync scheduling and concurrency:
processing:
concurrency: 1
scanIntervalCron: "*/15 * * * *"
# maxItemsToScan: 100Field | Required | Default | Description |
|---|---|---|---|
| No |
| Number of pages/attachments to submit for ingestion into Unique concurrently |
| No |
| Cron expression for the scheduled sync interval |
| No | -- (unlimited) | Maximum number of items (pages + attachments) to scan per run. Intended for testing purposes |
Scheduler and Sync Interval
The connector runs sync cycles on a per-tenant cron schedule. Key behaviors:
An initial sync is triggered immediately on startup for each active tenant.
Subsequent syncs run according to the
scanIntervalCronexpression.If a sync cycle for a tenant is still running when the next is scheduled, the new cycle is skipped (concurrent sync prevention).
During shutdown, all cron jobs are stopped gracefully.
Considerations:
Lower intervals increase Confluence API usage and may hit rate limits.
Higher intervals delay sync of new content.
Adjust
concurrencyandapiRateLimitPerMinutefor large instances with many pages.
Logging
Structured JSON Logs
The connector produces structured JSON logs. In production (NODE_ENV=production), logs are written as JSON to stdout. In development, logs use a human-readable format.
Log Levels
Set via the LOG_LEVEL environment variable:
Level | Description |
|---|---|
| Error conditions |
| Warning conditions |
| General operational information (default) |
| Detailed debugging information |
Tenant Context in Logs
Every log entry emitted within a tenant sync context automatically includes the tenantName field.
Diagnostics Data Policy
The LOGS_DIAGNOSTICS_DATA_POLICY environment variable controls how diagnostic data (emails, usernames, IDs) appears in logs:
Value | Behavior |
|---|---|
| Partially masks values (e.g., |
| Shows values in full |
This applies to diagnostic data only. Actual secrets (passwords, tokens, keys) are always fully redacted regardless of this setting.
Sensitive Header Redaction
The authorization request header is automatically redacted in HTTP request logs.
Metrics
OpenTelemetry Integration
The connector uses OpenTelemetry for metrics. To enable Prometheus metrics export, set the following environment variables:
connector:
env:
OTEL_METRICS_EXPORTER: "prometheus"
OTEL_EXPORTER_PROMETHEUS_HOST: "0.0.0.0"
OTEL_EXPORTER_PROMETHEUS_PORT: "51350"The Helm chart ships these values by default.
System Telemetry
The connector exposes standard host metrics (CPU, memory, event loop) and HTTP API metrics collected by the OpenTelemetry host and API instrumentations.
Application Telemetry
Custom connector metrics use the cfc_ prefix (Confluence Connector). Unique platform interaction metrics use the confluence_connector_unique_api_ prefix.
Sync Cycle Metrics
Metric | Type | Labels | Description |
|---|---|---|---|
| Histogram |
| Duration of a full synchronization cycle per tenant |
| Histogram |
| Duration of the page discovery (scan) phase |
| Histogram |
| Duration of a single attachment upload to Unique |
Attachment upload histogram buckets: 100ms, 200ms, 500ms, 1s, 2s, 3s, 5s, 10s, 20s, 30s, 60s.
Content Throughput Metrics
Metric | Type | Labels | Description |
|---|---|---|---|
| Counter |
| Pages ingested per sync cycle |
| Counter |
| Attachments ingested per sync cycle |
| Counter |
| Content items deleted from Unique |
| Counter |
| File change detection events ( |
| Counter |
| Space scopes removed after their Confluence space was removed or unlabeled |
| Counter |
| Files removed during orphaned space cleanup |
Tenant Cleanup Metrics
Metric | Type | Labels | Description |
|---|---|---|---|
| Histogram |
| Duration of a deleted tenant content cleanup |
| Counter |
| Content items deleted during tenant cleanup |
| Counter |
| Scopes deleted during tenant cleanup |
Confluence API Metrics
Metric | Type | Labels | Description |
|---|---|---|---|
| Histogram |
| Request latency for Confluence API calls, keyed by a normalized endpoint path |
| Counter |
| Confluence API rate-limit (429) events |
| Counter |
| Confluence API error responses grouped by HTTP status class |
Confluence API request histogram buckets: 100ms, 250ms, 500ms, 1s, 2.5s, 5s, 10s, 30s.
Unique API Metrics
Metric | Type | Labels | Description |
|---|---|---|---|
| Counter |
| Total Unique API requests |
| Counter |
| Total Unique API error responses |
| Histogram |
| Request latency for Unique API calls in milliseconds |
| Counter |
| Slow Unique API requests |
| Counter | -- | Zitadel auth token refreshes (only emitted in |
Grafana Dashboard
A Grafana dashboard ConfigMap is available in the Helm chart. The dashboard visualizes sync durations, content throughput, attachment uploads, Confluence API performance, Unique API performance, and Node.js runtime metrics. Enable it with:
grafana:
dashboard:
enabled: true
folder: connectorsAlerts
Default Alerts
The Helm chart provides one default alert:
Category | Alert Name | Description |
|---|---|---|
|
| Fires when the Unique API error rate (4xx/5xx responses) exceeds the configured threshold |
Default alert parameters:
Parameter | Default Value |
|---|---|
|
|
|
|
|
|
Alert Configuration
Enable alerts and customize per-alert parameters in Helm values.yaml:
alerts:
enabled: true
defaultAlerts:
uniqueApi:
enabled: true
# Disable specific alerts:
disabled: {}
# ConfluenceConnectorUniqueAPIErrors: true
# Override alert parameters:
customRules: {}
# ConfluenceConnectorUniqueAPIErrors:
# for: "15s"
# severity: "critical"
# threshold: 0.05
additionalLabels: {}
# environment: production
# team: backendAlerts require the monitoring.coreos.com/v1 API (Prometheus Operator) to be available in the cluster.
Health Endpoint
The connector exposes a GET /health endpoint that reports operational health. It is separate from the existing GET /probe endpoint used for K8s liveness/readiness probes. GET /health is intended for external monitoring and SRE tooling.
The endpoint returns HTTP 200 when all checks pass and HTTP 503 when any check fails. The response follows the @nestjs/terminus format with status, info, error, and details fields.
Health Checks
The endpoint runs three checks on every request:
Sync -- Evaluates each active tenant's sync history from a sliding window of the last N runs (configurable via HEALTH_SYNC_HISTORY_SIZE). Each tenant's failure ratio is computed independently as failures / appearances. If any tenant exceeds HEALTH_SYNC_TENANT_FAILURE_THRESHOLD, the check is down. When no sync has completed yet (e.g. shortly after startup), this check reports up with message: "No sync records yet". A single transient failure is absorbed by the window and does not trigger an alert. Skipped runs caused by an in-progress sync overlap are not recorded so they cannot dilute the window.
Sync health is evaluated at tenant level. In the Confluence connector, each tenant owns its own cron job, configuration, credentials, and operational lifecycle, so a tenant is the smallest unit that can independently fail or recover. Per-item ingestion failures are exposed through logs and metrics; /health.sync answers whether each active tenant's scheduled sync is consistently succeeding.
Connectivity -- Performs unauthenticated HTTP requests to the Atlassian API host (https://api.atlassian.com/, only when at least one Cloud tenant is configured) and to each unique active tenant confluence.baseUrl. Any HTTP response (including 401/403) proves the endpoint is reachable -- only transport-level failures (DNS, TLS, timeout, connection refused) are treated as unhealthy. Deleted tenants are excluded because they no longer talk to Confluence.
Unique API -- Sends a minimal { __typename } GraphQL query to each tenant's ingestion and scope-management endpoints, using the same auth and proxy routing the connector uses for production traffic. Non-2xx responses (401/403/500) are treated as unhealthy because they indicate the API is not functioning correctly. If token acquisition itself fails (Zitadel outage), the tenant's entry reports error: "AUTH_FAILURE". These requests bypass the per-tenant rate limiter to avoid queuing behind sync traffic.
Response Examples
Healthy (200):
{
"status": "ok",
"info": {
"sync": {
"status": "up",
"lastSyncAt": "2026-04-27T10:15:00.000Z",
"tenants": {
"tenant-a": { "failures": 0, "total": 5 },
"tenant-b": { "failures": 1, "total": 5 }
}
},
"connectivity": {
"status": "up",
"atlassian": "reachable",
"confluence": [
{ "tenant": "tenant-a", "status": "reachable" },
{ "tenant": "tenant-b", "status": "reachable" }
]
},
"uniqueApi": {
"status": "up",
"ingestion": [
{ "tenant": "tenant-a", "status": "reachable" },
{ "tenant": "tenant-b", "status": "reachable" }
],
"scopeManagement": [
{ "tenant": "tenant-a", "status": "reachable" },
{ "tenant": "tenant-b", "status": "reachable" }
]
}
},
"error": {},
"details": { "...same as info when healthy..." }
}Unhealthy (503) -- a tenant exceeds the sync failure threshold:
{
"status": "error",
"info": {
"connectivity": { "status": "up", "...": "..." },
"uniqueApi": { "status": "up", "...": "..." }
},
"error": {
"sync": {
"status": "down",
"lastSyncAt": "2026-04-27T10:15:00.000Z",
"threshold": 0.5,
"failingTenants": ["tenant-b"],
"tenants": {
"tenant-a": { "failures": 0, "total": 5 },
"tenant-b": { "failures": 4, "total": 5 }
}
}
},
"details": { "...all checks combined..." }
}Configuration
Variable | Default | Description |
|---|---|---|
|
| Number of recent sync runs kept per tenant in the sliding window |
|
| Per-tenant failure ratio (0--1) that triggers unhealthy when exceeded |
|
| Timeout in milliseconds for each reachability ping (connectivity checks) |
Complete Re-ingestion
To perform a complete re-ingestion of all synced Confluence content:
Prerequisites
Access to the Unique API or admin interface
Ability to update the tenant configuration
Step 1: Delete Ingested Content
Set the tenant status to deleted in its YAML configuration file and restart the connector. The cleanup runs immediately on startup and deletes all ingested files and child scopes while preserving the root scope. In a multi-tenant deployment, all other tenants configured in the same connector instance continue syncing normally and are not affected by this operation.
Warning: This operation is irreversible. Ensure you have backups if needed.
Step 2: Re-enable the Tenant
Set the tenant status back to active and restart the connector. The connector triggers an initial sync immediately on startup, re-ingesting all labeled content from scratch into the preserved root scope (no new scope needs to be created).
Further Guidance
A dedicated re-ingestion runbook with extended prerequisites, API request examples, and operational caveats will be linked here in a later documentation update.