Skip to main content
Nebula ships OAuth connectors that sync content from external sources into a collection. The connector runtime is built into every Enterprise release; this page covers the operator setup — registering the OAuth app and wiring its credentials into your deployment. Once that’s done, your users connect their own accounts through the Connectors API. The four Microsoft 365 connectors — Outlook, OneDrive, SharePoint, and Teams — share one Entra ID (Azure AD) app registration. Populating a single client ID + secret enables all four at once.
Connectors are off by default. A connector becomes available only when both its client ID and client secret are present in the deployment. No connector code path runs until then.

How it fits together

PieceWho provides itWhere it goes
Entra app registration (client ID, secret, tenant)You, in the Azure portalDeployment secrets (below)
OAuth callback base URLYour deployment’s public API originNEBULA_CONNECTOR_API_BASE_URL / connectors.apiBaseUrl
Token-signing HMACAuto-generated (Compose) or you (K8s)NEBULA_CONNECTOR_TOKEN_KEY
End-user account authorizationEach of your usersConnectors API / app UI
The token-signing key (NEBULA_CONNECTOR_TOKEN_KEY) signs every connector’s OAuth state and stored tokens. It is required for any connector and should be treated like NEBULA_SECRET_KEY — long-lived, rotating it invalidates all in-flight authorizations.

Step 1 — Register the Entra app

1

Create the registration

In the Azure portal: Entra ID → App registrations → New registration. Register a single-tenant app (or multi-tenant if you serve external organizations). Copy the Application (client) ID and the Directory (tenant) ID.
2

Create a client secret

Certificates & secrets → New client secret. Copy the secret Value (not the secret ID — the value is shown only once).
3

Add the redirect URIs

Authentication → Add a platform → Web, then add one redirect URI per connector, substituting your deployment’s public API origin:
https://nebula.example.com/v1/connectors/outlook/callback
https://nebula.example.com/v1/connectors/onedrive/callback
https://nebula.example.com/v1/connectors/sharepoint/callback
https://nebula.example.com/v1/connectors/teams/callback
The origin must match NEBULA_CONNECTOR_API_BASE_URL (Compose) / connectors.apiBaseUrl (Helm) exactly. Entra rejects non-HTTPS and non-public redirect URIs (except localhost).
4

Grant Graph permissions

API permissions → Microsoft Graph → Delegated permissions, add the scopes for the connectors you intend to offer, then Grant admin consent:
ConnectorDelegated scopes
OutlookMail.Read
OneDriveFiles.Read
SharePointSites.Read.All, Files.Read.All
TeamsTeam.ReadBasic.All, Channel.ReadBasic.All, ChannelMessage.Read.All, Chat.Read, ChatMessage.Read
AllUser.Read, offline_access

Step 2 — Wire the credentials into your deployment

# generate-secrets.sh already populated NEBULA_CONNECTOR_TOKEN_KEY.
# Set your public API origin and the Entra credentials:
NEBULA_CONNECTOR_API_BASE_URL=https://nebula.example.com
NEBULA_M365_CLIENT_ID=<application-client-id>
NEBULA_M365_CLIENT_SECRET=<client-secret-value>
# Tenant ID or a verified domain for single-tenant apps.
# Omit to default to "organizations" (any work/school tenant).
NEBULA_M365_TENANT=<directory-tenant-id>
With secrets.backend: eso-aws or eso-vault, put NEBULA_CONNECTOR_TOKEN_KEY, NEBULA_M365_CLIENT_ID, and NEBULA_M365_CLIENT_SECRET in your secret store under the path the ExternalSecret syncs. The chart envFrom-mounts the synced Secret onto all first-party Nebula workloads (api, worker, graph-engine, compactor, and the migration Job), so every key lands on every Nebula pod. Only the api (OAuth connect) and worker (sync) actually read the connector keys; the other workloads ignore them. Keep this synced path scoped to Nebula’s own secrets — don’t co-locate unrelated application secrets under it.
NEBULA_CONNECTOR_API_BASE_URL must be the externally reachable origin your users hit, because the browser is redirected there after authorizing. The in-image default (http://localhost:7272) only works for a single-host local trial. On Helm it auto-derives from ingress.host; on Compose you must set it explicitly.
Apply the change (bootstrap.sh re-run for Compose, helm upgrade for Kubernetes) and the connectors are live. Both the API pod (OAuth connect flow) and the worker pod (background sync + webhooks) read the same configuration.

Step 3 — Connect accounts

Connector setup is per-user, not per-deployment. Each user authorizes their own Microsoft account through the Connectors API or the app’s connector settings. The two-phase providers (OneDrive, SharePoint, Teams) prompt for a folder / library / channel selection after authorization; Outlook syncs immediately.

Other connectors

Gmail / Google Drive, Notion, and Slack follow the same base shape — register an OAuth app with that provider’s console, add the matching redirect URI (<base>/v1/connectors/<provider>/callback), and set the provider’s NEBULA_<PROVIDER>_CLIENT_ID / _SECRET pair (Compose) or the equivalent secrets.values keys (Helm). Two need provider-specific extras beyond that pair:
  • Slack also requires a signing secret (NEBULA_SLACK_SIGNING_SECRET) and an Events API subscription to verify and receive inbound events.
  • Gmail real-time sync requires Google Pub/Sub push: a topic and a verified push service account (NEBULA_GMAIL_PUBSUB_TOPIC, NEBULA_GMAIL_PUBSUB_SERVICE_ACCOUNT, NEBULA_GMAIL_PUBSUB_AUDIENCE). Without them the connector still authorizes, but live mail updates are disabled.
For Compose, the complete per-provider variable list lives in .env.enterprise.example. For Helm, only the M365 keys are pre-seeded in values.yaml secrets.values; add each other provider’s keys there the same way — any key under secrets.values becomes an env var on the pods.