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