Pick the one that fits: a shared app hosted on your cluster, a personal local app, a Dockerized local runner, or a dev checkout. They all build from the same single-file artifact.
| Hosted on ClickHouse® | Local app (curl) | Docker local runner | From source | |
|---|---|---|---|---|
| Who it's for | A whole team, shared URL | One developer, your laptop | Local/shared testing | Contributors |
| Served from | ClickHouse /sql | localhost:8900/sql | localhost:8900/sql | localhost:8900/sql |
| Prerequisites | Cluster admin + an IdP | python3 + curl | Docker | Node.js 22+ + npm |
| Auth | SSO (OIDC) or Basic | Your saved connections | Your saved connections | Your saved connections |
| Connects to | That cluster | Any cluster in your config | Any cluster in your config | Any cluster in your config |
| Install | deploy/install.sh | one curl | sh | docker compose up --build | npm run local |
The SPA and its config.json are uploaded into ClickHouse's
user_files directory; HTTP handlers serve them at /sql and
/sql/config.json. Every query then carries the signed-in user's JWT, validated by
ClickHouse's token processor (or a delegated verifier), so users get exactly their own grants.
One installer renders the config, fills the CSP connect-src from your IdP's OIDC
discovery document, and uploads everything:
# builds dist/sql.html, renders config + http_handlers.xml, uploads to user_files
CLICKHOUSE_PASSWORD=… ./deploy/install.sh \
--ch-host clickhouse.example.com \
--ch-user admin \
--client-id <oauth-client-id> \
[--issuer https://accounts.google.com] \
[--audience <api-audience>] \
[--cluster <cluster-name>] [--artifact sql.html] [--pull-url <url>] \
[--transport native|http] [--http-port N] [--ddl-timeout 180] [--verify-only] [--secure]
--cluster distributes the files to every node with server-side SQL in two phases
(stage and verify, then promote and verify) and checks each node's SHA-256. The cluster needs a
<secret> and the deploy user a few grants; see
ASSET-DISTRIBUTION.md. Altinity Cloud, clickhouse-operator and other restricted environments:
HOSTED-INSTALL.md.
config.json is served to
browsers, so prefer a PKCE public client. If your IdP requires a client_secret,
lock the redirect URI and treat the file as public.Recommended. Register a SPA / public client and omit the secret entirely.
Some IdPs require a client_secret even with PKCE — put it in config.json and lock the redirect URI.
An auth proxy holds the secret and exposes a public PKCE flow; config.json stays empty.
Full walk-throughs, including stock-ClickHouse JWT verification:
DEPLOYMENT.md · CLICKHOUSE-OAUTH.md · OSS (delegated verifier) · ASSET-DISTRIBUTION.md · HOSTED-INSTALL.md · LOGIN-SCREEN.md
A curl | sh installer downloads the latest release bundle (the prebuilt
sql.html plus a zero-dependency Python runner) and installs a launcher. The runner
reads the clusters from your ~/.clickhouse-client/config.xml and serves the app at
localhost:8900/sql.
curl -fsSL https://raw.githubusercontent.com/Altinity/altinity-sql-browser/main/install.sh | sh
It only needs python3 (preinstalled on macOS/Linux) and curl or wget.
See the full local-app guide →
The production image is a static Caddy server for the single-file SPA. It serves
/sql and a config.json you provide at
/sql/config.json; queries go from the browser straight to ClickHouse. This is also
the fallback when a managed provider does not let you install http_handlers (see
DEVELOPMENT.md).
docker run --rm -p 8900:8080 -v "$PWD/config.json:/config/config.json:ro" \
ghcr.io/altinity/altinity-sql-browser:latest # then open http://localhost:8900/sql
The repo also ships Kubernetes examples under deploy/k8s/: a Deployment, Service,
ConfigMap-backed connection file, and an Ingress example for cluster testing.
Source builds require Node.js 22 or newer. With nvm, run
nvm use in the checkout to select the committed version.
git clone https://github.com/Altinity/altinity-sql-browser cd altinity-sql-browser npm ci npm run local # build + connection picker at localhost:8900/sql npm run build # produce dist/sql.html npm test # vitest + coverage gate
Source is vanilla ES modules with no framework. Pure logic lives in src/core/,
network in src/net/ (with an injected fetch seam), and DOM rendering in
src/ui/. esbuild inlines everything — including Chart.js and the graph layout
engine — into the single served file.
The hosted handler ships a strict Content-Security-Policy: default-src 'none'
with an explicit allowlist, connect-src bounded to your cluster and IdP origins,
frame-ancestors 'none', plus X-Content-Type-Options: nosniff
and Referrer-Policy: no-referrer. The installer fills the IdP origins automatically
from OIDC discovery.
Start with the local app, or wire it into your cluster.