muscles

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 a muscles.yaml file. The configuration reference lists every variable.
  • MUSCLES_HTTP_ADDR and MUSCLES_HTTP_PORT set where the server listens, MUSCLES_WAL_DIR and MUSCLES_PARTS_DIR set the data directories, and MUSCLES_KAFKA_BOOTSTRAP names the Kafka brokers.
  • The architecture page shows how a row is stored and how a query runs.