This technology is called libvirt, and virt-manager you mentioned is just one of its clients.
That's normal default behaviour. Let's look at the documentation:
...
<devices>
...
<graphics type='vnc' port='5904' sharePolicy='allow-exclusive'>
<listen type='address' address='1.2.3.4'/>
</graphics>
<graphics type='rdp' autoport='yes' multiUser='yes' />
...
</devices>
...
...
vnc
Starts a VNC server. The port
attribute specifies the TCP port number (with -1 as legacy syntax indicating that it should be auto-allocated). The autoport
attribute is the new preferred syntax for indicating auto-allocation of the TCP port to use. The passwd
attribute provides a VNC password in clear text. If the passwd
attribute is set to an empty string, then VNC access is disabled. The keymap
attribute specifies the keymap to use. It is possible to set a limit on the validity of the password by giving a timestamp passwdValidTo='2010-04-09T15:51:00'
assumed to be in UTC. The connected
attribute allows control of connected client during password changes. VNC accepts keep value only since 0.9.3. NB, this may not be supported by all hypervisors.
So, if autoport
feature is used (the default with virt-manager
), when VM starts it gets assigned first available port starting with 5900: first one gets 5900, next 5901, etc. If you start them in a different order, they "swap" ports. If you bind it to some port, it will try to use that port, and if it's busy, the VM won't start.
I don't know whether t's possible to change the port using virt-manager
, but it's not the only libvirt control client available. Using virsh
you can directly edit the VM definition in XML format. On the server:
virsh list -all
virsh edit <name>
First command lists all your VMs, second one will will open a default editor (probably, vi
; you can set EDITOR
environment variable to use something else, for example try running EDITOR=nano virsh edit <name>
). After save and editor quit you need to stop and then start the VM for changes to take effect; the restart is not sufficient as it doesn't restart the Qemu process:
virsh shutdown <name>
virsh start <name>
(or from virt-manager GUI).
It should bind on the specified port only. Also it's possible to make it listen to the unix domain socket; read the linked libvirt documentation page further to learn, how. This will have the benefit of using the file name so to guarantee there will be nothing occupying the binding space for the VNC server. I never tried it myself (didn't use libvirt for 10+ years) and I don't know if virt-manager is able to connect to a socket.