Skip to content

Qubes OS for Tools & AI Agents

Qubes OS lets you run many operating systems and tools at once, each in its own isolated virtual machine (“qube”), on a single laptop. Different work goes in different qubes, and a problem in one — a malicious tool, a bad dependency, a runaway process — can’t reach the others.

This page is the practical / general-use companion to the security-focused Qubes OS hardening guide. Read that one for the threat model, install requirements, and the full compartmentalization model. Here we focus on two everyday uses: running multiple OSes for different tools, and — the part most worth your attention right now — running AI agents safely in a dedicated qube.


Run many operating systems & tools side by side

Section titled “Run many operating systems & tools side by side”

Because every qube is a real VM, Qubes is a clean way to keep toolchains separated:

  • TemplateVMs ship for Fedora and Debian; the community adds Whonix (Tor), Kali (offensive tooling), Arch, and others. Each AppVM inherits a template’s root filesystem, so you install a toolset once in a template and spin up as many disposable or persistent qubes from it as you like.
  • Standalone / HVM qubes run a full independent OS — including Windows or another Linux distro — when you need a tool that only exists there.
  • Disposable qubes give you a throwaway OS for one task (open a sketchy file, test an installer, run an untrusted binary) that vanishes on close.

The point: a radio/SDR toolkit, a malware-analysis sandbox, a banking-only browser, and your daily work can all live on one machine without sharing a filesystem, clipboard, or network path — unless you deliberately connect them.


A dedicated AppVM for AI agents (the important one)

Section titled “A dedicated AppVM for AI agents (the important one)”

AI coding agents are now powerful enough — and autonomous enough — that where you run them matters as much as how you prompt them. A modern agent will run shell commands, install packages, read and write files, and fetch from the internet on its own. Two real risks follow:

  • Footguns: an agent can rm the wrong thing, mangle a repo, or install something hostile by accident.
  • Prompt injection → exfiltration: content the agent reads (a web page, an issue, a dependency’s README) can contain instructions that hijack it into leaking secrets or reaching systems it shouldn’t.

Running the agent in its own qube turns both from “whole-machine problem” into “one-disposable-VM problem.” You still interact with it as easily as a normal terminal — but its blast radius is a single AppVM you can wipe and rebuild in seconds.

Why a qube beats a plain container or “just be careful”

Section titled “Why a qube beats a plain container or “just be careful””
  • It’s a full VM boundary (Xen), not a shared-kernel namespace — a far stronger wall around an agent that runs arbitrary code.
  • The agent’s network, files, and secrets are all separately controllable (below). A Docker container on your main OS shares your network and can usually see your SSH keys; a qube does neither unless you wire it up.
  • You can give it exactly the access it needs and nothing else, then leave it running.

Create one AppVM whose whole job is running the agent (CLI agent, editor, repo checkout). You interact with it like any other qube — open its terminal, run the agent, watch it work — but it is a separate machine from your daily one.

Terminal window
# in dom0 — create a persistent agent qube from a template
qvm-create --template debian-12-xfce --label orange agent-ai
qvm-prefs agent-ai memory 4000
qvm-prefs agent-ai maxmem 16000
qvm-prefs agent-ai vcpus 4

Install the agent’s runtime (Node/Python, the CLI) in the template so it persists; keep your working repos in the agent qube’s /home, which survives reboots.

This is the highest-leverage control. Decide what the agent is allowed to reach:

  • Locked to just its APIs. Route the agent qube through sys-firewall and restrict it to only the endpoints it actually needs (the model API, your git host) — everything else is dropped.
    Terminal window
    # in dom0 — example: allow only what the agent needs, deny the rest
    qvm-firewall agent-ai reset
    qvm-firewall agent-ai add accept dsthost=api.anthropic.com proto=tcp dstports=443
    qvm-firewall agent-ai add accept dsthost=git.example.org proto=tcp dstports=443
    qvm-firewall agent-ai add drop # implicit deny for everything else
  • Through a VPN/Tor ProxyVM. Point netvm at a VPN qube (or sys-whonix) so the agent can’t tie its traffic to your identity or location.
  • Fully offline. For an agent that only needs to operate on local files, give it no netvm at all (qvm-prefs agent-ai netvm ''). Prompt injection can’t exfiltrate over a network that doesn’t exist.

Because the agent’s network is its own, tightening it never touches your other qubes.

The agent can’t silently reach your other qubes’ files — there’s no shared filesystem. You move data on purpose:

Terminal window
# push a repo INTO the agent qube (run from the source qube; dom0 prompts to approve target)
qvm-copy ~/projects/myrepo # lands in agent-ai:~/QubesIncoming/<source>/
# pull results BACK OUT (run from the agent qube)
qvm-copy ~/myrepo/build/report.pdf # you approve the destination in a dom0 prompt

Every transfer is an explicit, user-approved action — so a compromised agent can’t quietly drain your other qubes, and you always know what crossed the boundary. The inter-qube clipboard (Ctrl+Shift+C / Ctrl+Shift+V) works the same deliberate way.

4. Give scoped secret access via vault — and deny everyone else

Section titled “4. Give scoped secret access via vault — and deny everyone else”

Agents need to push to git or reach a server, but they should never hold your private key. Qubes’ split-SSH/split-GPG pattern keeps the key in an offline vault qube; other qubes ask vault to use the key over a tightly-scoped qrexec service. The key bytes never enter the agent qube, and the policy says which qube may ask:

/etc/qubes/policy.d/30-ssh-agent.policy
# only the agent qube may use the agent key; everything else is denied
qubes.SshAgent * agent-ai vault allow
qubes.SshAgent * @anyvm @anyvm deny

You can go further:

  • Per-use confirmation — make the policy ask instead of allow so each key use pops a dom0 prompt (and a notification showing which qube asked). An injected agent trying to use the key at 3am is visible and refusable.
  • A dedicated key for the agent qube, separate from your personal key, so you can revoke it without touching anything else.
  • Different keys for different qubes — your daily qube and the agent qube can be scoped to entirely different keys.

The result: the agent can do its job (sign a commit, open an SSH session) while it is structurally incapable of stealing the key, and any other qube that tries is denied.

A persistent AppVM keeps its /home and configuration across reboots, so once the agent qube is built — runtime in the template, repos and config in /home, network locked, key scoped via vault — you can start it and let it run long jobs unattended. If a run ever goes sideways, you reset that one qube (or restore it from its template) without disturbing the rest of your machine.