Skip to content

Get started on bare-metal

Start a single-node bare-metal cluster, connect it to your workspace and run a first remote query. The cluster runs from the polars-nanook-compute Python package and is configured through one TOML file. Before you start, install the client and sign up.

You need a Linux server (x86-64 with AVX2, or ARM64) with uv.

Step 1: Create a service account

The cluster registers with your workspace through a service account: a client ID and secret for the workspace.

Create the service account with Add token in the Workspace service accounts section of your workspace settings, and copy the client ID and secret: they are shown only once. Find the workspace ID as described in Workspace ID.

nanook service-account create \
  --workspace-name "My workspace" \
  --name polars-bare-metal

The command prints the API client ID, the API secret and the Workspace ID you need in step 3. Store the secret: it is shown only once.

Step 2: Install the package

Install the polars-nanook-compute package in a virtual environment:

uv venv --python 3.12 && source .venv/bin/activate
uv pip install polars-nanook-compute

Step 3: Configure and start the cluster

This configuration runs every component on one node, with the service account from step 1:

cluster_id = "polars-cluster"
instance_id = "node-0"

[license.on_prem]
cert_dir = "./certs"
workspace_id = "<WORKSPACE_ID>"
client_id = "<CLIENT_ID>"
client_secret = "<CLIENT_SECRET>"

[scheduler]
enabled = true

[worker]
enabled = true
shuffle_location.local.path = "./shuffle-data-path"
task_service.public_addr = "127.0.0.1"
shuffle_service.public_addr = "127.0.0.1"

[observatory]
enabled = true
max_metrics_bytes_total = 104857600
database_path = "./observatory/"

[monitoring]
enabled = true

[static_leader]
leader_instance_id = "node-0"
observatory_service.public_addr = "127.0.0.1"
scheduler_service.public_addr = "127.0.0.1"

Save it as config.toml, create the directories it refers to, and start the service:

mkdir -p certs shuffle-data-path observatory
polars-nanook-compute service --config-path ./config.toml

The service registers the cluster with your workspace and then logs Finished boot procedure for cluster node. If a step fails, see Error messages.

Step 4: Run a test query

Open a second terminal on the same machine. A cluster context points the query at the scheduler:

ClusterContext · LazyFrameRemote

import polars as pl
import polars_nanook as pn

# The scheduler of the single-node cluster, on its default port 5051.
ctx = pn.ClusterContext(uri="http://127.0.0.1")

# A regular lazy Polars query; `.remote(ctx)` runs it on the cluster's worker.
result = (
    pl.LazyFrame({"a": [1, 2, 3], "b": [4, 4, 5]})
    .with_columns(pl.col("a").max().over("b").alias("c"))
    .remote(ctx)
    .collect()
)

print(result)

Save it as first_query.py and run it with uv from the directory of step 2. uv installs polars-nanook for the run on the cluster's Python, which the client needs (Set up explains why). Use the client release listed with the cluster release under Cluster software releases.

uv run --with polars-nanook first_query.py
Output
shape: (3, 3)
┌─────┬─────┬─────┐
│ a   ┆ b   ┆ c   │
│ --- ┆ --- ┆ --- │
│ i64 ┆ i64 ┆ i64 │
╞═════╪═════╪═════╡
│ 1   ┆ 4   ┆ 2   │
│ 2   ┆ 4   ┆ 2   │
│ 3   ┆ 5   ┆ 3   │
└─────┴─────┴─────┘

The query runs on the cluster's worker and .collect() streams the result back to the client. Its profile shows up under Queries in the portal and in the cluster's observatory on port 3001 of the server.

Remove the cluster

Stop the service with Ctrl+C. The service account stays valid until you delete it in the workspace settings.

Next steps