Help extending the 'mullvad-vpn' module for NixOS to include more configuration

The Issue

I’m looking to extend the NixOS module for Mullvad VPN to be able to configure the Mullvad daemon settings, which it stores in /etc/mullvad-vpn/settings.json.

It’s pretty straightforward to outline all of the available options in Nix format, and then use something like environment.etc."mullvad-vpn/settings.json".source with pkgs.formats.json.generate to turn that into an appropriate json file, but this approach has two issues:

  1. There is a section of the settings.json file called api_access_methods which mullvad expects to be able to write a unique(?) ID to when logging into a Mullvad account for the first time with mullvad account login, so it’s my impression that this file can’t be a symlink. (It’s worth noting I’m not very familiar with Rust which Mullvad is written in, so I’m not exactly clear on where this comes from.)
  2. The actual account number (a 16-digit number, credit-card style) is stored in /etc/mullvad-vpn/account-history.json, and the device configuration is created at the time of login at /etc/mullvad-vpn/device.json.

Possible Solutions

Based on this and some research, I’ve come up with a couple possible approaches:

  1. Use something like this blog post about declaratively setting up Mullvad with NixOS which would just tack on Mullvad CLI commands to the postStart of the systemd service to change the relevant settings. This feels a little clumsy, but would easily allow for supplying account details and adding mullvad account login to the postStart commands with some kind of check to make sure the user is not already logged in. It also limits configuring fancier stuff like custom endpoint lists which would be much easier to write in Nix/json.
  2. Outline all available configuration options in Nix format as described above, but instead use it to somehow modify the existing file in-place so that the necessary keys are still writable. I know this is definitely possible, but I’m not clear on exactly how to do so. This also still leaves out being able to configure in the account number. The account itself could be done with an activation script(?) or postStart command though.

My Question(s)

So I have a few questions based on my current understanding:

  1. What is the best-practice way to expand the module? Adding commands to the system service, modifying settings.json in-place, or some other approach I may be missing?
  2. If the first approach seems best, is postStart the way to go as detailed in the blog post I linked, or would it be better to use some other on-activation script?
  3. If the json approach seems best, how would I go about modifying the existing settings.json without just supplying the file wholesale?


  1. Example Mullvad settings.json
  2. The blog post detailing the first postStart method I discussed
  3. The current mullvad-vpn module
  4. My own sorta-working example module that generates settings.json from Nix
1 Like