console.vv Extensions and Interpretations¶
The standard virt-viewer connection file format (the .vv
file produced by virt-manager, oVirt, OpenStack, Kerbside,
and other SPICE deployment tools) has no formal extension
registry. Producers add custom keys ad-hoc, and consumers
either honour or ignore them. This document tracks the keys
that ryll (the SPICE client at https://github.com/shakenfist/ryll)
either:
- Reads with stronger or more specific semantics than the standard implies, or
- Defines as new extension keys for SPICE deployments that want to opt in to ryll-specific behaviour.
Producers (Kerbside, oVirt, OpenStack drivers, custom gateway implementations) can use this doc to populate their console.vv output for the best ryll experience. Other SPICE clients (remote-viewer, GNOME Boxes) ignore the extension keys and function as before — extensions degrade gracefully.
Standard format reference¶
The base console.vv format is documented in spice-gtk's
virt-viewer-file.c and (less authoritatively) the
virt-viewer manual. A minimal
file looks like:
[virt-viewer]
type=spice
host=spice.example.com
port=5900
password=ticket-string-goes-here
delete-this-file=1
ryll currently parses a subset: host, port, tls-port,
password, ca, host-subject. (Wider parity with the
standard format — title, fullscreen, disable-channels,
etc. — is tracked as a separate ryll work item; the keys
documented here are independent of that gap.)
ryll's interpretation of standard keys¶
delete-this-file=1 → single-use ticket¶
The standard meaning of delete-this-file=1 is "the consumer
should remove this file after reading it, because the
contents are sensitive". The spec is silent on whether the
ticket inside the file is single-use. Empirically, every
producer that emits one-shot tickets (Kerbside, oVirt) sets
delete-this-file=1, because a deleted file would be
useless for reuse anyway.
ryll treats delete-this-file=1 as a signal that the
ticket is single-use and therefore:
- Disables automatic reconnect on disconnect.
- On disconnect, shows an explanatory modal ("Session ended — cannot reconnect; this connection used a single-use ticket") rather than the generic "Connection lost; click Reconnect" modal.
- Skips the doomed retry ratchet that would otherwise produce a stream of failed link-establishment attempts and associated bug-report zips.
If a future producer wants the file deleted but the ticket reusable, this interpretation will surprise it. We have not encountered that case in the wild and consider it a deployment contradiction. If it ever arises, an explicit override key can be added; we are not speculatively defining one.
delete-this-file=0 or absent → reusable / permanent¶
ryll allows automatic reconnect against the same password
ticket. Suitable for development setups, local QEMU
instances, libvirt VMs reached over a stable host:port pair,
and any deployment where re-linking with the same credential
is expected to succeed.
ryll-defined extensions¶
ticket-valid-until=<unix-ts>¶
Status: defined by ryll, not in the standard format.
Format: integer Unix timestamp (seconds since epoch, UTC).
Example:
[virt-viewer]
host=spice.example.com
port=5900
password=ticket-string
delete-this-file=1
ticket-valid-until=1730500000
Semantics: the time after which the SPICE server will reject this ticket regardless of any other consideration (single-use status, whether it has been used before, etc.). Producers that issue tickets with explicit lifetimes (typically all gateway-style deployments) should set this.
ryll behaviour when set:
- The bottom status bar shows a countdown ("Session ends in 04:32") so the user knows when to expect disconnect.
- 30 seconds before expiry, ryll pushes a notification ("Session ticket expires in 30 seconds") so the user has time to save their work or request a new connection.
- If the ticket is not single-use (
delete-this-filenot set or=0), ryll still respects the expiry: auto-reconnect attempts skip if the deadline is in the past. - On disconnect after expiry, ryll shows a "Session ended — ticket expired" modal with the exact expiry time, instead of the generic disconnect modal.
ryll behaviour when absent: no behaviour change. The absence is the default and matches today's console.vv producers.
Edge case — clock skew: if the server appears to have
disconnected the session before ticket-valid-until (per
the client's local clock), ryll still renders the
expired-ticket modal (the server's view is authoritative)
and logs a warning about possible clock skew.
How to support these in your producer¶
Kerbside¶
Kerbside issues short-lifetime, single-use tickets. The recommended console.vv shape:
[virt-viewer]
type=spice
host={{ gateway_host }}
port={{ gateway_port }}
password={{ ticket }}
delete-this-file=1
ticket-valid-until={{ ticket_issued_unix + ticket_lifetime_secs }}
The ticket_lifetime_secs value should match the actual
server-side validity window — the SPICE server invalidates
expired tickets at reds.cpp ticket-validation, so a
producer-side value that doesn't match the server-side
lifetime will produce surprising behaviour (UI says "valid
until 14:30" but server rejects at 14:25).
oVirt¶
oVirt issues per-VM-console tickets via the engine API. The
existing console.vv emitted by oVirt sets delete-this-file=1
already, which ryll interprets correctly. Adding
ticket-valid-until requires a small enhancement to the
engine's console-file generation:
# pseudocode — oVirt-engine equivalent
ticket = api.vms_service().vm_service(vm_id).ticket(...)
vv_content = render_vv_template(
ticket_value=ticket.value,
ticket_expiry_unix=int((ticket.expiry).timestamp()),
)
OpenStack (nova-novncproxy / spice-html5 path)¶
OpenStack typically uses the noVNC / spice-html5 web
transcoder, which doesn't go through console.vv at all. If
your deployment also offers a native-viewer download (some
do, via novaclient get-spice-console), populate the same
two keys.
Custom / homebrew gateways¶
The minimum to enable the ryll-specific UX is:
- Set
delete-this-file=1if the ticket is single-use. - Set
ticket-valid-untilto the unix timestamp at which the server will stop accepting the ticket.
Both keys are independent. A reusable ticket with an expiry
sets only ticket-valid-until. A single-use ticket without
a known expiry sets only delete-this-file=1.
Future extensions under consideration¶
These are not implemented yet — they are placeholders to be discussed before any client-side work begins. PRs / issues welcome.
ticket-renewable=1plus aticket-renew-url=<https-url>: a client could request a fresh ticket from the named URL before expiry, allowing seamless long-running sessions without forcing the user back to the issuing portal. The obvious downside is the security model — the renew URL has to be authenticated by something other than the existing ticket, since the existing ticket is single-use.monitors=N: hint to the client about expected monitor count. Today ryll takes this as a CLI flag (--monitors N). Lifting to console.vv lets the deployment pre-configure multi-monitor setups based on what the guest can actually drive.bug-report-url=<https-url>: where ryll should POST bug-report zips for support cases, instead of leaving them on disk. Useful for managed-service deployments where users can't easily extract local files.
If you need a key not on this list, open an issue at https://github.com/shakenfist/ryll referencing this doc so the discussion lands somewhere lasting.