VorticPanel

Installation

Adding a node

A node is a KVM server that your customers’ servers run on. Adding one takes two steps: enroll it in the panel, then run one command on it. The command sets up everything on the node, including the network bridge and storage.

For a machine with NVIDIA cards that should run customers’ GPU containers instead of servers, see Adding a GPU container host.

What the node needs

  • Ubuntu 22.04 / 24.04 or Debian 12, freshly installed. (Rocky and Alma Linux 9 work too, but you make the bridge yourself.)

  • Hardware virtualization switched on. This has to print a number above 0:

    grep -Ec 'vmx|svm' /proc/cpuinfo

    If it prints 0, switch on VT-x or AMD-V in the BIOS. A VPS only works if your provider offers nested virtualization.

  • Root access over SSH, and ideally also a console that doesn’t depend on the network (IPMI, iDRAC, or your provider’s web console), in case the network change goes wrong.

  • Outbound HTTPS to the panel. Nothing has to be open to the node from the internet.

1. Enroll it in the panel

Go to Nodes → Enroll node and fill in:

Field Notes
What it runs KVM servers. (GPU containers makes it a GPU container host.)
Name Lowercase letters, digits and dashes, e.g. ams1-kvm-01
Management IPv4 The node’s IP address. Other nodes use it for moving servers.
Region Where the node is
Group The node group it joins. Nodes outside a group don’t receive new servers.

Choose Get install command. The panel shows a command with a one-time token. The token works once and expires after 60 minutes.

You can close the window and install later: the node waits at the top of the Nodes page, under Waiting to be installed. Show install command there gives a fresh command (the old one stops working), even after it expired, and Cancel drops it. The node moves into the node list once its agent connects.

2. Run the command on the node

SSH into the node as root and paste the command:

curl -fsSL https://panel.example.com/agent/install.sh | sudo sh -s -- --token enr_…

If your panel is on plain http:// for testing, the command already includes PANEL_AGENT_INSECURE=1; paste it as it is.

Optional: a spare disk for server disks. If the node has an empty second disk, add --storage-disk and its name (lsblk lists the disks). The script turns it into an LVM thin pool after you type yes. It refuses any disk with partitions or data on it.

curl -fsSL https://panel.example.com/agent/install.sh | sudo sh -s -- --token enr_… --storage-disk /dev/nvme1n1

What it does

  1. Checks that virtualization is on and that the panel is reachable.
  2. Installs KVM, libvirt, nftables, LVM tools, an SSH server and Node.js 24.
  3. With --storage-disk, turns that disk into storage.
  4. Moves the public network onto a bridge called br-public, which servers plug into. It shows you the change and asks first. The bridge keeps the node’s IP address and MAC address, so your provider sees nothing change.
  5. Enrolls the node and starts the panel-agent service.

The network change

This is the only step that can cut you off, so it protects itself:

  • The switch runs on its own, separately from your SSH session, so a dropped connection can’t stop it halfway.
  • Afterwards it checks that the panel can still be reached. Then it asks: “If you can read this, press Enter to keep the new network”. Press Enter.
  • If the panel can’t be reached, or nobody presses Enter within 90 seconds, the old network comes back by itself. If your SSH session froze, wait three minutes and connect again.

A copy of the old network files is kept in /var/lib/panel-agent/network-backup-….

Check: in the panel, the node shows as online within a few seconds. Its Storage tab shows its storage, already added and marked as the default: the thin pool on your spare disk, an LVM thin pool or ZFS dataset it found, or otherwise the /var/lib/libvirt/images folder.

3. Give it addresses

IP pools → New pool: your IP range and its gateway, the region, and this node. On the pool’s page, reserve every address that isn’t free for servers: the nodes themselves, the panel’s server, and anything else on that network. See IP pools.

4. A package and an OS image (first node only)

  1. Packages → New package: e.g. 2 vCPU, 2 GB memory, 20 GB disk, sold in your node group. See Packages.

  2. OS templates → Add from catalog, then Add next to the images you want, for example Ubuntu 24.04 and Debian 13.

    Every node downloads each one from its distribution and checks its checksum. When it shows as Hidden on the OS templates page, choose Publish. See OS templates and ISOs.

Then create your first server.

If the bridge wasn’t set up

The script carries on and enrolls the node anyway, and tells you why it didn’t make the bridge:

It says What to do
The network was undone because the panel wasn’t reachable Check the node can reach the panel normally (curl https://panel.example.com/api/v1/status), then run the command again with a new token.
NetworkManager, or no netplan or /etc/network/interfaces The network is managed in a way the script doesn’t change. Make the bridge by hand, then restart the agent.
The interface is in a bond Make the bridge by hand on top of the bond.
Already on a bridge Nothing to do. The panel uses the existing bridge.

Servers can’t be created on the node until it has a bridge.

Moving servers between nodes

With two or more nodes, allow these between them, on their management addresses:

Port For
TCP 22 Moving servers (the install script set up the SSH server). The disk and memory go through this SSH connection too, encrypted.
UDP 4789 Customers’ private networks (VXLAN)

The agents create their own keys, exchange them, and pin each other’s host keys.

How the node talks to the panel

  • The node connects out to wss://panel.example.com/agent/v1/connect.
  • It signs in with its own secret, issued when it enrolls and valid for a year. The panel renews it automatically within 30 days of expiry.
  • If the connection drops, the agent reconnects by itself. A node counts as offline after a minute without a connection; its servers keep running.

The agent’s files

Path What
/opt/panel-agent/panel-agent.mjs The program
/etc/panel-agent/agent.json Its panel address, node ID and credential, readable by root only
/var/lib/panel-agent/ Cached images, state, its SSH key for moves, and network backups
/etc/systemd/system/panel-agent.service The service, running as root
/etc/systemd/system/panel-firewall.service Loads the servers’ firewall (/var/lib/panel-agent/state/firewall.nft) when the node starts, before libvirt starts any server. The agent adds it itself.
journalctl -u panel-agent Logs

Every word has to appear. ↑ ↓ to move, Enter to open.