SPICE & Graphics Configuration

Complete guide to SPICE protocol setup, graphics port allocation, VNC fallback, and high-resolution graphics

SPICE & Graphics Configuration

Introduction

SPICE protocol for VM remote display. XMLGenerator (backend/app/utils/VirtManager/xmlGenerator.ts) configures SPICE with auto-port allocation, random passwords, optional OpenGL. GraphicPortService retrieves assigned ports from running VMs.

SPICE Protocol

Open-source protocol by Red Hat for VDI. Server runs in QEMU, client on user machine (virt-viewer, remote-viewer, spice-html5). Optimized for VMs with video streaming and adaptive compression.

Features

  • Image compression: GLZ, JPEG, zlib (auto-selection)
  • Video streaming: Detects/compresses video regions
  • Audio: Bidirectional (Opus codec)
  • USB redirection, clipboard (bidirectional), file transfer (drag-drop)
  • Multi-monitor, OpenGL acceleration

vs VNC: SPICE has better compression, video streaming, audio, file transfer. VNC simpler, wider client support.

SPICE Configuration

addSPICE Method

File: backend/app/utils/VirtManager/xmlGenerator.ts

Parameters: enableAudio (default: true), enableOpenGL (default: true). Returns random alphanumeric password.

Password: Random alphanumeric password (configurable length, recommend 16 characters for production). Stored in MachineConfiguration.graphicPassword.

Graphics init: Clears existing graphics array (ensures SPICE or VNC, not both).

Core Config

<graphics type='spice' autoport='yes' listen='0.0.0.0' passwd='abc12345'>
  <listen type='address' address='0.0.0.0'/>
</graphics>
  • autoport: libvirt assigns port from 5900-5999
  • listen: 0.0.0.0 (all interfaces) or 127.0.0.1 (local only)

Compression

<image compression='auto_glz'/>  <!-- GLZ for UI/text -->
<jpeg compression='auto'/>       <!-- JPEG for photos -->
<zlib compression='auto'/>       <!-- zlib for general data -->

Auto mode adapts to network conditions.

Features

<streaming mode='filter'/>        <!-- Auto-detect video regions -->
<clipboard copypaste='yes'/>      <!-- Bidirectional clipboard -->
<filetransfer enable='yes'/>      <!-- Drag-drop files -->
<mouse mode='server'/>            <!-- Server-side cursor (better with GPU) -->

All require SPICE agent in guest.

OpenGL Acceleration

<gl enable='yes' rendernode='/dev/dri/renderD128'/>

Requires host GPU, accessible render node, guest drivers. Provides hardware-accelerated 3D. Path hardcoded (TODO: dynamic detection).

Audio

<channel type='spicevmc'>
  <target type='virtio' name='com.redhat.spice.0'/>
  <address type='virtio-serial' controller='0' bus='0' port='3'/>
</channel>

Bidirectional audio (Opus codec). Requires SPICE agent, audio device in guest, PulseAudio/PipeWire on host.

Auto-Port Allocation

Libvirt assigns port from 5900-5999 range. GraphicPortService retrieves port from domain XML after VM starts. Configurable via /etc/libvirt/qemu.conf (increase range for >100 VMs).

GraphicPortService

File: backend/app/utils/VirtManager/graphicPortService.ts

Opens libvirt connection, retrieves port from domain XML. Methods: getGraphicPort(domainName, type) → looks up domain → gets XML → parses for graphics port.

VNC Fallback

addVNC (xmlGenerator.ts): Similar to SPICE but simpler (no compression/features). Updates existing VNC or creates new. Returns random alphanumeric password.

Use VNC: Wider client support, simpler, lower overhead. SPICE has more features (audio, file transfer, better compression).

High-Resolution Graphics

enableHighResolutionGraphics (xmlGenerator.ts): Configures video device with VRAM size and driver.

QXL (default): SPICE-optimized, flexible VRAM (ram/vram/vgamem), 2D/3D accel. Best for SPICE.

VirtIO: Experimental, OpenGL passthrough. "Works, but performance is not the best."

VRAM sizing: 512MB for 1080p, 1024MB for 4K, 2048MB for multi-4K.

Storage

Updates MachineConfiguration: graphicProtocol='spice', graphicPassword from addSPICE(), graphicHost from APP_HOST env, graphicPort=-1 (updated after VM starts via GraphicPortService).

Cron job UpdateGraphicsInformation periodically updates ports for running VMs.

Client Connection

Clients: virt-viewer, remote-viewer, GNOME Boxes, virt-manager, spice-html5 (browser).

Connection: remote-viewer spice://HOST:PORT?password=PASSWORD

Security: Password auth required. Enable TLS for production. Restrict port range (5900-5999) with firewall.

Troubleshooting

Port not assigned: Check VM running (virsh list), verify autoport in XML, check libvirt logs.

Cannot connect: Verify port open (netstat), firewall, password, SPICE agent, network (telnet).

Poor performance: Adjust compression, increase VRAM, check QXL driver, test bandwidth.

Audio issues: Check SPICE agent, audio device, client settings, PulseAudio on host.

Clipboard/file transfer: Install SPICE agent (spice-vdagent), restart agent, verify filetransfer enabled.

Environment Variables

Variable Description Default
APP_HOST Graphics host address for client connections '0.0.0.0'
INFINIBAY_BASE_DIR Base directory for UEFI NVRAM, sockets '/opt/infinibay'

Mermaid Diagrams

SPICE Configuration Flow

sequenceDiagram
    participant XMLGenerator
    participant CreateMachineService
    participant Database
    participant Libvirt
    participant CronJob
    participant GraphicPortService

    XMLGenerator->>XMLGenerator: addSPICE(enableAudio, enableOpenGL)
    XMLGenerator->>XMLGenerator: Generate random alphanumeric password
    XMLGenerator->>XMLGenerator: Clear existing graphics array
    XMLGenerator->>XMLGenerator: Create SPICE config object
    XMLGenerator->>XMLGenerator: Set basic attributes (type, autoport, listen, passwd)
    XMLGenerator->>XMLGenerator: Add listen element (address: 0.0.0.0)
    XMLGenerator->>XMLGenerator: Add compression (image, jpeg, zlib)
    XMLGenerator->>XMLGenerator: Add features (video, clipboard, filetransfer, mouse, streaming)
    alt enableOpenGL == true
        XMLGenerator->>XMLGenerator: Add gl element (enable: yes, rendernode)
    end
    alt enableAudio == true
        XMLGenerator->>XMLGenerator: Add SPICE audio channel (type: spicevmc)
    end
    XMLGenerator->>XMLGenerator: Push SPICE config to graphics array
    XMLGenerator->>CreateMachineService: Return password
    CreateMachineService->>Database: Update MachineConfiguration<br/>(graphicProtocol: spice, graphicPassword, graphicPort: -1)
    CreateMachineService->>Libvirt: Define and start VM
    Libvirt->>Libvirt: Assign port automatically (autoport=yes)
    Libvirt->>Libvirt: Update domain XML with assigned port
    CronJob->>GraphicPortService: getGraphicPort(domainName, 'spice')
    GraphicPortService->>Libvirt: Lookup domain by name
    GraphicPortService->>Libvirt: Get domain XML
    GraphicPortService->>GraphicPortService: Parse XML, extract port
    GraphicPortService->>CronJob: Return port number
    CronJob->>Database: Update MachineConfiguration.graphicPort

Port Allocation Process

flowchart TD
    Start([VM Definition with autoport=yes]) --> CheckRange[Libvirt: Check port range<br/>5900-5999]
    CheckRange --> FindPort[Find first available port]
    FindPort --> CheckInUse{Port in use?}
    CheckInUse -->|Yes| TryNext[Try next port<br/>5900 → 5901 → 5902...]
    TryNext --> CheckInUse
    CheckInUse -->|No| AssignPort[Assign port to VM]
    AssignPort --> UpdateXML[Update domain XML<br/>with assigned port]
    UpdateXML --> StartVM[Start VM with<br/>assigned port]
    StartVM --> ListenPort[SPICE server<br/>listens on port]
    ListenPort --> QueryXML[GraphicPortService:<br/>Query domain XML]
    QueryXML --> ExtractPort[Extract port from<br/>graphics element]
    ExtractPort --> ReturnPort[Return port to<br/>application]
    ReturnPort --> UpdateDB[Update database<br/>with port]
    UpdateDB --> ClientConnect[Client connects<br/>to host:port]
    ClientConnect --> End([End])

SPICE Feature Stack

graph TD
    SPICE[SPICE Protocol]
    SPICE --> Compression[Compression Layer]
    Compression --> GLZ[Image Compression<br/>GLZ]
    Compression --> JPEG[JPEG Compression]
    Compression --> Zlib[Zlib Compression]

    SPICE --> Features[Feature Layer]
    Features --> Video[Video Streaming]
    Features --> Clipboard[Clipboard Sharing]
    Features --> FileTransfer[File Transfer]
    Features --> Audio[Audio Redirection]
    Features --> USB[USB Redirection]

    SPICE --> Graphics[Graphics Layer]
    Graphics --> QXL[QXL Driver]
    Graphics --> OpenGL[OpenGL Acceleration]
    Graphics --> HighRes[High-Res Support]

    SPICE --> Transport[Transport Layer]
    Transport --> TCP[TCP/IP]
    Transport --> TLS[TLS<br/>optional]
    Transport --> Auth[Authentication<br/>password]