Skip to content

The NexoVirt node agent

NexoVirt runs a small agent on each connected Proxmox node. It does the work that the Proxmox API can’t do cleanly on its own: downloading OS images, applying NAT and WireGuard, reading the node firewall and logs, installing package updates, and feeding the panel accurate node facts. The current agent version is 0.24.1.

The agent is a single PHP script (/opt/nexovirt-agent.php, config in /etc/nexovirt-agent.conf) run by the nexovirt-agent systemd service. It runs on the stock Proxmox php-cli and needs no extra PHP extensions (no curl or mbstring extension).

It holds no open inbound port. It sends a heartbeat to the panel over HTTPS about every 15 seconds (every 3 seconds while it has work), picks up queued jobs from the response, runs them and posts the results back. It authenticates with a per-node token issued during onboarding. Nothing outside your panel can reach it.

The panel needs a working agent and checks it on every heartbeat:

  • Missing or not responding (no heartbeat for 5 minutes): the panel shows a blocking dialog on every admin page with the one-click fix (Set up agent or Update agent). The dialog clears itself once the agent reports in. Nodes that are down and handled by failover, and nodes where you deliberately used Remove agent, do not trigger it.
  • Outdated (the installed version differs from the one bundled with the panel): the agent keeps working. The panel shows a dismissible “node agents need updating” banner once per new agent version, and the Nodes list shows Update available with an Update button.

Some features need a minimum agent version and say so when the agent is older, for example node updates.

The agent only runs a fixed, allow-listed set of jobs. There is no “run this command” job: the panel can only ask for one of these named operations, each validates its own inputs on the node, and anything else is rejected as an unsupported job type.

JobWhat it does
Provision image storageCreates the managed nexovirt-images directory storage on the node.
Image cacheDownloads an OS cloud image once per node into the image cache (detached, resumable, SHA-256 verified), and deletes cached images. Older agents used a per-guest download instead.
Write cloud-init snippetWrites a validated cloud-init vendor snippet (for example to install the QEMU guest agent or enable root SSH).
LXC password / root SSHRuns pct exec in a container to set the root password or enable root SSH (Proxmox has no API for this).
Apply / clear NATPrograms only the dedicated NEXOVIRT-* iptables chains for masquerade and port forwards. Built-in and Proxmox chains are never flushed.
Apply / read WireGuardManages the wg-nexovirt interface and its own NEXOVIRT-VPN* chains, and reports VPN status and readiness.
SDN DHCP and egressInstalls dnsmasq only if absent and enables the per-zone DHCP backend; enables forwarding for SNAT subnets.
Set IP forwardingTurns net.ipv4.ip_forward on or off through its own sysctl.d file.
Scan IPsPing-sweeps a CIDR (at most 1024 addresses) and reads the ARP table to find addresses in use for IPAM.
Probe TCPChecks that a host and port are reachable (migration pre-flight).
Unlock guestRuns qm unlock / pct unlock for a guest left locked by a migration.
Configure DynDNSStores the DynDNS token and keeps the node’s DynDNS name updated every 5 minutes.
Package updatesRefreshes the package lists, simulates and installs Debian / Proxmox updates. See Node updates.

Separately from the jobs above, the agent reads node facts for the node page, health checks, firewall view and diagnostics. These reads are read-only:

  • System: OS release, kernel, CPU, memory, uptime, load average, pending package updates, SMART disk health, the state of pve-cluster, pvedaemon, pveproxy and pvestatd, and the ip_forward setting.
  • Proxmox VE: version, cluster, HA and Ceph status, and the storage list.
  • Firewall: the raw output of the firewall tooling present (iptables, nftables, ufw, firewalld, pve-firewall), which the panel parses into a read-only view.
  • Logs: recent system and Proxmox daemon log lines from journalctl, shown under Diagnostics.
  • Heartbeat stats: uptime, load, memory, and the image cache contents and free space.

The agent does not read your guests’ disks, your files or any secrets.

The agent runs as root (it needs pct, iptables, sysctl and apt-get), which is why the design is deliberately narrow: a fixed job list, validated inputs, dedicated firewall chains and detect-first behaviour.

  1. Set up. Add node (or Set up agent on an existing connection) connects once over SSH (host key pinned), installs php-cli if missing, installs the script and systemd service, and waits for the first heartbeat. See Nodes & onboarding.
  2. Update. Update agent on the node page (Settings tab) or the Update button in the Nodes list pushes the agent bundled with the panel, restarts the service and waits for a heartbeat at the new version. After a panel update, update the agent on every node.
  3. Remove. Remove agent uninstalls the service, script and config and revokes the token, while keeping the node, its inventory and metrics. Deleting the node from the panel can also wipe the agent and the nexovirt-images storage.

If SSH credentials are stored for the node, update and remove run without asking for them again. If the panel server blocks proc_open, run the worker manually; see CLI & daemons.

  • Root SSH access to the node for the one-time setup (password or the panel’s key).
  • php-cli on the node (installed automatically if missing).
  • Outbound HTTPS from the node to your panel. No inbound port is opened.