> ## Documentation Index
> Fetch the complete documentation index at: https://docs.textql.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deployment Configuration

> Helm values and settings for self-hosted TextQL deployments

## Overview

This guide covers the configuration options for self-hosted TextQL deployments. Settings are applied either through Helm values (at deploy time) or through the Settings UI (at runtime).

For IdP-specific SSO setup instructions, see [Single Sign-On (SSO)](/core/admin/sso).

## Authentication

### Single Sign-On (OIDC)

Single-tenant OIDC mode enforces one identity provider for all users in the deployment.

```yaml theme={null}
global:
  auth:
    singleOIDCTenant: true
    singleOidcIdleLogoutAfter: "45m"  # optional idle timeout
    oidc:
      providerType: "Okta OIDC"       # Okta OIDC | Microsoft OIDC | Ping OIDC
      issuerUrl: "https://your-idp.example.com"
      clientId: "your-client-id"
      clientSecret: "your-client-secret"
      scopes: "openid profile email"   # default: openid profile email
      attributeMapping: '{"role_sync_enabled": true, "preserve_admin_role": true}'
      emailVerification: true          # default: true

oathkeeper:
  enforceAuth: true
```

| Field                       | Required | Default                | Description                                          |
| --------------------------- | -------- | ---------------------- | ---------------------------------------------------- |
| `singleOIDCTenant`          | Yes      | `false`                | Enables single-tenant OIDC mode                      |
| `oidc.providerType`         | Yes      | —                      | Identity provider type                               |
| `oidc.issuerUrl`            | Yes      | —                      | OpenID Connect issuer URL                            |
| `oidc.clientId`             | Yes      | —                      | OAuth2 client ID                                     |
| `oidc.clientSecret`         | Yes      | —                      | OAuth2 client secret                                 |
| `oidc.scopes`               | No       | `openid profile email` | Space-separated OIDC scopes                          |
| `oidc.attributeMapping`     | No       | `{}`                   | JSON attribute mapping (see [Role Sync](#role-sync)) |
| `oidc.emailVerification`    | No       | `true`                 | Require IdP-verified email addresses                 |
| `singleOidcIdleLogoutAfter` | No       | none                   | Idle session timeout (e.g., `45m`, `2h`)             |
| `oathkeeper.enforceAuth`    | No       | `false`                | Require authentication on all routes                 |

<Warning>
  All four OIDC fields (`providerType`, `issuerUrl`, `clientId`, `clientSecret`) must be set together. Partial configuration will cause authentication failures.
</Warning>

When single-tenant OIDC is enabled:

* Users are redirected directly to the IdP — the login page is bypassed
* Email/magic-link login is disabled
* The OIDC provider appears as read-only in the Settings UI

When `enforceAuth` is also enabled:

* Every request must carry a valid session or API key
* Unauthenticated requests are automatically redirected to the IdP
* This is the recommended setting for locked-down deployments

<Warning>
  `enforceAuth` requires `singleOIDCTenant` to be `true`. The Helm chart will fail validation if `enforceAuth` is enabled without single-tenant OIDC.
</Warning>

### Multiple OIDC Providers

For deployments that need multiple OIDC providers or per-organization configuration, leave `singleOIDCTenant` as `false` and configure providers through **Settings → Security → OIDC Identity Providers**. See [Single Sign-On (SSO)](/core/admin/sso) for details.

When using multiple providers, each organization must be mapped to one or more providers. Users can switch between organizations that share the same provider.

### Email Domain Restrictions

```yaml theme={null}
global:
  auth:
    allowedDomains: "company.com,trusted.org"  # comma-separated
    banDisposableEmails: true                   # default: true
```

| Field                 | Default            | Description                                   |
| --------------------- | ------------------ | --------------------------------------------- |
| `allowedDomains`      | none (all domains) | Email domains that can sign up                |
| `banDisposableEmails` | `true`             | Block signups from disposable email providers |

When `allowedDomains` is set, only users with matching email domains can create new accounts. Existing users are not affected.

## Organization Settings

The following settings are configured per-organization through the TextQL Settings panel.

### Discoverability

Controls whether an organization appears when users sign up with a matching email domain.

| Value             | Behavior                                                     |
| ----------------- | ------------------------------------------------------------ |
| `true`            | Organization appears in domain-based discovery during signup |
| `false` (default) | Organization is hidden — users must be explicitly invited    |

**When to disable:**

* Single-tenant deployments where all users are provisioned via OIDC
* Organizations that should only be accessible by direct invitation
* Deployments using [SCIM](/core/admin/scim) for user provisioning

<Note>
  Organizations with an OIDC provider mapping are automatically hidden from email-based discovery regardless of this setting.
</Note>

### Tool Availability

Control which tools are available to users from **Settings → Capabilities**.

| Tool             | Description                            |
| ---------------- | -------------------------------------- |
| Text-to-SQL      | Query databases using natural language |
| Python           | Execute Python code in a sandbox       |
| Web Search       | Search the web for information         |
| Ontology         | Use ontology for structured queries    |
| Ontology Editing | Allow users to modify the ontology     |
| Context Editing  | Allow users to edit context documents  |
| File Upload      | Upload files for analysis              |
| Tableau          | Connect to Tableau                     |
| PowerBI          | Connect to PowerBI                     |
| Google Drive     | Access Google Drive files              |
| Microsoft 365    | Access Microsoft 365 data              |
| Bash             | Execute shell commands in a sandbox    |
| JavaScript       | Execute JavaScript code                |
| Playbooks        | Run and manage playbooks               |
| Form Editor      | Create and edit forms                  |
| Model Switching  | Allow users to switch LLM models       |
| Auto-Approve     | Skip approval for tool execution       |
| Parallel Tools   | Run multiple tools concurrently        |

Organization-level restrictions override defaults. Member-level overrides (if set) take precedence over organization defaults but not restrictions.

### LLM Configuration

Configure the default model and available models from **Settings → Models**.

| Setting            | Description                          |
| ------------------ | ------------------------------------ |
| Default model      | Model used for new chats             |
| Preferred provider | Anthropic or OpenAI                  |
| Enabled models     | Models available to the organization |
| Restricted models  | Models blocked for the organization  |

### Feature Flags

Toggle features on or off per-organization from **Settings → Capabilities**.

| Feature           | Description                             |
| ----------------- | --------------------------------------- |
| Dashboards        | Dashboard creation and viewing          |
| Activity Feed     | Activity feed for the organization      |
| Notifications     | In-app notifications                    |
| Secrets           | Allow members to store secrets          |
| Fast Mode         | Fast execution mode                     |
| Context Review    | Require context review before execution |
| Google Connectors | Enable Google connectors                |
| Training Mode     | Training mode for new users             |

## Role Sync

When enabled, user roles are automatically synchronized from IdP group claims on every login.

### Enabling Role Sync

Add `role_sync_enabled` to the OIDC attribute mapping:

```json theme={null}
{"role_sync_enabled": true, "preserve_admin_role": true}
```

* **Single-tenant mode:** Set via `oidc.attributeMapping` in Helm values
* **Multi-provider mode:** Set in the Attribute Mapping field in **Settings → Security → OIDC Identity Providers**

### How It Works

1. On login, TextQL reads group claims from the IdP token
2. Group names are matched case-insensitively to TextQL role names
3. Matching roles are assigned; roles not present in the IdP groups are removed
4. Groups with no matching TextQL role are silently ignored

When `preserve_admin_role` is `true`, the `admin` role is never removed by sync — this prevents accidental lockout if IdP groups change.

If the IdP cannot return group memberships (e.g., the user belongs to too many groups), role sync is skipped and a warning is shown.

### Troubleshooting

| Symptom                         | Resolution                                                             |
| ------------------------------- | ---------------------------------------------------------------------- |
| Roles not syncing               | Verify `role_sync_enabled` is set in the attribute mapping             |
| All roles removed on login      | Ensure your IdP group names match TextQL role names (case-insensitive) |
| "Role sync was skipped" warning | Configure a groups filter in your IdP or reduce group memberships      |
| Admin role unexpectedly removed | Add `"preserve_admin_role": true` to the attribute mapping             |

## Common Deployment Patterns

### Locked-Down Enterprise (Single IdP)

```yaml theme={null}
global:
  auth:
    singleOIDCTenant: true
    oidc:
      providerType: "Okta OIDC"
      issuerUrl: "https://company.okta.com"
      clientId: "..."
      clientSecret: "..."
      attributeMapping: '{"role_sync_enabled": true, "preserve_admin_role": true}'
    allowedDomains: "company.com"

oathkeeper:
  enforceAuth: true
```

* Discoverable: **off** (users are provisioned via OIDC)
* Configure tool restrictions per organization requirements

### Multi-Org with Shared IdP

```yaml theme={null}
global:
  auth:
    singleOIDCTenant: false
```

* Configure the OIDC provider once via **Settings → Security → OIDC Identity Providers**
* Map the provider to each organization that should use it
* Users can switch between organizations that share the provider
* Discoverable: **off** for each org (OIDC handles access)

### Email-Only (No SSO)

* No OIDC configuration needed
* Discoverable: **on** for organizations users should find via domain matching
* Set `allowedDomains` to your company domain to prevent external signups
