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

# Onboarding

> Install the ClickHouse Connector and enroll it on Kubernetes or a Linux VM

export const Image = ({img, alt, size = "lg", background}) => {
  const normalizedSize = ["sm", "md", "lg"].includes(size) ? size : "lg";
  const backgroundColor = background === "white" ? "white" : background === "black" ? "rgb(31 31 28)" : undefined;
  return <div className={`ch-image-${normalizedSize}`}>
      <Frame>
        <img src={img} alt={alt} style={{
    backgroundColor
  }} />
      </Frame>
    </div>;
};

This page takes you from an enrollment token to a healthy, verified connector. The connector installs on either of two targets: a Kubernetes cluster (Helm) or a Linux VM (systemd). Token enrollment is the standard flow; if your environment cannot reach ClickHouse endpoints directly, see [air-gapped and mirrored installs](#air-gapped-and-mirrored-installs).

<h2 id="prerequisites">
  Prerequisites
</h2>

For every install:

* **Your connector endpoint and enrollment token**, provided by ClickHouse during onboarding (see Step 1).
* **Egress on port 443** to `https://<subdomain>.<connector-domain>` and `https://<subdomain>.enroll.<connector-domain>`, plus `releases.clicklink.clickhouse.com` and Amazon ECR Public at install time. When any of these are unreachable, see [air-gapped and mirrored installs](#air-gapped-and-mirrored-installs).
* **A reachable ClickHouse native listener** from where the connector runs: secure (9440) or plaintext (9000), auto-detected on Kubernetes.
* **ClickHouse admin access for provisioning**: a passwordless `default` user, a password (prompted, or supplied with `--ch-admin-password-stdin`), or an operator-managed instance, where provisioning switches to CR injection and needs no password.
* **cosign** wherever you download release artifacts. The installer always verifies the SHA-256 checksum, adds cosign signature verification when cosign is installed, and refuses to proceed without it if you set `CLICKLINK_REQUIRE_COSIGN=1`.

For Kubernetes (Helm) installs:

* **Any conformant Kubernetes cluster.**
* **A kubeconfig** that can create and read the connector namespace, apply Secrets, exec into your ClickHouse pods (provisioning runs `clickhouse-client` in-pod), create ServiceAccounts, Roles, and RoleBindings, and install the chart.
* **A default StorageClass**, or a class to pass with `--storage-class`; the troubleshooter keeps state on a PersistentVolumeClaim.
* **Image pull access**: cluster nodes must be able to pull the public ECR image, or a mirror you host.

For Linux VM (systemd) installs:

* **Any systemd Linux host**, amd64 or arm64. Linux builds run in FIPS mode.
* **Root access** for the installer and for `init`.
* **Free ports** 8080, 8082, and 8084 (health) and 9090, 9092, and 9094 (metrics), plus 8443 when the support-session gateway is enabled.
* **Admin access to a Kubernetes API server** for provisioning, supplied by a kubeconfig on the host, by `--server` and `--ca-data`, or at the prompts. Access bundles are anchored to Kubernetes ServiceAccounts on both targets.

<Note>
  `--skip-provision` is the only way around the Kubernetes requirement, and it is stage-only: it skips ClickHouse user provisioning and, on a VM, the unit enable and verification, so it does not produce a running connector by itself.
</Note>

<h2 id="install-and-enroll">
  Install and enroll
</h2>

<Steps>
  <Step title="Get your connector endpoint and enrollment token" id="get-endpoint-and-token">
    ClickHouse provides your connector endpoint and a single-use enrollment token during onboarding. The endpoint has the form:

    ```text theme={null}
    https://<subdomain>.<connector-domain>
    ```

    The token is single-use and expires quickly, so plan to run enrollment soon after you receive it. Treat it as a secret: the CLI reads it from a hidden prompt (or the first line of stdin), never from command-line arguments, disk, or logs. If your token expires before you use it, contact your ClickHouse account team for a fresh one.
  </Step>

  <Step title="Install and verify the CLI" id="install-and-verify-the-cli">
    One command installs a verified `clicklink` binary: it detects your platform and architecture (macOS or Linux, amd64 or arm64), downloads the current release, verifies the SHA-256 checksum and, with cosign installed, the release signature, and installs the binary onto your `PATH`. For a Kubernetes install, run it on any workstation with kubeconfig access to the cluster:

    ```bash theme={null}
    curl -fsSL https://releases.clicklink.clickhouse.com/install.sh | bash
    ```

    For a VM install, run the same script on the host with `--host`. After the verified download it also creates the `clicklink` system user, the `/etc/clicklink`, `/var/lib/clicklink`, and `/var/log/clicklink` directories, and the systemd units, and seeds a default `/etc/clicklink/redaction-patterns.yaml` (preserved if one exists), so the next step starts directly at enrollment:

    ```bash theme={null}
    curl -fsSL https://releases.clicklink.clickhouse.com/install.sh | sudo bash -s -- --host
    ```

    Both forms accept `--version vX.Y.Z` to pin a release, and re-running either is safe: the host install backs up the previous binary and preserves your live configuration. To inspect the script before running it, or to fetch and verify the release tarball yourself, see [manual download and verification](#manual-download-and-verification).
  </Step>

  <Step title="Enroll and install the connector" id="enroll-and-install">
    Enrollment is a single command. It redeems your token, provisions ClickHouse access, obtains a signed client certificate, installs the connector, and verifies it, end to end.

    <Image img="https://mintcdn.com/private-7c7dfe99/TzCcbGCmOA6JQn6p/images/cloud/reference/byoc-connector-enrollment-flow.svg?fit=max&auto=format&n=TzCcbGCmOA6JQn6p&q=85&s=212a30441ee12dc294e9766cb97f0937" size="lg" alt="ClickHouse Connector enrollment flow" width="1320" height="800" data-path="images/cloud/reference/byoc-connector-enrollment-flow.svg" />

    <Tabs>
      <Tab title="Kubernetes">
        From your workstation, run:

        ```bash theme={null}
        clicklink clctl init --enroll https://<subdomain>.<connector-domain> --target helm
        ```

        Paste the enrollment token at the hidden prompt. The CLI then prompts for:

        * the connector namespace (default `clicklink`)
        * the namespace your ClickHouse instances run in
        * instance connection details, seeded from the ClickHouse Service it detects
        * a StorageClass, only when the cluster marks no default
        * the support-session posture and, if enabled, the operator email allowlist
        * the ClickHouse admin password, only when SQL provisioning needs one

        The single invocation then runs end to end: it redeems the token (saving the enrollment bundle as `handoff.yaml` in the working directory), stages the Helm values overlay `clicklink-values.yaml`, creates the namespace, applies the `clicklink-hmac` and `clicklink-mtls` Secrets, provisions read-only ClickHouse users for each instance (auto-selecting SQL grants or CR injection for operator-managed instances), generates a private key and CSR and has ClickHouse sign the client certificate, installs the `clicklink-connector` Helm release with the built-in Helm client (no `helm` binary required), and verifies health.

        For unattended runs, answer the prompts with flags instead. Use the saved bundle as the entry point, because `--enroll` reads the enrollment token from the first line of stdin in non-terminal runs and would consume the redirected password:

        ```bash theme={null}
        clicklink clctl init --handoff handoff.yaml --target helm \
          --instance name=<name>,host=<service-host>,port=9440,secure=true,database=default,namespace=<clickhouse-namespace> \
          --operators '<operator-email-1>,<operator-email-2>' \
          --storage-class <storage-class> \
          --ch-admin-password-stdin < admin-password.txt
        ```

        Repeat `--instance` for each ClickHouse instance. Pass `--no-gateway` instead of `--operators` to disable support sessions; the two flags are mutually exclusive.
      </Tab>

      <Tab title="Linux VM">
        The `--host` install in the previous step already laid down the binary, the `clicklink` system user and directories, and the systemd units. Enroll as root:

        ```bash theme={null}
        sudo clicklink clctl init --enroll https://<subdomain>.<connector-domain>
        ```

        Paste the enrollment token at the hidden prompt. The command redeems the token (saving the enrollment bundle as `handoff.yaml`), writes `/etc/clicklink/config.yaml`, installs the API credentials and CA chain, generates a private key and CSR and has ClickHouse sign the client certificate, provisions read-only ClickHouse users for both daemons, enables and starts the `clicklink-scraper` and `clicklink-troubleshooter` services, waits for each to report live, and finishes by running the full preflight check suite.
      </Tab>
    </Tabs>
  </Step>

  <Step title="Verify success" id="verify-success">
    `init` verifies the install before it reports success. On Kubernetes it polls each enabled component's `/livez` endpoint for up to five minutes and, when the support-session gateway is enabled, additionally requires the gateway to answer unauthenticated probes with `401`. On a VM it waits for each daemon's `/livez` and then runs the full preflight suite: config, files, port conflicts, network reachability, ClickHouse connectivity, systemd unit state, per-component access, disk, and redaction patterns.

    To confirm by hand on Kubernetes:

    ```bash theme={null}
    CONNECTOR_NAMESPACE='clicklink'   # the connector namespace you chose at init
    kubectl get pods -n "${CONNECTOR_NAMESPACE}"
    ```

    All connector pods should be `Running` and ready.

    To confirm by hand on a VM:

    ```bash theme={null}
    sudo clicklink clctl preflight
    ```

    It exits `0` when every check passes and `2` on any failure, printing the failing checks.
  </Step>

  <Step title="Clean up" id="clean-up">
    The enrollment bundle `handoff.yaml` (written with mode `0600` in the working directory) exists so that re-runs and recovery during the install never need a second token. It contains the connector's API secret in plaintext, so once the install has verified, delete it:

    ```bash theme={null}
    rm handoff.yaml        # workstation (Kubernetes installs)
    sudo rm handoff.yaml   # VM host (init ran as root, so the file is root-owned)
    ```

    The running connector holds its own copy of the credentials, so nothing operational depends on the file: upgrades and configuration changes never need it, and if you later need `init` again, request a fresh enrollment token from your ClickHouse account team and run `init --enroll --force`.
  </Step>
</Steps>

<h2 id="air-gapped-and-mirrored-installs">
  Air-gapped and mirrored installs
</h2>

Two independent pieces can move out of band, depending on what your environment can reach.

**Bundle delivery.** If you prefer not to redeem a token online, ClickHouse can provide the enrollment bundle directly during onboarding; run `clicklink clctl init --handoff <bundle-file>` in place of `--enroll`. `--handoff` replaces only the token redemption: certificate signing still happens over the enrollment endpoint, so use it alone when that endpoint is reachable from where you run `init`.

**Out-of-band certificate signing.** When the enrollment endpoint is unreachable from where you run `init`, add `--no-auto-sign`: `init` stages everything and writes `clicklink.csr`. Send the CSR to ClickHouse through your account team, then complete the install with the returned certificate and chain: `sudo clicklink clctl init --signed-cert client.crt --chain ca-chain.crt` on a VM, or the full completion command the staged run prints on Kubernetes (including `--target helm`). Only the CSR travels; the private key never leaves your environment.

On Kubernetes, `--chart` accepts a chart name resolved through `--chart-repo`, an `oci://` reference, a direct URL, or a local archive or directory, and `--chart-version` defaults to the CLI's own version so the binary and chart move together. To serve images from your own registry, mirror the container image and set `image.repository` in the values overlay. If your egress path presents a private CA to the connector, pass `--api-private-ca` so the API endpoint is verified against the CA chain from the enrollment bundle instead of the system trust store.

The installer works from a mirror too: host the release artifacts and `install.sh` on your own mirror and point at it with `CLICKLINK_MIRROR_URL`.

<h3 id="manual-download-and-verification">
  Manual download and verification
</h3>

When you prefer not to pipe the installer, fetch and verify the release yourself. The block detects your platform and architecture; run it as is on macOS or Linux, amd64 or arm64:

```bash theme={null}
CLICKLINK_VERSION="$(curl -fsSL https://releases.clicklink.clickhouse.com/latest-version.txt)"
# Or pin a specific release: CLICKLINK_VERSION='v0.9.0'
CLICKLINK_TARBALL="clicklink-${CLICKLINK_VERSION}-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m | sed 's/x86_64/amd64/; s/aarch64/arm64/').tar.gz"
for suffix in '' .sha256 .sig .crt; do
  curl -fsSLO "https://releases.clicklink.clickhouse.com/${CLICKLINK_TARBALL}${suffix}"
done
if command -v sha256sum >/dev/null; then
  sha256sum -c "${CLICKLINK_TARBALL}.sha256"
else
  shasum -a 256 -c "${CLICKLINK_TARBALL}.sha256"
fi
```

Verify the signature with cosign before extracting anything:

```bash theme={null}
cosign verify-blob \
  --certificate "${CLICKLINK_TARBALL}.crt" \
  --signature "${CLICKLINK_TARBALL}.sig" \
  --certificate-identity-regexp "^https://github\.com/ClickHouse/data-plane-clicklink/\.github/workflows/release\.yaml@refs/tags/v" \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  "${CLICKLINK_TARBALL}"
```

On a workstation (Kubernetes installs), extract the tarball and install the binary:

```bash theme={null}
tar -xzf "${CLICKLINK_TARBALL}"
sudo install -m 0755 clicklink /usr/local/bin/clicklink
```

On a VM, extract the tarball and run `sudo ./install.sh` from the extracted directory; next to its release artifacts it performs the same host install as `--host`.

<h2 id="if-something-fails">
  If something fails
</h2>

Re-run the same command. `init` is idempotent: re-runs converge on the same state, keep your existing config and staged files, and skip completed work. When a step fails partway through, the CLI prints the exact recovery commands for your situation, and those printed commands are safe to repeat.

If enrollment is refused, the token was either already redeemed (re-run with `--handoff handoff.yaml`, which exists until the final cleanup step) or is invalid or expired (contact your ClickHouse account team for a fresh token). If enrollment fails with a transport error, the token was not spent; re-run the same command.

`--force` is the explicit reset, not a routine retry: it overwrites the kept config or values overlay, regenerates the client key, and supersedes an unexpired client certificate (a `409` from the signing endpoint means one already exists). The connector's cluster UUID is preserved even across `--force`, so a re-initialized connector keeps its identity. Reach for it when rotating credentials or superseding a certificate, and see [operations](/docs/products/bring-your-own-cloud/connector/operations) for the full re-run and recovery model.
