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

# Trino

> Deploy Trino on Control Plane using the Template Catalog. A distributed SQL query engine that joins PostgreSQL, MySQL, ClickHouse, MongoDB and more in one query, with a coordinator plus a scalable worker tier. Covers catalogs, credential secrets, authentication, and access.

## Overview

Trino is a distributed SQL query engine that queries data where it lives. This template deploys a Trino cluster — one coordinator plus a scalable worker tier — that connects to PostgreSQL, MySQL, ClickHouse, MongoDB and 40+ other sources through **catalogs**, and joins across them in a single query without copying any data. Databases you already run on Control Plane are reachable over internal DNS, so a query can span several of them at once.

Trino stores nothing itself: it plans and executes queries against your existing systems, so there are no volumes and a restart costs only the queries in flight.

### Architecture

* **Coordinator** — Parses and plans queries, serves the Web UI and the JDBC/REST endpoint on port `8080`, and tracks the workers. Always exactly one replica.
* **Workers** — Stateless execution tier on port `8080`, `workers.replicas` replicas. Setting `workers.replicas: 0` collapses the cluster to a single node where the coordinator executes queries itself.
* **Catalogs** — One properties file per data source, mounted on every node. The image already ships the `tpch`, `tpcds`, `memory` and `jmx` catalogs, so a default install is queryable immediately.

### What Gets Created

* **Standard Coordinator Workload** — A single replica serving clients, the Web UI and worker discovery on port `8080`.
* **Standard Worker Workload** — `workers.replicas` interchangeable execution replicas on port `8080`. Not created when `workers.replicas: 0`.
* **Config Secrets** — The rendered `config.properties` (one per tier), `jvm.config` and `node.properties`, mounted into `/etc/trino`.
* **Catalog Secrets** *(optional)* — One per `catalogs[]` entry, mounted as `/etc/trino/catalog/<name>.properties` on every node.
* **Password-authenticator Secret** *(optional)* — Created on the coordinator when `auth.enabled`.
* **Identity & Policy** — One identity shared by both workloads, with a policy granting `reveal` on exactly the config, catalog and authentication secrets in use — including the credential secrets you created yourself.
* **No Volume Sets** — Trino owns no data.

<Note>
  This template does not create a GVC. You must deploy it into an existing GVC.
</Note>

## Prerequisites

* **None for a default install.** The built-in `tpch`, `tpcds`, `memory` and `jmx` catalogs make the cluster queryable the moment it is ready.
* **To query your own data sources:** one Control Plane secret per credential, created **before** installing — see [Connecting Data Sources](#connecting-data-sources). Credentials are never passed through values.
* **To enable authentication** (required for public access): two [opaque secrets](/guides/create-secret/opaque) created before installing — see [Authentication](#authentication).

## Installation

Install the template using your preferred method:

<CardGroup cols={2}>
  <Card title="UI" href="/template-catalog/install-manage/ui" icon="laptop">
    Browse, install, and manage templates visually
  </Card>

  <Card title="CLI" href="/template-catalog/install-manage/cli" icon="terminal">
    Manage templates from your terminal
  </Card>

  <Card title="Terraform" href="/template-catalog/install-manage/terraform" icon={<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M77.941 44.5v36.836L46.324 62.918V26.082zm0 0" fill="#5c4ee5"/><path d="M81.41 81.336l31.633-18.418V26.082L81.41 44.5zm0 0" fill="#4040b2"/><path d="M11.242 42.36L42.86 60.776V23.941L11.242 5.523zm0 0M77.941 85.375L46.324 66.957v36.82l31.617 18.418zm0 0" fill="#5c4ee5"/></g></svg>}>
    Declare templates in your Terraform configurations
  </Card>

  <Card
    title="Pulumi"
    href="/template-catalog/install-manage/pulumi"
    icon={<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" id="Pulumi-Icon--Streamline-Svg-Logos" height="24" width="24">
    <desc>
        Pulumi Icon Streamline Icon: https://streamlinehq.com
    </desc>
    <path fill="#f26e7e" d="M4.683025 13.3318c0.869125 -0.5018 0.870575 -2.1264 0.003225 -3.62865s-2.27504 -2.313275 -3.1441725 -1.811475C0.672945 8.3935 0.6715 10.0181 1.53885 11.52035c0.86735 1.502275 2.27505 2.313275 3.144175 1.81145Zm0.0052 3.2167c0.86735 1.502275 0.865925 3.126875 -0.003225 3.628675 -0.86915 0.5018 -2.2768275 -0.309225 -3.144175 -1.81145 -0.8673525 -1.50225 -0.8659075 -3.126875 0.003225 -3.628675 0.8691325 -0.5018 2.276825 0.309225 3.144175 1.81145Zm5.922875 3.4243c0.86735 1.50225 0.8659 3.126775 -0.003225 3.62875 -0.869125 0.501775 -2.27685 -0.309325 -3.1442 -1.81155 -0.867325 -1.50225 -0.865875 -3.12685 0.00325 -3.628675 0.869125 -0.5018 2.276825 0.309225 3.144175 1.811475Zm-0.001925 -6.845275c0.86735 1.50225 0.8659 3.12685 -0.003225 3.628675 -0.869125 0.5018 -2.276825 -0.309225 -3.144175 -1.811475 -0.86735 -1.50225 -0.8659 -3.12685 0.003225 -3.62865 0.869125 -0.501825 2.276825 0.3092 3.144175 1.81145Z" stroke-width="0.25"></path>
    <path fill="#8a3391" d="M22.45775 11.524125c0.86725 -1.502225 0.865925 -3.12685 -0.003225 -3.62865 -0.869125 -0.501825 -2.276825 0.3092 -3.144175 1.811475 -0.86735 1.50225 -0.8659 3.126825 0.003225 3.62865 0.869125 0.501825 2.276825 -0.3092 3.144175 -1.811475Zm0.000175 3.2151c0.869075 0.5018 0.870625 2.1264 0.003225 3.62865 -0.86735 1.50225 -2.27505 2.313275 -3.144175 1.81145 -0.869125 -0.5018 -0.870575 -2.126425 -0.003225 -3.62865 0.86735 -1.50225 2.27505 -2.313275 3.144175 -1.81145ZM16.536225 18.157875c0.86915 0.501825 0.8706 2.126425 0.00325 3.628675 -0.86735 1.502125 -2.275075 2.313225 -3.1442 1.81145 -0.869125 -0.50175 -0.870575 -2.126425 -0.003225 -3.62865 0.867375 -1.502275 2.27505 -2.3133 3.144175 -1.811475Zm-0.003325 -6.843775c0.869125 0.5018 0.870575 2.126425 0.003225 3.628675s-2.27505 2.313275 -3.1442 1.811475c-0.869125 -0.501825 -0.870575 -2.126425 -0.003225 -3.628675 0.86735 -1.502275 2.27505 -2.313275 3.1442 -1.811475Z" stroke-width="0.25"></path>
    <path fill="#f7bf2a" d="M15.138225 2.06721c0 1.003615 -1.40625 1.817215 -3.14095 1.817215 -1.7347 0 -3.14095 -0.8136 -3.14095 -1.817215C8.856325 1.06359 10.262575 0.25 11.997275 0.25c1.7347 0 3.14095 0.81359 3.14095 1.81721ZM9.2166 5.482375c0 1.003625 -1.40625 1.8172 -3.14095 1.8172 -1.7347 0 -3.14095 -0.813575 -3.14095 -1.8172s1.40625 -1.817225 3.14095 -1.817225c1.7347 0 3.14095 0.8136 3.14095 1.817225Zm8.71005 1.8172c1.7347 0 3.14095 -0.813575 3.14095 -1.8172s-1.40625 -1.817225 -3.14095 -1.817225c-1.7347 0 -3.14095 0.8136 -3.14095 1.817225s1.40625 1.8172 3.14095 1.8172Zm-2.788425 1.605625c0 1.003625 -1.40625 1.8172 -3.14095 1.8172 -1.7347 0 -3.14095 -0.813575 -3.14095 -1.8172 0 -1.0036 1.40625 -1.8172 3.14095 -1.8172 1.7347 0 3.14095 0.8136 3.14095 1.8172Z" stroke-width="0.25"></path>
    </svg>}
  >
    Declare templates in your Pulumi programs
  </Card>
</CardGroup>

## Configuration

The default `values.yaml` for this template:

```yaml theme={null}
image: trinodb/trino:483

# ─── Coordinator ──────────────────────────────────────────────────────────────
# One coordinator per cluster (Trino's design): plans queries, serves the Web UI,
# the JDBC/REST endpoint, and worker discovery.
coordinator:
  resources:
    minCpu: 500m
    maxCpu: 1000m
    minMemory: 2Gi
    maxMemory: 4Gi # JVM heap is a percentage OF THIS — see jvm.maxRAMPercentage

# ─── Workers ──────────────────────────────────────────────────────────────────
# Stateless query-execution tier. Raise replicas for more query capacity and to
# keep capacity through a rolling restart.
workers:
  replicas: 1 # 0 = single-node mode (the coordinator executes queries itself)
  resources:
    minCpu: 500m
    maxCpu: 2000m
    minMemory: 2Gi
    maxMemory: 4Gi # JVM heap is a percentage OF THIS — see jvm.maxRAMPercentage

# ─── JVM ──────────────────────────────────────────────────────────────────────
# Heap = this percentage of each tier's maxMemory. Trino derives per-node query
# memory (30% of heap) and headroom (30% of heap) from it, so maxMemory is the
# only number you normally change. Allowed range 40–80.
jvm:
  maxRAMPercentage: 70

# ─── Catalogs (data sources) ──────────────────────────────────────────────────
# One entry per data source. `properties` is a Trino connector properties file —
# copy it from the connector's documentation page. Never put a password here:
# create a Control Plane secret first and reference it as ${ENV:NAME} plus a
# `secrets` entry below. The image already ships the tpch, tpcds, memory and jmx
# catalogs, so a default install is queryable with no catalogs configured.
catalogs: [] # worked examples: see "Connecting Data Sources" below

# ─── Authentication ───────────────────────────────────────────────────────────
# Off by default: Trino is then unauthenticated and reachable only inside the
# GVC. REQUIRED before publicAccess can be enabled. Both secrets must exist
# BEFORE install. Note: the SERVER refuses password auth over plain HTTP, so
# auth requires publicAccess — the chart enforces it.
auth:
  enabled: false
  passwordFileSecretName: "" # opaque secret, payload = bcrypt password file (e.g. my-trino-passwords)
  sharedSecretName: "" # opaque secret, payload = random string shared by all nodes (e.g. my-trino-shared-secret)

# ─── Access ───────────────────────────────────────────────────────────────────
publicAccess:
  enabled: false # true = Web UI + JDBC on the automatic *.cpln.app HTTPS endpoint; requires auth.enabled

internalAccess: # who may reach the coordinator from inside Control Plane
  type: same-gvc # options: same-gvc, same-org, workload-list ('none' breaks Trino — the coordinator calls itself over this path)
  workloads: [] # used with workload-list, e.g. //gvc/GVC_NAME/workload/WORKLOAD_NAME
```

### Coordinator and Workers

* `image` — The Trino container image. The chart is shipped and tested on Trino 483.
* `coordinator.resources` — CPU and memory for the single coordinator replica.
* `workers.replicas` — Number of worker replicas. Raise it for more query throughput and to keep capacity available through a rolling restart; `0` collapses the cluster to a single node where the coordinator both plans and executes.
* `workers.resources` — CPU and memory per worker replica.

`maxMemory` must be a whole number of GiB and at least `2Gi`, `minMemory` may not exceed `maxMemory`, and `maxCpu:minCpu` may not exceed 4:1 (a Control Plane limit) — the chart refuses to render otherwise, with a message naming the value to fix.

### JVM and Memory

`jvm.maxRAMPercentage` (default `70`, allowed range 40–80) sets the JVM heap as a percentage of each tier's `maxMemory`. Trino derives its per-node query memory and headroom from that heap, so `maxMemory` is normally the only number you change. Capacity AI is disabled on both workloads: the JVM sizes its heap from the container limit at startup, so shrinking the container afterwards would be an out-of-memory kill with no diagnostic.

### Catalogs

Each `catalogs[]` entry renders one secret and mounts one file at `/etc/trino/catalog/<name>.properties` on every node:

| Field                  | Description                                                                                                                                             |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`                 | Catalog name, queried as `<name>.<schema>.<table>`. Lowercase letters, digits and underscores; `system` is reserved.                                    |
| `properties`           | The connector properties file, copied from the connector's documentation page. Must contain a `connector.name=` line.                                   |
| `secrets[].env`        | `UPPER_SNAKE_CASE` environment variable name, referenced from `properties` as `${ENV:NAME}`. Must be unique across all catalogs.                        |
| `secrets[].secretName` | Name of the Control Plane secret holding the credential. It must exist **before** install.                                                              |
| `secrets[].secretKey`  | Key within a [dictionary secret](/guides/create-secret/dictionary). Omit it for an [opaque secret](/guides/create-secret/opaque) (its payload is used). |

Object-storage catalogs (Hive, Iceberg, Delta Lake) need an external metastore, which this template does not bundle. For Iceberg, deploy the [Polaris](/template-catalog/templates/polaris) template as the REST catalog and point a `catalogs[]` entry at it — that pairing is tested end to end, including writing Iceberg tables to [SeaweedFS](/template-catalog/templates/seaweedfs).

### Authentication

`auth.enabled` turns on Trino's file-based password authentication on the coordinator and the shared secret that nodes use to authenticate to each other. It requires `publicAccess.enabled`, and both secret names are required when it is on.

Create both [opaque secrets](/guides/create-secret/opaque) before installing:

```bash theme={null}
# password file — bcrypt, cost >= 8, one user per line
htpasswd -B -C 10 -n alice | cpln secret create-opaque \
  --name my-trino-passwords --encoding plain -f -

# internal shared secret — a random string used by every node
printf '%s' "$(openssl rand -hex 32)" | cpln secret create-opaque \
  --name my-trino-shared-secret --encoding plain -f -
```

<Warning>
  `auth.enabled` requires `publicAccess.enabled`, and the chart enforces both directions. Trino's **server** refuses password authentication over plain HTTP, so an internal-only cluster with authentication on cannot be queried by anyone — in-GVC clients get `401 Password not allowed for insecure authentication`. Either enable public access (TLS terminates at the Control Plane edge) or leave authentication off and let the internal firewall be the boundary. Public access without authentication is rejected too: an unauthenticated Trino on the internet is a read primitive over every connected data source.
</Warning>

### Access

* `publicAccess.enabled` — Serve the Web UI and the JDBC/REST endpoint on the automatic `*.cpln.app` HTTPS endpoint. Requires `auth.enabled`. When off, external requests are blocked at the edge even though the workload still has a canonical endpoint.
* `internalAccess.type` — Which workloads inside Control Plane may reach the coordinator:

| Type            | Description                                                                                                                                                                            |
| --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `same-gvc`      | Allow access from all workloads in the same GVC (default).                                                                                                                             |
| `same-org`      | Allow access from all workloads in the same organization.                                                                                                                              |
| `workload-list` | Allow access only from the workloads listed in `internalAccess.workloads`. The chart automatically adds the coordinator itself and its worker workload, so you only list your clients. |

<Warning>
  `none` is rejected by the chart. The coordinator addresses itself by service DNS, so its own task and status calls travel through this internal firewall — with `none` every query fails with `403 RBAC: access denied`, even at `workers.replicas: 0`.
</Warning>

The worker tier keeps its own least-privilege firewall regardless of this setting: only the coordinator and sibling workers may reach it.

## Connecting Data Sources

Point a catalog at any database Trino can reach. Templates deployed in the same GVC are reachable at `{workload-name}.{gvc}.cpln.local`. Credentials always come from a secret you create first and are referenced with Trino's `${ENV:NAME}` substitution, so no password is written into values or into any rendered file — the mounted catalog file contains only the placeholder.

<Steps>
  <Step title="Create the credential secret">
    Use an [opaque secret](/guides/create-secret/opaque) for a single credential, or a [dictionary secret](/guides/create-secret/dictionary) when one secret holds several values:

    ```bash theme={null}
    # one credential — referenced without secretKey
    printf '%s' 'the-password' | cpln secret create-opaque \
      --name my-postgres-credentials --encoding plain -f -

    # several values — referenced with secretKey
    cpln secret create-dictionary --name my-mysql-credentials --entry password=the-password
    ```
  </Step>

  <Step title="Add the catalog to your values">
    Reference the secret by name and inject it as an environment variable:

    ```yaml theme={null}
    catalogs:
      - name: pg # queried as pg.<schema>.<table>
        properties: |
          connector.name=postgresql
          connection-url=jdbc:postgresql://my-postgres.my-gvc.cpln.local:5432/postgres
          connection-user=postgres
          connection-password=${ENV:PG_PASSWORD}
        secrets:
          - env: PG_PASSWORD
            secretName: my-postgres-credentials # must exist BEFORE install
            secretKey: password # omit for an opaque secret (uses its payload)
    ```
  </Step>

  <Step title="Query it">
    The catalog appears in `SHOW CATALOGS` once the cluster restarts with the new values.
  </Step>
</Steps>

### Catalog Examples

Worked entries for the sibling database templates:

```yaml theme={null}
catalogs:
  # postgres / postgres-highly-available / timescaledb / cockroach / postgis
  - name: pg
    properties: |
      connector.name=postgresql
      connection-url=jdbc:postgresql://my-postgres.my-gvc.cpln.local:5432/postgres
      connection-user=postgres
      connection-password=${ENV:PG_PASSWORD}
    secrets:
      - env: PG_PASSWORD
        secretName: my-postgres-credentials

  # mysql / mariadb / tidb — no database name in the URL
  - name: mysql
    properties: |
      connector.name=mysql
      connection-url=jdbc:mysql://my-mysql.my-gvc.cpln.local:3306
      connection-user=root
      connection-password=${ENV:MYSQL_PASSWORD}
    secrets:
      - env: MYSQL_PASSWORD
        secretName: my-mysql-credentials
        secretKey: password

  # clickhouse — HTTP interface on 8123
  - name: clickhouse
    properties: |
      connector.name=clickhouse
      connection-url=jdbc:clickhouse://my-clickhouse.my-gvc.cpln.local:8123/
      connection-user=default
      connection-password=${ENV:CLICKHOUSE_PASSWORD}
    secrets:
      - env: CLICKHOUSE_PASSWORD
        secretName: my-clickhouse-credentials

  # mongodb — credentials live inside the URL, so the whole URL is the secret
  - name: mongo
    properties: |
      connector.name=mongodb
      mongodb.connection-url=${ENV:MONGO_URL}
    secrets:
      - env: MONGO_URL
        secretName: my-mongo-url
```

The matching templates are [postgres](/template-catalog/templates/postgres), [postgres-highly-available](/template-catalog/templates/postgres-highly-available), [mysql](/template-catalog/templates/mysql), [mariadb](/template-catalog/templates/mariadb), [clickhouse](/template-catalog/templates/clickhouse) and [mongodb](/template-catalog/templates/mongodb).

### Querying Across Catalogs

With several catalogs configured, one statement spans all of them — including the built-in `tpch` data — and Trino performs the join itself:

```sql theme={null}
SELECT c.name AS customer, c.tier, n.name AS nation, count(*) AS orders, sum(o.amount) AS total
FROM pg.public.orders o
JOIN mysql.demo.customers c ON o.customer_id = c.customer_id
JOIN tpch.tiny.nation n ON o.nation_key = n.nationkey
GROUP BY c.name, c.tier, n.name
ORDER BY total DESC;
```

Trino reads from each source at query time; nothing is copied and nothing is written back.

## Connecting

| What                      | Value                                                                                                                    |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| Web UI / JDBC (public)    | `https://<canonical>.cpln.app` — `status.canonicalEndpoint` of `{release}-trino`. Available when `publicAccess.enabled`. |
| JDBC / clients (internal) | `jdbc:trino://{release}-trino.{gvc}.cpln.local:8080/<catalog>/<schema>`                                                  |
| REST API                  | `POST /v1/statement` on the same host                                                                                    |
| CLI inside the cluster    | `cpln workload exec {release}-trino --container trino -- trino --execute "SELECT 1"`                                     |
| Credentials               | A user from your password file when `auth.enabled`; none when it is off                                                  |
| Built-in catalogs         | `tpch`, `tpcds`, `memory`, `jmx`, `system`                                                                               |

With authentication on, the Web UI login form is served at `/ui/legacy/login.html` on the public endpoint.

## Availability

Trino has no fault-tolerant execution in this template: a query running on a node that goes away fails and must be retried. Measured on a 3-worker cluster:

| Event                                       | Impact                                                                                                                                       |
| ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| Worker-tier rolling restart (`replicas: 3`) | 3 of 80 queries failed, all inside the \~3 minute rollout window; every query after convergence succeeded.                                   |
| Worker replica lost                         | 0 of 90 queries failed. The replacement replica joined after \~40 s and the dead node was evicted from `system.runtime.nodes` after \~115 s. |
| Coordinator restart                         | \~6 seconds of `503` responses and one in-flight query lost (`Query is gone (server restarted?)`).                                           |

The coordinator is the single point of failure — open-source Trino has no coordinator failover, and this template does not claim otherwise. Workers are interchangeable, so `workers.replicas` is the knob for both capacity and restart tolerance. At the default `workers.replicas: 1` a rolling restart empties the execution tier entirely, so every query in flight fails for the duration.

## Important Notes

* **Every catalog credential secret must exist before installing** — a missing secret leaves the deployment waiting and the cluster never becomes ready.
* **Rotating a secret's payload does not take effect until the workloads are redeployed.** Control Plane resolves secret-backed environment variables at deployment time, so run a Helm upgrade after changing a credential.
* **`auth.enabled` requires `publicAccess.enabled`, and public access requires authentication** — the chart rejects either one on its own at render time.
* **`internalAccess.type: none` is rejected** — the coordinator must be able to reach itself over the internal path.
* **Trino is read-oriented here** — it queries the databases you connect; the template never installs or modifies them, and uninstalling removes only the cluster. Your own credential secrets are left in place.
* **Keep the GVC single-location** — coordinator-to-worker traffic is per-query and latency-sensitive.

## External References

<CardGroup cols={2}>
  <Card title="Trino Documentation" icon="book" href="https://trino.io/docs/current/">
    Official Trino documentation
  </Card>

  <Card title="Connectors" icon="plug" href="https://trino.io/docs/current/connector.html">
    Every available connector and its properties
  </Card>

  <Card title="SQL Reference" icon="database" href="https://trino.io/docs/current/sql.html">
    Trino SQL statement and syntax reference
  </Card>

  <Card title="JDBC Driver" icon="code" href="https://trino.io/docs/current/client/jdbc.html">
    Connect BI tools and applications over JDBC
  </Card>

  <Card title="Password File Authentication" icon="lock" href="https://trino.io/docs/current/security/password-file.html">
    How the bcrypt password file is used
  </Card>

  <Card title="Secrets in Properties Files" icon="key" href="https://trino.io/docs/current/security/secrets.html">
    The `${ENV:NAME}` substitution used by catalog credentials
  </Card>

  <Card title="Trino Template" icon="github" href="https://github.com/controlplane-com/templates/tree/main/trino">
    View the source files, default values, and chart definition
  </Card>
</CardGroup>
