Skip to content

How it connects

cv4pve-vdi is a client: every connection starts from the user’s computer. Knowing which ones it opens tells you what the firewall between users and the cluster has to allow.

Connection From the client to Port
Proxmox VE API, login, VNC The node in the cluster’s Hosts that answered at login 8006 (or the port in Hosts)
SPICE The SPICE proxy, by default the same node 3128
RDP, SSH, custom services The guest’s IP address The service’s port, e.g. 3389, 22
Update check api.github.com 443

At login cv4pve-vdi tries the hosts of the cluster in order and uses the first one that answers within the timeout. Every later call (the list of guests, status, start, shutdown, consoles) goes to that node, which forwards it inside the cluster when the guest runs elsewhere.

For a SPICE console cv4pve-vdi asks the API for a SPICE ticket (POST …/spiceproxy), writes a .vv file in the temporary folder and starts remote-viewer with it. remote-viewer does not connect to the node running the VM but to a SPICE proxy: the spiceproxy service every Proxmox VE node runs on port 3128, which forwards the connection to the right node.

The proxy is the node cv4pve-vdi is connected to. When users cannot reach that address (a node behind NAT, a different name from outside), set SPICE proxy in the cluster to the host name or IP address they should use. Proxmox VE takes it as a plain address (no port, no https://) and the viewer connects to it on port 3128.

The .vv file carries a one-time ticket and is deleted by remote-viewer once read.

The VNC console needs no port other than the API one. remote-viewer speaks plain VNC over TCP, while Proxmox VE offers the console as a WebSocket on the API port, so cv4pve-vdi bridges the two:

cv4pve-vdi Proxmox VE node Guest
│ │ │
│ 1. POST …/vncproxy (websocket=1) │ │
├──────────────────────────────────►│ │
│ 2. VNC ticket + port │ │
│◄──────────────────────────────────┤ │
│ 3. WebSocket on the API port, │ │
│ with the session cookie │ 4. relays to the guest's │
├══════════════════════════════════►│ VNC server │
│ ├─────────────────────────►│
remote-viewer ──TCP──► 127.0.0.1:<random port> ══ bridge in cv4pve-vdi ══ WebSocket ══► node:8006
  1. cv4pve-vdi asks the API for a VNC ticket for the guest.
  2. It opens the WebSocket to the node on the API port, authenticated with the login session.
  3. It listens on 127.0.0.1 on a random port and writes a .vv file pointing remote-viewer there, with the ticket as VNC password.
  4. When remote-viewer exits, the bridge is closed.

So the VNC console works through the same firewall rule as the API, and the bridge accepts connections only from the local computer.

Services start a local program (mstsc, xfreerdp, PuTTY, ssh) against the guest’s IP address, read from the QEMU guest agent or set per service. That connection goes straight from the client to the guest, not through Proxmox VE: the guest’s network must be reachable from the users’ computers, like with any RDP or SSH client.

At start-up and then every 12 hours cv4pve-vdi asks the GitHub API for the list of cv4pve-vdi releases. When a newer one exists, a red dot appears on the ⋮ menu with a link to the release. Nothing about the user or the cluster is sent.