$npx -y skills add clickhouse/agent-skills --skill clickhousectl-cloud-deployclickhousectl-cloud-deploy is an agent skill published from clickhouse/agent-skills, installable through the skills CLI.
| 1 | # Deploy to ClickHouse Cloud |
| 2 | |
| 3 | This skill walks through deploying to ClickHouse Cloud using `clickhousectl`. It covers account setup, CLI authentication, service creation, schema migration, and connecting your application. Follow these steps in order. |
| 4 | |
| 5 | ## When to Apply |
| 6 | |
| 7 | Use this skill when the user wants to: |
| 8 | - Deploy their ClickHouse application to production |
| 9 | - Host ClickHouse as a managed cloud service |
| 10 | - Migrate from a local ClickHouse setup to ClickHouse Cloud |
| 11 | - Create a ClickHouse Cloud service |
| 12 | - Set up ClickHouse Cloud for the first time |
| 13 | |
| 14 | --- |
| 15 | |
| 16 | ## Step 1: Sign up for ClickHouse Cloud |
| 17 | |
| 18 | Before using any cloud commands, the user needs a ClickHouse Cloud account. |
| 19 | |
| 20 | **Ask the user:** "Do you already have a ClickHouse Cloud account?" |
| 21 | |
| 22 | **If they do not have an account**, explain: |
| 23 | |
| 24 | > ClickHouse Cloud is a fully managed service that runs ClickHouse for you — no infrastructure to maintain, automatic scaling, backups, and upgrades included. There's a free trial so you can get started without a credit card. |
| 25 | > |
| 26 | > To create an account, go to: **https://clickhouse.cloud** |
| 27 | > |
| 28 | > Sign up with your email, Google, or GitHub account. Once you're in the console, let me know and we'll continue with the next step. |
| 29 | |
| 30 | **Wait for the user to confirm** they have signed up or already have an account before proceeding. |
| 31 | |
| 32 | --- |
| 33 | |
| 34 | ## Step 2: Authenticate the CLI |
| 35 | |
| 36 | First, ensure `clickhousectl` is installed. Check with: |
| 37 | |
| 38 | ```bash |
| 39 | which clickhousectl |
| 40 | ``` |
| 41 | |
| 42 | If not found, install it: |
| 43 | |
| 44 | ```bash |
| 45 | curl -fsSL https://clickhouse.com/cli | sh |
| 46 | ``` |
| 47 | |
| 48 | Authenticate `clickhousectl` with a ClickHouse Cloud API key. |
| 49 | |
| 50 | ### Create an API key |
| 51 | |
| 52 | Guide the user through creating one in the ClickHouse Cloud console: |
| 53 | |
| 54 | > 1. Click the **gear icon** (Settings) in the left sidebar |
| 55 | > 2. Go to **API Keys** |
| 56 | > 3. Click **Create API Key** |
| 57 | > 4. Give it a name (e.g., "clickhousectl") |
| 58 | > 5. Select the **Admin** role for the key. Admin is needed because `cloud service query` auto-provisions a per-service query endpoint API key on first use, which requires permission to create keys. Developer-scoped keys can manage services but may not be able to complete the auto-provisioning step. |
| 59 | > 6. Click **Generate API Key** |
| 60 | > 7. **Copy both the Key ID and the Key Secret** — the secret is only shown once |
| 61 | |
| 62 | ### Authenticate clickhousectl with the key |
| 63 | |
| 64 | Ask the user to **open a new terminal tab in the same working directory** and run the login command there with their Key ID and Secret — this keeps the secret out of the chat session. Tell them to come back and let you know once it's done. |
| 65 | |
| 66 | ```bash |
| 67 | clickhousectl cloud login --api-key <key> --api-secret <secret> |
| 68 | ``` |
| 69 | |
| 70 | Both `--api-key` and `--api-secret` are required — if the user only has one, tell them both are needed. |
| 71 | |
| 72 | --- |
| 73 | |
| 74 | **To verify authentication works:** |
| 75 | |
| 76 | ```bash |
| 77 | clickhousectl cloud org list |
| 78 | ``` |
| 79 | |
| 80 | This should return the user's organization. |
| 81 | |
| 82 | --- |
| 83 | |
| 84 | ## Step 3: Create a cloud service |
| 85 | |
| 86 | Create a new ClickHouse Cloud service: |
| 87 | |
| 88 | ```bash |
| 89 | clickhousectl cloud service create --name <service-name> |
| 90 | ``` |
| 91 | |
| 92 | From the output, add the HTTPS host and port to `.env` as `CLICKHOUSE_HOST` and `CLICKHOUSE_PORT`. Make sure `.env` is gitignored. |
| 93 | |
| 94 | Then poll until the service state is `running`: |
| 95 | |
| 96 | ```bash |
| 97 | clickhousectl cloud service get <service-id> |
| 98 | ``` |
| 99 | |
| 100 | --- |
| 101 | |
| 102 | ## Step 4: Migrate schemas |
| 103 | |
| 104 | If the user has local table definitions (e.g., from using the `clickhousectl-local-dev` skill), migrate them to the cloud service. |
| 105 | |
| 106 | Use `cloud service query` to run SQL against the cloud service over HTTP. Just pass the service name (or `--id`). |
| 107 | |
| 108 | **Read the local schema files** from `clickhouse/tables/` and apply each one to the cloud service: |
| 109 | |
| 110 | ```bash |
| 111 | clickhousectl cloud service query --name <service-name> \ |
| 112 | --queries-file clickhouse/tables/<table>.sql |
| 113 | ``` |
| 114 | |
| 115 | Apply them in dependency order — tables referenced by materialized views should be created first. |
| 116 | |
| 117 | **Also apply materialized views** if they exist: |
| 118 | |
| 119 | ```bash |
| 120 | clickhousectl cloud service query --name <service-name> \ |
| 121 | --queries-file clickhouse/materialized_views/<view>.sql |
| 122 | ``` |
| 123 | |
| 124 | To target a specific database, pass `--database <name>`. |
| 125 | |
| 126 | --- |
| 127 | |
| 128 | ## Step 5: Verify the deployment |
| 129 | |
| 130 | Connect to the cloud service and confirm tables exist: |
| 131 | |
| 132 | ```bash |
| 133 | clickhousectl cloud service query --name <service-name> --query "SHOW TABLES" |
| 134 | ``` |
| 135 | |
| 136 | Run a test query to confirm the schema is correct: |
| 137 | |
| 138 | ```bash |
| 139 | clickhousectl cloud service query --name <service-name> --query "DESCRIBE TABLE <table-name>" |
| 140 | ``` |
| 141 | |
| 142 | --- |
| 143 | |
| 144 | ## Step 6: Create a dedicated user for the application |
| 145 | |
| 146 | The `default` user has full admin rights and should not be used by the application. Create a dedicated user scoped to the schema deployed in Step 4. |
| 147 | |
| 148 | Generate a strong random password and append the cr |