nvcl-agent.service, the Hub sees it as online, and you can deploy nodes onto it from the UI.
The Agent is the bare-metal / VM executor: it runs as a systemd service and manages each node’s processes as their own systemd units. Choose it when your nodes live on hosts or VMs you already manage and you don’t want a Kubernetes dependency. For the executor concept and the Agent-vs-Operator choice, see Executors.
The exception is the container-only chain Igra, whose clients ship as images rather than binaries. The Agent runs it as Docker containers instead of systemd units, and installs and configures the Docker engine itself the first time one is deployed (Ubuntu hosts; see Docker prerequisite).
Prerequisites
- OS — a
linux/x86_64host withsystemd. - Privileges —
rootorsudo. - Network — outbound HTTPS to the Hub (
https://hub.novacula.io). No inbound ports are needed. - API key — see Connect an executor to issue one. You’ll need the
exc_-prefixed key in the next step.
Docker prerequisite
Deploying Igra onto an Agent needs a working Docker engine on the host. You don’t prepare one: before such a node’s first launch, the Agent checks whether it can reach the Docker daemon and, if it can’t, adds Docker’s official package repository (pinned, with a checksum-verified signing key), installsdocker-ce, enables the daemon, and joins itself to the docker group. It then restarts once so that group membership applies. The step is idempotent — a no-op on a host that already has a working Docker — and Docker stays installed after you delete the node.
Auto-install covers Ubuntu. On another distribution it fails with an explicit message rather than guessing at your package manager; install Docker yourself, make sure the Agent’s user can reach the daemon socket, and redeploy. A failed install surfaces as a failed operation on the node, so you see the reason instead of a cryptic launch error.
Chains whose clients ship as binaries are unaffected and need no Docker at all.
Docker daemon settings
A container-only node needs more than a running Docker — the Agent also reconciles/etc/docker/daemon.json to the settings the container backend depends on, restarting Docker once if it had to change the file. It sets three things:
userns-remap: default— runs node containers in a user namespace, so a node’s files are owned by a remapped, unprivileged uid on the host rather than by realroot. This is a hard requirement: if it can’t be turned on, node provisioning fails with an explicit message rather than running the node without the isolation. Turning it on moves Docker’s data root, so images and containers from before it was enabled drop out ofdocker images/docker ps(they aren’t deleted).userland-proxy: false— publishes container ports in the kernel instead of through a per-port proxy process, so a container sees the caller’s real source address rather than the bridge gateway’s. Anything that judges a request by where it came from — a firewall rule in front of a node’s published port, for one — depends on it.default-address-pools— a wide private range each node’s bridge network carves a subnet from. It defaults to10.201.0.0/16in/24blocks; change it withaddress_pool_baseandaddress_pool_sizeunder a[docker]section inagent.tomlif it clashes with a network your host routes.
daemon.json but replaces default-address-pools wholesale. On a non-Ubuntu host, or one where userns-remap can’t be activated, apply these yourself and restart Docker before deploying.
Steps
1
Run the installer
The production way to bring a host online is the Hub’s one-line installer: the Hub serves a script that downloads the Agent, writes its config, and starts it as a The script — served by the Hub and rendered from its latest active Agent release — downloads the self-contained Agent image, verifies its SHA-256 checksum, extracts it to
systemd service — the host then syncs to the Hub and reconciles whatever nodes it’s assigned. From the Connect Executor screen in the UI, copy the command (the Hub renders it for your organization, with your Hub URL already baked in). It looks like this:/opt/nvcl/agent, writes /etc/nvcl/agent.toml (mode 0600, with your Hub URL and API key baked in), registers nvcl-agent.service, and starts it. If no active Agent release is published yet, /install.sh returns a 404.2
Confirm online in the UI
From Executors, your new executor row should be
online, with capabilities populated for every chain it supports.The executor reports in within a few seconds and the row turns online. If it stays offline:- Check
journalctl -u nvcl-agent.service -n 100for auth or network errors. - Confirm outbound HTTPS to the Hub URL.
- Verify the API key was copied without trailing whitespace.
What the installer does
Under the hood, the one-line command:- Downloads the self-contained Agent image tarball from the Hub’s latest active release and verifies its SHA-256 checksum.
- Extracts it to
/opt/nvcl/agent(launcherbin/agent, jars underlib/, and a bundled JRE underruntime/— no host Java needed). - Writes
/etc/nvcl/agent.toml(mode0600) with[source] type = "hub", the Hub URL (hub.url), your API key (hub.token), and the executor name. - Registers and starts
nvcl-agent.service(start on boot, restart on failure).
What the Agent owns on disk
After install:[agent] data_dir = "/var/lib/nvcl") holds everything the agent manages:
systemd units named nvcl-node-<id>-<role>.service. Node data is preserved: removing a node stops and deletes its units and releases its ports, but nodes/<id>/ stays on disk — delete it manually to reclaim space.
A container-only chain is the exception. Its roles run as Docker containers rather than systemd units, with the same nodes/<id>/<role>/ directory bind-mounted into the container (at /data/<role>), plus a shared nodes/<id>/secrets/. Inspect those with docker ps instead of systemctl. Removal differs too: the container backend removes the node’s containers, its network, and its whole nodes/<id>/ tree — so unlike a systemd node, nothing is left behind to reclaim, and nothing is left behind to recover either.
Managing the agent on the host
The installer runs the agent for you; you never start the daemon by hand. Manage it withsystemctl, and read what it observes with the agent CLI:
sudo systemctl stop nvcl-agent.service) does not stop the nodes — their nvcl-node-<id>-<role>.service units keep running.
Uninstall / wipe the host:
/opt/nvcl/agent keeping one .prev, and restarts). See Upgrade an executor.
Configuration (agent.toml)
The installer writes /etc/nvcl/agent.toml (mode 0600) for you; edit it afterward to tune behaviour, then sudo systemctl restart nvcl-agent.service (the config is read once at startup). A hub-driven config looks like:
[source] typeis the one mandatory key; in hub mode[hub] urlandtokenare required (the agent won’t sync without them).- Parsing is strict — an unknown key or section is a startup error.
- In hub mode, telemetry is routed through the Hub automatically; you don’t configure a collector here.
agent.toml — you set them per node in the UI. See Deploy a node and Edit a running node.
Hardening
- Keep
agent.tomlmode0600, owned byroot. The API key (hub.token) is the credential. - Let the Hub drive upgrades — self-update verifies the sha256 and keeps a
.prevfor rollback. - Restrict outbound to the Hub URL plus the per-chain client download mirrors if you want strict egress.
Next steps
- Deploy a node onto your fresh executor.