Connect a cluster
Turn a fresh Ubuntu or Debian server into a NebulaCtrl cluster by running one install command, and watch the agent connect from the console.
A cluster is the K3s cluster your services run on. You create it in the console, then run one command on a server. The command installs K3s and the NebulaCtrl agent, and the agent dials out to the control plane. The server needs no inbound port for NebulaCtrl.
Before you begin
- A signed-in admin or owner in the control plane. See Install NebulaCtrl.
- A fresh server running Ubuntu 22.04 or newer, or Debian 12 or newer, on x86_64 or aarch64. It needs at least 2 CPUs and about 2 GB of memory. See Requirements for sizing.
- Root access, either as
rootor throughsudo. - Ports 80, 443 and 6443 free on the server. The first install on a server refuses to start if something else holds them.
- No other K3s on the server, and
firewalldnot running. NebulaCtrl manages the firewall withufw. - Outbound HTTPS from the server to your control plane's public URL.
The command takes the server over
It installs packages, turns swap off, changes the firewall and, when root or your sudo user already has an authorized SSH key, turns off SSH password login. Use a server you can rebuild. The full list is in What the command changes.
1. Name the cluster
If your organization has no cluster yet, the console opens the setup wizard at Connect your first cluster. For a later cluster, open Clusters and select Connect cluster. Both show the same field.
Enter a Cluster name, for example home-lab. The console shows the slug it derives from the name, such as home-lab: lowercase letters, digits and dashes, set once. Select Generate install credentials.
You see an Install command and a One-time token.
2. Run the command on the server
Copy the install command and run it in a shell on the server. It asks for the token at a hidden prompt:
NebulaCtrl token:Copy the One-time token from the console and paste it. Nothing is echoed. The token goes to curl through standard input, so it never appears in your shell history, the process list or the environment. It works once and expires after one hour. If it expires, select New install credentials in the wizard, or Rotate in the Connect a cluster dialog, and run the command again.
You see the script print its progress in your terminal. Keep the session open until it prints Installed.
What the command changes
The command is one script that runs these steps in order. It reports each one to the control plane under the name in bold, and GET /api/v1/clusters/CLUSTER_ID/install lists one row per node per step.
- preflight. Checks root, the
sscommand, the operating system, the CPU architecture, CPU and memory,firewalld, existing K3s, and ports 80, 443 and 6443. Nothing is changed if a check fails. - packages. Installs
curl,ca-certificates,jq,ufw,fail2ban,unattended-upgrades,apt-listchanges,wireguard-toolsandnftables. - sysctl. Enables IP forwarding, raises inotify and memory-map limits, turns swap off and comments out swap entries in
/etc/fstab(a backup is kept at/etc/fstab.nebula-bak), and enables NTP. - mesh. Joins your organization's WireGuard mesh on UDP port 51821, before K3s starts. Every node of every cluster in the organization joins the same mesh, and node-to-node traffic runs only inside it. See Networking.
- join. For a node added to an existing cluster only: fetches the join configuration.
- k3s. Installs a pinned K3s release with secrets encryption on, and configures the bundled Traefik ingress with a
letsencryptresolver that answers the HTTP-01 challenge. Traefik trusts forwarded headers only from Cloudflare's published address ranges. - cnpg. On a server install: installs cert-manager, the CloudNativePG operator and the Barman Cloud plugin, which Postgres databases need. See Databases.
- firewall. With
ufw, denies incoming traffic except SSH, ports 80 and 443, and traffic from the cluster's own pod and service ranges. The mesh keeps its ownnftablesrules. - ssh. When
authorized_keysalready holds a key for root or thesudouser, turns off SSH password login. - fail2ban. Bans an address for one hour after five failed SSH logins within ten minutes.
- updates. Turns on unattended security updates, without automatic reboots.
- agent. On the first node: applies the agent manifest to the
nebula-systemnamespace and waits for the agent Deployment to roll out.
When a cluster is promoted to high availability, the same report also carries an etcd step.
Running the command again on the same server for the same cluster is safe. K3s restarts only if its configuration changed.
3. Watch the cluster join
Back in the console, the setup wizard shows a checklist that fills in as the server reports progress:
- Agent installed
- Joined the WireGuard mesh
- Secure tunnel open
- First heartbeat
- Node ready
Outside the wizard, the Connect a cluster dialog shows one status box instead. It reads Waiting for the agent… with the step the server last reported, then home-lab connected with the node count and K3s version.
The install takes a few minutes. When the last stage is done, the checklist turns green and lists the node's name. If a step fails, the console shows the step, the message the server reported and a button to issue new credentials. See Troubleshooting clusters and agents.
4. Decide how the cluster is reached
When the cluster is connected, the wizard shows one of two notes:
- Reachable from the internet at an address. A public domain can point straight at the server.
- home-lab isn't reachable from the internet yet. The server sits behind NAT. Apps still deploy and run. To serve public domains, add a public gateway, serve the cluster through another public cluster, or choose Keep it private for now. You can decide later.
Select Continue. You see Link a Git provider.
Verify
Open Clusters. The cluster is listed with the health Healthy and its node count. A cluster whose agent has not connected yet reads Never connected, and one that connected before and is waiting for the agent to return reads Awaiting agent. A connected cluster with a node that isn't Ready reads Degraded, and one whose agent stopped reporting reads Disconnected.
Next steps
To add a machine to a connected cluster, select the cluster in Clusters and then + Add server. Choose the role Worker, Public gateway or Control plane, and an install method: Script, Cloud-init, SSH or Terraform. The join token is single-use. Set its default lifetime in Settings > Security & policy under Server join tokens, to 15 min, 1 hour, 6 hours or 24 hours.