Merge #361424: refactor lib.packagesFromDirectoryRecursive (v2)
[NixPkgs.git] / nixos / modules / services / networking / wg-access-server.nix
bloba0777fd86e3089bbc88d0706d00eb272aa12b1bf
2   config,
3   pkgs,
4   lib,
5   ...
6 }:
7 let
8   inherit (lib)
9     mkEnableOption
10     mkPackageOption
11     mkOption
12     types
13     ;
15   cfg = config.services.wg-access-server;
17   settingsFormat = pkgs.formats.yaml { };
18   configFile = settingsFormat.generate "config.yaml" cfg.settings;
22   options.services.wg-access-server = {
23     enable = mkEnableOption "wg-access-server";
25     package = mkPackageOption pkgs "wg-access-server" { };
27     settings = mkOption {
28       type = lib.types.submodule {
29         freeformType = settingsFormat.type;
30         options = {
31           dns.enabled = mkOption {
32             type = types.bool;
33             default = true;
34             description = ''
35               Enable/disable the embedded DNS proxy server.
36               This is enabled by default and allows VPN clients to avoid DNS leaks by sending all DNS requests to wg-access-server itself.
37             '';
38           };
39           storage = mkOption {
40             type = types.str;
41             default = "sqlite3://db.sqlite";
42             description = "A storage backend connection string. See [storage docs](https://www.freie-netze.org/wg-access-server/3-storage/)";
43           };
44         };
45       };
46       description = "See https://www.freie-netze.org/wg-access-server/2-configuration/ for possible options";
47     };
49     secretsFile = mkOption {
50       type = types.path;
51       description = ''
52         yaml file containing all secrets. this needs to be in the same structure as the configuration.
54         This must to contain the admin password and wireguard private key.
55         As well as the secrets for your auth backend.
57         Example:
58         ```yaml
59         adminPassword: <admin password>
60         wireguard:
61           privateKey: <wireguard private key>
62         auth:
63           oidc:
64             clientSecret: <client secret>
65         ```
66       '';
67     };
68   };
70   config = lib.mkIf cfg.enable {
71     assertions =
72       map
73         (attrPath: {
74           assertion = !lib.hasAttrByPath attrPath config.services.wg-access-server.settings;
75           message = ''
76             {option}`services.wg-access-server.settings.${lib.concatStringsSep "." attrPath}` must definded
77             in {option}`services.wg-access-server.secretsFile`.
78           '';
79         })
80         [
81           [ "adminPassword" ]
82           [
83             "wireguard"
84             "privateKey"
85           ]
86           [
87             "auth"
88             "sessionStore"
89           ]
90           [
91             "auth"
92             "oidc"
93             "clientSecret"
94           ]
95           [
96             "auth"
97             "gitlab"
98             "clientSecret"
99           ]
100         ];
102     boot.kernel.sysctl = {
103       "net.ipv4.conf.all.forwarding" = "1";
104       "net.ipv6.conf.all.forwarding" = "1";
105     };
107     systemd.services.wg-access-server = {
108       description = "WG access server";
109       wantedBy = [ "multi-user.target" ];
110       requires = [ "network-online.target" ];
111       after = [ "network-online.target" ];
112       script = ''
113         # merge secrets into main config
114         yq eval-all "select(fileIndex == 0) * select(fileIndex == 1)" ${configFile} $CREDENTIALS_DIRECTORY/SECRETS_FILE \
115           > "$STATE_DIRECTORY/config.yml"
117         ${lib.getExe cfg.package} serve --config "$STATE_DIRECTORY/config.yml"
118       '';
120       path = with pkgs; [
121         iptables
122         # needed by startup script
123         yq-go
124       ];
126       serviceConfig =
127         let
128           capabilities = [
129             "CAP_NET_ADMIN"
130           ] ++ lib.optional cfg.settings.dns.enabled "CAP_NET_BIND_SERVICE";
131         in
132         {
133           WorkingDirectory = "/var/lib/wg-access-server";
134           StateDirectory = "wg-access-server";
136           LoadCredential = [
137             "SECRETS_FILE:${cfg.secretsFile}"
138           ];
140           # Hardening
141           DynamicUser = true;
142           AmbientCapabilities = capabilities;
143           CapabilityBoundingSet = capabilities;
144         };
145     };
146   };