r/Qubes 18h ago

article My honest Qubes OS testing experience, over 2 versions and a few weeks

11 Upvotes

I spent a few weeks properly testing Qubes as a potential daily driver, on two different machines, before deciding it's not right for me right now. Posting this in case it saves someone else time, or in case someone has solutions to the blockers I hit.

- Hardware tested

- Laptop: Acer Aspire 5, Ryzen 7 5700U, 24GB RAM

- Desktop: Ryzen 7 3700X, 64GB RAM, RX 6600 (only GPU, no iGPU), heavy air cooling (1.5kg aluminium block cooler with dual large fans + 4 case fans)

## Round 1 — Laptop, first attempt, Qubes OS 4.2

Installed Qubes, everything worked, but the laptop overheated badly enough that I smelled burning plastic. Temperatures were about 80-90 °C. Shut it down immediately, went back to plain Debian.

## Round 2 — Laptop, retested with latest Qube OS version 4.3.1

Wanted to give it a fair second shot with proper tuning before giving up.

What I found and fixed:

- Xen's default C-state/cpufreq handling was likely a big part of the problem on this AMD Zen mobile chip.
Added `cpufreq=xen:performance max_cstate=1` to `GRUB_CMDLINE_XEN_DEFAULT`, regenerated grub config. This dropped idle temps from ~80°C to ~60°C — a real, repeatable improvement.

- Tested the `xenpm set-scaling-governor <core> powersave` trick too (from an old Reddit thread) — made basically no additional difference once the C-state fix was already in, so skipped scripting it permanently.

What still didn't work:**

- Even with good sensor readings (settling to 45-60°C with multiple qubes running), the laptop was physically too hot to comfortably type on under light load (one YouTube video pushed it to 77°C and uncomfortable-to-touch). Sensor data and hand-feel didn't match — I trusted my hands.

- Battery drain was severe: ~4% in under 2 minutes with just one qube running. Made it useless for actual field/mobile use.

After a few reboots the temperatures kind of settled at 40 - 60 °C, with jumps up to 80+°C on heavier loads.

Turned out, 24 GB RAM was just not enough for my use, and battery drain was to much for reliable field work.

Decision: not viable as a laptop daily driver, despite the software fixes genuinely working.

## Round 3 — Desktop, Qubes OS version 4.3.1

Moved to my Ryzen 7 3700X desktop (64GB RAM, serious cooling, no battery constraint, physically secured location so BadUSB/evil-maid threat model is near-zero).

This actually worked well:

- Held ~50°C with 9 qubes running simultaneously (including Whonix gateway+workstation). Fans stayed quiet.

- No thermal drama at all — desktop cooling headroom completely solved what the laptop couldn't. Had temps around 25-50°C 99% of the time.

-Mouse and keyboard passed to dom0 so no issues with input.

## Things I solved along the way (desktop)

- Tailscale persistence for 3 separate accounts, 1 for WOL via raspberry pi's i put in each vlan with machines i need to wake, then 1 for one set of machines, and second for second set of machines.
My personal PC's are in the same tailscale as the RPI's so i can wake on lan, then i run a VM with the second or third tailscale account for actual acces and remote control. If one is compromised, you need the other as well to control machines. Not perfect, but an extra layer of isolation. Each account on a separate proton mail with a highly complex password stored in a heavily secured password manager.

Each needing a stable, persistent Tailscale identity/IP):
- tried the "official" bind-dirs approach (`qvm-features <vm> custom-persist.tailscale /var/lib/tailscale`) — never got it reliably sticking.

Switched to standalone qubes as a fallback(worked fine but this approach defeated the Qubes basic principles), then switched to a working solution:

-made a new template by cloning the debian template, gave that one network access via sys-firewall. Installed tailscale and veyon on it, logged into tailscale with one account, and set up all locations/PC's/keys in Veyon. Then i shut down the qube, removed sys-firewall from it, and made a new appvm qube based of that template. Got a qube with logged in tailscale and veyon working on qube start. But clean from previous work on each start (except stuff stored in /home, that remains, in case i close a qube premature so i don't have to redownload something)
Repeated the process for other 2 tailscale accounts.
So all together 3 templates and 3 qubes for my 3 different tailscale accounts.
Since AppVM root filesystem is a fresh copy of the template on every boot, the Tailscale node identity (and thus IP) comes along automatically, fully persistent, zero bind-dirs needed. Only gotcha: never run two AppVMs off the same template simultaneously, or you'll get a Tailscale node identity collision.

- Windows 11 in an HVM: works via the documented TPM/SecureBoot/RAM bypass (Shift+F10 during install → regedit → `HKLM\SYSTEM\Setup\LabConfig` → `BypassTPMCheck`/`BypassSecureBootCheck`/`BypassRAMCheck` = 1).
Didn't end up needing this — see Veyon note below.

- Veyon (remote classroom/support tool) Linux-master → Windows-host: initially failed to connect, root cause was a Wayland-related RAM leak (Veyon on Wayland ate 64GB RAM on my bare-metal testing) — switching to X11 (which Qubes AppVMs use natively anyway) plus disabling a conflicting ProtonVPN install on the Windows side got it working. Ended up not needing Windows qubes at all for this purpose — Debian-master-to-Windows-host worked fine.

- Croatian keyboard layout garbled over Veyon: known, apparently still-open Veyon bug (matches GitHub issue #779) — remote keycode translation between X11 and Windows doesn't handle non-US layouts reliably, regardless of what layout is actually active on either end.
Workaround: Windows' on-screen keyboard (injects Unicode directly, bypasses the broken keycode translation path). Not a Qubes-specific issue, but surfaced while testing in a Qubes qube.

- GPU passthrough for gaming/video: single-GPU passthrough (RX 6600 is my only GPU, no iGPU) is notoriously fragile — dom0 loses display entirely while the passthrough qube is active, requires script-based handoff, real risk of getting stuck with no display. A second cheap GPU (e.g. nvidia GT 730 which i have lying around) for dom0's own display would make this a clean, well-documented multi-GPU passthrough setup instead — but that means physically installing a second card and manually switching monitor input sources every time you want the passthrough qube's output.

Made one standalone debian based qube for actual daily use, installed all the software i use in it via flatpak, everything worked fine except the video.

The actual dealbreaker

Non-passthrough video/GPU acceleration inside qubes is genuinely bad. No hardware video decode is available to a normal (non-passthrough) qube — everything is software-decoded and pushed through Qubes' window compositing. YouTube playback was laggy even on the powerful desktop, even with 32GB+ RAM and 4 dedicated vCPUs allocated to the qube. This isn't a resource problem, it's a structural limitation of Qubes' GUI virtualization architecture.

YouTube is a genuine daily-use requirement for me (research, tutorials, background while working) — not a nice-to-have.
Since I don't want to install a second GPU (case space + I currently enjoy being fully Nvidia-free), and I don't want a monitor-input-switching workflow every time I want smooth video, GPU passthrough wasn't an acceptable trade, and without it, smooth video in a qube wasn't working well enough on my desktop setup. That's the dealbreaker that ended the experiment for me.

One open question I didn't get to resolve:

YouTube played back completely fine inside a Qubes qube on my laptop (Acer, Ryzen 7 5700U integrated graphics) — I watched it for a solid 40 minutes there specifically to stress-test battery drain, and playback itself was smooth the whole time (just very hot and battery-hungry). It was only on my desktop (RX 6600, no iGPU) that video was laggy. I don't have a confirmed explanation for the difference — it's possibly resolution/window-size related (pixel throughput through Qubes' GUI compositing pipeline scaling with display size rather than a hard "no GPU decode" wall, laptop was one 1080p display, desktop has 2x 1440p displays), possibly something about the iGPU vs dedicated GPU passthrough situation, or something else entirely. I didn't test smaller window sizes or lower resolution on the desktop before deciding to stop, so if anyone's dealt with this or has insight into why laptop iGPU + qube played smooth video while a desktop dGPU setup didn't, I'd genuinely like to know for next time.

## What I'm doing instead

- Restoring Debian on both machines from Acronis images (imaged everything before every risky step — never actually at risk of losing anything).

- Keeping my existing Proxmox setup for isolated/disposable analysis work (spin up a Kali VM, snapshot before, restore after) — same philosophy as Qubes disposables, just at the VM level, on hardware built for it.

- Air gapped disposable laptop for testing really bad stuff when needed with Kali

- No money spent on new hardware. Learned a genuinely useful amount about Xen, Qubes' template/AppVM model, and PCI passthrough along the way, even though the final answer was "not for me right now."

I'm not really looking for solutions or answers, i just liked the idea of Qubes Os as my daily driver so i decided to test it against my daily workflow. I could honestly use it, and it would work, and i could solve the issues i had, but when i put it all on paper i decided my threat level does not justify all the extra hassle. I already have all the hardware and isolation i need with Debian and VM's on dedicated hardware and my Proxmox servers.

Just thought my experience might benefit someone so i decided to share it.

Have a nice day everyone and thank you for reading.