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

# ClickHouse

> Deploy ClickHouse to Magic Containers

This guide walks you through deploying ClickHouse to Magic Containers, either as a standalone container or as part of a [multi-container](https://bunny.net/docs/magic-containers/multi-container.md) app alongside your application.

> [!TIP]
>
> Don't have a bunny.net account yet? [Sign up](https://dash.bunny.net/auth/register) and enable Magic Containers to get started.

## Quickstart

**1. Create a new app**

Go to the [bunny.net dashboard](https://dash.bunny.net), select **Magic Containers**, and click **Add App**. Select **Single region deployment**.

> [!WARNING]
>
> Databases should use single region deployment with a single instance. Each pod gets its own dedicated volume with no data replication — this applies both across regions and within the same region. Scaling to multiple pods or regions would result in separate, isolated databases each with their own data.

**2. Add the ClickHouse container**

Click **Add Container** and configure the image:

* **Registry**: Docker Hub
* **Image**: `clickhouse/clickhouse-server`
* **Tag**: `latest`

Magic Containers will automatically detect the required endpoint and environment variables for the image. Configure the environment variables as needed:

* `CLICKHOUSE_DB` = `app`
* `CLICKHOUSE_USER` = `app`
* `CLICKHOUSE_PASSWORD` = a strong password
* `CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT` = `1`

**3. Add persistent volumes**

In the **Volumes** section of the container settings, add two volumes:

* **Name**: `clickhouse-data`, **Mount path**: `/var/lib/clickhouse`
* **Name**: `clickhouse-logs`, **Mount path**: `/var/log/clickhouse-server`

This ensures your database files and logs persist across restarts and redeployments. Without volumes, all data is lost when the container stops.

See [persistent volumes](https://bunny.net/docs/magic-containers/persistent-volumes.md) for more details on volume behavior and pricing.

**4. Deploy**

Review your settings and click **Confirm and Create**.

> [!NOTE]
>
> Always set a strong `CLICKHOUSE_PASSWORD`, even if ClickHouse is not exposed
> externally. Other containers in the same pod can access the network, and a
> password protects against accidental or unauthorized access.

## Environment variables

The official ClickHouse image supports these environment variables:

| Variable | Description | Default |
| - | - | - |
| `CLICKHOUSE_DB` | Default database created on start | `default` |
| `CLICKHOUSE_USER` | Username to create | `default` |
| `CLICKHOUSE_PASSWORD` | Password for the user | - |
| `CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT` | Enable SQL-driven access management | `0` |

## Connect from your app

In a [multi-container](https://bunny.net/docs/magic-containers/multi-container.md) setup, your app and ClickHouse share the same localhost network. ClickHouse exposes two interfaces:

* **HTTP**: port `8123`
* **Native**: port `9000`

> [tab] HTTP
>
> ```
> http://app:YOUR_PASSWORD@127.0.0.1:8123/?database=app
> ```

> [tab] Node.js
>
> ```javascript theme={null}
> import { createClient } from "@clickhouse/client";
>
> const client = createClient({
>   url: "http://127.0.0.1:8123",
>   username: "app",
>   password: process.env.CLICKHOUSE_PASSWORD,
>   database: "app",
> });
>
> const result = await client.query({ query: "SELECT now()" });
> ```

> [tab] Go
>
> ```go theme={null}
> import "github.com/ClickHouse/clickhouse-go/v2"
>
> conn, err := clickhouse.Open(&clickhouse.Options{
> 	Addr: []string{"127.0.0.1:9000"},
> 	Auth: clickhouse.Auth{
> 		Database: "app",
> 		Username: "app",
> 		Password: os.Getenv("CLICKHOUSE_PASSWORD"),
> 	},
> })
> if err != nil {
> 	log.Fatal(err)
> }
> defer conn.Close()
> ```

> [tab] Python
>
> ```python theme={null}
> import clickhouse_connect
>
> client = clickhouse_connect.get_client(
>   host="127.0.0.1",
>   port=8123,
>   username="app",
>   password=os.environ["CLICKHOUSE_PASSWORD"],
>   database="app",
> )
>
> result = client.query("SELECT now()")
> ```

## Multi-container example

A typical setup pairs ClickHouse with your application. When configuring the app, add two containers:

### App container

* **Image**: your app image (e.g. `ghcr.io/<your-username>/my-app:latest`)
* **Endpoint**: the port your app listens on
* **Environment variables**:
  * `CLICKHOUSE_PASSWORD` = a strong password

### ClickHouse container

* **Image**: `clickhouse/clickhouse-server:latest`
* **Volumes**: `/var/lib/clickhouse` and `/var/log/clickhouse-server`
* **Environment variables**:
  * `CLICKHOUSE_DB` = `app`
  * `CLICKHOUSE_USER` = `app`
  * `CLICKHOUSE_PASSWORD` = a strong password
  * `CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT` = `1`

> [!NOTE]
>
> Both containers share the same localhost network, so your app connects to
> ClickHouse at `127.0.0.1:8123` (HTTP) or `127.0.0.1:9000` (native). See
> [multi-container apps](https://bunny.net/docs/magic-containers/multi-container.md) for more details.

## External access

To connect to ClickHouse from outside Magic Containers (e.g. from your local terminal), add either a [CDN or Anycast endpoint](https://bunny.net/docs/magic-containers/endpoints.md). CDN endpoints work for ClickHouse's HTTP interface only; Anycast endpoints support both HTTP and the native protocol.

### Anycast endpoint

1. Go to your app's **Endpoints** tab and click **Add New Endpoint**
2. Select **Anycast** as the type
3. Set **Container Port** to `8123`
4. Set **Exposed Port** to `8123`
5. Click **Add Endpoint**

Then connect using the Anycast IP and the **exposed port**:

```bash theme={null}
curl "http://<anycast-ip>:<exposed-port>/?query=SELECT+1&user=app&password=YOUR_PASSWORD"
```

Or using the ClickHouse client:

```bash theme={null}
clickhouse-client --host <anycast-ip> --port <exposed-port> --user app --password YOUR_PASSWORD
```

> [!NOTE]
>
> The exposed port and container port may differ. When connecting externally,
> always use the exposed port shown in your endpoint configuration.

> [!NOTE]
>
> The `clickhouse-client` uses the native protocol (port `9000`). If you want to
> use the native client externally, add a second Anycast endpoint for port
> `9000`.

### CDN endpoint

A CDN endpoint exposes ClickHouse's HTTP interface through bunny.net's edge network at a `b-cdn.net` hostname, giving you HTTPS out of the box.

1. Go to your app's **Endpoints** tab and click **Add New Endpoint**
2. Select **CDN** as the type
3. Set **Container Port** to `8123`
4. Click **Add Endpoint**

Then connect using the assigned hostname. Replace `username` and `password` with your `CLICKHOUSE_USER` and `CLICKHOUSE_PASSWORD`, and `database` with your `CLICKHOUSE_DB`.

> [tab] Query
>
> ```bash theme={null}
> curl -u 'username:password' \
>   'https://mc-abc123xyz0.b-cdn.net/?query=SELECT+1'
> ```

> [tab] Create
>
> ```bash theme={null}
> curl -u 'username:password' \
>   'https://mc-abc123xyz0.b-cdn.net/?database=database' \
>   --data-binary "
>     CREATE TABLE IF NOT EXISTS events (
>       ts        DateTime,
>       user_id   UInt64,
>       event     String,
>       value     Float64
>     )
>     ENGINE = MergeTree()
>     ORDER BY (ts, user_id)
>   "
> ```

> [tab] Insert
>
> ```bash theme={null}
> curl -u 'username:password' \
>   'https://mc-abc123xyz0.b-cdn.net/?database=database&query=INSERT+INTO+events+FORMAT+JSONEachRow' \
>   --data-binary '
>     {"ts":"2026-04-20 10:00:00","user_id":1,"event":"view","value":1.0}
>     {"ts":"2026-04-20 10:01:00","user_id":2,"event":"click","value":2.5}
>     {"ts":"2026-04-20 10:02:00","user_id":1,"event":"view","value":1.0}
>   '
> ```

> [tab] Aggregate
>
> ```bash theme={null}
> curl -u 'username:password' \
>   'https://mc-abc123xyz0.b-cdn.net/?database=database' \
>   --data-binary "
>     SELECT event, count() AS n, sum(value) AS total
>     FROM events
>     GROUP BY event
>     ORDER BY n DESC
>     FORMAT PrettyCompact
>   "
> ```

> [!WARNING]
>
> CDN endpoints are publicly reachable with no authentication at the edge —
> anyone who knows the hostname can reach ClickHouse, and only the database's
> basic auth stands in the way. Always set a strong `CLICKHOUSE_PASSWORD`
> (never leave it as `clickhouse/clickhouse`), especially with
> `CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT=1` enabled.

> [!NOTE]
>
> CDN endpoints only expose the HTTP interface (port `8123`). The native
> protocol (port `9000`) and clients that depend on it — including
> `clickhouse-client` without `--secure` and most BI tools' native drivers —
> won't work. Use HTTP-based drivers, or add an Anycast endpoint for port
> `9000`.

> [!WARNING]
>
> Exposing your database to the internet means anyone with the credentials can
> connect. Use a strong password and consider removing the endpoint when
> external access is no longer needed.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.