terraform-providers.sumologic: 2.31.5 -> 3.0.0 (#365043)
[NixPkgs.git] / nixos / modules / services / networking / openvpn.nix
blob56b1f6f5ab8f263cb770dc9840651271bd697226
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
7   cfg = config.services.openvpn;
9   inherit (pkgs) openvpn;
11   makeOpenVPNJob = cfg: name:
12     let
14       path = makeBinPath (getAttr "openvpn-${name}" config.systemd.services).path;
16       upScript = ''
17         export PATH=${path}
19         # For convenience in client scripts, extract the remote domain
20         # name and name server.
21         for var in ''${!foreign_option_*}; do
22           x=(''${!var})
23           if [ "''${x[0]}" = dhcp-option ]; then
24             if [ "''${x[1]}" = DOMAIN ]; then domain="''${x[2]}"
25             elif [ "''${x[1]}" = DNS ]; then nameserver="''${x[2]}"
26             fi
27           fi
28         done
30         ${cfg.up}
31         ${optionalString cfg.updateResolvConf
32            "${pkgs.update-resolv-conf}/libexec/openvpn/update-resolv-conf"}
33       '';
35       downScript = ''
36         export PATH=${path}
37         ${optionalString cfg.updateResolvConf
38            "${pkgs.update-resolv-conf}/libexec/openvpn/update-resolv-conf"}
39         ${cfg.down}
40       '';
42       configFile = pkgs.writeText "openvpn-config-${name}"
43         ''
44           errors-to-stderr
45           ${optionalString (cfg.up != "" || cfg.down != "" || cfg.updateResolvConf) "script-security 2"}
46           ${cfg.config}
47           ${optionalString (cfg.up != "" || cfg.updateResolvConf)
48               "up ${pkgs.writeShellScript "openvpn-${name}-up" upScript}"}
49           ${optionalString (cfg.down != "" || cfg.updateResolvConf)
50               "down ${pkgs.writeShellScript "openvpn-${name}-down" downScript}"}
51           ${optionalString (cfg.authUserPass != null)
52               "auth-user-pass ${pkgs.writeText "openvpn-credentials-${name}" ''
53                 ${cfg.authUserPass.username}
54                 ${cfg.authUserPass.password}
55               ''}"}
56         '';
58     in
59     {
60       description = "OpenVPN instance ‘${name}’";
62       wantedBy = optional cfg.autoStart "multi-user.target";
63       after = [ "network.target" ];
65       path = [ pkgs.iptables pkgs.iproute2 pkgs.nettools ];
67       serviceConfig.ExecStart = "@${openvpn}/sbin/openvpn openvpn --suppress-timestamps --config ${configFile}";
68       serviceConfig.Restart = "always";
69       serviceConfig.Type = "notify";
70     };
72   restartService = optionalAttrs cfg.restartAfterSleep {
73     openvpn-restart = {
74       wantedBy = [ "sleep.target" ];
75       path = [ pkgs.procps ];
76       script = let
77         unitNames = map (n: "openvpn-${n}.service") (builtins.attrNames cfg.servers);
78       in "systemctl try-restart ${lib.escapeShellArgs unitNames}";
79       description = "Sends a signal to OpenVPN process to trigger a restart after return from sleep";
80     };
81   };
86   imports = [
87     (mkRemovedOptionModule [ "services" "openvpn" "enable" ] "")
88   ];
90   ###### interface
92   options = {
94     services.openvpn.servers = mkOption {
95       default = { };
97       example = literalExpression ''
98         {
99           server = {
100             config = '''
101               # Simplest server configuration: https://community.openvpn.net/openvpn/wiki/StaticKeyMiniHowto
102               # server :
103               dev tun
104               ifconfig 10.8.0.1 10.8.0.2
105               secret /root/static.key
106             ''';
107             up = "ip route add ...";
108             down = "ip route del ...";
109           };
111           client = {
112             config = '''
113               client
114               remote vpn.example.org
115               dev tun
116               proto tcp-client
117               port 8080
118               ca /root/.vpn/ca.crt
119               cert /root/.vpn/alice.crt
120               key /root/.vpn/alice.key
121             ''';
122             up = "echo nameserver $nameserver | ''${pkgs.openresolv}/sbin/resolvconf -m 0 -a $dev";
123             down = "''${pkgs.openresolv}/sbin/resolvconf -d $dev";
124           };
125         }
126       '';
128       description = ''
129         Each attribute of this option defines a systemd service that
130         runs an OpenVPN instance.  These can be OpenVPN servers or
131         clients.  The name of each systemd service is
132         `openvpn-«name».service`,
133         where «name» is the corresponding
134         attribute name.
135       '';
137       type = with types; attrsOf (submodule {
139         options = {
141           config = mkOption {
142             type = types.lines;
143             description = ''
144               Configuration of this OpenVPN instance.  See
145               {manpage}`openvpn(8)`
146               for details.
148               To import an external config file, use the following definition:
149               `config = "config /path/to/config.ovpn"`
150             '';
151           };
153           up = mkOption {
154             default = "";
155             type = types.lines;
156             description = ''
157               Shell commands executed when the instance is starting.
158             '';
159           };
161           down = mkOption {
162             default = "";
163             type = types.lines;
164             description = ''
165               Shell commands executed when the instance is shutting down.
166             '';
167           };
169           autoStart = mkOption {
170             default = true;
171             type = types.bool;
172             description = "Whether this OpenVPN instance should be started automatically.";
173           };
175           updateResolvConf = mkOption {
176             default = false;
177             type = types.bool;
178             description = ''
179               Use the script from the update-resolv-conf package to automatically
180               update resolv.conf with the DNS information provided by openvpn. The
181               script will be run after the "up" commands and before the "down" commands.
182             '';
183           };
185           authUserPass = mkOption {
186             default = null;
187             description = ''
188               This option can be used to store the username / password credentials
189               with the "auth-user-pass" authentication method.
191               WARNING: Using this option will put the credentials WORLD-READABLE in the Nix store!
192             '';
193             type = types.nullOr (types.submodule {
195               options = {
196                 username = mkOption {
197                   description = "The username to store inside the credentials file.";
198                   type = types.str;
199                 };
201                 password = mkOption {
202                   description = "The password to store inside the credentials file.";
203                   type = types.str;
204                 };
205               };
206             });
207           };
208         };
210       });
212     };
214     services.openvpn.restartAfterSleep = mkOption {
215       default = true;
216       type = types.bool;
217       description = "Whether OpenVPN client should be restarted after sleep.";
218     };
220   };
223   ###### implementation
225   config = mkIf (cfg.servers != { }) {
227     systemd.services = (listToAttrs (mapAttrsToList (name: value: nameValuePair "openvpn-${name}" (makeOpenVPNJob value name)) cfg.servers))
228       // restartService;
230     environment.systemPackages = [ openvpn ];
232     boot.kernelModules = [ "tun" ];
234   };