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:
- There is a section of the
settings.json
file calledapi_access_methods
whichmullvad
expects to be able to write a unique(?) ID to when logging into a Mullvad account for the first time withmullvad 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.) - 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:
- 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 addingmullvad account login
to thepostStart
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. - 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:
- 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? - 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? - If the json approach seems best, how would I go about modifying the existing
settings.json
without just supplying the file wholesale?