How to show the odio UI on a screen wired to your node
The embedded web UI is meant to be opened from another machine. It can also be shown on a screen wired to the node itself, a small panel on a Raspberry Pi for instance, without installing a desktop.
A framebuffer browser draws straight onto /dev/fb0, so there is no X server, no Wayland compositor and no window manager in the picture. It is not free, though: the engine is still Chromium and it brings the Qt stack with it. The odio-kiosk binary itself weighs a few tens of kB (39 kB on amd64, 68 kB on arm64), the rest is QtWebEngine. What you save is the display server and the session around it, not the browser. The debian-fr thread this approach comes from counted about 30 packages and 185 MB of Qt once installed.
Credit where it is due: that thread worked through the alternatives first (Links2 has no framebuffer driver left, NetSurf renders SVG poorly, Dillo wants X11) before landing on a Qt kiosk build of Framebuffer-browser. odio’s browser, odio-kiosk, started from it.
Enable it
Section titled “Enable it”The screen is an optional odios component. It needs amd64 or arm64: Raspberry Pi OS armhf ships no QtWebEngine, so the installer does not offer it on a 32-bit system.
- at install, answer yes to
Install display (odio-kiosk)?, or setINSTALL_DISPLAY=Yfor a non-interactive install - on an existing node, enable the display row under System on the settings page, then apply an upgrade
The component installs the odio-kiosk package from apt.odio.love, adds the odio user to the tty and video groups and enables the odio-kiosk@odio.service user unit. That unit waits for odio-api to serve its UI, then opens http://localhost:8018/ui full screen, and restarts along with odio-api. The URL comes from ~/.config/odio-kiosk/odio.conf, and the tie to odio-api from a drop-in the installer writes next to the unit.
The screen is drawn on /dev/fb0. A panel that shows up as another framebuffer is selected with FB=/dev/fb1 in odio.conf. The Qt settings shared by every screen on the node are in /etc/default/odio-kiosk, which the package preserves on upgrade.
A node that ran the b2 screen is migrated by the upgrade: fbrowser-kiosk is replaced by odio-kiosk, and the old odio-screen.service and its config are removed.
The screen is then listed in the Services panel of the embedded UI, where it can be restarted like any other service.
A plain display, with no touch panel and no keyboard, is a perfectly good target. The UI holds an SSE connection to /ui/events and swaps its own sections as the node’s state changes, so a screen nobody touches still shows what is playing, the volume, and the state of every service.
Hide the console cursor
Section titled “Hide the console cursor”On a screen that never shows anything else, the console cursor is better hidden: add vt.global_cursor_default=0 to the kernel command line, then reboot.
On a Raspberry Pi, the command line is the single line of /boot/firmware/cmdline.txt. Append the option to the end of that line, separated by a space:
sudo sed -i '1 s/$/ vt.global_cursor_default=0/' /boot/firmware/cmdline.txtThe file must stay on a single line, which then ends like this:
console=serial0,115200 console=tty1 … vt.global_cursor_default=0On an amd64 machine booting with GRUB, add the option inside the quotes of GRUB_CMDLINE_LINUX_DEFAULT in /etc/default/grub. On a default Debian install the line becomes:
GRUB_CMDLINE_LINUX_DEFAULT="quiet vt.global_cursor_default=0"then regenerate the GRUB configuration:
sudo update-grubScreen size
Section titled “Screen size”The UI lays out in one column, two from 640px wide, three from 1024px. A 7” panel at 800×480 therefore gets two columns, a 3.5” at 480×320 gets one. Both are usable; the 480px height is the tighter constraint, so expect to scroll.
Engine
Section titled “Engine”Since 2026.9.0b3, odio-kiosk is built on Qt 6, which embeds Chromium 122. The b2 screen ran QtWebEngine 5.15 and Chromium 87, on which a single unknown pseudo-class such as :where() silently dropped a whole CSS rule. odio-api v0.17.2 works around those gaps in the embedded UI. On Chromium 122 they are gone, and the sliders take the gold accent through accent-color.