Understanding Qubes: Why is it not a problem to have many apps in the template?

From a separation point of view: Wouldn’t it be better to have e.g. a browser only in a template VM that is dedicated for web browsing instead of launching an instance of a VM that has nearly all applications?


According to qubes-docs:

When properly configured and used, minimal templates can be less resource-intensive, reduce attack surface, and support more fine-grained compartmentalization.

If you have enough system resources an desire to “reduce attack surface” even more - go for it!
Personally, I do use minimal-templates in such fashion, but not sure how much it actually helps security-wise.


One can clone templates at install time so that you can create a tree of different templates for different purposes. Keep one branch basic, create other branches with more applications based on how you want to categorize their usage. Then create App VMs using those templates as needed.

This does increase the number of updates one has to make, etc. But you still keep the protection of a template root filesystem being fresh on each AppVM reboot.



It is possible to create a vanilla template (minimal installed apps) and then simply install snaps or flat-packs in the AppVM specific for that single application. This containerized separation method insures that none of the apps can cross contaminate other AppVM’s via the shared template. The downside of this is if you get infected by some malware it can then modify that one app which will not revert back to the pristine state upon AppVM reboot. You could perform a checksum on that application directory on VM boot if you want to be sure it has not been modified, but then, have your checksum apps been modified? Its a deep rabbit-hole of trust.

Its all a security trade off, and only you can decide on what your specific usecase is important to you. My personal preference is to use the default apps available in the main OS repository and for any apps which come from a non-certified repository I may install that in the AppVM itself. I may also reverse engineer the app (e.g. IDA Pro) or run it under system trace diagnostics just to ensure it behaves “as expected” before “trusting” it. Your mileage may vary.

Another possible method might be to create a separate app storage pool for each untrusted app and then mount it as read-only into your specific AppVM. This removes the possibility of being overwritten by an adversary with persistence across reboots. This is something I had thoughts to look into. Perhaps mounting these on /opt on an AppVM basis. You could first map the storage volume into a disposable AppVM as read-write, install the app into /opt and then load that same volume into your AppVM as read-only. Just a thought.

Only storage, as ram usage will benefit from minimal templates.

Less code running on a vm means less code that can potentially be exploited!

You should look into an apt-cacher-ng qube: it replaces the default proxy used for updates and caches the packages, so you only have to download them once for all your templates.

These notes are enough to get you started: https://github.com/unman/notes/blob/master/apt-cacher-ng


See also:

There are a few different aspects to this:

  1. There is a theory that installing programs is generally less of a security risk than running programs. This means that installing many programs inside a template should be fine, as long you don’t run those programs in that template (and instead run those programs inside app qubes that are based on that template).

  2. Nonetheless, it is generally true that the less you “do” inside of a template, the lower the risk that your actions will introduce some undesirable security consequence. As a result, installing fewer programs inside each template should, ceteris paribus, be safer. However, this depends on several factors, such as (a) the types of programs you’re installing; (b) the source of the installation packages; (c) whether and how the packages are cryptographically signed; (d) how you came to trust the keys used to sign the packages; (e) how those signing keys are handled by their owners; (f) your susceptibility to attacks, targeted or otherwise, in the course of downloading, installing, and updating those packages; and many other factors.

  3. In general, having more software installed in the template on which an app qube is based might make it easier for certain types of attacks within that app qube to succeed. For example, an attack that requires opening a certain type of file or URL is less likely to succeed if the template on which that app qube is based doesn’t have any program installed that can open the file or the URL.

  4. However, it doesn’t follow that everyone should install a maximum of only one program in every template, because there are other values besides security to consider, and people have different use cases. For example, some people have an “untrusted template” (and untrusted app qubes based on that template) in which security is not a concern. Even though Qubes OS itself prioritizes security above all else, it grants users the flexibility to create zones domains in which security is trumped by other values (such as convenience, productivity, or even enjoyment). This means that you can have some ultra-secure single-application templates while also having less-secure general-purpose templates. In this sense, Qubes allows you to have your cake and eat it too. :slight_smile:


I just looked at those notes. Maybe I’m a bit dense but I can’t tell whether he wants those commands done on the qube, or in dom0. One block does say “in the qube” but others, even though they seem intuitively to be ones you’d want to run in the qube, don’t say that.

In apt-cacher-ng qube template:

apt-get install apt-cacher-ng, and mask in the template.
systemctl mask apt-cacher-ng

In dom0:

Set this as updateProxy in /etc/qubes-rpc/policy/qubes.UpdatesProxy

Everything else in apt-cacher-ng qube.



I don’t actually have such a file. OK, so I realize that maybe I’m supposed to create it if it’s not there, but in that case I’ll need to know exactly what to put in the now-nonexistent file; it’s not a matter of changing an existing line.

Update: should I instead be looking at: /etc/qubes/policy.d/90-default.policy and changing the line that reads qubes.UpdatesProxy with type Template VM allow target=sys,net to this item instead?

Yes, you need to change the qubes.UpdatesProxy for templates there.
It’s a new Qubes policy format:
Qubes Architecture Next Steps: The New Qrexec Policy System | Qubes OS

1 Like

Don’t do this - that file contains the default policy settings, and
may be overwritten by updates.
If you want to change the defaults, put the new policy in a file with a
lower number - it’s explained at the top of /etc/qubes/policy.d/90-default.policy
E.g, create a file /etc/qubes/policy.d/30-user.policy and write in it:

qubes.UpdatesProxy * fedora-35          @default    allow   target=sys-net
qubes.UpdatesProxy * @type:TemplateVM   @default    allow   target=CACHER_QUBE

If you do this then it will be easy for you to see what changes you have
made to the defaults, and you can easily revert to the default

1 Like

There is the abstract but real benefit of ‘reduced attack surface’. However, I am much more concerned with myself doing something stupid. Especially in qubes that communicate/receive data from the outside world.

In particular these would be qubes used to receive email, run messengers or web browsers. Those qubes I like to keep one-app-per-qube so that if I accidentally attempt to open a file there instead of sending it to a disposable viewer qube … chances are nothing happens because there is nothing installed to handle it.

I classify my qubes:

  1. offline storage qubes
    …they hold files and do little else; every view/edit action happens in disposables; some may have one specialized application to manage/view them like calibre for the ‘library’ qube or vlc for the ‘music’ qube. Key here again is offline and the data is compartmentalized, so a malicious audio file can exploit my music collection but nothing else.

  2. offline disposable qube(s)
    … this is where I view/edit stuff; I don’t care if this has multiple applications, in fact I prefer it so I can set this as the default_dispvm. LibreOffice, evince, vlc etc.

  3. disposable web qube(s)
    … this is where most of the browsing happens. This qube has nothing in it other then the browser.

  4. specialized web qube(s)
    … these are not disposable / have state and are only used for specific destinations (e.g. bank, amazon, netflix) … more or less a one-website-per-qube approach

  5. specialized online qubes
    … thunderbird, signal, element … one-app-per-qube

  6. development qube(s)
    … these might have specialized toolsets (gcc/make, python, ruby, git, visual code, other IDEs) tailored for a specific project/context. offline or tightly firewalled to only allow github connections.


That setup is amazing! Gives you great power over your computing activities.

I’m not sure how it might be done, but could there possibly be a type of inheritance for template qubes? For example, one template qube with a base set of applications and another that is based on that with some more. Then the first could be updated and would provide those updates to the second, and the second could just update the applications that differ.

@Sven, in your one-app qubes, how do you do this? Are these individual cloned templates that get their own updates, are they AppVMs using snap, flatpak, etc., or are you doing something else?

I customize my own minimal template with my settings (themes, packages I want in all templates etc) and then clone all other templates from this one / add specific packages. Building all my templates is automated via bash scripts. I only use apt no snap/flatpack etc.

In addition I use apt-cacher-ng to streamline updates.