Back to all log entries

homelab · 05 September 2026

Turning a Spare Proxmox Screen into a Homelab Command Display

I turned the monitor attached to one Proxmox host into a full-screen fleet wallboard, while keeping the normal console one key away.

I had a perfectly good 1920×1080 monitor attached to one of my Proxmox hosts, and it spent most of its life displaying the standard login prompt. Useful when something goes wrong, certainly, but not exactly earning its keep the other 99.9% of the time.

It now runs a full-screen homelab command display. At a glance I can see seven systems, Proxmox cluster quorum, real memory use, storage pressure, container workloads and the state of two separate backup paths. Pressing Esc still brings back the normal login prompt, so I haven’t traded away the console to get it.

This was built with AI assistance, but the interesting part wasn’t persuading Python to draw some colourful boxes. It was deciding what the numbers actually meant, which failures should be visible, and how to keep a dashboard from becoming another fragile service that needs its own dashboard.

No desktop, browser or automatic login

The obvious way to build something like this is a web dashboard in kiosk mode. That would have meant adding a graphical desktop, browser, automatic login and probably another local web service to a Proxmox host. It would work, but it felt like a lot of machinery just to make use of a directly attached screen.

Instead, the wallboard is a Python program using Pillow to render a complete image and write it straight to the Linux framebuffer. A systemd service owns the first virtual console and updates the display every five seconds. There’s no web server listening for connections and no logged-in desktop session hiding behind the graphics.

The console behaviour was non-negotiable. A standalone Esc restores text mode and hands the terminal to the normal agetty login program. Logging out returns to the wallboard because systemd starts it again. The second virtual console remains an independent fallback as well, which is the sort of boring escape hatch that becomes extremely interesting when the pretty screen stops being pretty.

Making the numbers honest

My first lesson came from memory usage. Proxmox can report how much memory is allocated to a virtual machine, but that isn’t the same thing as how much memory the guest is genuinely using. A generously sized VM can look almost full even when Linux has plenty available for applications.

The guest collectors now calculate real use as MemTotal - MemAvailable from inside Linux. Physical Proxmox nodes are labelled Host Memory , fresh guest readings are labelled Real Memory , and an allocation fallback is explicitly called VM Allocated . The distinction sounds fussy until a supposedly 97% full machine turns out to be using roughly a third of its memory.

The larger guests are read through the Proxmox QEMU Guest Agent. Small physical systems use a dedicated SSH key that is restricted to one forced telemetry command: it can’t open a shell, forward ports or choose another program. A monitoring convenience shouldn’t quietly become a general-purpose route around the network.

One screen, several kinds of truth

The top strip shows the Proxmox cluster state, including both nodes and the QDevice vote. The display says Nominal only when the cluster is quorate and the expected three votes are present. Beside that are compact operating-system cells, including the exact installed Debian point release and whether it matches the current stable release.

Each system card shows CPU, memory, root filesystem, uptime, load and failed systemd units. Separate workload panels summarise the important container services without trying to reproduce a full monitoring platform. The storage panel is deliberately limited to the three filesystems I care about operationally on the core services VM: home, bulk storage and application data.

The backup panel is similarly conservative. It doesn’t assume a destination is healthy merely because it answers a ping. The local recovery generation comes from its completion record, the off-site copy needs its own confirmed record, and the Proxmox Backup Server lifecycle has to end successfully. Each schedule has a grace period long enough for its normal cadence, then turns into an overdue warning if a run is missed.

The refresh bug I could see but couldn’t measure

The strangest problem appeared after the dashboard looked finished. File captures of the framebuffer changed every five seconds, yet the clock on the physical monitor stayed several minutes behind. The program was updating memory; the screen simply wasn’t being told that anything had changed.

The culprit was the memory-mapped framebuffer path on the Intel graphics stack. Replacing those assignments with ordinary framebuffer write(2) calls caused the driver to receive the display-damage notification it needed. The physical clock immediately began moving again. It was a good reminder that checking the bytes behind a display isn’t quite the same as checking the display.

There’s now also a public-preview switch. It uses the same live render path but replaces private network addresses and the recovery-directory name, which is how the screenshots in this post were made. That feels much safer than trying to remember which operational detail needs blurring each time.

What I’d keep from the build

The LCARS-inspired colour and layout make the screen fun, but the useful decisions are underneath it:

label the source and meaning of each metric;

derive backup health from durable evidence rather than reachability;

give restricted collectors only the one command they need;

keep a real console available without automatic login; and

verify what appears on the physical panel, not just what a framebuffer capture claims is there.

The monitor is finally doing something worthwhile, and the login prompt is still waiting one key away. That’s a much better use of a screen than watching it advertise the hostname all day.

Kirk out.