# Confluence Connector - Configuration

15 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 |
| --- | --- | --- |
| `NODE_ENV` | `production` | Environment mode (`development`, `production`, `test`) |
| `PORT` | `51349` | HTTP port the application binds to |
| `LOG_LEVEL` | `info` | Log verbosity: `error`, `warn`, `info`, `debug`. |
| `LOGS_DIAGNOSTICS_DATA_POLICY` | `conceal` | Controls whether diagnostic data (emails, usernames, IDs) is logged in full (`disclose`) or partially masked (`conceal`). |
| `TENANT_CONFIG_PATH_PATTERN` | -- | Required; Glob pattern to tenant configuration YAML files |
| `OTEL_METRICS_EXPORTER` | -- | OpenTelemetry metrics exporter (e.g., `prometheus`). |
| `OTEL_EXPORTER_PROMETHEUS_HOST` | -- | Prometheus exporter bind host |
| `OTEL_EXPORTER_PROMETHEUS_PORT` | -- | Prometheus exporter bind port |
| `NODE_EXTRA_CA_CERTS` | -- | Path to a PEM file containing additional CA certificates for TLS verification if the pod's trust store doesn't have them |
| `MAX_HEAP_MB` | `1920` (Helm) / `1024` (Docker) | Node.js V8 max old space size in MB |
| `HEALTH_SYNC_HISTORY_SIZE` | `5` | Number of recent sync runs kept per tenant in the sliding window for health evaluation. |
| `HEALTH_SYNC_TENANT_FAILURE_THRESHOLD` | `0.5` | Per-tenant failure ratio (0--1) across the window that marks the service unhealthy when exceeded. |
| `HEALTH_CONNECTIVITY_TIMEOUT_MS` | `3000` | Timeout in milliseconds for each reachability ping used by the health endpoint. |

The following environment variables are typically loaded from Kubernetes Secrets:

| Variable | Description |
| --- | --- |
| `CONFLUENCE_CLIENT_SECRET` | OAuth 2.0 client secret (used when `confluence.auth.mode` is `oauth_2lo`) |
| `CONFLUENCE_PAT` | Personal Access Token (used when `confluence.auth.mode` is `pat`; Data Center below 10.1 only) |
| `ZITADEL_CLIENT_SECRET` | Zitadel client secret (required when `unique.serviceAuthMode` is `external`) |
| `PROXY_PASSWORD` | Proxy password (required when proxy `authMode` is `username_password`) |

Secret values in tenant YAML files are referenced via the `os.environ/` prefix (e.g., `os.environ/CONFLUENCE_CLIENT_SECRET`).

## 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.

### Tenant Status

Each tenant configuration file can include a top-level `status` field:

| Status | Default | Behavior |
| --- | --- | --- |
| `active` | Yes | Tenant is loaded and sync jobs are scheduled |
| `inactive` | -- | Tenant config is validated but no sync jobs run |
| `deleted` | -- | Ingested content is deleted from the Unique knowledge base and sync is stopped |

### Complete Example (Cloud + External Auth)

yaml
```
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: enabled
  pageIngestionConfig:
    htmlConfig:
      imageContentExtraction:
        enabled: true
        languageModel: your-kb-visual-llm
```

### Complete Example (Data Center + Cluster-Local Auth)

yaml
```
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 * * *"

## Confluence Connection Settings

The `confluence` section configures how the connector connects to the Confluence instance:

yaml
```
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
```

| Field | Required | Default | Description |
| --- | --- | --- | --- |
| `instanceType` | Yes | -- | `cloud` or `data-center` |
| `baseUrl` | Yes | -- | Base URL of the Confluence instance (e.g., `https://acme.atlassian.net`). Must not end with a trailing slash |
| `cloudId` | Yes (Cloud only) | -- | Atlassian Cloud ID (UUID) for the Confluence site |
| `auth` | Yes | -- | Authentication configuration |
| `apiRateLimitPerMinute` | Yes | -- | Number of Confluence API requests allowed per minute |
| `ingestSingleLabel` | Yes | -- | Confluence label that marks individual pages for synchronization |
| `ingestAllLabel` | Yes | -- | Confluence label that marks a page and all its descendants for synchronization |

**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).

### 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 | `global`, `collaboration` |
| Data Center | `global` |

## 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`).

yaml
```
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 |
| --- | --- | --- | --- |
| `serviceAuthMode` | Yes | -- | `cluster_local` or `external` |
| `ingestionServiceBaseUrl` | Yes | -- | Base URL for the Unique ingestion service. Must not end with a trailing slash |
| `scopeManagementServiceBaseUrl` | Yes | -- | Base URL for the Unique scope management service. Must not end with a trailing slash |
| `apiRateLimitPerMinute` | No | `100` | Number of Unique API requests allowed per minute |

The additional fields required for each auth mode are documented in the [Authentication Guide -- Unique Platform Authentication Methods].

## 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.

| Mode | Description |
| --- | --- |
| `none` | Proxy disabled (default) |
| `no_auth` | Proxy enabled without authentication |
| `username_password` | Basic authentication proxy |
| `ssl_tls` | TLS client certificate proxy |

**Common options**:
| Variable | Description |
| --- | --- |
| `PROXY_HOST` | Proxy server hostname |
| `PROXY_PORT` | Proxy server port |
| `PROXY_PROTOCOL` | `http` or `https` |
| `PROXY_SSL_CA_BUNDLE_PATH` | Path to CA bundle for verifying proxy TLS certificate |
| `PROXY_HEADERS` | JSON string of custom headers for CONNECT request |

**`username_password` mode adds:**
| Variable | Description |
| --- | --- |
| `PROXY_USERNAME` | Proxy username |
| `PROXY_PASSWORD` | Proxy password (loaded from secret) |

**`ssl_tls` mode adds:**
| Variable | Description |
| --- | --- |
| `PROXY_SSL_CERT_PATH` | Path to TLS client certificate |
| `PROXY_SSL_KEY_PATH` | 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 `unique.serviceAuthMode` is `external`. |
| 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:

yaml
```
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: enabled
  pageIngestionConfig:
    htmlConfig:
      imageContentExtraction:
        enabled: true
        languageModel: your-kb-visual-llm
```

| Field | Required | Default | Description |
| --- | --- | --- | --- |
| `ingestionMode` | No | `flat` | Ingestion traversal mode. Currently only `flat` is supported |
| `scopeId` | Yes | -- | Root scope ID in the Unique platform. The scope must exist before the connector starts |
| `storeInternally` | No | `enabled` | Whether to store content internally in Unique (`enabled` or `disabled`) |
| `useV1KeyFormat` | No | `disabled` | Use v1-compatible ingestion key format (`spaceId_spaceKey/pageId`) without tenant prefix |
| `attachments` | No | (see sub-fields) | Configuration for file attachment ingestion |
| `pageIngestionConfig` | No | -- | Ingestion configuration applied to each ingested page. |

### Attachment Configuration

The `attachments` sub-section controls ingestion of file attachments from Confluence pages:
| Field | Required | Default | Description |
| --- | --- | --- | --- |
| `attachments.mode` | No | `enabled` | Whether to ingest file attachments (`enabled` or `disabled`) |
| `attachments.allowedMimeTypes` | No | See [Default Allowed MIME Types] | MIME types to include when ingesting attachments. |
| `attachments.maxFileSizeMb` | No | `200` | Maximum file size in megabytes. Attachments larger than this are skipped |
| `attachments.imageOcr` | No | `enabled` | Whether the connector should request OCR-based ingestion for image attachments |

## Processing Settings

The `processing` section controls sync scheduling and concurrency:

yaml
```
processing:
  concurrency: 1
  scanIntervalCron: "*/15 * * * *"
```

| Field | Required | Default | Description |
| --- | --- | --- | --- |
| `concurrency` | No | `1` | Number of pages/attachments to submit for ingestion into Unique concurrently |
| `scanIntervalCron` | No | `*/15 * * * *` | Cron expression for the scheduled sync interval |
| `maxItemsToScan` | No | -- | Maximum number of items (pages + attachments) to scan per run. Intended for testing purposes |

## 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` | Error conditions |
| `warn` | Warning conditions |
| `info` | General operational information (default) |
| `debug` | Detailed debugging information |

## Health Endpoint

The connector exposes a `GET /health` endpoint that reports operational health. The endpoint returns HTTP `200` when all checks pass and HTTP `503` when any check fails.
