1 { config, lib, pkgs, ... }:
5 inherit (builtins) toFile;
6 inherit (lib) concatMapStringsSep concatStringsSep mapAttrsToList
7 mkIf mkEnableOption mkOption types literalExpression;
9 cfg = config.services.strongswan;
11 ipsecSecrets = secrets: toFile "ipsec.secrets" (
12 concatMapStringsSep "\n" (f: "include ${f}") secrets
15 ipsecConf = {setup, connections, ca}:
17 # https://wiki.strongswan.org/projects/strongswan/wiki/IpsecConf
18 makeSections = type: sections: concatStringsSep "\n\n" (
19 mapAttrsToList (sec: attrs:
21 (concatStringsSep "\n" ( mapAttrsToList (k: v: " ${k}=${v}") attrs ))
24 setupConf = makeSections "config" { inherit setup; };
25 connectionsConf = makeSections "conn" connections;
26 caConf = makeSections "ca" ca;
29 builtins.toFile "ipsec.conf" ''
35 strongswanConf = {setup, connections, ca, secretsFile, managePlugins, enabledPlugins}: toFile "strongswan.conf" ''
37 ${if managePlugins then "load_modular = no" else ""}
38 ${if managePlugins then ("load = " + (concatStringsSep " " enabledPlugins)) else ""}
41 secrets_file = ${secretsFile}
47 config_file = ${ipsecConf { inherit setup connections ca; }}
53 options.services.strongswan = {
54 enable = mkEnableOption (lib.mdDoc "strongSwan");
57 type = types.listOf types.str;
59 example = [ "/run/keys/ipsec-foo.secret" ];
60 description = lib.mdDoc ''
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
69 type = types.attrsOf types.str;
71 example = { cachecrls = "yes"; strictcrlpolicy = "yes"; };
72 description = lib.mdDoc ''
73 A set of options for the ‘config setup’ section of the
74 {file}`ipsec.conf` file. Defines general
75 configuration parameters.
79 connections = mkOption {
80 type = types.attrsOf (types.attrsOf types.str);
82 example = literalExpression ''
85 keyexchange = "ikev2";
90 leftcert = "/run/keys/moonCert.pem";
91 leftid = "@moon.strongswan.org";
92 leftsubnet = "10.1.0.0/16";
97 description = lib.mdDoc ''
98 A set of connections and their options for the ‘conn xxx’
99 sections of the {file}`ipsec.conf` file.
104 type = types.attrsOf (types.attrsOf types.str);
109 cacert = "/run/keys/strongswanCert.pem";
110 crluri = "http://crl2.strongswan.org/strongswan.crl";
113 description = lib.mdDoc ''
114 A set of CAs (certification authorities) and their options for
115 the ‘ca xxx’ sections of the {file}`ipsec.conf`
120 managePlugins = mkOption {
123 description = lib.mdDoc ''
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.
130 enabledPlugins = mkOption {
131 type = types.listOf types.str;
133 description = lib.mdDoc ''
134 A list of additional plugins to enable if
135 {option}`managePlugins` is true.
143 secretsFile = ipsecSecrets cfg.secrets;
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;
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 after = [ "network-online.target" ];
158 STRONGSWAN_CONF = strongswanConf { inherit setup connections ca secretsFile managePlugins enabledPlugins; };
161 ExecStart = "${pkgs.strongswan}/sbin/ipsec start --nofork";
164 # with 'nopeerdns' setting, ppp writes into this folder
165 mkdir -m 700 -p /etc/ppp