How to manipulate the Qubes OS menu via salt?

thread title adjustment?

I could be wrong but, I’ve been trying to track down this annoyance as well. It’s my impression that both @SteveC and myself have been wrestling with “salting menu items” per the official docs w/o much luck.

Perhaps an adjustment to reflect such might be more clear?

I’ve detected two topics in @SteveC and @unman’s communication and had the impression that the menu part was somewhat handled:

Let’s have to threads:


This was the original thread that discussed issues with the menu (not sequencing).

Possible glitch in KDE menuing (and other menus too) for Qubes disposable templates - User Support / General - Qubes OS Forum (

Originally, I was having trouble with DVM templates not showing up properly in the KDE menus, and originally I had to resort to creating the DVM template under a different name, then rename it to the proper one. If I didn’t do that, it never showed up as anything other than a normal AppVM (one that is not a DVM Template). That of course made it impossible to use the menu to launch a disp1234 type disposable.

THAT problem got solved, but as I tinkered more and more with it it appeared that different “classes” of VMs (and I am for purposes here considering a dvm template to be a different class than an AppVM…I know they’re technically the same under the hood, but from the user standpoint they are very different). I can’t give details right now as I am not on my Qubes system; I will amplify on this later.

[To repeat: For my purposes there are four “classes” of VM, four different cases: TemplateVMs, AppVMs, DVM Templates, and named DVMs. AppVMs and DVM Templates behave differently here.]

Another discovery I made is that calling qvm-sync-appmenus from within salt does absolutely nothing. In a “base” (dom0) run sls file, I can start the VM, run qvm-sync-appmenus, then shut down the VM (all in sequence of course, with requires and the like to ensure they don’t run in the wrong order), and the menu is not altered in the slightest (note: to verify this, make sure the menu is wrong before you start; run it in isolation rather than as part of a bigger sls file, which may have the menus right before even doing this, for some other reason). If I run those steps from the command line in a dom0 terminal, it works; and certainly the applications tab on the settings window works. I can also run the steps from a bash script. So I do. After every VM configure (invoked from a bash script) the bash script then does a start vm, qvm-sync-appmenus, shutdown vm. Yet another reason I have to run salt from bash, because salt won’t do this. I haven’t had to bring up the settings GUI to fix my menus and desktop shortcuts after the fact now, for several months (since I started doing this).

(NB, though: If the GUI tab page refresh is being run for a named dvm, and the disconnect is in the template VM, the GUI does not work; it only goes to the parent template (a DVM Template) for “updates”; it doesn’t go back to the DVM Template’s Template VM.)

This isn’t true, but perhaps it depends on how it’s called.

Here’s what I do, broken down by steps:

  1. Clone a template - clone
    - set menu-items and default-menu-items
    - start the template
  2. Run the installs
  3. Set config - any services, prefs, features etc
    - qvm-sync-appmenus
  4. Stop template
  5. Create any child qubes.

Starting the template early reduces the overhead of repeatedly
3, 4, and 5 can all be handled in a single qubesctl call.

I’ll wait for your details on the different cases.

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

qvm-sync-appmenus: I wrote a “post” sls file that I ran after setting everything up…so in essence, I’m going from step 1 through the first line of your step 3…then shutting down. Then -post.sls runs, and it starts the template, runs qvm-sync-appmenus, and stops the template. It never fixes anything when I do this. (I also tried putting commands for dom0 to wait a few seconds into the sequence.)

My sequence is -create.sls (clone, prefs, features, tags, menu-items and/or default-menu-items [but see below where I talk about menu setup]. This all happens on dom0. Then I run the installs (-configure.sls; this causes the disp-mgmt to start the vm and do the installs, with the states running on the vm. Finally I do -post.sls…if there’s anything to be done after installing; this is where I tried to use qvm-sync-appmenus but I removed it when it had no effect. (Without it I very rarely need a post.sls file.)

If I issue those three commands from the command prompt, it works. If i do it with a bash script, it works. But from salt, I can rerun it until I’m blue in the face and it won’t work.

I note that you appear to be setting the menu-items and default-menu-items before installing things. (Of course anything that existed on the qube you cloned is already there, but possibly other items haven’t been installed yet when you add them to the menu.) I’m doing that as well.

OK now on to what I have to do to get qubes to show up in the menu properly. I know this is going to get VERY confusing, but it turns out there are four distinct cases, and there’s a template-for-dispvms pref and an appmenus-dispvm feature involved too.

To recap that for the benefit of anyone trying to follow along:

A TemplateVM should show up as “template: ” with a double cube icon with the upper left of the qubes being a “ghost.” (Apparently that means “template” be it either a TemplateVM or Dvm Template.)

An AppVM that is not a DVM template should show up as “Qube: ” with a plain cube icon if icons are visible.

A DVM template should show up as “Template (disp): ” with a double cube icon with the upper left of the two qubes being a “ghost.” Note that this is the one that will actually run something on the DVM template itself, not on a disposable made from the template.

Then also (if enabled with “qvm-features appmenus-dispvm 1” [I don’t recall whether 0 or one is the default; I always just set it to one or the other without relying on the default]) “Disposable: ”–this will run disp1234. In this case it’s a double cube icon with the lower right qube being the “ghost”. If it’s a DVM template why would you want to disable this? It makes sense to do so if a named DVM is based on this DVM template and you never want to run disp1234 disposables off of it.

A Named DVM will look like “Qube: ” with the same “disposable” icon, solid cube upper left, ghost qube lower right. (The name of its DVM template does not appear, and that’s a good thing.)

For a TemplateVM OR an Appvm that isn’t a dvm template, I set menu-items only, not default-menu-items, during create.

For a DVM Template, I set default-menu-items only during create. I found that if I set menu-items here, the dvm template will show up in the KDE menu looking exactly like a regular AppVM, and you can’t launch disp1234 disposables from it. (This was the subject of this thread: Possible glitch in KDE menuing (and other menus too) for Qubes disposable templates - User Support / General - Qubes OS Forum (–I found out that if I didn’t do it the way I am describing here the qube would not be treated as a dvm template in the menus). Only after installing software do I then go back (in a bash shell, though I could create a “post.sls” file–the bash shell allows me to do it in just one place) and find out what’s in default-menu-items and set menu-items to the same thing. (This would probably be unnecessary if only I could set the template-for-dispvm during the qvm.present state, but apparently it has to be set in qvm.prefs state that runs after qvm.present. This is why cloning a “broken” vm worked: the clone is made of a qube that has the flag already properly set.) In that old thread, I was doing both default-menu-items and menu-items, and had to remove the menu-items setting in my create.sls file to get it to work properly. You reported yours was working fine, I started removing things from the sls file until I found the thing that was preventing it from working.

In all of the above cases, I then have to run qvm-sync-appmenus (as discussed above, I have to do it in bash because doing it in salt has no effect).

That leaves one case, the Named DVM. All I have to do there is set menu-items only. It just works, I won’t even have to run qvm-sync-appmenus on it. (I am not sure…since it should pick up the DVMT’s settings, I may not even need to set menu-items on it, unless it want it to differ from its template.)

I do not recall if I found that setting default-menu-items was harmful for non-dvmt-AppVMs, named dvms and Templates, or just useless. I do know that setting menu-items during create for dvm templates is harmful (as recounted in that other thread).

I can assure you that following this method works for me in creating
templates and qubes with the correct menu items. If you want to look at
working code look at the mutt shaker
Sometimes in KDE it’s necessary to log out and log back in to pick up
the new menu. This isn’t unique to Qubes menu manipulation.
I’ve just checked in Xfce, and that’s all working - I’ll have to lie
down now to recover from the horror of Xfce.

For changing a menu for a qube, I use something like this:

# vim: set syntax=yaml ts=2 sw=2 sts=2 et :

I know it’s been a nagging bother for both @SteveC and myself thus, thanks :handshake: SO much :pray: for jumping in on this!

My typical workflow (debian-11-minimal & debian-12-minimal preferred) is as follows:

  • A) Clone minimal template → new
    – 1) Install all teh t’ings
  • B) Create AppVM (Template for disposable)
    – 1) Configure teh t’ings (as necessary)
  • C) Create (Named) DispVM

Case #1)

Most of the time, when the package in question is installed via repo/manually downloaded package, shortcuts are immediately available within the new TemplateVM and as such, due to heredity, also immediately available in subsequent derived qubes.

Case #2)

Some of the time, when the package in question is installed via repo/manually downloaded package, shortcuts are not immediately available within the new TemplateVM and as such, due to heredity, also not immediately available in subsequent derived qubes.

Case #3)

Most of the time, when the package in question is installed via manually downloaded package/binary/source and a desktop shortcut is manually created (read created with vi/generated by piping some strings to file), shortcuts are not immediately available within the new TemplateVM and as such, due to heredity, not immediately available in subsequent derived qubes.

I’ve done my best to review “official” salt documentation, Qubes’ as well as scouring the forum/mail list/interwebs and. have generally came up mostly empty or less than preferred results.

I’ll start tacking this in to future formulae and circle back if need be. :carousel_horse:

Pretty sure I had my head in the sand :desert: because I was focusing more on the native salt docs. :person_facepalming:

As I was quite confident that the problem existed between the chair and the keyboard, I’m sending appreciation to you for this clarification. :bowing_woman:

The other sticking point for me is salting “Selected” Applications.

I’m primarily doing this for (Named) DispVMs but, also sometimes AppVMs (more often than not, “Template for disposible”) as well.

Albeit a bit hacky, I “thought” this via shell script would work:

echo 'most_excellent_application.desktop' | qvm-appmenus --set-whitelist - most_excellent_application

And, it does in fact “work” as, most_excellent_application is indeed “Selected” (displayed on the right-hand side of the Applications Tab within Qubes Manager) yet, not truly “Selected” as, most_excellent_application is not available via icon nor search in menu.

I’m thinking that the solution above may also address this :interrobang:

Because I don’t have the largest audience just yet; in the end, I often just breakdown to doing this dance :dancer: via the GUI. Absurd but, “just works”.

I think it would be a great help to know exactly which qvm-* cmds are being executed throughout that GUI ~workflow~ dance. :dancing_women:




Any noteworthy ~hacks~ workarounds to avoid this?

My last post seems to be severely truncated in the middle of a code block -
this looks like a pretty severe bug to me.
Assuming it’s been triggered by a hash followed by an empty line I will
try again without that combo:

It should say:

For changing a menu for a qube, I use something like this:

    - name: mutt
    - set:
      - menu-items: "mutt.desktop mutt_setup.desktop "
      - default-menu-items: "mutt.desktop mutt_setup.desktop "

'qvm-sync-appmenus mutt':
    - runas: user

Of course, it needs to be run against a running qube, but you can
include qvm.start in that state.

Again, that works in KDE and Xfce.

I hope this helps.
I need to take a break now, but I’ll try to pick up tomorrow.

1 Like

You also need to update the appmenus for that vm. e.g.

[user@dom0 ~]$ echo xterm.desktop | qvm-appmenus --set-whitelist - [VMNAME]
[user@dom0 ~]$ qvm-appmenus --update [VMNAME]

You can see the usage with qvm-appmenus -h.
There is also the man page (as you already know), but for qvm-appmenus,
the --help, -h give more infos.

1 Like

Thanks much for this. :handshake:

I’m beginning to wonder if my expectations of the Qubes saltstack implementation is unobtainium as, I’m trying to do this all-inclusive with salt state files w/o having the need to stop/start the VM just to perform this simple task (feel clumsy to me).

Very open to hearing from yourself or others with more experience with the Qubes saltstack implementation than I as to if this will/will not ever be possible such that I can either:

  1. do something differently
  2. accept it, incorporate into workflow & move on


I can’t help with Salt, I have any experience with it.

There’s an open issue for proper management of menus in salt in Qubes.

Many methods, including qvm-appmenus, require some extra action
for changes to be reflected in the menu. Menu entries are hard


Thanks mucho por the sanity check!

I see a few menu-related; ATM is there any one specifically worth tracking?

Ah, thanks for all of this. At least I’m not wrong in thinking there’s an issue here. I’ve obviously been using a workaround; now I know there are other workarounds (log out, log back in) that don’t involve a bash script or issuing commands outside of salt some other way. (Subject, of course to me experimenting to verify I’m not unknowingly doing something else that prevents logout/in from working as well.)

OKAY…I’ve learned something, at least with respect to qvm-sync-appmenus not working from salt.

Well, I’ve learned two things.

  1. Cayce is quite right that actual .deb packages installed will show up in the menus without having to do this. But if you “manually” install by doing file.managed on executables and desktop files, yes, the menus are broken and qvm-sync-appmenus is necessary. Ironically, I started rolling my own packages for things like split-veracrypt and my personally-written text editor, and even those crude packages “work” right. So I actually didn’t need to solve this problem, but I am OCD enough to be glad I did. (I had to do some extra work to get my test case to do it the old “manual” way on one of my apps, just so I could break the menu and prove this was a fix.)

  2. Apparently I was running qvm-sync-appmenus wrong. If you simply run it with, it complains that it can’t run as root, and then says --force root is necessary. DON’T DO THIS (I almost certainly did, months ago!). Instead do runas: user (or whatever your name is on dom0. (Interestingly --force-root is in my bash script…which works.)

Like this:

{% if grains['nodename'] == 'dom0' %}

        - name: deb11m-test-1

        - name: qvm-sync-appmenus deb11m-test-1
        - runas: user
#NOTE:  if your user name on dom0 is not 'user', put the correct dom0 user name here instead.
        - require: 
            - tmpl-test-1-update-startup

        - name: deb11m-test-1
        - require:
            - tmpl-test-1-update-menus

{% endif %}

I have to start and stop the VM, because the install .sls file shuts the VM down after running (it’s being done by disp-mgmt). However, it seems to run faster than my bash scripting of the same process does.

OK, that still leaves me with playing with the different kinds of VMs to see if the rules that I outlined above still hold. In the meantime, I can now write a generic “post” salt file to do this process for each VM after I create and configure/install it, and call that from my generic bash script (until I go back to the issue from the other side of the split and learn to control things more gracefully from a tls file).

More info:

I’m basing this on some simple test qubes…a template which installs the xfce terminal and thunar using apt install, and also installs my self-written text editor (named teg) “manually” (i.e. by copying the executable, desktop and icon files into the right places, rather than installing from a package). Even my self-rolled, very unelaborate deb packages seem to behave like “professional” packages.

Installing all three as stated into the template, and then trying to put all three in the menu, results in the links, and so forth, claiming that there is no teg. If I run the procedure in my prior message, teg shows up properly.

But, let’s say I don’t run that procedure, and don’t even try to put teg into menu-items in this template. Note that I apparently need not set default-menu-items at all. (I’m honestly not sure what this is supposed to do.) I’m doing this here because I want to see what happens when appvms and dvms add things to the menu. [Why would I want to do this? For instance, I don’t actually want libre office apps in the menu for the libre office template because I should never ever run it there; the disposable or regular appvm based on the template, on the other hand, yes it should be there. So I will want to add libre office to the menu in the dvm template or appvm as appropirate.]

If I create an appvm (that is not a dvm template) based on the template, and set the appvm’s menu items to include teg. it works, without any need to invoke qvm-sync-appmenus. (This is NOT what I remembered from before.) Again, no apparent need nor use for default-menu-items.

OK now for the tricky one, a dvm template. I’m still having to set default-menu-items to the desired list and then later set menu-items to that same list, in order to get the dvmt to show up as a disposable template, and a disposable (disp1234 type). However, I’ve discovered I can do both in the same salt file, I don’t have to do the menu-items later (as in in another sls file or from the bash script that invokes the first sls file. I just have to write two qvm.features states. In one of them I set default-menu-items; in the other, I set menu-items. I make the latter “require” the former. And it works. (That’s one less bash gyration to do; furthermore having both in the same .sls file makes it easy to ensure both default-menu-items and menu-items have the same list of .desktop files.) So it appears I’ve now avoided the necessity of logging out, and also don’t need anything outside of the creation .sls file (including qvm-sync-appmenus). Win-win!!

One last case, a dvm template with appmenus-dispvm disabled and a named disposable based on it. This seems to work properly without having to set default-menu-items or call qvm-sync-appmenus…PROVIDED you explicitly disable appmenus-dispvm. If you simply don’t reference it at all in features, then it breaks, and your dvm template looks like an ordinary AppVM in the menus. In other words, in the dvm template create sls file do this:

      - name: YourDVMTemplate
      - set:
           - default-menu-items: "<list your stuff here>"
      - disable:
           - appmenus-dispvm

not this:

      - name: YourDVMTemplate
      - set:
           - default-menu-items: "<list your stuff here>"

OK, I lied. One more thing. Let’s say you want the named disposable template (Test1-Disposable) to have a different menu from its dvm template. The only way I could find to make this work is to call qvm-appmenus-sync. The good news is, this can be done in the create file, since you will not be installing any software onto the named disposable.


  • Templates
    1 set menu-items in the create.sls file (dom0 target)
    2 create a “post.sls” file that invokes qvm-appmenus-sync, as described in my previous comment. Dom0 is the target.
    3 Between these two files you’ll have an sls file to do installs (runs on the template target).

  • Regular AppVms
    1 Simply set the menu-items in the create; it should work (even if the list is different from the template’s)

  • DVM templates
    1 set default-menu-items in the create.sls file
    2 make sure to either explicitly enable or explictily disable appmenus-dispvm in that same qvm.features state
    3 create a second qvm.features state that sets menu-items to the same thing as default-menu-items; use “require” to ensure it executes after the first one.

  • Named Disposables
    1 IF you want the menu-items to be different from the disposable template, set it in a qvm.features state, then, also in the create file (no need for a post), put the sequence of states to run qvm-appmenus-sync. If you don’t want it to be different you don’t have to do anything; it will inherit.


  • DVM templates
    1 set default-menu-items in the create.sls file
    2 make sure to either explicitly enable or explictily disable appmenus-dispvm in that same qvm.features state
    3 create a second qvm.features state that sets menu-items to the same thing as default-menu-items; use “require” to ensure it executes after the first one.

For some reason, now, this isn’t working for me. It probably does work fine if all you’re going to do with the DVM template is to base named DVMs off of it; in that case you don’t want the DVM template showing up as “Disposable:” in your menu, But if you want to create regular disposables (disp1234) from it, you DO want it showing up as “Disposable:” in the menu, and you have to set menu-items equal to whatever is in default-menu-items, in a separate sls file.

1 Like