Can we automatically set default disposable template at the time of App qube creation?

Is there a way to automatically set the default disposable template for a new AppVM at the moment of its creation?

Specifically, I want to set whonix-workstation-18-dvm as the default disposable template for all new App qubes based on the whonix-workstation-18 template.

Currently, I have to set the default disposable template manually for every AppVM at the time of creation, because by default it is always set to “none”.

You could set default disposable template in qubes global settings, but it will affect all qubes, not just whonix-workstation-18.

Good alternative is to use salt, or a script.

Setting it in global configuration is not an option because that will set it for everything else.
Using salt? then I’ll have to create every app qube of whonix workstation using salt. Right?
Using script? How?

Here’s top shelf hack job for you:

#!/usr/bin/env bash

(
    set -o errexit
    set -o errtrace

    CMD="qvm-create"

    while [ $# -gt 0 ]
    do
        if [ "$1" == "--template" ] || [ "$1" == "-t" ]
        then
            CMD="$CMD $1"
            shift
            if [ "$1" == "whonix-workstation-18" ]
            then
                echo 'WOOF! whonix!!!'
                CMD="$CMD --prop default_dispvm=whonix-workstation-18-dvm"
            fi
        fi
        CMD="$CMD $1"
        shift
    done

    # Test it plenty, once confident - replace echo with just `$CMD`
    echo "$CMD"
)

Just give it the same arguments as you would to qvm-create

If I understand correctly, I’d have to use this script every time I want to create a new App qube (instead of the usual method). If that’s the case, Salt seems like a much better option.

Well yes, since it’s essentially a proxy between you and qvm-create. Depends on your preference between qvm-create and salt.

I assume seamless alternative would be either a daemon that listens for qube creation event or a hook script that runs on such an event. Unfortunately I don’t know how to do either.

You probably should ask for something like that in mailing list or matrix chat

This specific thing should happen automatically thanks to GitHub - QubesOS/qubes-core-admin-addon-whonix. It should default to (template-name)-dvm which is whonix-workstation-18-dvm here. But, you can also customize it by setting whonix-default-dispvm qvm-feature on the template to a name of disposable template to be used for app qubes based on such template.

For all of this to work, the template needs to have whonix-ws qvm-feature enabled, but again, it should be there by default.

So, if it doesn’t work, can you show what qvm-features prints for the whonix workstation template and the new app qube?

1 Like

On a fresh Qubes install, nothing related to disposables is set by default for the Whonix template:

qvm-features whonix-workstation-18
default-menu-items                             systemcheck.desktop janondisttorbrowser.desktop anondist-torbrowser_update.desktop pcmanfm-qt.desktop lxqt-config.desktop qterminal.desktop
menu-items                                     sysmaint-panel.desktop systemcheck.desktop repository-dist-wizard.desktop anondist-torbrowser_update.desktop lxqt-config.desktop qterminal.desktop
netvm-menu-items                               systemcheck.desktop janondisttorbrowser.desktop anondist-torbrowser_update.desktop pcmanfm-qt.desktop lxqt-config.desktop qterminal.desktop
qrexec                                         1
supported-rpc.qubes.SetDateTime.anondist-orig  1
supported-rpc.qubes.WaitForSession             1
supported-rpc.qubes.Filecopy                   1
supported-rpc.qubes.Gpg                        1
supported-rpc.qubes.SetDateTime                1
supported-rpc.qubes.SetMonitorLayout           1
supported-rpc.qubes.SelectFile                 1
supported-rpc.qubes.ShowInTerminal             1
supported-rpc.qubes.GpgImportKey               1
supported-rpc.qubes.SelectDirectory            1
supported-rpc.qubes.GetImageRGBA               1
supported-rpc.qubes.SuspendPostAll             1
supported-rpc.qubes.PdfConvert                 1
supported-rpc.qubes.TemplateDownload           1
supported-rpc.qubes.WaitForNetworkUplink       1
supported-rpc.qubes.GuiVMSession               1
supported-rpc.qubes.DetachPciDevice            1
supported-rpc.qubes.WaitForRunningSystem       1
supported-rpc.qubes.VMExecGUI                  1
supported-rpc.qubes.PostInstall                1
supported-rpc.qubes.VMExec                     1
supported-rpc.sdwdate-gui.ConnectCheck         1
supported-rpc.qubes.SetDateTime.anondist       1
supported-rpc.qubes.USBDetach                  1
supported-rpc.qubes.InstallUpdatesGUI          1
supported-rpc.qubes.USB                        1
supported-rpc.qubes.UpdatesProxy.anondist      1
supported-rpc.qubes.SuspendPre                 1
supported-rpc.qubes.StartApp                   1
supported-rpc.qubes.USBAttach                  1
supported-rpc.qubes.OpenURL                    1
supported-rpc.qubes.VMRootExec                 1
supported-rpc.qubes.OpenInVM                   1
supported-rpc.qubes.SuspendPreAll              1
supported-rpc.qubes.SuspendPost                1
supported-rpc.qubes.TemplateSearch             1
supported-rpc.qubes.ResizeDisk                 1
supported-rpc.qubes.VMRootShell                1
supported-rpc.qubes.Backup                     1
supported-rpc.qubes.GetAppmenus                1
supported-rpc.qubes.RestoreById                1
supported-rpc.qubes.VMShell                    1
supported-rpc.qubes.RegisterBackupLocation     1
supported-rpc.qubes.SyncNtpClock               1
supported-rpc.qubes.SyncNtpClock.anondist      1
supported-rpc.qubes.UpdatesProxy               1
supported-rpc.qubes.Restore                    1
supported-rpc.qubes.GetDate                    1
whonix-ws                                      1
supported-service.crond                        1
supported-service.gui-agent-clipboard-wipe     1
supported-service.minimal-netvm                1
supported-service.qubes-update-check           1
supported-service.minimal-usbvm                1
supported-service.pipewire                     1
supported-service.updates-proxy-setup          1
supported-service.qubes-network                1
supported-service.apparmor                     1
apparmor                                       1
supported-service.no-qubesincoming-cleanup     1
supported-service.qubes-updates-proxy          1
supported-service.qubes-firewall               1
supported-service.clocksync                    1
supported-service.meminfo-writer               1
os                                             Linux
os-distribution                                whonix
os-distribution-like                           debian
os-version                                     18
qubes-agent-version                            4.3
boot-mode.kernelopts.sysmaint                  boot-role=sysmaint systemd.unit=sysmaint-boot.target
boot-mode.kernelopts.unrestricted              remove-sysmaint-qubes
boot-mode.kernelopts.user                      
boot-mode.default-user.sysmaint                sysmaint
boot-mode.name.sysmaint                        PERSISTENT Mode - SYSMAINT Session
boot-mode.name.unrestricted                    PERSISTENT Mode - UNRESTRICTED Session
boot-mode.name.user                            PERSISTENT Mode - USER Session
boot-mode.active                               sysmaint
boot-mode.appvm-default                        user
gui                                            1
qubes-firewall                                 1
vmexec                                         1
template-name                                  whonix-workstation-18
template-epoch                                 0
template-version                               4.3.0
template-release                               202512111204
template-reponame                              @commandline
template-buildtime                             2025-12-11 12:24:35
template-installtime                           2025-12-22 13:54:47
template-license                               GPLv3+
template-url                                   http://www.qubes-os.org
template-summary                               Qubes OS template for whonix-workstation-18
template-description                           Qubes OS template for whonix-workstation-18.
updates-available                              
last-updates-check                             2025-12-31 10:11:43
supported-service.shutdown-idle                1
gui-events-max-delay                           100

When I create a new App qube based on this template, the resulting App qube automatically has whonix-workstation-18-dvm set as its default disposable template.

However, I then created a clone of the original template named whonix-workstation-18-web. Checking its features shows:

qvm-features whonix-workstation-18-web
default-menu-items                             systemcheck.desktop janondisttorbrowser.desktop anondist-torbrowser_update.desktop pcmanfm-qt.desktop lxqt-config.desktop qterminal.desktop
menu-items                                     repository-dist-wizard.desktop lxqt-config.desktop pcmanfm-qt.desktop qterminal.desktop systemcheck.desktop sysmaint-panel.desktop anondist-torbrowser_update.desktop
netvm-menu-items                               systemcheck.desktop janondisttorbrowser.desktop anondist-torbrowser_update.desktop pcmanfm-qt.desktop lxqt-config.desktop qterminal.desktop
qrexec                                         1
supported-rpc.qubes.SetDateTime.anondist-orig  1
supported-rpc.qubes.WaitForSession             1
supported-rpc.qubes.Filecopy                   1
supported-rpc.qubes.Gpg                        1
supported-rpc.qubes.SetDateTime                1
supported-rpc.qubes.SetMonitorLayout           1
supported-rpc.qubes.SelectFile                 1
supported-rpc.qubes.ShowInTerminal             1
supported-rpc.qubes.GpgImportKey               1
supported-rpc.qubes.SelectDirectory            1
supported-rpc.qubes.GetImageRGBA               1
supported-rpc.qubes.SuspendPostAll             1
supported-rpc.qubes.PdfConvert                 1
supported-rpc.qubes.TemplateDownload           1
supported-rpc.qubes.WaitForNetworkUplink       1
supported-rpc.qubes.GuiVMSession               1
supported-rpc.qubes.DetachPciDevice            1
supported-rpc.qubes.WaitForRunningSystem       1
supported-rpc.qubes.VMExecGUI                  1
supported-rpc.qubes.PostInstall                1
supported-rpc.qubes.VMExec                     1
supported-rpc.sdwdate-gui.ConnectCheck         1
supported-rpc.qubes.SetDateTime.anondist       1
supported-rpc.qubes.USBDetach                  1
supported-rpc.qubes.InstallUpdatesGUI          1
supported-rpc.qubes.USB                        1
supported-rpc.qubes.UpdatesProxy.anondist      1
supported-rpc.qubes.SuspendPre                 1
supported-rpc.qubes.StartApp                   1
supported-rpc.qubes.USBAttach                  1
supported-rpc.qubes.OpenURL                    1
supported-rpc.qubes.VMRootExec                 1
supported-rpc.qubes.OpenInVM                   1
supported-rpc.qubes.SuspendPreAll              1
supported-rpc.qubes.SuspendPost                1
supported-rpc.qubes.TemplateSearch             1
supported-rpc.qubes.ResizeDisk                 1
supported-rpc.qubes.VMRootShell                1
supported-rpc.qubes.Backup                     1
supported-rpc.qubes.GetAppmenus                1
supported-rpc.qubes.RestoreById                1
supported-rpc.qubes.VMShell                    1
supported-rpc.qubes.RegisterBackupLocation     1
supported-rpc.qubes.SyncNtpClock               1
supported-rpc.qubes.SyncNtpClock.anondist      1
supported-rpc.qubes.UpdatesProxy               1
supported-rpc.qubes.Restore                    1
supported-rpc.qubes.GetDate                    1
whonix-ws                                      1
supported-service.crond                        1
supported-service.gui-agent-clipboard-wipe     1
supported-service.minimal-netvm                1
supported-service.qubes-update-check           1
supported-service.minimal-usbvm                1
supported-service.pipewire                     1
supported-service.updates-proxy-setup          1
supported-service.qubes-network                1
supported-service.apparmor                     1
apparmor                                       1
supported-service.no-qubesincoming-cleanup     1
supported-service.qubes-updates-proxy          1
supported-service.qubes-firewall               1
supported-service.clocksync                    1
supported-service.meminfo-writer               1
os                                             Linux
os-distribution                                whonix
os-distribution-like                           debian
os-version                                     18
qubes-agent-version                            4.3
boot-mode.kernelopts.sysmaint                  boot-role=sysmaint systemd.unit=sysmaint-boot.target
boot-mode.kernelopts.unrestricted              remove-sysmaint-qubes
boot-mode.kernelopts.user                      
boot-mode.default-user.sysmaint                sysmaint
boot-mode.name.sysmaint                        PERSISTENT Mode - SYSMAINT Session
boot-mode.name.unrestricted                    PERSISTENT Mode - UNRESTRICTED Session
boot-mode.name.user                            PERSISTENT Mode - USER Session
boot-mode.active                               sysmaint
boot-mode.appvm-default                        user
gui                                            1
qubes-firewall                                 1
vmexec                                         1
template-name                                  whonix-workstation-18
template-epoch                                 0
template-version                               4.3.0
template-release                               202512111204
template-reponame                              @commandline
template-buildtime                             2025-12-11 12:24:35
template-installtime                           2025-12-22 13:54:47
template-license                               GPLv3+
template-url                                   http://www.qubes-os.org
template-summary                               Qubes OS template for whonix-workstation-18
template-description                           Qubes OS template for whonix-workstation-18.
updates-available                              
last-updates-check                             2026-01-04 04:26:46
supported-service.shutdown-idle                1
gui-events-max-delay                           100

App qubes created from this cloned template do not get any default disposable template set on creation.

I manually tried to set the feature on the cloned template:

qvm-features whonix-workstation-18-web whonix-default-dispvm whonix-workstation-18-dvm

But new App qubes based on whonix-workstation-18-web still do not inherit whonix-workstation-18-dvm as their default disposable template.

This looks correct.
I think I know what happened. There is a check if default_dispvm is none, with a comment user must have changed it manually - in which case the above default does not apply. But that may also happen if the global default dispvm is set to none - is it? Is it better if you change the global default to something else?

@arraybolt3 should it maybe check for vm.property_is_default("default_dispvm") instead?

This sounds plausible, but why then do AppVMs made from the first template have their default_dispvm set properly? Do they inherit it from the template they’re built from? If so, that would mean marcos-morar’s original template has the property set. But then why would it not be set on the cloned template, wouldn’t it inherit it from that template? There might be a deeper issue here.

As long as it can differentiate between “property is defaulting to the global default” and “property was set by the user to a value that happens to be the same as the global default”, that sounds like it would work. I would guess it can do that.

There’s definitely a deeper issue here. I can reproduce this on my machine, even though the “Default disposable template” in Qubes OS Global Config is set to default-dvm. Will investigate and try to find a fix.

Edit: Found it:

            elif template is not None:
                # If we have a template, use it for assuming a name.
                default_dispvm = template.name + "-dvm"

default_dispvm (the variable, not the property) ends up set to whonix-workstation-18-web-dvm, which doesn’t exist, so it ends up logging an error and setting the default_dispvm to None. (The error is in my qubesd journal logs.)

The fix should be easy enough; make sure that the VM name built by template.name + "-dvm" actually exists, and if it doesn’t, continue to the next fallback (hardcoded whonix-workstation-18-dvm).

Edit 2: PR created to fix: Fix a default_dispvm autodetect failure by ArrayBolt3 · Pull Request #29 · QubesOS/qubes-core-admin-addon-whonix · GitHub

global default is not none it is set to default-dvm

Similar to @arraybolt3 diagnosis:

On creating an app qube on a cloned template, qvm-create show following error in log:

qubesd[2988]: ERROR: vm.test: QubesWhonixExtension: default dispvm 'whonix-workstation-18-web-dvm' does not exist

1 Like

This is all whonix specific.

For more general use case you can set the default_dispvm at creation using:
qvm-create -t TEMPLATE -l LABEL --property default_dispVM=DVM QUBE

Or salted as:

create_qube_with_deb_dvm_disposable:
  qvm.vm:
    - name: test
    - present:
      - template: debian-13
      - label: purple
    - prefs:
      - default_dispvm: deb-dvm

Obviously you do not want a separate state file for each qube you create,
so create a list and iterate over it in jinja.

You could also add a check to make sure that the qube does not already
exist: qvm.exists provides such a check.

The advantage of salt is that it is self documenting. You will have
a record of the qubes and how they were created.

I never presume to speak for the Qubes team.
When I comment in the Forum I speak for myself.

1 Like

I do need to learn Salt, though. I feel it will make life a lot easier on Qubes, but I’ve been hesitant to get started for months now. :sweat:

The thing is to just start(salt or ansible).

You can easily begin to create qubes, and configure them. And you can
do a lot with just basic state files. If you want a step by step guide
you could look here which starts with the basics
and gradually adds more detail. There are many simple example states.

In the shaker you will find somewhat
more complicated configurations, but the states are deliberately kept
simple, and should be understandable by relative beginners.

Once you have the basics you can build on them, and you will have a self
documented system. One advantage - you can move to a new or temporary
machine, download some states and build a partial copy of your original
qubes, ready to restore (some or all) data. Good to do this when travelling.

I never presume to speak for the Qubes team. When I comment in the Forum I speak for myself.
1 Like