 1d0fc9729d
			
		
	
	
		1d0fc9729d
		
			
		
	
	
	
	
		
			
			Many options define their example to be a Nix value without using literalExample. This sometimes gets rendered incorrectly in the manual, causing confusion like in https://github.com/NixOS/nixpkgs/issues/25516 This fixes it by using literalExample for such options. The list of option to fix was determined with this expression: let nixos = import ./nixos { configuration = {}; }; lib = import ./lib; valid = d: { # escapeNixIdentifier from https://github.com/NixOS/nixpkgs/pull/82461 set = lib.all (n: lib.strings.escapeNixIdentifier n == n) (lib.attrNames d) && lib.all (v: valid v) (lib.attrValues d); list = lib.all (v: valid v) d; }.${builtins.typeOf d} or true; optionList = lib.optionAttrSetToDocList nixos.options; in map (opt: { file = lib.elemAt opt.declarations 0; loc = lib.options.showOption opt.loc; }) (lib.filter (opt: if opt ? example then ! valid opt.example else false) optionList) which when evaluated will output all options that use a Nix identifier that would need escaping as an attribute name.
		
			
				
	
	
		
			171 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			171 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
| { config, lib, pkgs, ... }:
 | ||
| 
 | ||
| let
 | ||
| 
 | ||
|   inherit (builtins) toFile;
 | ||
|   inherit (lib) concatMapStringsSep concatStringsSep mapAttrsToList
 | ||
|                 mkIf mkEnableOption mkOption types literalExample;
 | ||
| 
 | ||
|   cfg = config.services.strongswan;
 | ||
| 
 | ||
|   ipsecSecrets = secrets: toFile "ipsec.secrets" (
 | ||
|     concatMapStringsSep "\n" (f: "include ${f}") secrets
 | ||
|   );
 | ||
| 
 | ||
|   ipsecConf = {setup, connections, ca}:
 | ||
|     let
 | ||
|       # https://wiki.strongswan.org/projects/strongswan/wiki/IpsecConf
 | ||
|       makeSections = type: sections: concatStringsSep "\n\n" (
 | ||
|         mapAttrsToList (sec: attrs:
 | ||
|           "${type} ${sec}\n" +
 | ||
|             (concatStringsSep "\n" ( mapAttrsToList (k: v: "  ${k}=${v}") attrs ))
 | ||
|         ) sections
 | ||
|       );
 | ||
|       setupConf       = makeSections "config" { inherit setup; };
 | ||
|       connectionsConf = makeSections "conn" connections;
 | ||
|       caConf          = makeSections "ca" ca;
 | ||
| 
 | ||
|     in
 | ||
|     builtins.toFile "ipsec.conf" ''
 | ||
|       ${setupConf}
 | ||
|       ${connectionsConf}
 | ||
|       ${caConf}
 | ||
|     '';
 | ||
| 
 | ||
|   strongswanConf = {setup, connections, ca, secretsFile, managePlugins, enabledPlugins}: toFile "strongswan.conf" ''
 | ||
|     charon {
 | ||
|       ${if managePlugins then "load_modular = no" else ""}
 | ||
|       ${if managePlugins then ("load = " + (concatStringsSep " " enabledPlugins)) else ""}
 | ||
|       plugins {
 | ||
|         stroke {
 | ||
|           secrets_file = ${secretsFile}
 | ||
|         }
 | ||
|       }
 | ||
|     }
 | ||
| 
 | ||
|     starter {
 | ||
|       config_file = ${ipsecConf { inherit setup connections ca; }}
 | ||
|     }
 | ||
|   '';
 | ||
| 
 | ||
| in
 | ||
| {
 | ||
|   options.services.strongswan = {
 | ||
|     enable = mkEnableOption "strongSwan";
 | ||
| 
 | ||
|     secrets = mkOption {
 | ||
|       type = types.listOf types.str;
 | ||
|       default = [];
 | ||
|       example = [ "/run/keys/ipsec-foo.secret" ];
 | ||
|       description = ''
 | ||
|         A list of paths to IPSec secret files. These
 | ||
|         files will be included into the main ipsec.secrets file with
 | ||
|         the <literal>include</literal> directive. It is safer if these
 | ||
|         paths are absolute.
 | ||
|       '';
 | ||
|     };
 | ||
| 
 | ||
|     setup = mkOption {
 | ||
|       type = types.attrsOf types.str;
 | ||
|       default = {};
 | ||
|       example = { cachecrls = "yes"; strictcrlpolicy = "yes"; };
 | ||
|       description = ''
 | ||
|         A set of options for the ‘config setup’ section of the
 | ||
|         <filename>ipsec.conf</filename> file. Defines general
 | ||
|         configuration parameters.
 | ||
|       '';
 | ||
|     };
 | ||
| 
 | ||
|     connections = mkOption {
 | ||
|       type = types.attrsOf (types.attrsOf types.str);
 | ||
|       default = {};
 | ||
|       example = literalExample ''
 | ||
|         {
 | ||
|           "%default" = {
 | ||
|             keyexchange = "ikev2";
 | ||
|             keyingtries = "1";
 | ||
|           };
 | ||
|           roadwarrior = {
 | ||
|             auto       = "add";
 | ||
|             leftcert   = "/run/keys/moonCert.pem";
 | ||
|             leftid     = "@moon.strongswan.org";
 | ||
|             leftsubnet = "10.1.0.0/16";
 | ||
|             right      = "%any";
 | ||
|           };
 | ||
|         }
 | ||
|       '';
 | ||
|       description = ''
 | ||
|         A set of connections and their options for the ‘conn xxx’
 | ||
|         sections of the <filename>ipsec.conf</filename> file.
 | ||
|       '';
 | ||
|     };
 | ||
| 
 | ||
|     ca = mkOption {
 | ||
|       type = types.attrsOf (types.attrsOf types.str);
 | ||
|       default = {};
 | ||
|       example = {
 | ||
|         strongswan = {
 | ||
|           auto   = "add";
 | ||
|           cacert = "/run/keys/strongswanCert.pem";
 | ||
|           crluri = "http://crl2.strongswan.org/strongswan.crl";
 | ||
|         };
 | ||
|       };
 | ||
|       description = ''
 | ||
|         A set of CAs (certification authorities) and their options for
 | ||
|         the ‘ca xxx’ sections of the <filename>ipsec.conf</filename>
 | ||
|         file.
 | ||
|       '';
 | ||
|     };
 | ||
| 
 | ||
|     managePlugins = mkOption {
 | ||
|       type = types.bool;
 | ||
|       default = false;
 | ||
|       description = ''
 | ||
|         If set to true, this option will disable automatic plugin loading and
 | ||
|         then tell strongSwan to enable the plugins specified in the
 | ||
|         <option>enabledPlugins</option> option.
 | ||
|       '';
 | ||
|     };
 | ||
| 
 | ||
|     enabledPlugins = mkOption {
 | ||
|       type = types.listOf types.str;
 | ||
|       default = [];
 | ||
|       description = ''
 | ||
|         A list of additional plugins to enable if
 | ||
|         <option>managePlugins</option> is true.
 | ||
|       '';
 | ||
|     };
 | ||
|   };
 | ||
| 
 | ||
| 
 | ||
|   config = with cfg;
 | ||
|   let
 | ||
|     secretsFile = ipsecSecrets cfg.secrets;
 | ||
|   in
 | ||
|   mkIf enable
 | ||
|     {
 | ||
| 
 | ||
|     # here we should use the default strongswan ipsec.secrets and
 | ||
|     # append to it (default one is empty so not a pb for now)
 | ||
|     environment.etc."ipsec.secrets".source = secretsFile;
 | ||
| 
 | ||
|     systemd.services.strongswan = {
 | ||
|       description = "strongSwan IPSec Service";
 | ||
|       wantedBy = [ "multi-user.target" ];
 | ||
|       path = with pkgs; [ kmod iproute iptables utillinux ]; # XXX Linux
 | ||
|       after = [ "network-online.target" ];
 | ||
|       environment = {
 | ||
|         STRONGSWAN_CONF = strongswanConf { inherit setup connections ca secretsFile managePlugins enabledPlugins; };
 | ||
|       };
 | ||
|       serviceConfig = {
 | ||
|         ExecStart  = "${pkgs.strongswan}/sbin/ipsec start --nofork";
 | ||
|       };
 | ||
|       preStart = ''
 | ||
|         # with 'nopeerdns' setting, ppp writes into this folder
 | ||
|         mkdir -m 700 -p /etc/ppp
 | ||
|       '';
 | ||
|     };
 | ||
|   };
 | ||
| }
 | ||
| 
 |