at 24.11-pre 4.9 kB view raw
1{ config, lib, pkgs, ... }: 2 3let 4 5 inherit (builtins) toFile; 6 inherit (lib) concatMapStringsSep concatStringsSep mapAttrsToList 7 mkIf mkEnableOption mkOption types literalExpression optionalString; 8 9 cfg = config.services.strongswan; 10 11 ipsecSecrets = secrets: toFile "ipsec.secrets" ( 12 concatMapStringsSep "\n" (f: "include ${f}") secrets 13 ); 14 15 ipsecConf = {setup, connections, ca}: 16 let 17 # https://wiki.strongswan.org/projects/strongswan/wiki/IpsecConf 18 makeSections = type: sections: concatStringsSep "\n\n" ( 19 mapAttrsToList (sec: attrs: 20 "${type} ${sec}\n" + 21 (concatStringsSep "\n" ( mapAttrsToList (k: v: " ${k}=${v}") attrs )) 22 ) sections 23 ); 24 setupConf = makeSections "config" { inherit setup; }; 25 connectionsConf = makeSections "conn" connections; 26 caConf = makeSections "ca" ca; 27 28 in 29 builtins.toFile "ipsec.conf" '' 30 ${setupConf} 31 ${connectionsConf} 32 ${caConf} 33 ''; 34 35 strongswanConf = {setup, connections, ca, secretsFile, managePlugins, enabledPlugins}: toFile "strongswan.conf" '' 36 charon { 37 ${optionalString managePlugins "load_modular = no"} 38 ${optionalString managePlugins ("load = " + (concatStringsSep " " enabledPlugins))} 39 plugins { 40 stroke { 41 secrets_file = ${secretsFile} 42 } 43 } 44 } 45 46 starter { 47 config_file = ${ipsecConf { inherit setup connections ca; }} 48 } 49 ''; 50 51in 52{ 53 options.services.strongswan = { 54 enable = mkEnableOption "strongSwan"; 55 56 secrets = mkOption { 57 type = types.listOf types.str; 58 default = []; 59 example = [ "/run/keys/ipsec-foo.secret" ]; 60 description = '' 61 A list of paths to IPSec secret files. These 62 files will be included into the main ipsec.secrets file with 63 the `include` directive. It is safer if these 64 paths are absolute. 65 ''; 66 }; 67 68 setup = mkOption { 69 type = types.attrsOf types.str; 70 default = {}; 71 example = { cachecrls = "yes"; strictcrlpolicy = "yes"; }; 72 description = '' 73 A set of options for the config setup section of the 74 {file}`ipsec.conf` file. Defines general 75 configuration parameters. 76 ''; 77 }; 78 79 connections = mkOption { 80 type = types.attrsOf (types.attrsOf types.str); 81 default = {}; 82 example = literalExpression '' 83 { 84 "%default" = { 85 keyexchange = "ikev2"; 86 keyingtries = "1"; 87 }; 88 roadwarrior = { 89 auto = "add"; 90 leftcert = "/run/keys/moonCert.pem"; 91 leftid = "@moon.strongswan.org"; 92 leftsubnet = "10.1.0.0/16"; 93 right = "%any"; 94 }; 95 } 96 ''; 97 description = '' 98 A set of connections and their options for the conn xxx 99 sections of the {file}`ipsec.conf` file. 100 ''; 101 }; 102 103 ca = mkOption { 104 type = types.attrsOf (types.attrsOf types.str); 105 default = {}; 106 example = { 107 strongswan = { 108 auto = "add"; 109 cacert = "/run/keys/strongswanCert.pem"; 110 crluri = "http://crl2.strongswan.org/strongswan.crl"; 111 }; 112 }; 113 description = '' 114 A set of CAs (certification authorities) and their options for 115 the ca xxx sections of the {file}`ipsec.conf` 116 file. 117 ''; 118 }; 119 120 managePlugins = mkOption { 121 type = types.bool; 122 default = false; 123 description = '' 124 If set to true, this option will disable automatic plugin loading and 125 then tell strongSwan to enable the plugins specified in the 126 {option}`enabledPlugins` option. 127 ''; 128 }; 129 130 enabledPlugins = mkOption { 131 type = types.listOf types.str; 132 default = []; 133 description = '' 134 A list of additional plugins to enable if 135 {option}`managePlugins` is true. 136 ''; 137 }; 138 }; 139 140 141 config = with cfg; 142 let 143 secretsFile = ipsecSecrets cfg.secrets; 144 in 145 mkIf enable 146 { 147 148 # here we should use the default strongswan ipsec.secrets and 149 # append to it (default one is empty so not a pb for now) 150 environment.etc."ipsec.secrets".source = secretsFile; 151 152 systemd.services.strongswan = { 153 description = "strongSwan IPSec Service"; 154 wantedBy = [ "multi-user.target" ]; 155 path = with pkgs; [ kmod iproute2 iptables util-linux ]; # XXX Linux 156 wants = [ "network-online.target" ]; 157 after = [ "network-online.target" ]; 158 environment = { 159 STRONGSWAN_CONF = strongswanConf { inherit setup connections ca secretsFile managePlugins enabledPlugins; }; 160 }; 161 serviceConfig = { 162 ExecStart = "${pkgs.strongswan}/sbin/ipsec start --nofork"; 163 }; 164 preStart = '' 165 # with 'nopeerdns' setting, ppp writes into this folder 166 mkdir -m 700 -p /etc/ppp 167 ''; 168 }; 169 }; 170} 171