chmonitor
Features

User Connections (Server Storage)

Save personal ClickHouse connections to the server so they sync across devices when signed in with Clerk — encrypted at rest with AES-256-GCM.

Save personal ClickHouse hosts to the server so they sync across devices when signed in with Clerk — encrypted at rest with AES-256-GCM.

Prop

Type

What it does

When enabled, users can choose Save to server in the Add Host dialog. Credentials are encrypted at rest with CHM_USER_CONNECTIONS_ENCRYPTION_KEY and never returned to the client after save.

Browser-only storage remains available when server storage is disabled or the user prefers a local connection.

Using it

Server storage needs four things present together. If any one is missing the server returns "User connections database storage is not enabled" and the Save to server toggle stays hidden.

  1. CHM_FEATURE_USER_CONNECTIONS_DB=true — the feature flag.
  2. Clerk auth (CHM_AUTH_PROVIDER=clerk) — connections are keyed by the signed-in Clerk userId.
  3. CHM_USER_CONNECTIONS_ENCRYPTION_KEY — a 32-byte base64 key used to encrypt credentials at rest (AES-256-GCM).
  4. A database backendCHM_CLOUD_D1 on Cloudflare, or DATABASE_URL / POSTGRES_URL on Docker / Kubernetes.

One canonical name

Set the canonical CHM_* name once. The browser-side VITE_FEATURE_USER_CONNECTIONS_DB / VITE_AUTH_PROVIDER are derived from CHM_FEATURE_USER_CONNECTIONS_DB / CHM_AUTH_PROVIDER at build time (see vite.config.ts) — you don't set them separately. Because the client value is inlined at build time, set these before pnpm run build (or build a custom image), then keep them in the runtime env too.

Enable the feature and Clerk auth

CHM_FEATURE_USER_CONNECTIONS_DB=true
CHM_AUTH_PROVIDER=clerk

Configure a database backend

Use the CHM_CLOUD_D1 binding (shared D1 database; migration 0002_user_connections.sql).

Set DATABASE_URL or POSTGRES_URL.

Set the encryption key

32-byte key, base64-encoded (a secret — never commit it):

wrangler secret put CHM_USER_CONNECTIONS_ENCRYPTION_KEY
# Docker / Kubernetes: pass CHM_USER_CONNECTIONS_ENCRYPTION_KEY via -e or a Secret

Redeploy the dashboard

The Add Host dialog shows an enabled Save to server toggle when all four requirements are met. Otherwise it displays a note with a link to this page.

Permissions & access

Per-user isolation

Each connection row is keyed by the signed-in Clerk userId. List, read, update, delete, and chart/table proxy routes all resolve auth first and query with WHERE user_id = ?. Guessing another user's connectionId returns 404 — never their credentials.

  • Not org-shared: Connections belong to the individual Clerk account, not the whole organization. Two teammates each see only their own server-stored hosts.
  • Passwords are encrypted with AES-256-GCM before writing to D1/Postgres.
  • API routes return connection metadata only; passwords are never echoed after create.
  • Browser-stored hosts use short-lived session tokens so passwords are not sent on every chart/table request.
  • The client cache for server connections is scoped per Clerk user, cleared on sign-out / account switch, and excluded from persisted localStorage so another login on the same browser cannot flash a prior user's host list.
  • Shared ?host=-1000 URLs only work for the same signed-in user with that connection saved.

On this page