Getting started
This page takes you from a binary to a first query on one node.
What you need
You need the muscles binary or container image from your beta onboarding, and the tools curl, jq and openssl.
Create a user
The command hash-password takes a user name and a role, reads the password on stdin and prints the line that the users file needs. The role admin can do everything, and the role viewer can only read.
echo 'change-me' | ./muscles hash-password alice admin > users.txt
chmod 600 users.txt
The server refuses a users file that other users are allowed to write.
Start the server
Give the server a secret for signing session tokens, and the users file.
MUSCLES_AUTH_SECRET=$(openssl rand -hex 32) \
MUSCLES_USERS_FILE=users.txt \
./muscles
The server listens on 127.0.0.1:18080 and keeps its data in ./muscles-data.
Log in
In a second terminal, log in and keep the token.
TOKEN=$(curl -s -XPOST localhost:18080/api/auth/login \
-d 'username=alice&password=change-me' | jq -r .token)
Create a table and query it
Create a table, insert three rows and query them.
curl -s -XPOST localhost:18080/api/query \
-H "Authorization: Bearer $TOKEN" \
-d 'CREATE TABLE orders (
id UInt64, customer String, amount Float64, placed DateTime)'
curl -s -XPOST localhost:18080/api/query \
-H "Authorization: Bearer $TOKEN" \
-d "INSERT INTO orders VALUES
(1, 'ann', 12.5, '2026-10-20 09:15:00'),
(2, 'bob', 3.0, '2026-10-20 10:40:00'),
(3, 'ann', 7.25, '2026-10-21 08:05:00')"
curl -s -XPOST localhost:18080/api/query \
-H "Authorization: Bearer $TOKEN" \
-d 'SELECT customer, count(*) AS n, sum(amount) AS total
FROM orders GROUP BY customer ORDER BY total DESC'
The last command prints the result as columnar JSON, on one line. It is indented here to show its shape. Each column has a name, its values and its muscles type in type. A column whose ClickHouse type the server knows, such as a table column or a count, also carries that name in ch_type; a computed column such as total has none.
{
"query_id": "…",
"rows_fetched": 2,
"row_limit": 1000000,
"columns": [
{"name": "customer", "values": ["ann", "bob"],
"type": "varchar", "ch_type": "String"},
{"name": "n", "values": [2, 1], "type": "int64", "ch_type": "UInt64"},
{"name": "total", "values": [19.75, 3], "type": "float64"}
]
}
Use the ClickHouse HTTP interface
The ClickHouse HTTP interface takes the same SQL and returns tab-separated text.
curl -s -u alice:change-me localhost:18080/ \
-d 'SELECT customer, sum(amount) FROM orders
GROUP BY customer ORDER BY customer'
ann 19.75
bob 3
Open the console
Open http://127.0.0.1:18080/ in a browser and log in as alice.
A throwaway server
To skip the secret and the users file on a local test server, start it with MUSCLES_AUTH_DEV_INSECURE=1 MUSCLES_ADMINS=alice ./muscles. The server then accepts any name with any password, and a name listed in MUSCLES_ADMINS logs in as an administrator. Anyone who can reach the server gets in. Never use this on a network that others can reach.
Expose it to a network
The server serves plain HTTP, without TLS. Before you expose it beyond the local machine, put a TLS proxy or an ingress in front of it, and keep traffic between nodes on a private network. Set MUSCLES_HTTP_ADDR to the address the proxy reaches.
Next steps
- Look up a function or a setting in the reference.
- The server reads
MUSCLES_*environment variables, and optionally amuscles.yamlfile. The configuration reference lists every variable. MUSCLES_HTTP_ADDRandMUSCLES_HTTP_PORTset where the server listens,MUSCLES_WAL_DIRandMUSCLES_PARTS_DIRset the data directories, andMUSCLES_KAFKA_BOOTSTRAPnames the Kafka brokers.- The architecture page shows how a row is stored and how a query runs.