diff --git a/src/server/vms/vms.go b/src/server/vms/vms.go
index 72a0cbb92507472cebde7b3fc75753b57d1a31c7..8ddf6c8750eea3d27755d751e1d6f900490498a1 100644
--- a/src/server/vms/vms.go
+++ b/src/server/vms/vms.go
@@ -29,7 +29,7 @@ type (
         m map[string]*VM
         dir string             // Base directory where VMs are stored
         rwlock *sync.RWMutex   // RWlock to ensure the VMs' map (m) coherency
-        usedPorts [65536]bool  // Ports used by VMs
+        usedPorts [65536]bool  // Ports used by VMs for spice
         usedRAM int            // RAM used by running VMs (in MB)
     }
 )
@@ -51,6 +51,9 @@ func GetVMsInstance() *VMs {
 func InitVMs() error {
     vmsDir := conf.VMsDir
     vms = &VMs { m: make(map[string]*VM), dir: vmsDir, rwlock: new(sync.RWMutex), usedRAM: 0 }
+    for i, _ := range vms.usedPorts {
+        vms.usedPorts[i] = false
+    }
     vms.usedPorts[conf.Core.APIDefaultPort] = true
 
     errMsg := "Failed reading VMs directory: "
@@ -324,19 +327,40 @@ func (vms *VMs)StartVMWithCreds(vmID uuid.UUID, port int, checkPort bool, pwd st
     return nil
 }
 
-// Allocates and returns a free port randomly chosen within [VMSpiceMinPort,VMSpiceMaxPort].
+// Allocates and returns a free port, randomly chosen between [VMSpiceMinPort,VMSpiceMaxPort].
+// When the number of free port becomes very small,
+// randomly picking a port is very time consuming (many attempts).
+// TODO: A better approach would be to do this instead:
+// If there are more than 20% of free ports: pick one randomly in the range.
+// Otherwise: pick the first available one either from the beginning or the end (randomly).
 // REMARK: this function updates the vms map.
 // Concurrency: safe
-func (vms *VMs)allocateFreeRandomPort() int {
+func (vms *VMs)allocateFreeRandomPort() (int, error) {
     vms.rwlock.Lock()
     defer vms.rwlock.Unlock()
 
+    minPort := conf.Core.VMSpiceMinPort
+    maxPort := conf.Core.VMSpiceMaxPort
+
+    isFreePortLeft := func() bool {
+        for i := 0; i < maxPort-minPort+1; i++ {
+            port := minPort+i
+            if !vms.usedPorts[port] && utils.IsPortAvailable(port) {
+                return true
+            }
+        }
+        return false
+    }
+
     for {
-        port := utils.Rand(conf.Core.VMSpiceMinPort, conf.Core.VMSpiceMaxPort)
+        if !isFreePortLeft() {
+            return -1, errors.New("No free port left")
+        }
+        port := utils.Rand(minPort, maxPort)
         if !vms.usedPorts[port] {
             if utils.IsPortAvailable(port) {
                 vms.usedPorts[port] = true
-                return port
+                return port, nil
             }
         }
     }
@@ -346,13 +370,18 @@ func (vms *VMs)allocateFreeRandomPort() int {
 // Returns the port on which the VM is running and the access password.
 // Concurrency: safe
 func (vms *VMs)StartVM(vmID uuid.UUID) (int, string, error) {
-    port := vms.allocateFreeRandomPort()
+    port, err := vms.allocateFreeRandomPort()
+    if err != nil {
+        msg := "Failed starting VM "+vmID.String()+": "+err.Error()
+        log.Error(msg)
+        return -1, "", errors.New(msg)
+    }
 
     // Randomly generates a 8 characters long password with 4 digits, 0 symbols,
     // allowing upper and lower case letters, disallowing repeat characters.
     pwd, err := passwordGen.Generate(conf.VMPwdLength, conf.VMPwdDigitCount, conf.VMPwdSymbolCount, false, conf.VMPwdRepeatChars)
     if err != nil {
-        msg := "Failed starting VM: password generation error: "+err.Error()
+        msg := "Failed starting VM "+vmID.String()+": password generation error: "+err.Error()
         log.Error(msg)
         return -1, "", errors.New(msg)
     }