at 17.09-beta 5.2 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.services.openvpn; 8 9 inherit (pkgs) openvpn; 10 11 makeOpenVPNJob = cfg: name: 12 let 13 14 path = (getAttr "openvpn-${name}" config.systemd.services).path; 15 16 upScript = '' 17 #! /bin/sh 18 export PATH=${path} 19 20 # For convenience in client scripts, extract the remote domain 21 # name and name server. 22 for var in ''${!foreign_option_*}; do 23 x=(''${!var}) 24 if [ "''${x[0]}" = dhcp-option ]; then 25 if [ "''${x[1]}" = DOMAIN ]; then domain="''${x[2]}" 26 elif [ "''${x[1]}" = DNS ]; then nameserver="''${x[2]}" 27 fi 28 fi 29 done 30 31 ${cfg.up} 32 ${optionalString cfg.updateResolvConf 33 "${pkgs.update-resolv-conf}/libexec/openvpn/update-resolv-conf"} 34 ''; 35 36 downScript = '' 37 #! /bin/sh 38 export PATH=${path} 39 ${optionalString cfg.updateResolvConf 40 "${pkgs.update-resolv-conf}/libexec/openvpn/update-resolv-conf"} 41 ${cfg.down} 42 ''; 43 44 configFile = pkgs.writeText "openvpn-config-${name}" 45 '' 46 errors-to-stderr 47 ${optionalString (cfg.up != "" || cfg.down != "" || cfg.updateResolvConf) "script-security 2"} 48 ${cfg.config} 49 ${optionalString (cfg.up != "" || cfg.updateResolvConf) 50 "up ${pkgs.writeScript "openvpn-${name}-up" upScript}"} 51 ${optionalString (cfg.down != "" || cfg.updateResolvConf) 52 "down ${pkgs.writeScript "openvpn-${name}-down" downScript}"} 53 ''; 54 55 in { 56 description = "OpenVPN instance ${name}"; 57 58 wantedBy = optional cfg.autoStart "multi-user.target"; 59 after = [ "network.target" ]; 60 61 path = [ pkgs.iptables pkgs.iproute pkgs.nettools ]; 62 63 serviceConfig.ExecStart = "@${openvpn}/sbin/openvpn openvpn --config ${configFile}"; 64 serviceConfig.Restart = "always"; 65 serviceConfig.Type = "notify"; 66 }; 67 68in 69 70{ 71 72 ###### interface 73 74 options = { 75 76 services.openvpn.servers = mkOption { 77 default = {}; 78 79 example = literalExample '' 80 { 81 server = { 82 config = ''' 83 # Simplest server configuration: http://openvpn.net/index.php/documentation/miscellaneous/static-key-mini-howto.html. 84 # server : 85 dev tun 86 ifconfig 10.8.0.1 10.8.0.2 87 secret /root/static.key 88 '''; 89 up = "ip route add ..."; 90 down = "ip route del ..."; 91 }; 92 93 client = { 94 config = ''' 95 client 96 remote vpn.example.org 97 dev tun 98 proto tcp-client 99 port 8080 100 ca /root/.vpn/ca.crt 101 cert /root/.vpn/alice.crt 102 key /root/.vpn/alice.key 103 '''; 104 up = "echo nameserver $nameserver | ''${pkgs.openresolv}/sbin/resolvconf -m 0 -a $dev"; 105 down = "''${pkgs.openresolv}/sbin/resolvconf -d $dev"; 106 }; 107 } 108 ''; 109 110 description = '' 111 Each attribute of this option defines a systemd service that 112 runs an OpenVPN instance. These can be OpenVPN servers or 113 clients. The name of each systemd service is 114 <literal>openvpn-<replaceable>name</replaceable>.service</literal>, 115 where <replaceable>name</replaceable> is the corresponding 116 attribute name. 117 ''; 118 119 type = with types; attrsOf (submodule { 120 121 options = { 122 123 config = mkOption { 124 type = types.lines; 125 description = '' 126 Configuration of this OpenVPN instance. See 127 <citerefentry><refentrytitle>openvpn</refentrytitle><manvolnum>8</manvolnum></citerefentry> 128 for details. 129 ''; 130 }; 131 132 up = mkOption { 133 default = ""; 134 type = types.lines; 135 description = '' 136 Shell commands executed when the instance is starting. 137 ''; 138 }; 139 140 down = mkOption { 141 default = ""; 142 type = types.lines; 143 description = '' 144 Shell commands executed when the instance is shutting down. 145 ''; 146 }; 147 148 autoStart = mkOption { 149 default = true; 150 type = types.bool; 151 description = "Whether this OpenVPN instance should be started automatically."; 152 }; 153 154 updateResolvConf = mkOption { 155 default = false; 156 type = types.bool; 157 description = '' 158 Use the script from the update-resolv-conf package to automatically 159 update resolv.conf with the DNS information provided by openvpn. The 160 script will be run after the "up" commands and before the "down" commands. 161 ''; 162 }; 163 164 }; 165 166 }); 167 168 }; 169 170 }; 171 172 173 ###### implementation 174 175 config = mkIf (cfg.servers != {}) { 176 177 systemd.services = listToAttrs (mapAttrsFlatten (name: value: nameValuePair "openvpn-${name}" (makeOpenVPNJob value name)) cfg.servers); 178 179 environment.systemPackages = [ openvpn ]; 180 181 boot.kernelModules = [ "tun" ]; 182 183 }; 184 185}