--- description: Let a self-managed deployment of Actian AI Analyst reach your warehouses, turn on the JDBC bridge for Actian-family warehouses, limit which connectors members can use, and fix connection problems. --- # Warehouse connectivity !!! info "Availability" - **Deployment:** Self-managed deployments only. On Actian SaaS, Actian manages these settings. Members connect warehouses in Studio, under **Connections** → **Add a connection** → **Warehouses**. As the operator of a self-managed deployment of Actian AI Analyst, you decide: - Which private networks the server may connect to. - Whether the Actian-family connectors are available, by running the JDBC bridge. - Which connectors members are offered. - Which egress IP addresses Studio shows members for their firewall rules. ## How AI Analyst connects to a warehouse - **Most connectors** (PostgreSQL, Snowflake, BigQuery and others) connect directly from the AI Analyst server. - **Actian, Ingres, Informix and ZenDB** connect through the *JDBC bridge*, a separate service that holds their JDBC drivers. The server sends each query to the bridge, which connects to the warehouse. For every connector, the server first resolves the warehouse host name and checks the address against its egress rules. See [Reach warehouses on private networks](#reach-warehouses-on-private-networks). A connector appears under **Add a connection** → **Warehouses** only when all of these allow it: | Gate | Set by | Effect | |---|---|---| | The JDBC bridge | `JDBC_BRIDGE_URL` | Actian, Ingres, Informix and ZenDB are offered only when `JDBC_BRIDGE_URL` is set. | | The connector allowlist | `CONNECTORS_ENABLED` | When set, only the listed connectors are offered. | | Your Licence | The Licence Actian issues | A connector is offered unless your Licence explicitly excludes it. | ## Reach warehouses on private networks ### The server's egress rules Before it connects to a warehouse, the server resolves the host name and checks every address it gets back: - **Private address space is denied unless you allow it.** This covers `0.0.0.0/8`, `10.0.0.0/8`, `127.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `::/128`, `::1/128` and `fc00::/7`. To allow a range, list it in `WAREHOUSE_EGRESS_ALLOW_PRIVATE_CIDRS` as comma-separated CIDRs, for example `10.20.0.0/16,192.168.50.0/24`. - **Some destinations are always denied**, even if you list them: link-local addresses (`169.254.0.0/16` and `fe80::/10`, which include cloud metadata services) and the host names `metadata.google.internal`, `metadata.goog`, `kubernetes.default`, `kubernetes.default.svc` and `kubernetes.default.svc.cluster.local`. - **Public addresses are allowed.** The same rules apply to the LLM and Embedding endpoints that organizations add under **Settings** → **Inference**. They don't apply to the deployment default endpoints in [Configure inference](configure-inference.md). When `WAREHOUSE_EGRESS_ALLOW_PRIVATE_CIDRS` isn't set at all, the default depends on where the server runs: | Where the server runs | Default when the variable is unset | |---|---| | Kubernetes (Helm chart) | All private ranges are denied. The Helm chart always sets the variable, so this applies when your list is empty. | | Docker Compose | `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `127.0.0.0/8` and `::1` are allowed. | Once you set the variable, only the ranges you list are allowed. ### Compose bundle Every container except the reverse proxy sits on a Docker network with no route off the host. Out of the box, the server and the JDBC bridge can reach only the containers in the stack. To reach warehouses on your network: 1. Attach the stack to your network with the override file: ```sh docker compose -f docker-compose.yml -f compose.customer-network.yml up -d --wait ``` The override attaches the `server`, `keycloak` and `jdbc-bridge` services to one more, routed Docker network. You can name it with `CUSTOMER_NETWORK_NAME` (default `ai-analyst-customer`). 2. Restrict egress with the host firewall. From now on, **the host firewall is what keeps the installation Air-gapped**. Allow traffic out of that network only to your own address ranges, such as warehouses, LLM and Embedding endpoints and your SMTP relay. On Linux, the `DOCKER-USER` iptables chain is the usual place for these rules. 3. Optional: restrict which private ranges the server may reach. On Compose, private ranges are already allowed by default. If you want to limit the server to specific ranges, list them in `.env`: ```sh WAREHOUSE_EGRESS_ALLOW_PRIVATE_CIDRS=10.20.0.0/16 ``` Then run the same `docker compose ... up -d --wait` command again. !!! tip Use the same `-f` options every time you run `docker compose` for this stack, or the override is dropped. ### Helm chart List the private ranges in a chart value: ```yaml jdbcBridge: networkPolicy: allowPrivateEgressCidrs: - 10.20.0.0/16 ``` Then run `helm upgrade`. The chart uses this one list in two places: - It sets `WAREHOUSE_EGRESS_ALLOW_PRIVATE_CIDRS` on the server pods. This value overrides the same key in your Secret, so don't set it there. - When the JDBC bridge is enabled, it adds an egress rule for each range to the bridge's NetworkPolicy. The chart doesn't ship a NetworkPolicy for the server pods. Your cluster's own egress policy must allow the server to reach your warehouses. ## Enable Actian-family warehouses (JDBC bridge) The JDBC bridge serves the **Actian**, **Ingres**, **Informix** and **ZenDB** connectors. It's off by default. While `JDBC_BRIDGE_URL` is unset, these connectors aren't offered. The bridge refuses to start without `JDBC_BRIDGE_TOKEN`, a shared secret that the server sends with each request. There's no default token. Generate one: ```sh openssl rand -hex 32 ``` === "Compose bundle" 1. In `.env`, set: ```sh JDBC_BRIDGE_URL=http://jdbc-bridge:8080 JDBC_BRIDGE_TOKEN= ``` The server and the bridge both read the same `JDBC_BRIDGE_TOKEN`. 2. Start the stack with the `jdbc` profile. Add the `compose.customer-network.yml` override if your warehouses are on your network: ```sh docker compose --profile jdbc -f docker-compose.yml -f compose.customer-network.yml up -d --wait ``` !!! tip To avoid typing `--profile jdbc` every time, set `COMPOSE_PROFILES=jdbc` in `.env`. This is a standard Docker Compose setting. === "Helm chart" 1. Push the `jdbc-bridge` image from the [Release bundle](release-bundle.md) to your registry, as you did for the other images. 2. Set these values: ```yaml jdbcBridge: enabled: true image: repository: registry.example.internal/ai-analyst/jdbc-bridge tag: "" ``` `jdbcBridge.image.repository` is empty by default, so you must set it. 3. Add `JDBC_BRIDGE_URL` and `JDBC_BRIDGE_TOKEN` to the server Secret (`server.existingSecret`). The bridge pod reads its token from the same Secret. ```sh kubectl -n ai-analyst patch secret ai-analyst-secrets --type merge \ -p '{"stringData":{"JDBC_BRIDGE_URL":"http://ai-analyst-jdbc-bridge:8080","JDBC_BRIDGE_TOKEN":""}}' ``` The bridge's Service is named `-jdbc-bridge` and listens on port 8080. `` is: - the release name, when it contains `ai-analyst` (release `ai-analyst` gives `http://ai-analyst-jdbc-bridge:8080`); - otherwise `-ai-analyst` (release `prod` gives `http://prod-ai-analyst-jdbc-bridge:8080`); - or `fullnameOverride`, when you set it. 4. Run `helm upgrade`, then restart the server pods so they read the updated Secret. See [How you supply configuration](configuration-reference.md#how-you-supply-configuration). After the server restarts, the four connectors appear under **Add a connection** → **Warehouses**, unless `CONNECTORS_ENABLED` or your Licence excludes them. For each connector's connection form, see [Actian Data Platform](../connections/connect-a-data-source/actian-data-platform.md), [Actian Ingres](../connections/connect-a-data-source/actian-ingres.md) and [Actian Zen](../connections/connect-a-data-source/actian-zen.md). ### How the bridge is protected - **It stores no warehouse credentials.** The server decrypts the credentials and sends them with each request. The bridge doesn't keep them or pool connections. - **It needs the token.** Only requests that carry `JDBC_BRIDGE_TOKEN` can run queries. - **On Helm, it's reachable only from the server.** The bridge has a ClusterIP Service and no ingress route. Its NetworkPolicy accepts connections on port 8080 only from the chart's server pods. Its egress allows DNS and public addresses, but not `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16` or `169.254.0.0/16`, except for the ranges you list in `allowPrivateEgressCidrs`. - **On Compose, the token is the main control.** There's no NetworkPolicy. Any container on the stack's network can reach the bridge. !!! warning "NetworkPolicy needs a CNI that enforces it" If your cluster's network plugin doesn't enforce NetworkPolicy, the bridge's ingress and egress rules have no effect, and nothing reports it. Check your network plugin before you rely on these rules. On Helm, the bridge pod loads the whole server Secret, but it reads only `JDBC_BRIDGE_TOKEN` from it. ### Check which drivers the bridge can load The bridge answers `GET /health` without a token. The response lists each driver and whether the bridge can load it: ```json {"ok": true, "drivers": {"ACTIAN": true, "INGRES": true, "INFORMIX": true, "ZENDB": false}} ``` This example shows a bridge that can't load the ZenDB driver. The endpoint is reachable only from inside the deployment, and the bridge image has no `curl`: === "Compose bundle" Ask from the server container: ```sh docker compose exec server node -e "fetch('http://jdbc-bridge:8080/health').then(r => r.text()).then(console.log)" ``` === "Helm chart" Forward the bridge's port, then ask from your machine: ```sh kubectl -n ai-analyst port-forward svc/-jdbc-bridge 8080:8080 curl -s http://127.0.0.1:8080/health ``` Replace `-jdbc-bridge` with your bridge Service name (see above). AI Analyst doesn't read this endpoint itself. Studio offers all four connectors whenever `JDBC_BRIDGE_URL` is set, even if the bridge can't load a driver. !!! warning "ZenDB" If the health response shows `"ZENDB": false`, ZenDB connections fail even though Studio offers the connector: tests and queries are refused because the driver isn't available. Contact Actian about the ZenDB driver. Until then, you can hide ZenDB with `CONNECTORS_ENABLED` on the Helm chart. ## Limit which connectors are offered `CONNECTORS_ENABLED` is a comma-separated list of connector IDs. When you set it, members are offered only the listed connectors. When it's unset or empty, every connector is offered. ```sh CONNECTORS_ENABLED=POSTGRESQL,SNOWFLAKE,ACTIAN ``` IDs are upper case and must match exactly: | ID | Connector | ID | Connector | |---|---|---|---| | `POSTGRESQL` | PostgreSQL | `BIGQUERY` | BigQuery | | `MYSQL` | MySQL | `SNOWFLAKE` | Snowflake | | `MARIADB` | MariaDB | `DATABRICKS` | Databricks | | `REDSHIFT` | Amazon Redshift | `MOTHERDUCK` | MotherDuck | | `MSSQL` | Microsoft SQL Server | `ACTIAN` | Actian | | `SYNAPSE` | Azure Synapse | `INGRES` | Ingres | | `FABRIC` | Microsoft Fabric | `INFORMIX` | Informix | | `CLICKHOUSE` | ClickHouse | `ZENDB` | ZenDB | - **It can't turn on a bridge connector.** `ACTIAN`, `INGRES`, `INFORMIX` and `ZENDB` still need `JDBC_BRIDGE_URL`. - **CSV file uploads aren't affected.** Files aren't a connector. - **Existing connections keep working.** For a connector that isn't offered, members can't create a connection, test an unsaved connection, list schemas for an unsaved connection, or change an existing connection's credentials. The API refuses these actions with a `CONNECTOR_UNAVAILABLE` error (HTTP 409) and the message *not offered by this deployment*. Members can still browse, query, rename and re-test existing connections. - **Set it on the Helm chart only.** Add `CONNECTORS_ENABLED` to the server Secret. The shipped Compose file doesn't pass this key to the server, so setting it in `.env` has no effect. When your Licence excludes a connector, the same actions are refused with `CONNECTOR_UNAVAILABLE` and the message *not included in your plan*. !!! warning "Removing the bridge breaks existing Actian-family connections" If you remove `JDBC_BRIDGE_URL` or `JDBC_BRIDGE_TOKEN` later, the server can no longer reach the bridge. Every query on an existing Actian, Ingres, Informix or ZenDB connection fails, and connection tests show **This warehouse type isn't available right now**. ## Show your egress IP addresses to members Members often need to allow AI Analyst's IP addresses through their warehouse firewall. Studio's **Setup help** panel for a warehouse connection can list those addresses under **Which IPs to allow**. By default, a self-managed deployment lists no addresses, and the panel shows general guidance instead. To list your deployment's outbound (NAT or egress) addresses, set `WAREHOUSE_EGRESS_IPS` to a comma-separated list: ```sh WAREHOUSE_EGRESS_IPS=203.0.113.10,203.0.113.11 ``` On the Helm chart, add it to the server Secret. The shipped Compose file doesn't pass this key to the server. On Compose, give members the addresses yourself. ## Credential encryption key AI Analyst encrypts stored warehouse credentials with `WAREHOUSE_CREDENTIAL_ENCRYPTION_KEY`. Keep this key safe and never change it. If you lose it, AI Analyst can't read any stored credential. See [Credential encryption key](configuration-reference.md#credential-encryption-key). ## Slack and Microsoft Teams The Slack and Microsoft Teams integrations need vendor-hosted services. On an Air-gapped deployment, which includes every Compose installation, the server refuses to start if any Slack or Teams key is set, so these integrations aren't available. See [Connected and Air-gapped deployments](network-posture.md). ## Troubleshooting | Symptom | Likely cause | Fix | |---|---|---| | Actian, Ingres, Informix or ZenDB is missing under **Add a connection** → **Warehouses**. | `JDBC_BRIDGE_URL` is unset, `CONNECTORS_ENABLED` leaves the connector out, or your Licence excludes it. | Set up the [JDBC bridge](#enable-actian-family-warehouses-jdbc-bridge) and check `CONNECTORS_ENABLED`. | | Another connector is missing. | `CONNECTORS_ENABLED` leaves it out, or your Licence excludes it. | Add its ID to `CONNECTORS_ENABLED`, or contact Actian about your Licence. | | The JDBC bridge doesn't start. | `JDBC_BRIDGE_TOKEN` is empty. | Set a non-blank token for both the server and the bridge. | | A connection test shows **This warehouse type isn't available right now**. | The server has no `JDBC_BRIDGE_URL` or `JDBC_BRIDGE_TOKEN`. | Set both and restart the server. | | A connection to a warehouse on a private network fails. | The server's egress rules deny the address, or the network doesn't route to it. A connection test shows **Could not connect** with the detail "Warehouse host is not allowed". Other requests, such as listing schemas, answer HTTP 400 with the code `WAREHOUSE_HOST_DENIED`. | List the warehouse's range in `WAREHOUSE_EGRESS_ALLOW_PRIVATE_CIDRS` (Compose) or `allowPrivateEgressCidrs` (Helm). On Compose, private ranges are allowed by default, so a denial usually means a link-local address or a list you set that leaves the range out. On Compose, use the customer network override and check the host firewall. On Helm, check your cluster's egress policy. | | ZenDB tests fail although the bridge runs. | The bridge can't load the ZenDB driver. | [Check the bridge's drivers](#check-which-drivers-the-bridge-can-load). | | A connection test shows **Stored credentials could not be read**. | `WAREHOUSE_CREDENTIAL_ENCRYPTION_KEY` changed since the credentials were saved. | Restore the original key. | | `CONNECTORS_ENABLED` has no effect on Compose. | The Compose file doesn't pass this key to the server. | This setting is available on the Helm chart. |