template.kicker
items.agentInstallation.title
items.agentInstallation.description
Nebua Agent Installation Guide
The Nebua Agent is the host-level communication service for private clusters. It runs directly on the target Linux host with systemd, connects outbound to NebuaCloud, and owns local k3s lifecycle tasks such as bootstrap, health checks, restart, and kubeconfig sync. Autonomous add-on reconciliation, policy enforcement, and self-healing belong to nebua-operator inside the cluster instead — see the Operator Installation Guide to install it. For exposing an environment's reverse proxy, see the Gateway Installation Guide. Nebua Runtime Components explains how the three fit together.
Install nebua-agent.service on the first control-plane node at minimum. For stronger node-level visibility, install it on every private cluster node and set NODE_TYPE appropriately.
Every node needs its own agent ID and its own token — never reuse one pair across multiple hosts. Generate a separate token from the dashboard's API Keys tab for each node you install on (control-plane or worker). The generated token has that node's agent ID baked into it, so --agent-id and --token on a given host must be the matching pair from the same generation — not values copied from another node's install command. Reusing one pair across two hosts makes Core treat them as a single agent reconnecting back and forth: whichever host's connection is currently registered silently overwrites the other's, so commands like listing nodes intermittently reach a host that may not even have cluster API access (a plain k3s worker has no /etc/rancher/k3s/k3s.yaml), and the dashboard ends up missing nodes unpredictably.
Prerequisites
- Ubuntu, Debian, or another systemd-based Linux host
curlandtar- Outbound HTTPS/WebSocket access to NebuaCloud on port
443 - Cluster ID, agent ID, and NebuaCloud agent token from the dashboard
- Root access on the target host
- cgroup v2 enabled if the cluster runs k3s v1.32 or newer (see Host Requirement: cgroup v2)
- At least 4GB of RAM on every control-plane node (see Host Requirement: Memory)
The hosted installer downloads a Nebua agent bundle that already contains the Node.js runtime and compiled agent code. The target host does not need Node.js, pnpm, or a monorepo checkout.
The agent should run as root for production private-cluster hosts because it manages local k3s bootstrap and service operations through systemd.
Host Requirement: cgroup v2
Kubernetes removed cgroup v1 support, so k3s v1.32 and newer require the host to run the unified cgroup v2 hierarchy. On a cgroup v1 host the kubelet refuses to start, k3s never becomes ready, and the node never registers — so the cluster shows "not connected" and any worker join silently fails to appear. Older distributions (e.g. Ubuntu 20.04 / kernel 5.4) default to cgroup v1.
The agent cannot change the cgroup hierarchy for you: switching to cgroup v2 requires a kernel boot parameter and a host reboot, which the agent will not perform automatically. The agent detects the mismatch and reports an actionable error; the host owner must apply the change.
Check the host's cgroup version:
# Prints "CGROUP_V2" when the host is ready for k3s v1.32+, otherwise "CGROUP_V1"
test -f /sys/fs/cgroup/cgroup.controllers && echo CGROUP_V2 || echo CGROUP_V1
Enable cgroup v2 (Ubuntu/Debian with GRUB):
# 1. Add the kernel flag (idempotent)
sudo sed -i 's/^GRUB_CMDLINE_LINUX_DEFAULT="\(.*\)"/GRUB_CMDLINE_LINUX_DEFAULT="\1 systemd.unified_cgroup_hierarchy=1"/' /etc/default/grub
# 2. Regenerate the boot config and reboot
sudo update-grub
sudo reboot
# 3. After reboot, confirm cgroup v2 is active
test -f /sys/fs/cgroup/cgroup.controllers && echo CGROUP_V2 || echo CGROUP_V1
Alternatives if you cannot reboot to cgroup v2:
- Pin the cluster to a cgroup-v1-compatible k3s release (v1.31 or older, e.g.
v1.29.3+k3s1). All nodes must use the same line — a cgroup-v1 worker cannot join a k3s v1.32+ control plane. - Set
NEBUA_K3S_CGROUPV1_VERSIONin/etc/nebua/nebua-agent.envto force a compatible version on cgroup-v1 hosts.
A node that was added before fixing cgroup may leave stale state under
/var/lib/rancher/k3s. After enabling cgroup v2, remove it (sudo rm -rf /var/lib/rancher/k3s /usr/local/bin/k3s /usr/local/bin/kubectl) so the next join installs cleanly.
Host Requirement: Memory
k3s server alone routinely holds over 1GB resident once the control plane, embedded etcd/SQLite, and the built-in controllers are all running - before counting anything the cluster actually schedules. On an undersized host this is not a one-time cost that settles down: the kernel's OOM killer starts repeatedly killing whichever process looks biggest, which on a control-plane node is usually nebua-agent itself (since it's what's watching and restarting things). The agent comes back up, gets killed again, and the cycle repeats - visible as the agent's systemd restart count climbing continuously and the node dropping in and out of NebuaCloud without ever fully failing.
A real production case: a 1.9GB control-plane node with only 6 pods total running cluster-wide had k3s server alone consuming ~1.25GB RSS (63% of total memory), with swap fully exhausted on top of that. kubectl top nodes and kubectl top pods -A both timed out reaching the local API server - the control plane was too memory-starved to answer its own metrics requests. This was not a "too many pods scheduled without resource requests" overcommit problem (the usual cause of node pressure); with only 6 pods in the entire cluster, k3s server itself was the dominant consumer.
Recommendations:
- 4GB minimum for any control-plane node, 8GB or more if the cluster will run a meaningful workload alongside the control plane.
- Don't rely on swap to make a small node work. Kubernetes assumes swap is disabled; a control-plane node that's swapping is already past the point of being reliably manageable, and a full swap is a strong signal the node needs more RAM, not more swap.
- If
nebua-agentis stuck in a restart loop on a node that otherwise looks "up", check for memory pressure before assuming an agent or networking bug:
free -h
sudo dmesg -T | grep -i 'killed process'
ps aux --sort=-%mem | head -10
Repeated Out of memory: Killed process ... (nebua-agent) or (k3s) lines in dmesg confirm the node itself needs more memory - no agent or cluster configuration change fixes this short of adding RAM or moving workloads off the node.
Quick Host Installation
Run the hosted installer on the target host. The NebuaCloud dashboard should generate this command with the correct cluster ID, agent ID, and token — the agent ID is auto-generated when you create the token and shown alongside it in the dashboard's API Keys tab; it must be passed through so it matches the ID embedded in the token, otherwise the agent generates its own random ID locally and /v1/agent/validate rejects it as a mismatch.
curl -fsSL https://nebuacloud.com/install/nebua-agent.sh | sudo bash -s -- \
--cluster-id <cluster-id> \
--agent-id <control-plane-agent-id> \
--token '<control-plane-agent-token>' \
--node-type control-plane \
--k3s-install-script-sha256 <sha256-of-get.k3s.io> \
--env production
For worker nodes, generate a separate token from the dashboard for each worker host — do not reuse the control-plane's --agent-id/--token pair here, or any other worker's:
curl -fsSL https://nebuacloud.com/install/nebua-agent.sh | sudo bash -s -- \
--cluster-id <cluster-id> \
--agent-id <worker-agent-id> \
--token '<worker-agent-token>' \
--node-type worker \
--k3s-install-script-sha256 <sha256-of-get.k3s.io> \
--env production
--k3s-install-script-sha256 is required before the agent will bootstrap or (re)join k3s — before running the official https://get.k3s.io installer script, the agent verifies it against this checksum and refuses to proceed if it's missing, so a node installed without it can connect to NebuaCloud and look otherwise healthy but never actually get k3s running (the node then shows as not-ready with no k3s process, and the agent log has NEBUA_K3S_INSTALL_SCRIPT_SHA256 is required before downloading the K3s installer script). Compute the current value once, from a trusted network, and reuse it for every node in the cluster:
curl -sfL https://get.k3s.io | sha256sum
The hosted bootstrap script downloads the NebuaCloud agent bundle for the selected release, runs the host installer, installs bundled Node under /usr/local/lib/nebua/bin/node, installs the runtime under /usr/local/lib/nebua/runtime, writes /etc/nebua/nebua-agent.env, installs /etc/systemd/system/nebua-agent.service, and starts the service.
Environment File
The systemd unit reads configuration from /etc/nebua/nebua-agent.env. This file is owned by root and installed with 0600 permissions.
BUILD_ENV=production
NODE_ENV=production
NEBUACLOUD_API_URL=https://api.nebuacloud.com
CLUSTER_ID=605819
NEBUACLOUD_TOKEN=token
AGENT_ID=nebua-agent-xxx
NODE_TYPE=control-plane
NEBUA_K3S_INSTALL_SCRIPT_SHA256=<sha256-of-get.k3s.io>
Common values:
CLUSTER_ID: NebuaCloud cluster IDNEBUACLOUD_TOKEN: agent token with agent connection scopesNEBUACLOUD_API_URL: API base URL, defaults tohttps://api.nebuacloud.comAGENT_ID: stable host agent ID - must match the agent ID the token was generated with, or/v1/agent/validaterejects the token as not valid for this agentNODE_TYPE:control-plane,server,worker, oragentNEBUA_K3S_INSTALL_SCRIPT_SHA256: pinned checksum ofhttps://get.k3s.io- required before the agent will bootstrap or (re)join k3s (see Quick Host Installation)
After changing the env file, restart the service:
sudo systemctl restart nebua-agent
Verify Installation
sudo systemctl status nebua-agent --no-pager
sudo journalctl -u nebua-agent -f
Check k3s after bootstrap:
sudo systemctl status k3s --no-pager
kubectl get nodes
The agent writes the kubeconfig in readable mode (write-kubeconfig-mode: 0644), so kubectl works directly — no sudo or k3s prefix needed.
The agent should validate its token, connect to NebuaCloud, bootstrap or detect k3s, then report cluster health.
Updating The Agent
To update the agent, rerun the hosted installer with the same cluster values:
curl -fsSL https://nebuacloud.com/install/nebua-agent.sh | sudo bash -s -- \
--cluster-id <cluster-id> \
--agent-id <agent-id> \
--token '<agent-token>' \
--node-type control-plane \
--env production
The installer replaces /usr/local/lib/nebua/runtime, refreshes the env file, reloads systemd, and restarts nebua-agent.service.
Troubleshooting
Agent does not start
sudo journalctl -u nebua-agent -n 100 --no-pager
Common causes:
- missing or invalid
NEBUACLOUD_TOKEN - missing
CLUSTER_IDfor an existing cluster - target host cannot reach
NEBUACLOUD_API_URL curlortaris missing during initial installation
k3s does not become healthy
sudo systemctl status k3s --no-pager
sudo journalctl -u k3s -n 100 --no-pager
sudo journalctl -u nebua-agent -n 100 --no-pager
The agent reports host recovery signals, but autonomous remediation belongs to nebua-operator. Disk pressure, unsupported kernels, broken cgroups, occupied ports, or memory pressure (see Host Requirement: Memory) may still require manual host cleanup. If nebua-agent's restart count keeps climbing and dmesg shows OOM kills, the fix is host memory, not agent config.
If nebua-agent -n 100 shows NEBUA_K3S_INSTALL_SCRIPT_SHA256 is required before downloading the K3s installer script, k3s never installed at all - systemctl status k3s correctly reports no such unit, since the agent stopped before creating it. Add NEBUA_K3S_INSTALL_SCRIPT_SHA256 to /etc/nebua/nebua-agent.env (see Environment File) and restart nebua-agent.
Node shows "not ready" or a node's API calls fail with 500
Almost always caused by two hosts sharing one AGENT_ID/token pair (see the warning in the intro above) - whichever host's WebSocket connection is currently registered silently answers for both, so the other node's status goes stale or its commands hit a host that isn't actually it. Confirm on each host:
hostname
sudo grep AGENT_ID /etc/nebua/nebua-agent.env
If two hosts report the same AGENT_ID, generate a fresh token/agent-id pair for one of them from the dashboard's API Keys tab, update its /etc/nebua/nebua-agent.env, and restart nebua-agent on that host. Also double-check NODE_TYPE on each host matches its real role - a control-plane node installed with NODE_TYPE=worker (or vice versa) causes the same kind of inconsistent behavior even with distinct agent IDs.
Uninstall
Uninstalling nebua-agent stops the host connectivity service. It does not touch k3s or the cluster by default — the cluster keeps running, it just stops reporting to NebuaCloud and can't be managed from the dashboard until an agent is reinstalled.
sudo systemctl stop nebua-agent
sudo systemctl disable nebua-agent
sudo rm -f /etc/systemd/system/nebua-agent.service
sudo systemctl daemon-reload
sudo rm -f /etc/nebua/nebua-agent.env
sudo rm -rf /var/lib/nebua-agent /var/log/nebua-agent
If this host also runs nebua-gateway: both services share /usr/local/lib/nebua/runtime and /usr/local/lib/nebua/bin/node — deleting them while another Nebua service is still installed breaks that service too. Only remove them once every Nebua service on the host has been uninstalled:
sudo rm -rf /usr/local/lib/nebua/runtime /usr/local/lib/nebua/bin
Also removing k3s (full teardown)
Removing the agent alone leaves k3s and the cluster's data intact. To tear down the cluster on this host entirely, k3s ships its own uninstall scripts (installed by the k3s installer itself, not by nebua-agent):
# On a control-plane/server node
sudo /usr/local/bin/k3s-uninstall.sh
# On a worker/agent node
sudo /usr/local/bin/k3s-agent-uninstall.sh
This removes the k3s binary, its systemd unit, and all cluster state under /var/lib/rancher/k3s, /etc/rancher/k3s, and /var/lib/kubelet. This is destructive and cannot be undone — back up anything you need first (kubectl get all -A -o yaml, PersistentVolume data).
If you only want to disconnect this host from NebuaCloud without touching it at all, delete the cluster from the dashboard instead — that revokes the agent's token but leaves the host, the agent process, and k3s untouched.
Security Considerations
- The agent connects outbound only; no inbound firewall rule is required.
- Store tokens only in
/etc/nebua/nebua-agent.envor your secret manager. - Keep
/etc/nebua/nebua-agent.envowned byrootwith0600permissions. - Rotate tokens after accidental exposure in shell history, logs, tickets, or screenshots.