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

# Clusters

> How Niro registers, monitors, and communicates with k3s clusters.

## What is a cluster?

In Niro, a **cluster** represents a single k3s installation. It has:

* A unique ID (assigned at enrollment)
* A user-defined name
* An [environment tag](/concepts/environments) (`dev`, `staging`, `production`, or `unspecified`)
* An in-cluster [agent](/concepts/agents) that reports heartbeats and executes commands

Clusters can be anywhere — edge sites, on-premises servers, homelabs, or cloud VMs. Niro doesn't care where the cluster runs as long as it can reach `api.niro.cx` over outbound HTTPS.

## Cluster lifecycle

### Enrollment

Enrollment is a one-time exchange that establishes the cluster's identity:

1. A Niro user creates a cluster and receives a **single-use enrollment token** (valid for 1 hour)
2. The installer script runs on the cluster, creates the `niro-system` namespace, and deploys the agent
3. The agent contacts Niro with the token
4. Niro exchanges the token for a **long-lived agent key**, which is stored in a Kubernetes Secret inside `niro-system`
5. The enrollment token is invalidated immediately after exchange

The agent key never leaves the cluster — it's stored only in the cluster's Secret, and Niro stores only a hash of it.

### Heartbeat

After enrollment, the agent sends a heartbeat every \~15 seconds. The heartbeat is the primary state channel:

* Updates node inventory (status, version, capacity, usage)
* Updates pod inventory (phase, restarts, resources, images)
* Reports recent Kubernetes Warning events
* Advertises which capabilities are enabled
* Triggers incident detection and policy evaluation

The **last heartbeat** timestamp on the fleet page ticks on every 5-second dashboard refresh. If no heartbeat arrives for a configurable timeout, the cluster transitions to **offline** and an incident fires.

### Commands

Commands flow from Niro to the cluster over a persistent connection the agent maintains. When Niro needs to send a command (apply a deployment, stream logs, etc.), it delivers it over this connection. The agent processes the command and immediately re-establishes the connection.

This design means **no inbound port forwarding is required** — the agent only needs outbound HTTPS access.

## Cluster status

The fleet overview shows a status badge for each cluster:

| Status       | Meaning                                                                    |
| ------------ | -------------------------------------------------------------------------- |
| **Healthy**  | Agent is heartbeating and no active incidents                              |
| **Warning**  | Active low/medium severity incidents                                       |
| **Critical** | Active high severity incidents (crash loop, node not ready, etc.)          |
| **Unknown**  | No heartbeat received within the expected window                           |
| **Offline**  | Heartbeat has been absent long enough to fire a `cluster_offline` incident |

## Cluster detail view

Clicking a cluster opens its detail view with:

* **Overview** — live node list with CPU/memory capacity and usage
* **Workloads** — pod count grouped by namespace and phase
* **Deployments** — managed workloads with apply status and last sync time
* **Timeline** — activity feed (restarts, apply events, policy findings, drift)
* **Settings** — rename, change environment, delete

## Deleting a cluster

Deleting a cluster from the dashboard removes it from Niro. The agent continues running inside the cluster (it just stops receiving commands and its heartbeats are rejected). To fully uninstall:

```bash theme={"theme":{"light":"github-light","dark":"vesper"}}
kubectl delete namespace niro-system
```

This removes the agent Deployment, the RBAC resources, and the Secret containing the agent key.

## Multiple clusters

There's no hard limit on clusters per organization (subject to your [plan](/reference/plans)). The fleet overview shows all clusters at once. The pod inventory page aggregates pods across all clusters in the org.

## Related

* [Connect a Cluster](/guides/connect-cluster) — step-by-step enrollment walkthrough
* [Agent Capabilities](/reference/agent-capabilities) — opt-in features: logs, apply, self-update
* [Environments](/concepts/environments) — tag clusters for policy severity control
