1 { config, lib, pkgs, ... }:
5 inherit (builtins) toFile;
6 inherit (lib) concatMapStrings concatStringsSep mapAttrsToList
7 mkIf mkEnableOption mkOption types literalExpression optionalString;
9 cfg = config.services.strongswan;
11 ipsecSecrets = secrets: concatMapStrings (f: "include ${f}\n") secrets;
13 ipsecConf = {setup, connections, ca}:
15 # https://wiki.strongswan.org/projects/strongswan/wiki/IpsecConf
16 makeSections = type: sections: concatStringsSep "\n\n" (
17 mapAttrsToList (sec: attrs:
19 (concatStringsSep "\n" ( mapAttrsToList (k: v: " ${k}=${v}") attrs ))
22 setupConf = makeSections "config" { inherit setup; };
23 connectionsConf = makeSections "conn" connections;
24 caConf = makeSections "ca" ca;
27 builtins.toFile "ipsec.conf" ''
33 strongswanConf = {setup, connections, ca, secretsFile, managePlugins, enabledPlugins}: toFile "strongswan.conf" ''
35 ${optionalString managePlugins "load_modular = no"}
36 ${optionalString managePlugins ("load = " + (concatStringsSep " " enabledPlugins))}
39 secrets_file = ${secretsFile}
45 config_file = ${ipsecConf { inherit setup connections ca; }}
51 options.services.strongswan = {
52 enable = mkEnableOption "strongSwan";
55 type = types.listOf types.str;
57 example = [ "/run/keys/ipsec-foo.secret" ];
59 A list of paths to IPSec secret files. These
60 files will be included into the main ipsec.secrets file with
61 the `include` directive. It is safer if these
67 type = types.attrsOf types.str;
69 example = { cachecrls = "yes"; strictcrlpolicy = "yes"; };
71 A set of options for the ‘config setup’ section of the
72 {file}`ipsec.conf` file. Defines general
73 configuration parameters.
77 connections = mkOption {
78 type = types.attrsOf (types.attrsOf types.str);
80 example = literalExpression ''
83 keyexchange = "ikev2";
88 leftcert = "/run/keys/moonCert.pem";
89 leftid = "@moon.strongswan.org";
90 leftsubnet = "10.1.0.0/16";
96 A set of connections and their options for the ‘conn xxx’
97 sections of the {file}`ipsec.conf` file.
102 type = types.attrsOf (types.attrsOf types.str);
107 cacert = "/run/keys/strongswanCert.pem";
108 crluri = "http://crl2.strongswan.org/strongswan.crl";
112 A set of CAs (certification authorities) and their options for
113 the ‘ca xxx’ sections of the {file}`ipsec.conf`
118 managePlugins = mkOption {
122 If set to true, this option will disable automatic plugin loading and
123 then tell strongSwan to enable the plugins specified in the
124 {option}`enabledPlugins` option.
128 enabledPlugins = mkOption {
129 type = types.listOf types.str;
132 A list of additional plugins to enable if
133 {option}`managePlugins` is true.
139 config = with cfg; mkIf enable
142 # here we should use the default strongswan ipsec.secrets and
143 # append to it (default one is empty so not a pb for now)
144 environment.etc."ipsec.secrets".text = ipsecSecrets cfg.secrets;
146 systemd.services.strongswan = {
147 description = "strongSwan IPSec Service";
148 wantedBy = [ "multi-user.target" ];
149 path = with pkgs; [ kmod iproute2 iptables util-linux ]; # XXX Linux
150 wants = [ "network-online.target" ];
151 after = [ "network-online.target" ];
153 STRONGSWAN_CONF = strongswanConf {
154 inherit setup connections ca managePlugins enabledPlugins;
155 secretsFile = "/etc/ipsec.secrets";
159 ExecStart = "${pkgs.strongswan}/sbin/ipsec start --nofork";
162 # with 'nopeerdns' setting, ppp writes into this folder
163 mkdir -m 700 -p /etc/ppp