diff --git a/internal/api/virt.go b/internal/api/virt.go
index cc90c31..0d0dc1b 100644
--- a/internal/api/virt.go
+++ b/internal/api/virt.go
@@ -527,7 +527,8 @@ func (s *Server) virtVGA(w http.ResponseWriter, r *http.Request) {
jsonErr(w, 400, "bad name")
return
}
- conn, err := websocket.Accept(w, r, &websocket.AcceptOptions{CompressionMode: websocket.CompressionDisabled})
+ // spice-html5 asks for the "binary" subprotocol and gives up unless the server agrees to it
+ conn, err := websocket.Accept(w, r, &websocket.AcceptOptions{CompressionMode: websocket.CompressionDisabled, Subprotocols: []string{"binary"}})
if err != nil {
return
}
diff --git a/web/src/Virtualization.tsx b/web/src/Virtualization.tsx
index 234dcdb..11ca41c 100644
--- a/web/src/Virtualization.tsx
+++ b/web/src/Virtualization.tsx
@@ -244,9 +244,9 @@ function Detail({ i, st, onBack, onChanged, onTask }: { i: VirtInstance; st: Vir
{i.name}{kind(i)}{i.status.toLowerCase()}
-
Image{i.image || '—'}{i.arch ? · {i.arch} : ''}
+
Image{i.image || (Object.keys(i.devices).some((d) => d.startsWith('iso')) ? 'none — installed from an ISO' : 'none')}{i.arch ? · {i.arch} : ''}
{i.description &&
About{i.description}
}
- {running &&
Using{i.cpu_pct.toFixed(0)}% of a core · {fmtBytes(i.mem_usage)}{i.mem_peak ? ` (peak ${fmtBytes(i.mem_peak)})` : ''}{i.processes ? ` · ${i.processes} processes` : ''}
}
+ {running &&
Using{i.cpu_pct.toFixed(0)}% of a core · {fmtBytes(i.mem_usage)}{i.mem_peak ? ` (peak ${fmtBytes(i.mem_peak)})` : ''}{i.processes > 0 ? ` · ${i.processes} processes` : ''}
}
Limits{i.cpu ? `${i.cpu} CPU` : 'all CPUs'} · {i.memory || 'unlimited memory'}
{i.disk_total > 0 &&
Disk{fmtBytes(i.disk_usage)} of {fmtBytes(i.disk_total)}
}
Network{i.ipv4.length ? i.ipv4.join(' ') : running ? 'no address yet' : '—'}
diff --git a/web/src/styles.css b/web/src/styles.css
index 756edd8..846d82f 100644
--- a/web/src/styles.css
+++ b/web/src/styles.css
@@ -900,7 +900,8 @@ pre.diff .add { color: var(--ok); background: color-mix(in srgb, var(--ok) 12%,
.virt-pick .svc-row { padding: 6px 10px; }
.virt-kv { display: grid; grid-template-columns: max-content 1fr; gap: 2px 12px; font-size: 12px; word-break: break-all; }
.virt-form-row { display: flex; gap: 8px; }
-.virt-form-row > label { flex: 1; min-width: 0; }
+.virt-form-row > label { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 4px; }
+.virt-form-row > label > input, .virt-form-row > label > select { width: 100%; box-sizing: border-box; }
.virt .modal { max-width: 640px; }
.vga-back { align-items: stretch; padding: 10px; }
.vga { display: flex; flex-direction: column; gap: 6px; width: 100%; height: 100%; max-width: none; max-height: none; background: var(--bg); border: 1px solid var(--border); border-radius: 8px; padding: 8px; }