| 
									
										
										
										
											2012-10-12 17:01:49 -04:00
										 |  |  | pkgs: with pkgs.lib; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-08 13:31:18 +02:00
										 |  |  | rec { | 
					
						
							| 
									
										
										
										
											2012-10-12 17:01:49 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-16 22:34:26 +10:00
										 |  |  |   # Copy configuration files to avoid having the entire sources in the system closure | 
					
						
							|  |  |  |   copyFile = filePath: pkgs.runCommandNoCC (builtins.unsafeDiscardStringContext (builtins.baseNameOf filePath)) {} ''
 | 
					
						
							|  |  |  |     cp ${filePath} $out | 
					
						
							|  |  |  |   '';
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-26 17:05:21 -07:00
										 |  |  |   # Check whenever fileSystem is needed for boot.  NOTE: Make sure | 
					
						
							|  |  |  |   # pathsNeededForBoot is closed under the parent relationship, i.e. if /a/b/c | 
					
						
							|  |  |  |   # is in the list, put /a and /a/b in as well. | 
					
						
							|  |  |  |   pathsNeededForBoot = [ "/" "/nix" "/nix/store" "/var" "/var/log" "/var/lib" "/etc" ]; | 
					
						
							|  |  |  |   fsNeededForBoot = fs: fs.neededForBoot || elem fs.mountPoint pathsNeededForBoot; | 
					
						
							| 
									
										
										
										
											2016-08-23 18:01:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-25 19:09:09 +00:00
										 |  |  |   # Check whenever `b` depends on `a` as a fileSystem | 
					
						
							| 
									
										
										
										
											2018-12-24 14:05:55 +01:00
										 |  |  |   fsBefore = a: b: a.mountPoint == b.device | 
					
						
							|  |  |  |                 || hasPrefix "${a.mountPoint}${optionalString (!(hasSuffix "/" a.mountPoint)) "/"}" b.mountPoint; | 
					
						
							| 
									
										
										
										
											2015-11-25 19:09:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-12 17:01:49 -04:00
										 |  |  |   # Escape a path according to the systemd rules, e.g. /dev/xyzzy | 
					
						
							|  |  |  |   # becomes dev-xyzzy.  FIXME: slow. | 
					
						
							|  |  |  |   escapeSystemdPath = s: | 
					
						
							| 
									
										
										
										
											2014-09-03 18:40:05 -07:00
										 |  |  |    replaceChars ["/" "-" " "] ["-" "\\x2d" "\\x20"] | 
					
						
							| 
									
										
										
										
											2020-03-14 04:13:04 +01:00
										 |  |  |    (removePrefix "/" s); | 
					
						
							| 
									
										
										
										
											2012-10-12 17:01:49 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-12 20:03:14 +01:00
										 |  |  |   # Returns a system path for a given shell package | 
					
						
							|  |  |  |   toShellPath = shell: | 
					
						
							|  |  |  |     if types.shellPackage.check shell then | 
					
						
							|  |  |  |       "/run/current-system/sw${shell.shellPath}" | 
					
						
							| 
									
										
										
										
											2016-07-04 15:10:51 +01:00
										 |  |  |     else if types.package.check shell then | 
					
						
							|  |  |  |       throw "${shell} is not a shell package" | 
					
						
							| 
									
										
										
										
											2016-06-12 20:03:14 +01:00
										 |  |  |     else | 
					
						
							|  |  |  |       shell; | 
					
						
							| 
									
										
										
										
											2019-09-06 16:38:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* Recurse into a list or an attrset, searching for attrs named like
 | 
					
						
							|  |  |  |      the value of the "attr" parameter, and return an attrset where the | 
					
						
							|  |  |  |      names are the corresponding jq path where the attrs were found and | 
					
						
							|  |  |  |      the values are the values of the attrs. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      Example: | 
					
						
							|  |  |  |        recursiveGetAttrWithJqPrefix { | 
					
						
							|  |  |  |          example = [ | 
					
						
							|  |  |  |            { | 
					
						
							|  |  |  |              irrelevant = "not interesting"; | 
					
						
							|  |  |  |            } | 
					
						
							|  |  |  |            { | 
					
						
							|  |  |  |              ignored = "ignored attr"; | 
					
						
							|  |  |  |              relevant = { | 
					
						
							|  |  |  |                secret = { | 
					
						
							|  |  |  |                  _secret = "/path/to/secret"; | 
					
						
							|  |  |  |                }; | 
					
						
							|  |  |  |              }; | 
					
						
							|  |  |  |            } | 
					
						
							|  |  |  |          ]; | 
					
						
							|  |  |  |        } "_secret" -> { ".example[1].relevant.secret" = "/path/to/secret"; } | 
					
						
							|  |  |  |   */ | 
					
						
							|  |  |  |   recursiveGetAttrWithJqPrefix = item: attr: | 
					
						
							|  |  |  |     let | 
					
						
							|  |  |  |       recurse = prefix: item: | 
					
						
							|  |  |  |         if item ? ${attr} then | 
					
						
							|  |  |  |           nameValuePair prefix item.${attr} | 
					
						
							|  |  |  |         else if isAttrs item then | 
					
						
							|  |  |  |           map (name: recurse (prefix + "." + name) item.${name}) (attrNames item) | 
					
						
							|  |  |  |         else if isList item then | 
					
						
							|  |  |  |           imap0 (index: item: recurse (prefix + "[${toString index}]") item) item | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           []; | 
					
						
							|  |  |  |     in listToAttrs (flatten (recurse "" item)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Takes an attrset and a file path and generates a bash snippet that
 | 
					
						
							|  |  |  |      outputs a JSON file at the file path with all instances of | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      { _secret = "/path/to/secret" } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      in the attrset replaced with the contents of the file | 
					
						
							|  |  |  |      "/path/to/secret" in the output JSON. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      When a configuration option accepts an attrset that is finally | 
					
						
							|  |  |  |      converted to JSON, this makes it possible to let the user define | 
					
						
							|  |  |  |      arbitrary secret values. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      Example: | 
					
						
							|  |  |  |        If the file "/path/to/secret" contains the string | 
					
						
							|  |  |  |        "topsecretpassword1234", | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        genJqSecretsReplacementSnippet { | 
					
						
							|  |  |  |          example = [ | 
					
						
							|  |  |  |            { | 
					
						
							|  |  |  |              irrelevant = "not interesting"; | 
					
						
							|  |  |  |            } | 
					
						
							|  |  |  |            { | 
					
						
							|  |  |  |              ignored = "ignored attr"; | 
					
						
							|  |  |  |              relevant = { | 
					
						
							|  |  |  |                secret = { | 
					
						
							|  |  |  |                  _secret = "/path/to/secret"; | 
					
						
							|  |  |  |                }; | 
					
						
							|  |  |  |              }; | 
					
						
							|  |  |  |            } | 
					
						
							|  |  |  |          ]; | 
					
						
							|  |  |  |        } "/path/to/output.json" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        would generate a snippet that, when run, outputs the following | 
					
						
							|  |  |  |        JSON file at "/path/to/output.json": | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |        { | 
					
						
							|  |  |  |          "example": [ | 
					
						
							|  |  |  |            { | 
					
						
							|  |  |  |              "irrelevant": "not interesting" | 
					
						
							|  |  |  |            }, | 
					
						
							|  |  |  |            { | 
					
						
							|  |  |  |              "ignored": "ignored attr", | 
					
						
							|  |  |  |              "relevant": { | 
					
						
							|  |  |  |                "secret": "topsecretpassword1234" | 
					
						
							|  |  |  |              } | 
					
						
							|  |  |  |            } | 
					
						
							|  |  |  |          ] | 
					
						
							|  |  |  |        } | 
					
						
							|  |  |  |   */ | 
					
						
							|  |  |  |   genJqSecretsReplacementSnippet = genJqSecretsReplacementSnippet' "_secret"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   # Like genJqSecretsReplacementSnippet, but allows the name of the | 
					
						
							|  |  |  |   # attr which identifies the secret to be changed. | 
					
						
							|  |  |  |   genJqSecretsReplacementSnippet' = attr: set: output: | 
					
						
							|  |  |  |     let | 
					
						
							|  |  |  |       secrets = recursiveGetAttrWithJqPrefix set attr; | 
					
						
							|  |  |  |     in ''
 | 
					
						
							|  |  |  |       if [[ -h '${output}' ]]; then | 
					
						
							|  |  |  |         rm '${output}' | 
					
						
							|  |  |  |       fi | 
					
						
							|  |  |  |     ''
 | 
					
						
							|  |  |  |     + concatStringsSep | 
					
						
							|  |  |  |         "\n" | 
					
						
							|  |  |  |         (imap1 (index: name: "export secret${toString index}=$(<'${secrets.${name}}')") | 
					
						
							|  |  |  |                (attrNames secrets)) | 
					
						
							|  |  |  |     + "\n" | 
					
						
							|  |  |  |     + "${pkgs.jq}/bin/jq >'${output}' '" | 
					
						
							|  |  |  |     + concatStringsSep | 
					
						
							|  |  |  |       " | " | 
					
						
							|  |  |  |       (imap1 (index: name: ''${name} = $ENV.secret${toString index}'') | 
					
						
							|  |  |  |              (attrNames secrets)) | 
					
						
							|  |  |  |     + ''
 | 
					
						
							|  |  |  |       ' <<'EOF' | 
					
						
							|  |  |  |       ${builtins.toJSON set} | 
					
						
							|  |  |  |       EOF | 
					
						
							|  |  |  |     '';
 | 
					
						
							| 
									
										
										
										
											2012-10-12 17:01:49 -04:00
										 |  |  | } |