Does anyone use kuhbs on a regular basis?

I already have a lot of scripts that configure and set up my new DispVMs. I’d already thought about automating the whole process and making it more professional. But it wasn’t a big enough pain in the ass yet.
That’s where kuhbs comes in handy. I don’t have to reinvent the wheel.

Which project are you using?
Is it ready for production?

Personally, I just use Ansible but I’d be interested to hear people’s experiences with kuhbs.

2 Likes

Does anyone use kuhbs on a regular basis?

Yeah, me xD I’m the author though :stuck_out_tongue:

“kuhbs 2” isn’t ready yet, but its pretty close by now. I’m at the point where I’m running audits on the code and alike. Its pretty much usable at this point. All the features I want are implemented. Whats missing is the documentation / new website / lots of example kuhb’s and so on - I will do this valve style and say “its ready when its ready”. The goal is for endusers to do a curl | bash essentially and then just use the gui to click “install browser, install thunderbird, install signal” and so on. It can do that now, but I might still find things to fix.

It VERY much is worth the wait. There is no tool for Qubes that even closely compares to the level of abstraction and automation, let alone usability by endusers.

PS: kuhbs 1 (bash version) is not supported / maintained anymore, so for anyone reading this, its not worth your time to try any of the kuhbs versions rn.

While I’m here doing marketing for myself check out Qubes-Snitch as a replacement for the classic qvm-firewall. This one is in alpha - I’d be super happy to get feedback on it.

has only been on GitHub since June 2026

Honestly thats because I’m a bit shy to release code to the Qubes community, which is vastly comprised of people much smarter / much better techies than me.. I’ve been working on kuhbs 2 for quite a while.
I’m really good at automating things / Linux administration but I am a bit shy about coding or showing it lol :wink:
Anyways, kuhbs 2 has been in the making for about a year or so.

2 Likes

I am using project “manual’. To stay fit, honestly, and as a caution not to use third party scripts blindly while having no time to audit the code myself. Maybe with the AI in the future I would try them. Thanks anyway, undeniable effort was put in this.

1 Like

manual as in man <tool> ? As in understand how tools work, and use them?

Or is there a Qubes automation tool called manual?

Or you mean you type each qvm-bla command when you want to do sth manually?

Update: ah now i get it (to stay fit was the clue lol). Well this is good if you know how to teach this yourself, and if you have the time, but lets face the facts, Qubes OS is pretty much inaccessible to endusers at this point. They need an appstore.

Without AI audits I wouldn’t touch something like kuhbs myself if I hadn’t written it myself - I’m with you 100% there. With AI audits I’m reasonably sure this is becoming reasonably safe now..

I’m actually working on sth called “repositories” where people can publish their own list of kuhbs.. Meaning their configs on “how to install tool XYZ”. In order to trust those, they have to be (at least) AI audited as well.

But then again, if we didn’t have AI, somebody would code sth like this as well.

The fact remains that Qubes needs an automation system for endusers, and this will be kuhbs, unless somebody codes something better of course. They finally need a GUI where they can say click “install browser” and thats it.

3 Likes

The latter, hahaha with the combination of my notes/hh/bash-eternal-history. So for example WHEN I want to upgrade Qubes manually I first read manual for it, then I do it step-by step, by copy/pasting a long command from my notes which step I am in, which netvm, usvbm, other vms will be used/live by using qvm-ls in parallel to get qube names and paste them instead obsolete ones, all of that in order to prevent typos, which I especially hate. Then I replace the last one used with the most recent command in my notes.

For these to be effective I am using immensely neat xfce4-terminal option to automatically put the selection to clipboard and middle mouse click to paste it.

So basically 80-90% of copy/pasting to terminal of the commands I once typed in a whole.

Why it would be hard for me to use your automation tools? Let’s say your tool offers me to install vault (WHEN it doesn’t exist for the sake of argument). But, my system is extremely minimalized and compartmentalized.. What would your system offer me as a template for it?

In my system I have minimal template which I clone for each other template, and for a vault I even further strip it down from mousepad meld pipewire pipewire-alsa pipewire-jack-audio-connection-kit pipewire-jack-audio-connection-kit-libs pipewire-libs pipewire-pulseaudio ModemManager-glib NetworkManager-libnm clamtk webrtc-audio-processing, for example.

I never connect to ethernet with wifi modules in its template installed. So I have separate minimalized templates for both sys-nets.

And things like that for each cloned template which is maximally stripped of unnecessary packages with only minimally necessary ones needed for a qube to function as desired and which I once studied years ago, so I can’t see how your tool even could help me with all of these, when extra steps are the point of creation in my routine.

Now I see that you edited your response meanwhile, but I hope my time to type this wasn’t wasted and is still related to your initial question “to stay fit” in my case means I know what I want and where to find the command for that, because it’s impossible to remember them other wise.

But for the majority of users, default setups are still incomparably better then what they used in other OS and your tool is of a great help to them, WHEN they trust your code.

1 Like

Developers or half way tech savy people will write kuhb definitions. A kuhb is a logical combination of configuration, bash scripts for setups / hooks during creation and so on. Here are some examples:

Simplest one: my-kuhbs/airgap at main · kuhbs/my-kuhbs · GitHub ← doesnt do much but install an apt package or two, and has no netvm

Bit more complex one: my-kuhbs/kuhbs-net-gateway at main · kuhbs/my-kuhbs · GitHub ← installs dnscrypt-proxy, wireguard and apt-cacher-ng

And so on. It should be reasonably easy to get how this works from clicking aorund, but I will publish on the website how it works exactly once its ready to be used.

Long story short - the idea behind building a kuhb is to not have to do much more than create a kuhb.yml and a file where you copy paste the bash commands you need to install your app in. That should do for most cases.
kuhb’s will support firewall rules for qubes-snitch too (or already do, kinda), and I’m eyeballing the switch to kicksecure atm as my fav default template (but this all works with fedora too for example). Right now I’m starting new templates with debian-13-minimal.

I have to really hold back not to textwall you here randomly :wink: There is a lot of info on this project. I have to wait here and put it all in the documentation on kuhbs.com later on. I’ll revamp the whole website, the current one is for kuhbs 1 (bash) (deprecated).

xfce4-terminal

hehe plus one, also my fav terminal. kuhbs makes heavy use of that :wink: Looking into qterminal rn, which seems to be preferred by kicksecure.

I never connect to ethernet with wifi modules in its template installed. So I have separate minimalized templates for both sys-nets.

Not sure what that means, but whatever it means I’m 99.9% sure kuhbs would support that config.
I will ship kuhbs with a set of default network kuhbs that you can install / use or not. Up to you. Endusers that dont know how qubes networking works most likely will. These kuhb’s start with kuhbs- in the GitHub - kuhbs/my-kuhbs: Personal KUHBS definitions for a Qubes workstation: network gateway/firewall/Tor/USB plus app and standalone qubes for browsing, code, media, messaging, Hermes, GeForce NOW, and backups. · GitHub repo here (I call them system kuhb’s). PCI stuff is managed by bash hook scripts, for example: my-kuhbs/kuhbs-net-nic/hooks/ndp/create-post.sh at main · kuhbs/my-kuhbs · GitHub

And things like that for each cloned template which is maximally stripped of unnecessary packages

Yeah same here. Kuhbs idea is “for each kuhb, start from debian-13-minimal and install only what we need (apt install firefox)”. Then each kuhb has its own template. So for a named disposable kuhbs-net-gateway, you have:

tpl-kuhbs-net-gateway (TemplateVM)
app-kuhbs-net-gateway (AppVM)
ndp-kuhbs-net-gateway (Named DisposableVM)

Kuhbs also manages updates (not just apt, but flatpak or whatever you write a upgrade hook script for) as well as backups.

“to stay fit” in my case means I know what I want and where to find the command for that, because it’s impossible to remember them other wise.

You are not exactly the target group. The target group are people who install Qubes and then kinda want to look at this (unfinished) gui:

(kuhbs has a cli too, which is also a good bit more powerful than the gui, the gui really only targets endusers).

But for the majority of users, default setups are still incomparably better then what they used in other OS and your tool is of a great help to them

I think endusers are quickly overwhelmed by the complexity. Then they either use sth else or they start configuring stuff wrong. Both not ideal. Some may stay and learn Linux. Great, but I don’t think those are many.
Qubes loudly says “for human rights activists, for lawyers, for bla”, but it really isn’t because they cant use it. kuhbs is for them, with this tool, they can 1) install Qubes 2) do the curl | bash for kuhbs 3) open the gui and be (kinda) done with it.

Btw the i3wm setup is not forced (works with xfce too) but recommended :stuck_out_tongue:

WHEN they trust your code

Luckily with AI, we don’t really have to anymore. Anyone can run a high quality audit before they install sth (AND THEY SHOULD!!!). Kuhbs 1 in bash always had “read the source” written all over it, but thats nonsense for endusers anyways.

I’m currently annoyed by different AIs finding different valid flaws in code, but lets give this another 6 month or so, then most of them should be smart enough alone to find all bugs / security issues in sth like kuhbs (which btw is ~4k lines py excluding comments and newlines - and a bit of bash lol).

1 Like

That’s very interesting. Do you have a tutorial on that?
(Maybe we can continue this discussion in a new post.)

As long as you know how to use Ansible, you just use GitHub - QubesOS/qubes-ansible: Ansible module and connection plugin for Qubes OS · GitHub as a connection plugin and you’re good to go. Otherwise, I’d say RedHat’s resources on Ansible are great.

1 Like

I think kuhbs might be a frame for many of my notes to go in, instead to a text document. And I have tons of them. I hope I will have a will once you finish it, to fill it in, because there are tons of them, while on the other hand it would be one-time-once-a-pile-to-do and after that just updating over time, and adding particular new ones once in a while.

I don’t want to discourage ansible, I build a whole company on it (and am in the process of automating a second one with 99% ansible). Ansible is lovely.

But it is not the answer I’m looking for with Qubes. I wanted something there that is super easy, so everyone can build a new.. idk I’ll just say kuhb :stuck_out_tongue: when they see the “paste these 3 lines into your terminal to install our tool” on a website.

With ansible you have to understand plays, states, inventories, bla. Its not super hard, but you really have to understand Linux to use it.

The entry level to build your own (simple) kuhb is MUCH MUCH lower, yet there is not really a limit to what kind of Qube setup you can build with it (there is a limit, but its WIDE).

2 Likes

The biggest drawback for me is that Kuhbs runs in dom0.
I’ve created a sort of “Kuhbs Lite” with my scripts over the years, and these run from within an AppVM.
So I asked my AI the following questions:

Analyze the technical feasibility of moving a VM management/orchestration tool (like kuhbs) out of dom0 and into an isolated AppVM within Qubes OS.
1. Is it architecturally possible for an AppVM to trigger operations normally handled by dom0?
2. How can Qubes OS frameworks like qrexec or the Qubes Admin API (AdminVM/GUIVM paradigms) be utilized to allow an AppVM to operate as the orchestrator?
3. What are the primary security implications and technical limitations of rewriting a tool to operate from this posture?
Response from Fable 5 with high effort

I’ve surveyed the codebase: kuhbs today is a dom0 CLI/GUI that shells out to the qvm-* tools (qvm-create, qvm-clone, qvm-prefs, qvm-volume, qvm-pci, qvm-start/shutdown/kill, qvm-run, qvm-copy-to-vm, qvm-appmenus, qubes-prefs), plus a few genuinely dom0-local things: launching dom0 terminals, tarring dom0 paths for backup, and downloading kuhb definitions into dom0. Here’s the feasibility assessment.

TL;DR

Yes, this is architecturally supported — the Qubes Admin API (Qubes 4.0+) exists precisely to let a non-dom0 qube manage other qubes, and roughly 90% of what kuhbs does maps directly onto it. The real work is (a) qrexec policy design, (b) replacing the handful of genuinely dom0-local features (dom0 backup, dom0 terminals) with narrow custom services or dropping them, and (c) accepting that a fully-privileged orchestrator VM is close to dom0-equivalent unless you scope its policy with tags.

1. Is it architecturally possible?

Yes, and it’s an explicit design goal of Qubes, not a hack. Since Qubes 4.0, qubesd in dom0 exposes every management operation as a qrexec service under admin.* (e.g. admin.vm.Create.AppVM, admin.vm.Start, admin.vm.property.Set, admin.vm.volume.Resize, admin.vm.device.pci.Attach, admin.pool.*, admin.Events). The qvm-* CLI tools and the qubesadmin Python library from qubes-core-admin-client are transport-agnostic: in dom0 they talk to the local qubesd socket; installed inside an AppVM they issue the same calls over qrexec. Whether a given call succeeds is then purely a question of qrexec policy in dom0.

There are two shipping precedents that prove the model end-to-end: the GUI domain (sys-gui / sys-gui-gpu), which is an AppVM granted broad admin.* access and runs the full management stack including Qube Manager outside dom0; and Salt’s management disposables (default-mgmt-dvm), which configure target VMs from outside dom0 via qubes.VMShell.

2. How the frameworks map to kuhbs specifically

The lifecycle core ports almost mechanically. Because kuhbs already shells out to qvm-* rather than importing dom0-only Python, most of kuhbs/qubes.py and the operations package would run unmodified inside a “kuhbs-mgmt” qube whose template has qubes-core-admin-client installed. The mapping:

kuhbs uses today From an AppVM becomes
qvm-create, qvm-clone, qvm-remove admin.vm.Create.*, admin.vm.Clone, admin.vm.Remove
qvm-prefs, qvm-features, qvm-service, qubes-prefs admin.vm.property.*, admin.vm.feature.* (property name travels as the qrexec argument, so policy can filter per-property)
qvm-start/shutdown/kill/check, qvm-ls admin.vm.Start/Shutdown/Kill, admin.vm.List, admin.vm.CurrentState
qvm-volume admin.vm.volume.*
qvm-run into managed VMs qubes.VMShell / qubes.VMExec VM→VM (no dom0 hop for the payload)
qvm-copy-to-vm qubes.Filecopy VM→VM
qvm-pci admin.vm.device.pci.Attach etc. — works but is the most sensitive surface (see §3)

Policy is the enabling mechanism. In /etc/qubes/policy.d/ you grant kuhbs-mgmt specific services against specific targets. The key primitive for scoping is tags: any VM created via the Admin API is automatically tagged created-by-<creator>, so you can write rules like:

# /etc/qubes/policy.d/30-kuhbs.policy  (representative; check the shipped
# 90-admin-default.policy for the exact target=dom0 idiom)
admin.vm.Create.AppVM  *  kuhbs-mgmt  dom0                        allow
admin.vm.Start         *  kuhbs-mgmt  @tag:created-by-kuhbs-mgmt  allow target=dom0
admin.vm.Remove        *  kuhbs-mgmt  @tag:created-by-kuhbs-mgmt  allow target=dom0
qubes.VMShell          *  kuhbs-mgmt  @tag:created-by-kuhbs-mgmt  allow

This gives kuhbs full lifecycle control over the kuhs it built while making it structurally unable to touch sys-net, vault, or dom0 itself. Qubes also ships include/admin-global-rwx, include/admin-local-ro, etc. policy snippets (used via !include-service) for the coarse “make this VM a full AdminVM” case — that’s how sys-gui is wired, but for kuhbs the tag-scoped version is strictly better.

What doesn’t map, and what to do about it:

  • dom0 backup (backup.py tarring dom0_paths): an AppVM cannot read dom0’s filesystem, by design. Either keep a ~20-line kuhbs.Dom0Backup custom qrexec service in dom0 that tars a fixed allowlist of paths and streams them out, or drop the feature. Notably, once kuhbs itself lives in the mgmt VM, most of what it currently backs up from dom0 (its own config, definitions, logs) moves with it and no longer needs dom0 backup at all.
  • dom0 terminal launching (terminal.py): from a mgmt VM you’d open terminals in the mgmt VM or target kuhs instead — arguably what you want anyway; the backup_mount.py flow already runs its interactive part inside the backup kuh, so it survives intact.
  • qvm-appmenus: dom0/GUIVM territory. In a GUI-domain setup it works from there; otherwise you need a small dom0 helper or accept manual appmenu sync.
  • kuhbs install (downloading definitions from the internet): this stops needing dom0 file-injection entirely — definitions land in the mgmt VM, which is a pure improvement.
  • GUI: the GTK GUI runs more naturally in an AppVM than in dom0.

admin.Events is worth adopting during the rewrite: each Admin API call is a qrexec round-trip, so list-heavy paths (listing.py is your biggest module) should use the qubesadmin event/caching machinery rather than repeated qvm-ls polls.

3. Security implications and limitations

The win is real and specific to kuhbs. Today kuhbs downloads third-party kuhb definitions from the internet and parses YAML, hooks, and setup scripts in dom0. That is exactly the pattern Qubes’ architecture says shouldn’t exist: a dom0 process consuming network-sourced input. Moving to a mgmt qube means a malicious kuhb or a parser bug compromises a VM whose blast radius is bounded by policy, not the hypervisor’s control domain. It also removes the awkward dom0 installation story (install/install.sh, no package manager path) — the tool becomes an ordinary package in a template.

The main caveat: a broadly-privileged orchestrator is dom0-lite. A VM that can create VMs, set arbitrary properties (template, kernel options, netvm), attach PCI devices, and run qubes.VMShell everywhere can escalate to effective control of the whole system. The mitigations, in descending order of importance:

  1. Tag-scope the policy (@tag:created-by-kuhbs-mgmt) so kuhbs can only manage what it created — this is the difference between “orchestrator” and “second dom0.”
  2. Deny or ask the dangerous services: admin.vm.device.pci.Attach (DMA-capable devices ≈ host compromise on non-IOMMU-perfect hardware), admin.vm.property.Set+default_dispvm/+netvm toward unmanaged VMs, anything targeting @adminvm. qrexec ask prompts route to dom0/GUIVM, so the user still confirms sensitive one-offs — but note that batch operations (upgrade-all, backup-all) become unusable if they trigger prompts, which pressures you toward blanket allows; decide the allow/ask split per service up front.
  3. Keep the mgmt VM offline (netvm none) and feed it kuhb definitions via qubes.Filecopy from a fetcher qube, or go further and run operations from a disposable based on a minimal template, Salt-style. The mgmt VM’s template joins your TCB — a compromised template means a compromised orchestrator on next boot, so it should be a minimal, rarely-touched template, not your daily-driver one.

Technical limitations to plan for:

  • Per-call qrexec overhead makes chatty code paths noticeably slower than local socket calls; batch and cache.
  • Policy can filter by service, argument (hence per-property), source, and target — but not by value (it can stop kuhbs setting netvm on a VM, not stop it setting netvm=sys-net vs none where allowed).
  • qvm-run --pass-io semantics differ VM→VM vs dom0→VM (it becomes qubes.VMShell with its own policy line); the command.py runner abstraction you already have is the right seam to absorb that.
  • Error surfaces change: instead of subprocess exit codes from local tools you also get policy denials, which the CLI should distinguish (“dom0 refused this” vs “operation failed”).

Overall verdict: feasible with moderate effort, and for this tool specifically it’s the architecturally correct direction — the existing subprocess-based qvm-* seam means the port is mostly packaging plus policy design, with dom0 backup and appmenus as the only features needing dedicated dom0-side shims.

My conclusion:
For me, kuhbs is only interesting if it runs in an AppVM.
Qubes OS offers that capability. And it’s also best practice to install as little as possible in dom0 and keep dom0 as small as possible.

My question for the developer @kuhbs
Would you change kuhbs from being dom0-based to AppVM-based?
Or is that a no-go?

I’ve been eyeballing that very hard myself lately. Something like sys-kuhbs in a sense, or in my terms kuhbs-admin.

Right now I’m drowning a bit in that idiotic gui needing states for bloody everything just to gray out those stupid buttons so that endusers don’t mess up their system by pressing backup and remove at the same time “rant rant” xD

But yes, I kinda would want that too tbh (kuhbs-admin) - I THINK.

On the other hand, if I create an admin VM that has access to all kuh’s (Qube’s / VMs), I don’t fully see the point. It can infect all of them, and then whats the point of owning dom0 still, the data can still be silently manipulated.

Its not that I don’t trust my own code :stuck_out_tongue: (you shouldn’t and audit it before using it later when its ready ofc lol). Its that I have to let kuhb’s (one kuhb two kuhb’s, as in “the browser kuhb”) run hooks in dom0, for example to reassign pci devices, to create / remove i3wm configs and alike. This means that if you add a repo from a third party, which contains kuhb’s, these scripts would be the biggest risk to you.
Of course you won’t just add a random repo full of kuhb definitions without AI scanning it first..

I’m sure there is a way to hack around that (having the admin VM do qvm-pci stuff, somehow manage i3 configs in dom0).

Not sure if its worth the effort (extra code in kuhbs).

I don’t see to much difference between “admin VM that has 99% of the power of dom0” and “kuhbs runs in dom0”.

Salt runs in dom0, so does ansible-qubes.

Give me arguments I can’t refuse :stuck_out_tongue:

PS: I think kuhbs (on my laptop rn) has no more –pass-io now. I hate it, and I will see that its gone before release. Backup / Restore file copy stuff works directly VM to VM without prompt now. The prompt is nonsense in this case for a number of reasons. Its secure enough now.

PPS: More rant… Write a half way complex cli: 4k lines of code. Add a gui: 5k lines of code. States: 10k lines of code. UAH!! So annoying lol.

PPPS: btw your audit excludes kuhbs-i3-integration, which I highly recommend (and most likely integrate back directly into the kuhbs-for-qubes repo). I’ll make it work with xfce, but a properly configured i3 is so VASTLY superior that I will “force” users to use it. I have it in a way (almost) that its enduser friendly. I’ll add a wallpaper that explains things x) This should actually work for endusers.

Qubes’ architecture says shouldn’t exist: a dom0 process consuming network-sourced input. Moving to a mgmt qube means a malicious kuhb or a parser bug compromises a VM whose blast radius is bounded by policy, not the hypervisor’s control domain

Well yeah, but if the policy is “do whatever you want” than that argument doesn’t make sense.

if I have root@ in all VMs, which I need, then the whole model breaks, and kuhbs being config management for all VMs.. needs root@ in all VMs :stuck_out_tongue:

What is protected with a kuhbs-admin?

If kuhbs-admin is infected, I could delete literally all Qubes. But then its most likely faster to just reinstall Qubes OS and setup kuhbs again and restore backups - which btw kuhbs is explicitly build for (it has a kuhbs create-all, where you don’t have to do anything but press enter once (ok twice) to restore EVERYTHING from scratch).

Provided you trust the backups.

You have to trust the kuhb definitions, but those you can AI scan more easily than the tar.gz backups (those you can scan too, you just have to copy them to the hermes kuhb lol).

Anyways long story short, I don’t really see the big advantage except for more complexity. If the admin VM is compromised you have to wipe and reinstall anyways (or at least I would) because its faster.

I was eyeballing the idea of having a command that creates a usb stick with a Qubes installation that is presseeded and a post install script that installs kuhbs, reboots, and then runs kuhbs backup-mount && kuhbs create-all x)

Anyways, I love splitting things and permissions too, but I feel like (bellyfeeling, feel free to let your AI scan this thread and argue with me, I hope I’m wrong lol) that in this particular case its kinda nonsense.

1 Like

I took the time to argue this out with chatgpt. In the end we concluded:

So the only real win is:

- less code in dom0
- dom0 survives adminVM compromise
- adminVM can be rebuilt

That’s it.

Imho thats nonsense. Just reinstall Qubes then. Thats more secure. I wouldn’t trust a “mini dom0 permission” VM being compromised enough to still trust the dom0 that runs it.. I’d just wipe the whole box and start over.

So long story short, unless you have an argument that I didn’t think of, I think admin VM for kuhbs doesnt make sense, because it would need to many permissions (kinda all the permissions to be exact). It needs root@ in all VMs, and a touch of dom0 specific stuff.

So imho not worth it, but I’d love to hear your counter arguments @queen , I don’t want to bury the argument by saying “I am right”. Feel free to counter please.

1 Like

Architectural Counter-Arguments

The “Read vs. Write” Privilege Separation:
Your argument assumes that a compromise always means “destroy everything.” But the biggest threat isn’t deletion; it’s silent exfiltration and persistence. If kuhbs runs in dom0, a malicious third-party repo hook gets immediate access to your disk decryption keys, your bare-metal hardware firmware, and can patch your Xen hypervisor in memory. A compromised kuhbs-admin VM can destroy your VMs, yes, but it cannot infect your BIOS/EFI or read dom0 memory where master keys live.

Parsing Untrusted Input:
You mentioned AI-scanning definitions, but parsers (YAML, JSON, or custom CLI outputs) are notoriously prone to memory corruption or injection bugs. If a parser exploits kuhbs inside dom0, the attacker has ring 0 execution on the host. If it happens in kuhbs-admin, they are trapped in a VM.

The “Trusting Backups” Paradox:
If dom0 is compromised, you can no longer trust the integrity of the backup files kuhbs is generating before the reinstall. A compromised dom0 can silently inject backdoors into your backup templates or alter the kuhbs create-all script definitions on the fly. If only kuhbs-admin is compromised, it cannot manipulate the core Xen/dom0 isolation logging that proves a breach occurred.

1 Like

It makes total sense why you lean this way. If your security baseline is “at the first sign of any anomaly, I wipe the entire bare metal from a trusted USB anyway,” then a management Qube does look like a lot of extra engineering for very little operational return.

However, there is still one foundational architectural argument that doesn’t focus on how fast you can reinstall, but on how an attacker behaves before you even notice you need to reinstall.

Here is the counter-argument based on Attacker Lifecycle and Visibility:

1. The “Invisible Compromise” vs. The “Loud Exploit”

Your argument assumes you will know the kuhbs-admin VM is infected, prompting you to wipe the machine. But modern advanced attacks don’t run rm -rf / or throw errors. They want to sit quietly, log your keystrokes, steal your crypto keys, or alter your git commits.

  • If it happens in dom0: Once an attacker gets code execution in dom0 via a malicious kuhbs hook or parser bug, they own the hypervisor. They can hook into Xen memory, patch the kernel, and falsify what the system tells you. They can make kuhbs status or your file hashes look completely normal while silently exfiltrating data via a covert channel. You will never trigger that USB reinstall because your system will lie to you perfectly. [1]

  • If it happens in a management Qube: The management Qube can still be compromised silently, but it cannot hide from dom0. Dom0 sits outside the attacker’s execution bubble. Dom0’s intrinsic logs, memory monitoring, or basic system checksums cannot be manipulated by a VM, no matter how many permissions that VM has over other Qubes. You retain an un-fakeable “source of truth.”

2. Root inside the Qubes != Hypervisor Control

You mentioned that kuhbs needs root@ in all VMs anyway, so the model breaks. But from a strict Qubes OS security perspective, owning a Guest OS kernel is vastly different from owning the Xen Hypervisor.

If an attacker compromises your management Qube, they inherit root across your client VMs. That is a massive data breach, yes. But they are still trapped inside the hardware virtualization matrix managed by Xen. They cannot write directly to your bare-metal NVMe controller firmware, they cannot flash your BIOS/UEFI, and they cannot read the raw LUKS decryption keys stored in dom0’s memory.

If they get into dom0 via kuhbs, your hardware itself is now potentially burnt. A simple OS wipe and reinstall from a USB stick might not save you if they persistently backdoored your motherboard’s SPI flash.

3. The “Blast Radius” of Malicious Repos

You noted that third-party repos containing kuhbs definitions are the biggest risk because of dom0 hooks (like qvm-pci or i3wm configs).

If a management Qube handles this, you don’t actually have to give it “all of dom0.” You can use rigid qrexec policies. For example, instead of letting kuhbs run arbitrary bash scripts in dom0, dom0 only listens for very specific, tightly-parsed requests (e.g., “Only allow this VM to execute qvm-pci attach with these specific allowed IDs”).

If the management Qube is tricked by a bad repo, it can only abuse the specific commands dom0 allows it to trigger. It cannot accidentally execute a rogue rm -rf / or a malicious binary inside dom0.

Summary: Is it worth the 10k lines of GUI/State code?

If kuhbs is a highly personal tool built by you, for you, and you strictly audit what goes into it—running it in dom0 with a clean, lightweight CLI is completely reasonable. The added complexity of a management Qube might feel like over-engineering.

But if kuhbs is meant to be distributed to other end-users who will blindly copy-paste third-party templates and repos, pushing it out of dom0 isn’t about making reinstallation easier. It’s about preventing a rogue script from gaining permanent, undetectable hardware persistence.

How do you plan to handle third-party definition safety if you keep it in dom0? Would you rely entirely on that AI-scanning pre-flight check, or are you thinking about implementing a strict internal sandboxing/parsing mechanism within kuhbs itself?

2 Likes

ccess to your disk decryption keys, your bare-metal hardware firmware, and can patch your Xen hypervisor in memory.

disk encryption keys: true
firmware attack vector: true
patch xen hypervisor: also true

you can no longer trust the integrity of the backup files

kuhbs admin vm would control all other vms (it creates the usb vm, and also manages backups / restores, and hence has root@ all VMs), so thats true even with kuhbs-admin.

can silently inject backdoors into your backup templates or alter the kuhbs create-all script definitions

so can a compromised kuhbs-admin

it cannot manipulate the core Xen/dom0 isolation logging that proves a breach occurred

hm well i think qrexec stuff is logged in dom0, but I’m not sure, anyways, if we have kuhbs-admin, it could not mess with journal in dom0, correct

then a management Qube does look like a lot of extra engineering for very little operational return.

That being said, I am massively with you on the firmware side of things. I don’t much like that either.

how an attacker behaves before you even notice you need to reinstall.

you will not notice, which is one of the reasons I build kuhbs in the first place - to completely automate the installation and setup of Qubes OS, so I can do it in the morning while drinking coffee - each day. Including reinstalling Qubes and before that flashing the firmware.
Automating that will be fun, but its possible. Mostly automating at least, the Qubes install path you can fully automate, the crappy firmware tool not ofc x)

My approach to security has been shifting for a while from “build secure software / systems to trust things” to “destroy things and setup from scratch” bcs AI gives attackers fancy capabilities, but developers too, so you can kinda always assume your system is compromised, and its best to destroy everything and start from scratch every day (fresh install) because the CVE the attacker used might have been patched.
I’d also recommend recycling hardware regularly, understanding that this is a cost factor, which I cant write py for to help you with :stuck_out_tongue:

Your argument assumes you will know the kuhbs-admin VM is infected

I always assume everything is infected, which is why I wrote kuhbs, because start from scratch is the only way to cope with this when I receive an email once a day with 300 new CVEs found in fucking thunderbird alone.

They want to sit quietly, log your keystrokes, steal your crypto keys, or alter your git commits.

+1

You retain an un-fakeable “source of truth.”

I actually do not know WHAT is logged in dom0 (menaing I / me personally never bothered to look at the systemd journal in dom0). If it logs when qrexec calls happened, I highly doubt you (or me) will be able to say “ah! that means an attack!” - but it is possible to derive this from this data, yes.

If they get into dom0 via kuhbs, your hardware itself is now potentially burnt. A simple OS wipe and reinstall from a USB stick might not save you if they persistently backdoored your motherboard’s SPI flash.

If they are hardcore enough to mess with firmware (I think!!!) they are most likely state level actors, against which only anonymity will protect you, because No Such Agency has 0days for xen / qubes.

But I am with you on your argument none the less, yes.

If a management Qube handles this, you don’t actually have to give it “all of dom0.” You can use rigid qrexec policies. For example, instead of letting kuhbs run arbitrary bash scripts in dom0, dom0 only listens for very specific, tightly-parsed requests (e.g., “Only allow this VM to execute qvm-pci attach with these specific allowed IDs”).

Its hard (impossible) to know what kind of things one might want / need in hooks. Luckily hooks are just stupid bash scripts, and if you write something fishy in there, your AI audit will detect that 100%.
A kuhb definition is so utterly stupidly simple that you can audit that yourself without AI. It is much simpler than reading / understanding salt or ansible in fact. Its yaml and a bit of bash, in most cases.

But I do see your point. However it is extremely easy to audit (by design), and that is a valid counterpoint imho.

You’re still not wrong, I’m not dismissing your argument.

If kuhbs is a highly personal tool built by you, for you, and you strictly audit what goes into it—running it in dom0 with a clean, lightweight CLI is completely reasonable. The added complexity of a management Qube might feel like over-engineering.

Hm yeah well keep in mind that salt runs in dom0 and thats provided by the Qubes people, who encourage you to use salt :wink: Which means you’re somewhat encouraged to use the salt from other people, because nobody who doesn’t like MASSIVE pain is messing with qubes salt (trust me I tried lol).

So not fully with you on that one :wink:

But if kuhbs is meant to be distributed to other end-users who will blindly copy-paste third-party templates and repos, pushing it out of dom0 isn’t about making reinstallation easier. It’s about preventing a rogue script from gaining permanent, undetectable hardware persistence.

True, but for endusers the smallest problem will then be that the attacker has the ability to flash the firmware, because the attacker will most likely not need that capability - they will only need to make friends with that person and send them an email with “check out my fancy kuhb definitions” and then they own all the VMs (excluding dom0) - which as you noted, the enduser wont notice.

How do you plan to handle third-party definition safety if you keep it in dom0? Would you rely entirely on that AI-scanning pre-flight check, or are you thinking about implementing a strict internal sandboxing/parsing mechanism within kuhbs itself?

A kuhb definition lives from bash scripts, so you can simply implement stuff like this: Signal >> Download Signal for Linux

There is no way in code for me (that is sane) to validate “is this bash code malicious” - that can only be done by AI.

So I do see your arguments with state level actor capabilities and them permanently compromising the machine via firmware. However state level actors don’t need kuhbs for that, they get into your box with regular Qubes OS as well (I think). Or they just break in when you’re not at home to own your box. Not that hard really.

I still don’t fully see the reason for the extra code. However I also have said that I would love to have this - dont get me wrong here. I f-ing LOVE (!!!) the whole puzzle game around Qubes OS. I kinda do this because it soooo much fun to me, its like MASSIVE OCD addiction to make Qubes more secure and what not.
I still dont fully see the reason here. The arguments I took from your arguments that make sense to me are:

  • firmware
  • disk encryption keys
  • well, you know, root@dom0. god mode.

compared to pretty much god mode (root@kuhbs-admin) - zero difference to an enduser, all of the endusers data is owned / can be manipulated, they wont notice anyways.

As said, kuhbs is still in development, and I will 100% research how much effort it is to run this all in kuhbs-admin. But just from the risk factors, I’m not super convinced its worth it. If its a ton of efforts and has lots of drawbacks.. Idk. Maybe its simpler than I think.

I need to setup some qrexec policies with qubes, and I need the ability to mess with i3wm. From what I know that kinda requires dom0, or at least sending data into dom0, which I could verify somehow but meh. Then there is a bug in there…

Gimme some time to check this out :wink: If its reasonably feasable, I’ll do it just for loving to do it :wink: I mean I want kuhbs-admin too, but not at to high a cost, because at the end its about the data (root@all-the-vms) and not defending against state level / high persistence threats with LOTS of cash for 0days. That war is lost in my opinion. I really dont think qubes gives even the slightest bit of protection against No Such Agency (only anonymity does, imho).

Kuhbs, even running in dom0, would still be vastly more secure than anything else available for endusers at this point. So to endusers, even kuhbs in dom0 is still a MASSIVE security upgrade compared to, say, OSX or ubuntu or so.

Kuhbs is (kinda) not really targeted at the ultra pro hacker using Qubes - I know they will find stuff they don’t like one way or another.
I mean the bloody thing has a gui for christ sake xD That would make even me raise an eyebrow (has a cool CLI too though, you are not at all forced to use the gui :P)

2 Likes

That is absolutely correct! That is the strongest point for your argument. Both qubes-ansible and SaltStack run natively in dom0 because they have to make deep system modifications.

Why did the Qubes team design it this way, even though it goes against their own core philosophy (“Keep dom0 isolated”), you ask? For the exact same reason you are facing right now: Pragmatism and code complexity.

However, there is one massive, critical difference between how qubes-ansible/Salt operate and what you are planning with kuhbs:

The Critical Difference: Where do the data inputs come from?

When the Qubes team uses Salt or Ansible in dom0, they do it under a strict premise: The configuration files (YAML/Formulas) are static and have already been pre-verified. They arrive via official, cryptographically signed system updates through the Whonix/Fedora update templates into dom0. In this case, dom0 only ever parses data that it already 100% trusts.

With kuhbs, you are planning a much more dynamic ecosystem:

  1. You want to move backups directly from VM to VM (without --pass-io prompts).
  2. You mentioned third-party repositories with kuhbs definitions that would be AI-scanned.

If these potentially untrusted or dynamic definitions/file paths are read and parsed directly by dom0, you bypass the security barrier. A single parser bug inside dom0 while processing a malicious kuhbs configuration would result in a total system compromise.

Why your gut feeling is still right

Let’s be real: For a one-man project that you are primarily building for yourself, the Admin VM architecture is an absolute engineering nightmare.

If you use qubes-ansible as a precedent, your decision to keep it in dom0 is completely legitimate:

  • Less Code: You save yourself from writing a complex, messy qrexec policy web between an Admin VM and dom0.
  • Zero Overhead: You don’t have to write hundreds of lines of wrapper code just to safely tunnel commands like qvm-pci across VM boundaries.
  • Focus on Features: You can focus on making kuhbs create-all and the i3 integration work flawlessly, rather than spending months hardening an architecture that you would just wipe from a USB anyway if things went south.

The Verdict

If the official Qubes OS project gets to put Salt in dom0, you have every right to put kuhbs there too. You just have to accept the trade-off: The moment you introduce features where dom0 processes input originating from another VM (like an unencrypted backup path or a remote git repo), you step outside the safe boundaries that Ansible operates in.

If you stick with the dom0 route, how do you plan to handle the security risk of reading those third-party definitions? Will you rely entirely on that pre-flight AI scanner, or are you thinking about running a “sanitizer” script inside a disposable VM before the files ever touch dom0?

1 Like

True. Mine comes via github :wink: git has stuff like this too, but it is ofc third party.

I will bug @unman until he merges kuhbs into qubes itself xD HAHA (zero hope of that, just joking).

My point was rather on how you could use salt - everybody here could provide salt formulas instead of tutorials. This would make it (somewhat) more easy to share configurations. These would have to arrive in dom0 (yes you can have an admin qube run salt, but it isn’t the default! :wink: )

So the default stuff is shipped with the iso, yes, but if you want to USE salt to share configurations, you have the same problem as with kuhbs, however kuhbs you can read, while salt you can kinda read too but its much more annoying than auditing a kuhb (personal opinion).

You want to move backups directly from VM to VM (without --pass-io prompts).

If you like pain you can enable the prompts here, but if you have 20 VMs to backup then you will go insane, thats why I automated it (but prompt thingy with qvm-copy is optional, not sure if I’ drop it though because it is JUST SO STUPID…). Anyways, you can only trigger those backup / restore transfers (wihtout a prompt) from dom0, so this is where you would also click “ok” (or write the vm name) for a qvm-copy command.

If these potentially untrusted or dynamic definitions/file paths are read and parsed directly by dom0, you bypass the security barrier. A single parser bug inside dom0 while processing a malicious kuhbs configuration would result in a total system compromise.

Exactly the same for “sharing your salt formulas or ansible roles”. This is an issue for “sharing configuration / automation for qubes in other form that forum tutorials”, and not a kuhbs thing.

primarily building for yourself,

well I hope not :stuck_out_tongue:

the Admin VM architecture is an absolute engineering nightmare.

I honestly don’t know yet. I just still don’t see the BIG advantage, other than firmware, that topic bugs even me quite a bit.

(like an unencrypted backup path

Dont get this one - you can define backup paths in a kuhb.yml, like for example “app-signal needs to backup /home/user/.config/Signal” or so. But that doesn’t really touch dom0 - I mean the kuhb.yml is in dom0, but the archive is in the usb vm.

processes input originating from another VM

It kinda doesn’t. There is one usecase for this I don’t get around, and that is kuhbs restore dom0, where you restore a backup from usb vm to dom0. there I need qvm-run –pass-io, other than that I DON’T use –pass-io to get “info from VMs into dom0” - and I don’t do that very religiously.

As for the git repo, yes, but as said, that is the same for all “sharing configuration code”, regardless of ansible, salt, bash script, whatever or kuhbs.

Btw kuhbs repo-add works by spawning a dispvm and doing a git clone, then archiving it and getting it into dom0 (via, you guessed it, qvm-run –pass-io, bcs thats the only way to get stuff into dom0). There you have to trust the dvm template.
Similar to qubes-dom0-update btw, which also gets data into dom0 from a VM hehe :wink:

handle the security risk of reading those third-party definitions?

As said above, I can’t parse bash for installing a backdoor. AI has to do that. Forum can do that, I can do that. You can do that. And then you only install repos from a specific git commit ID which you have AI scanned before.

Similar to qubes-dom0-update , just bcs that is in fedora doesn’t mean its secure. You should Ai scan it (or audit it youself) before you use it. This is not a kuhbs thing, but an admin thing, and even if I use kuhbs-admin, that problem remains, with the only difference being the ability to fuck up the firmware (in a nutshell, I know there is more, but the effect on root@all-the-vms is the same, which imho is the true goal of most attacks).

are you thinking about running a “sanitizer” script inside a disposable VM before the files ever touch dom0?

As said above, that is not possible. A kuhb, via hooks, gives the ability to run arbitrary bash in dom0, and for good reason in many cases. You have to pick a git commit ID, audit it, and then pull the kuhb repo with that commit ID into dom0.

Exactly the same way you get any and all software into dom0, be it salt, ansible, or qubes-dom0-upgrade.

The only exception is that a kuhb is much simpler to audit :wink: And that is a big plus over the other options.

1 Like

Maybe you should write a brief description of the attack vectors that kuhbs is designed to address.
You must have identified a problem that you specifically want to solve with kuhbs.
And maybe kuhbs isn’t even the solution to my specific problem. (It’s just that I can’t tell because I don’t know exactly why you created kuhbs.)

Example:
If dom0 was compromised, setting up my entire Qubes system was a huge hassle.
That’s why I came up with the idea for kuhbs, which is supposed to do everything automatically with just one click.

1 Like