at 15.09-beta 4.5 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 ''; 33 34 downScript = '' 35 #! /bin/sh 36 export PATH=${path} 37 ${cfg.down} 38 ''; 39 40 configFile = pkgs.writeText "openvpn-config-${name}" 41 '' 42 errors-to-stderr 43 ${optionalString (cfg.up != "" || cfg.down != "") "script-security 2"} 44 ${cfg.config} 45 ${optionalString (cfg.up != "") "up ${pkgs.writeScript "openvpn-${name}-up" upScript}"} 46 ${optionalString (cfg.down != "") "down ${pkgs.writeScript "openvpn-${name}-down" downScript}"} 47 ''; 48 49 in { 50 description = "OpenVPN instance ${name}"; 51 52 wantedBy = optional cfg.autoStart "multi-user.target"; 53 after = [ "network-interfaces.target" ]; 54 55 path = [ pkgs.iptables pkgs.iproute pkgs.nettools ]; 56 57 serviceConfig.ExecStart = "@${openvpn}/sbin/openvpn openvpn --config ${configFile}"; 58 serviceConfig.Restart = "always"; 59 serviceConfig.Type = "notify"; 60 }; 61 62in 63 64{ 65 66 ###### interface 67 68 options = { 69 70 /* !!! Obsolete. */ 71 services.openvpn.enable = mkOption { 72 default = true; 73 description = "Whether to enable OpenVPN."; 74 }; 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 = types.attrsOf types.optionSet; 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 }; 155 156 }; 157 158 }; 159 160 161 ###### implementation 162 163 config = mkIf (cfg.servers != {}) { 164 165 systemd.services = listToAttrs (mapAttrsFlatten (name: value: nameValuePair "openvpn-${name}" (makeOpenVPNJob value name)) cfg.servers); 166 167 environment.systemPackages = [ openvpn ]; 168 169 boot.kernelModules = [ "tun" ]; 170 171 }; 172 173}