Writing a module with fragile stateful data

I am planning to write something to make it easier to set up a simple OpenVPN server on NixOS. It would handle all of the boilerplate config, certificate generation, and system setup, similar to openvpn-install. The problem is that in order to connect to the server, each client needs a config. If anything on the server changes, then every client will need a brand new config in order to connect. This is on top of managing all of the files that need to be generated and saved on the server’s end. I am trying to figure out a proper way to do this, but struggling.

I’ve considered:

  1. Just make a module to set things up, use a startup script to generate/regenerate all the stuff if it doesn’t exist. Simplest option, but also the most fragile. Any mistakes on the server admin’s part will require a complete reissuing of client configs.
  2. Module with some sort of “lock” setting. Basically, nothing is touched when the lock is turned on, but when it is turned off the whole thing gets regenerated basically every restart of the service. This idea just feels all-around awkward to me, and more of a bandaid than a real fix.
  3. A shell script similar to the one I linked, that generates all of the necessary files as well as an openvpn.nix file to put into the server config. This would be pretty stable and easy to use (I would think), but doesn’t feel like a “Nix-ic” way to do things.

I did something similar this when I was using nebula (since switched to tailscale).

The config had information about each host, each host then had a config file generated to make it work.

This file has the bulk of the information. It has paths to other files in the repo (at this commit) that it references to help generate the config. Comments are near non-existent, sorry about that. Hopefully this can help.

Thanks for the resource. However, this seems more like a personal setup, somewhat akin to option 1. What I’m trying to do is make a general resource that anyone can plug-n-play, to save people the headache I had getting this working.

I ended up going with option 1, but made it work by severely limiting the available configurations in the module. I think this is ok since it’s intended to be “sensible defaults”, not highly configurable. For reference to any googlers, GitHub - fin444/auto-openvpn.nix: Automatic configuration, certificate generation, and user management for OpenVPN on NixOS so you don't have to.