VPN access setup in Salt Formula - please give me feedback

Hi all,

I’m currently trying to create a ‘post-install script’ for my qubes setup, that is I run the script once after a fresh qubes install and everything is setup-up for me.

I intend to create this using a salt formula, I have used the following guide to teach myself the basics of salt in qubes: Configuration Management — Fieldnotes documentation

I am trying to come up with the best strategy for VPN access, best practices outlined by Mullvad for Qubes are specified here: WireGuard on Qubes OS | Mullvad VPN

Simply put, it recommends setting up a separate qube (ProxyVM) which will then function as another qubes NetVM.

The main part of this process is generating a .conf file using WireGuard configuration file generator.

This .conf file specifies a single wireguard server that the ProxyVM qube will connect to. This is somewhat of an issue as in order to follow best practices and if I want all server options available (like in the Mullvad app) I need to create a ProxyVM qube for each and every available Mullvad server endpoint.

As I mentioned earlier I am writing a salt formula to auto-setup qubes for me.

The salt formula would loop over each .conf file and generate a ProxyVM qube for each connection, each individual ProxyVM qube would follow the naming convention of the .conf file being used.


  • ‘al-tia-wg-001’ - this is a ProxyVM qube that connects to server 1 in Tirana, Albainia

  • ‘al-tia-wg-002’ - this is a ProxyVM qube that connects to server 2 in Tirana, Albainia

  • … and so on

In order to run the salt formula I would bulk download all of the .conf files (Mullvad allows you to do this) and copy all of the .conf files along with the salt formula into the /srv/user_salt directory in dom0 and execute the salt formula.

Then when I want to connect to a different VPN endpoint (if for example something is region locked) I start the ProxyVM qube I intend to use & connect the AppVM qube that I am working in to the new ProxyVM.

I don’t anticipate changing the VPN server endpoint for an AppVM very often but the goal is to have access to all available server endpoints provided by Mullvad.

I am new to qubes - could anyone provide any feedback on what I have outlined?

Is there a better way to accomplish this that I am not aware of?


1 Like

I think that would be the most convenient way to do this.
Maybe with some development it could be done in a more neat way but this seems to be the best approach right now.

Thankyou for your feedback.

I suspect your right, do you have any thoughts as to what the ‘neat’ approach would look like in the future?

I’d find that annoying too. My first thought to avoid the proliferation of ProxyVMs would be to change the .conf file and restart the ProxyVM. Do you think that has a chance to work?

Not related to Mullvad, a note on my Fieldnotes and a heads up on how I'm thinking about creating vs configuring VMs (in progress!)

Unrelated to that, while the notes you’re reading remain valid (I wrote them, in case it’s not obvious), please note that if you find yourself writing complicated Jinja files I’d recommend you to take a step back and shout here (you can ping me directly).

The reason for that is that since I wrote my notes, I’ve started thinking that it is often best (from a maintainer’s perspective) to separate the VM creation from the VM configuration in the Salt formulas. And a lot of the complexity in my experience tends to appear when trying to make the VM creation steps configurable by the end user. (You might not be there, but that’s the point of this heads up, that you can recognize when you get there. :slightly_smiling_face:)

I’m in the process of validating the work flow before updating my notes. (Don’t hold your breath, and please don’t stop what you’re doing; it’ll take time for me to write down everything, so keep going, and watch for complexity. A lot of complexity involving Jinja is a good indicator to pause and think.)

Happy to talk more about that in a separate topic. If you think you’re at that point, I’ve started discussing and documenting those ideas in this GitHub issue (follow the links there, stsrting by that issue #14 I’ve cross-references other issues and pull requests there — if you’re not familiar with GitHub, feel free to ask me for direct links, I can write down a little tour of those issues / pull requests):

For further context, the initial idea was discussed here:

And I’ve mentioned that idea of keeping VM creation and configuration separate here:

I’ll keep following this thread either way, the Mullvad config interests me, so I won’t be far :wink:

Well, you could do this, but the idea of having many almost identical
qubes hanging around unused, given that you “dont anticipate changing the VPN
server endpoint for an AppVM very often”, pains me.
If you’re happy with this, and it looks as if you are, then fine.
But your menus and manager are going to be unspeakably hard to use.

An alternative approach would be to generate the first one or two vpn
proxies, and then create new proxies as and when needed, using the base
wireguard template, and configuring them from one of the conf files you
have on hand.

Not really a good way to do it.
If you have 6 sys-mullvad-X VMs (sys-mullvad-1 - sys-mullvad-6) and you change confs in them from time to time it’ll be easy to forget which config is in which numbered sys-mullvad and mix them up.

I had a thought of a new VM type (along with AppVM, DisposableVM, etc) - dynamically named disposable.
You’ll create a qube named sys-mullvad and set it as disposable template (template_for_dispvm=True) and set a new preference that it’s a dynamically named disposable template (dynamically_named_template_for_dispvm=True).
It’ll be the same as DisposableVM but instead of creating dispX qubes it’ll create named disposables with naming “prefix + disposable template name + postfix”.
Prefix and postfix will be set as features in the qubes connected to this dynamically named disposable.
E.g. myqube1 will have sys-mullvad as its netvm and you’ll set a postfix feature for myqube1 with the name of the mullvad server e.g. al-tia-wg-001 (dyn_disp_postfix=al-tia-wg-001).
Now when you start myqube1 it’ll create and start (or use if it’s already started) a disposable named sys-mullvad-al-tia-wg-001 and use it as its netvm.
When sys-mullvad-al-tia-wg-001 is started it can use its postfix to select the needed VPN config.
And there’s also a need to add an ability to edit VM features with GUI using separate tab in qube Settings.

But all of it is just random thought and I don’t know if it’s a good way or even feasible to implement.

Let me clarify: I meant swapping config to avoid having more than one VM in the first place.

Oh, you mean to use only one sys-vpn. That’d be a specific case where you won’t need to use different locations for different qubes simultaneously. But it’s still a possible use case.

Good point, that was un unspoken assumption of mine, indeed. I see why it might not hold true!

I like the general idea of renaming VMs, sadly, because renaming implies cloning and deleting the original VM, I don’t see how that idea could be used to overcome this limitation. Thanks for pointing it out!