Skip to content
M↓ View as Markdown ↗

Configuration reference

Availability

  • Deployment: Self-managed deployments only. On Actian SaaS, Actian manages this configuration.

This page lists the deployment-wide settings you supply to a self-managed deployment. Members of an organization manage their own settings in Settings in the app.

Most settings are environment variables that the AI Analyst server reads when it starts. With the Helm chart, a few settings are chart values instead.

Tip

This page lists the settings supported for self-managed deployments. Don't set other environment variables unless Actian asks you to.

How you supply configuration

  1. Copy .env.example to .env next to docker-compose.yml, and fill in every value marked REQUIRED.
  2. Start or update the stack:

    docker compose up -d --wait
    

After you edit .env, run docker compose up -d --wait again. Compose recreates the containers whose settings changed. A plain docker compose restart doesn't pick up changes to .env.

The Compose file passes only the keys it lists. The server container doesn't read all of .env. It receives only the keys named in the server service's environment block of docker-compose.yml. A key that this page marks Helm only has no effect when you put it in .env.

Some settings are fixed by the Compose bundle. You can't change them in .env:

Setting Fixed value Why
NETWORK_POSTURE air-gapped The Compose bundle always runs Air-gapped. See Connected and Air-gapped deployments.
ROLES all The whole server runs as one process.
IDENTITY_BACKEND keycloak The bundle includes Keycloak.
STORAGE_DRIVER local Uploaded files live in the storage_data Docker volume.
ENTITLEMENT_BACKEND licence The server reads your Licence from ./licence.

The Compose file also derives the database URL, the public origin and the identity settings from PUBLIC_HOST, POSTGRES_PASSWORD and related keys. See Install with Docker Compose.

The chart loads one Kubernetes Secret onto every server pod. Its name is set by server.existingSecret (default ai-analyst-secrets). You create this Secret yourself; the chart never creates it. Put environment variables in this Secret. The JDBC bridge pod, when enabled, loads the same Secret.

The single-page app reads its public settings (the VITE_* keys) from a separate Secret named by web.configSecretName (default ai-analyst-web-config). See Install on Kubernetes with Helm.

Some settings are chart values. The chart renders these as environment variables on the server pods, and they override any value for the same key in your Secret:

Chart value Sets Notes
server.networkPosture NETWORK_POSTURE connected (the chart default) or air-gapped. Set air-gapped explicitly for a deployment with no internet access.
server.apiPathPrefix API_PATH_PREFIX Set to api so the server answers under /api, as your ingress forwards it. The values-airgap.example.yaml file sets it, together with server.healthProbePath: /api/health.
jdbcBridge.networkPolicy.allowPrivateEgressCidrs WAREHOUSE_EGRESS_ALLOW_PRIVATE_CIDRS A list of CIDRs. Also opens egress from the JDBC bridge. See Warehouse connectivity.
semqlLlmSqlFallback SEMQL_LLM_SQL_FALLBACK Default true. See Timeouts and limits.
server.licence.existingSecret The Licence paths and the Licence entitlement backend See Licence.
server.extraCaCerts.configMap and server.extraCaCerts.key The private CA bundle the server trusts See Private certificate authorities.
embeddings.enabled EMBEDDING_MODEL and EMBEDDING_BASE_URL Leave it false (the default). This section of the chart isn't for customer installs. See Configure inference.

Applying changes:

  • After you change chart values, run helm upgrade with your values file.
  • After you change only the Secret, restart the server pods so they read it again. With a release named ai-analyst and the default single server Deployment:

    kubectl -n ai-analyst rollout restart deployment/ai-analyst-server-server
    

    If you split the server into several roles, restart each server Deployment. If you changed a key that the JDBC bridge reads, restart the bridge Deployment too.

Settings at a glance

Area Main keys Where it's described
Core and identity ENVIRONMENT, DATABASE_URL, FRONTEND_ORIGIN, IDENTITY_BACKEND, KEYCLOAK_*, BOOTSTRAP_* Core settings
Licence LICENCE_DIR, LICENCE_FILE (Compose), server.licence.existingSecret (Helm) Licence
Chat LLM_*, AGENT_STREAM_TIMEOUT_MS Chat and embeddings
Guardrails AGENT_GUARDRAILS_* Guardrails
Embeddings EMBEDDING_*, EMBEDDING_NEXT_* Chat and embeddings
Product email EMAIL_TRANSPORT, EMAIL_FROM, SMTP_*, UNSUBSCRIBE_SIGNING_KEY Product email
File storage STORAGE_DRIVER, S3_* File storage
Encryption key WAREHOUSE_CREDENTIAL_ENCRYPTION_KEY Credential encryption key
Warehouses JDBC_BRIDGE_*, WAREHOUSE_EGRESS_ALLOW_PRIVATE_CIDRS, CONNECTORS_ENABLED, WAREHOUSE_EGRESS_IPS Warehouse connectivity
Timeouts and limits AGENT_STREAM_TIMEOUT_MS, FILE_UPLOAD_MAX_BYTES, SEMQL_LLM_SQL_FALLBACK Timeouts and limits
TLS trust SERVER_EXTRA_CA_CERTS (Compose), server.extraCaCerts (Helm) Private certificate authorities

Core settings

The install guides walk through these settings in order. This table is a summary.

Key Required Description
ENVIRONMENT Yes Set to production. The Compose bundle defaults it to production.
NETWORK_POSTURE Yes connected or air-gapped. Fixed by the Compose bundle; set with server.networkPosture on Helm.
DATABASE_URL Yes The Postgres connection URL for the product database. The Compose bundle builds it from POSTGRES_USER and POSTGRES_PASSWORD.
FRONTEND_ORIGIN Yes The URL members open, for example https://analyst.example.internal. On Compose it comes from PUBLIC_HOST, or from PUBLIC_ORIGIN when you use a port other than 443.
API_PORT Yes The port the server listens on: 8080. The Compose bundle sets it for you.
PLG_CONFIG Yes Set to off. The Compose bundle sets it for you.
IDENTITY_BACKEND Yes on Air-gapped keycloak. If you leave it unset, the server assumes Auth0, which an Air-gapped deployment refuses.
KEYCLOAK_BASE_URL, KEYCLOAK_REALM, KEYCLOAK_ADMIN_CLIENT_ID, KEYCLOAK_ADMIN_CLIENT_SECRET With Keycloak How the server reaches Keycloak's admin API.
AUTH0_DOMAIN, AUTH0_AUDIENCE Yes Despite the names, with Keycloak these hold the token issuer (the realm URL) and the API audience.
BOOTSTRAP_ORG_NAME, BOOTSTRAP_ADMIN_EMAIL Yes, for the first start The first organization and its administrator. BOOTSTRAP_ADMIN_PASSWORD and BOOTSTRAP_SIGNUP_DOMAINS are optional. See Identity and first sign-in.

Chat and embeddings

No model ships with AI Analyst. You point the deployment at your own OpenAI-compatible APIs. Configure inference explains each setting, with examples.

Key Required Default Compose Description
LLM_PROVIDER No Unset (no deployment default) Yes openai-compatible for your own API.
LLM_BASE_URL With LLM_PROVIDER Yes The API's base URL, including /v1.
LLM_MODEL With LLM_PROVIDER Yes The model id the API serves.
LLM_CAPABILITY_PRESET With LLM_PROVIDER Yes generic or reasoning.
LLM_API_KEY No Yes Sent as a bearer token.
LLM_FAST_MODEL No LLM_MODEL Yes The model for quick calls, such as conversation titles.
AGENT_STREAM_TIMEOUT_MS No 240000 Yes How long one agent response may take, in milliseconds.
EMBEDDING_MODEL No Unset (keyword-only search) Yes A preset id or your own model id.
EMBEDDING_BASE_URL Yes on Air-gapped, and for qwen3-embedding-0.6b and custom models Yes The API's base URL, without /v1. Always set it to your own endpoint. See Configure inference.
EMBEDDING_API_KEY No Yes Sent as a bearer token.
EMBEDDING_DIMENSIONS For a custom model Yes The length of the model's vectors.
EMBEDDING_MAX_DISTANCE, EMBEDDING_QUERY_PREFIX No Helm only Tuning for a custom model.
EMBEDDING_NEXT_* No Helm only The next model, while you change models.

Guardrails

Input guardrails check each message a person types for prompt injection and for harmful content. Organizations turn Guardrail blocking on themselves. These settings control the check for the whole deployment. PII masking has no deployment setting.

The Compose bundle does not forward these keys, so a Compose deployment always uses the defaults. On Helm, set them in the server Secret. The Secret is loaded on every server pod, including when you split roles. Restart the server pods after a change. An invalid value stops the server from starting.

Key Required Default Compose Description
AGENT_GUARDRAILS_ENABLED No true Helm only true or false. false runs no check, and the organization's Guardrail blocking switch is disabled.
AGENT_GUARDRAILS_INJECTION_THRESHOLD No 0.7 Helm only Score at or above which prompt injection is recorded as a flag. The message still runs. A number from 0 (exclusive) to 1.
AGENT_GUARDRAILS_INJECTION_BLOCK_THRESHOLD No 0.9 Helm only Score at or above which prompt injection stops the message, when the organization has Guardrail blocking on. Must be at least AGENT_GUARDRAILS_INJECTION_THRESHOLD, or the server refuses to start.
AGENT_GUARDRAILS_MODERATION_THRESHOLD No 0.5 Helm only Score at or above which content moderation is recorded as a flag. Content moderation never stops a message.

The default block threshold is the lowest cut that had no false stops on a synthetic set of ordinary analytics questions, including questions that mention age, gender or nationality. Lowering it stops more override attempts and can also stop a legitimate follow-up that uses words such as "disregard". Revisit the value if you change the chat model. What the check covers is described in Input guardrails.

Product email

AI Analyst sends product email, such as Scheduled Insights and notifications, through an SMTP relay that you run.

Key Required Default Description
EMAIL_TRANSPORT To send email Unset Set to smtp.
EMAIL_FROM With smtp The sender, for example AI Analyst <analyst@example.internal>.
SMTP_HOST With smtp Your relay's host name.
SMTP_PORT No 587 The relay's port.
SMTP_TLS No starttls How the connection is secured: starttls, implicit (typically port 465) or none.
SMTP_USER, SMTP_PASSWORD No Credentials, if the relay needs them.
UNSUBSCRIBE_SIGNING_KEY No Signs the unsubscribe links in notification emails. Generate one with openssl rand -hex 32. Without it, notification emails carry no unsubscribe link. The link is built from a separate public API base URL setting that the Compose bundle doesn't pass, so on Compose the links don't resolve.
  • If EMAIL_TRANSPORT is unset, nothing is sent. The server writes each email to its log instead.
  • Use only smtp on a self-managed deployment. ses is vendor-hosted, and an Air-gapped deployment refuses SES_* keys. An unknown value stops the server at startup. With smtp, a missing SMTP_HOST or EMAIL_FROM, an invalid SMTP_PORT or an unknown SMTP_TLS value also stops it.
  • Keycloak sends its own email. Invitations, password resets and email verification for sign-up domains come from Keycloak, not from these settings. Configure Keycloak's relay in the Keycloak admin console, under the aianalyst realm → Realm settings → Email. See Identity and first sign-in.
  • On Compose, the server and Keycloak can't reach a relay on your network by default. Run the relay as a container on the stack's network, or use the compose.customer-network.yml override. See Warehouse connectivity for how the override works.

File storage

AI Analyst keeps uploaded files, their converted Parquet copies and attachments in file storage, separate from Postgres.

Files live in the storage_data Docker volume. You don't configure anything. Include the volume in your backups. See Upgrade and backup.

Use S3-compatible object storage, such as MinIO or Ceph RGW. Put these keys in the server Secret:

Key Required Default Description
STORAGE_DRIVER Yes Set to s3.
S3_BUCKET Yes The bucket name.
S3_ENDPOINT Yes on Air-gapped Unset (AWS S3) Your S3-compatible server, for example https://minio.example.internal.
S3_REGION No us-east-1 The region your storage expects.
S3_FORCE_PATH_STYLE No true when S3_ENDPOINT is set Path-style addressing, which most S3-compatible servers need.
S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY No Static credentials. Without them, the server uses the default AWS credential chain.

Always set STORAGE_DRIVER=s3 on Helm

If STORAGE_DRIVER is unset, the server keeps files on the pod's temporary disk. Files are lost when a pod restarts, and other pods can't see them.

On an Air-gapped deployment, STORAGE_DRIVER=s3 without S3_ENDPOINT stops the server at startup, because the files would go to AWS S3.

Credential encryption key

WAREHOUSE_CREDENTIAL_ENCRYPTION_KEY encrypts secrets that AI Analyst stores in its database:

  • Warehouse credentials.
  • Catalog connection secrets.
  • API keys of LLM and Embedding endpoints that an organization adds under Settings → Inference.

The key is required. Generate it once:

openssl rand -hex 32

Keep this key safe and never change it

Store the key outside the deployment, with your other secrets, and keep it with your backups. If you lose or change it after the first start, AI Analyst can't decrypt any credential it stored before. A connection test then fails with Stored credentials could not be read.

Timeouts and limits

Key Default Compose Description
AGENT_STREAM_TIMEOUT_MS 240000 (4 minutes) Yes The longest one agent response may take. Raise it for a self-hosted model that needs minutes to answer and call tools, for example 900000.
FILE_UPLOAD_MAX_BYTES 262144000 (250 MiB) Helm only The largest CSV file members can upload. An invalid value falls back to the default. If you raise it, raise your ingress request-body limit and the server's memory in proportion. The 260 MB and 1 GiB figures below apply to the 250 MiB default.
SEMQL_LLM_SQL_FALLBACK On Helm only (semqlLlmSqlFallback) When the warehouse rejects generated SQL with a dialect or syntax error, AI Analyst asks the LLM to rewrite that SQL once and retries. The rewrite can only use tables and columns that the original SQL already used. Set semqlLlmSqlFallback: false to turn it off.

About file uploads:

  • Request size. The Compose bundle's reverse proxy accepts request bodies up to 260 MB. On Helm, configure your ingress to accept request bodies of at least 260 MB, with a read timeout of at least 600 seconds for large uploads.
  • Memory. Converting a 250 MiB CSV file peaks near 1 GiB on top of the running server, so keep headroom above that. On Compose, the SERVER_MEMORY_LIMIT default is 3g.

Private certificate authorities

The server makes HTTPS calls to services you run: Keycloak (to fetch the token signing keys), your LLM and Embedding endpoints, and warehouses. If any of these presents a certificate from a private certificate authority (CA), the server must trust that CA. The server reads the CA bundle only when it starts, so restart it after you change the bundle.

By default, the server trusts the internal CA that the bundled Caddy proxy uses for its certificate. To trust your own CA instead:

  1. Create one PEM file in ./certs that contains every CA the server needs, including the CA that signed the proxy's certificate. If you still use Caddy's internal certificate, copy its root CA out of the proxy first:

    docker compose cp proxy:/data/caddy/pki/authorities/local/root.crt ./caddy-root.crt
    cat ./caddy-root.crt ./your-internal-ca.pem > ./certs/ca.crt
    
  2. In .env, set:

    SERVER_EXTRA_CA_CERTS=/etc/ai-analyst/certs/ca.crt
    
  3. Run docker compose up -d --wait.

Warning

SERVER_EXTRA_CA_CERTS replaces the default trust of Caddy's internal CA. If your file leaves out the CA that signed the proxy's certificate, the server can't verify sign-in tokens and every API call fails with 401.

  1. Put the PEM bundle in a ConfigMap:

    kubectl -n ai-analyst create configmap ai-analyst-ca --from-file=ca.crt=internal-ca.pem
    
  2. Set these values and run helm upgrade:

    server:
      extraCaCerts:
        configMap: ai-analyst-ca
        key: ca.crt
    

Health endpoint

The server answers GET /api/health with its status (with the Helm chart, this assumes server.apiPathPrefix: api). The Compose bundle uses it as the server's health check, and the Helm example values use it for the pods' probes.

The response includes an embeddings field: ok, degraded (the Embedding endpoint didn't answer the last check), unconfigured (no EMBEDDING_MODEL) or unknown (not checked yet). This field is for information only. An Embedding endpoint that's down never makes the server unhealthy, because search falls back to keyword matching.

How the server reports configuration problems

The server checks its configuration when it starts. If something is wrong, it refuses to start and logs an error that names the setting. To read the error:

  • Compose: docker compose logs server
  • Helm: kubectl -n ai-analyst logs deployment/ai-analyst-server-server (adjust the name for your release and roles)
Problem Example error
A required key is missing. DATABASE_URL, ENVIRONMENT and NETWORK_POSTURE are always required. Missing required env vars for roles [...]: NETWORK_POSTURE
NETWORK_POSTURE has an unknown value. Unknown NETWORK_POSTURE "...". Known postures: ...
ROLES isn't a known composition. ROLES=... is not a known deploy composition.
On an Air-gapped deployment, a vendor-hosted key is set. NETWORK_POSTURE=air-gapped forbids vendor-hosted env vars: ...
On an Air-gapped deployment, a setting would reach a vendor-hosted service. NETWORK_POSTURE=air-gapped: ...
The deployment default LLM endpoint is incomplete or unknown. LLM_PROVIDER=openai-compatible requires LLM_CAPABILITY_PRESET (one of generic, reasoning); ...
Product email, embedding or file storage settings are invalid. For example SMTP_HOST is required when EMAIL_TRANSPORT=smtp, or EMBEDDING_DIMENSIONS must be set to a positive integer for custom embedding model ...

For the full list of Air-gapped checks, see How Air-gapped is enforced.

Split server roles on Helm

When server.strictEnv is true (the default), a server pod also refuses to start if the Secret contains a key that only a different server role uses. The error lists each key as set but not declared by any loaded role. If you split the server into several roles that share one Secret, set server.strictEnv: false. Required keys are still checked. See Scaling and operations.