> ## 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](/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](/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](/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`

**HTTP**

```
http://app:YOUR_PASSWORD@127.0.0.1:8123/?database=app
```

**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()" });
```

**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()
```

**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](/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](/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`.

**Query**

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

**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)
  "
```

**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}
  '
```

**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.