nixfiles/lib/default.nix

263 lines
8.8 KiB
Nix
Raw Normal View History

2022-02-06 00:06:26 +00:00
{ lib }:
2022-02-13 13:10:21 +00:00
let
2022-06-11 16:33:32 +01:00
inherit (builtins) length match replaceStrings elemAt mapAttrs head split filter;
2022-02-19 22:55:53 +00:00
inherit (lib)
genAttrs mapAttrs' mapAttrsToList filterAttrsRecursive nameValuePair types
2022-06-11 16:33:32 +01:00
mkOption mkOverride mkForce mkIf mergeEqualOption optional hasPrefix
showWarnings concatStringsSep flatten unique;
2022-02-13 13:10:21 +00:00
inherit (lib.flake) defaultSystems;
in
rec {
# Yoinked from nixpkgs/nixos/modules/services/networking/nat.nix
2022-05-17 23:27:14 +01:00
isIPv6 = ip: length (lib.splitString ":" ip) > 2;
2022-02-13 13:10:21 +00:00
parseIPPort = ipp:
let
v6 = isIPv6 ipp;
matchIP = if v6 then "[[]([0-9a-fA-F:]+)[]]" else "([0-9.]+)";
2022-05-28 21:50:26 +01:00
m = match "${matchIP}:(.+)" ipp;
2022-02-13 13:10:21 +00:00
checked = v: if m == null then throw "bad ip:ports `${ipp}'" else v;
in
{
inherit v6;
ip = checked (elemAt m 0);
2022-05-28 21:50:26 +01:00
ports = checked (elemAt m 1);
2022-02-13 13:10:21 +00:00
};
2022-05-17 23:27:14 +01:00
naiveIPv4Gateway = ip: "${head (elemAt (split ''([0-9]+\.[0-9]+\.[0-9]+)\.[0-9]+'' ip) 1)}.1";
2022-02-19 22:55:53 +00:00
attrsToNVList = mapAttrsToList nameValuePair;
2022-02-13 23:06:31 +00:00
mkDefaultSystemsPkgs = path: args': genAttrs defaultSystems (system: import path ((args' system) // { inherit system; }));
2022-02-13 13:44:37 +00:00
mkApp = program: { type = "app"; inherit program; };
2022-02-13 14:28:49 +00:00
mkShellApp = pkgs: name: text: mkApp (pkgs.writeShellScript name text).outPath;
2022-02-14 00:56:43 +00:00
mkShellApp' = pkgs: args:
let
app = pkgs.writeShellApplication args;
in mkApp "${app}/bin/${app.meta.mainProgram}";
2022-02-13 23:06:31 +00:00
flakePackageOverlay' = flake: pkg: system: (final: prev:
let
pkg' = if pkg != null then flake.packages.${system}.${pkg} else flake.defaultPackage.${system};
name = if pkg != null then pkg else pkg'.name;
in
{
${name} = pkg';
});
flakePackageOverlay = flake: flakePackageOverlay' flake null;
2022-02-06 00:06:26 +00:00
inlineModule' = path: module: {
_file = path;
imports = [ module ];
};
inlineModule = path: inlineModule' path (import path);
2022-02-19 22:55:53 +00:00
# Merge together modules which are defined as functions with others that aren't
naiveModule = with types; (coercedTo (attrsOf anything) (conf: { ... }: conf) (functionTo (attrsOf anything)));
2022-02-13 13:10:21 +00:00
mkOpt = type: default: mkOption { inherit type default; };
2022-02-13 17:44:14 +00:00
mkOpt' = type: default: description: mkOption { inherit type default description; };
2022-02-13 13:10:21 +00:00
mkBoolOpt = default: mkOption {
inherit default;
type = types.bool;
example = true;
};
2022-02-13 17:44:14 +00:00
mkBoolOpt' = default: description: mkOption {
inherit default description;
type = types.bool;
example = true;
};
2022-02-19 22:55:53 +00:00
nullOrOpt' = type: description: mkOpt' (types.nullOr type) null description;
2022-02-13 13:10:21 +00:00
dummyOption = mkOption { };
2022-02-13 17:44:14 +00:00
2022-02-19 22:55:53 +00:00
# Slightly higher precedence than mkDefault
mkDefault' = mkOverride 900;
2022-02-13 17:44:14 +00:00
mkVMOverride' = mkOverride 9;
2022-06-11 16:33:32 +01:00
# This is shocking...
duplicates = l:
flatten
(map
(e:
optional
((length (filter (e2: e2 == e) l)) > 1)
e)
(unique l));
applyAssertions = config: res:
let
failedAssertions = map (x: x.message) (filter (x: !x.assertion) config.assertions);
in
if failedAssertions != []
then throw "\nFailed assertions:\n${concatStringsSep "\n" (map (x: "- ${x}") failedAssertions)}"
else showWarnings config.warnings res;
homeStateVersion' = hmBranch: (if (hmBranch == "stable" || hmBranch == "mine-stable") then "22.11" else "23.05");
homeStateVersion = hmBranch: {
# The flake passes a default setting, but we don't care about that
2022-07-10 14:15:12 +01:00
home.stateVersion = mkForce (homeStateVersion' hmBranch);
};
2022-02-19 22:55:53 +00:00
commonOpts = with types; {
moduleType = mkOptionType {
name = "Inline flake-exportable module";
merge = loc: defs: inlineModule (mergeEqualOption loc defs);
};
system = mkOpt' (enum defaultSystems) null "Nix-style system string.";
nixpkgs = mkOpt' (enum [ "unstable" "stable" "mine" "mine-stable" ]) "unstable" "Branch of nixpkgs to use.";
home-manager = mkOpt' (enum [ "unstable" "stable" "mine" "mine-stable" ]) "unstable" "Branch of home-manager to use.";
};
2022-05-17 23:27:14 +01:00
networkdAssignment = iface: a: {
matchConfig.Name = iface;
address =
[ "${a.ipv4.address}/${toString a.ipv4.mask}" ] ++
2022-11-21 01:21:50 +00:00
(optional (a.ipv6.address != null && a.ipv6.iid == null) "${a.ipv6.address}/${toString a.ipv6.mask}");
2022-05-17 23:27:14 +01:00
gateway =
(optional (a.ipv4.gateway != null) a.ipv4.gateway) ++
(optional (a.ipv6.gateway != null) a.ipv6.gateway);
2022-05-18 22:52:42 +01:00
networkConfig = {
IPv6AcceptRA = a.ipv6.gateway == null || a.ipv6.iid != null;
2022-05-18 22:52:42 +01:00
# NOTE: LLDP emission / reception is ignored on bridge interfaces
LLDP = true;
EmitLLDP = "customer-bridge";
};
2022-05-23 00:57:25 +01:00
ipv6AcceptRAConfig = {
Token = mkIf (a.ipv6.iid != null) "static:${a.ipv6.iid}";
2022-05-23 00:57:25 +01:00
UseDNS = true;
UseDomains = true;
};
2022-05-17 23:27:14 +01:00
};
systemdAwaitPostgres = pkg: host: {
after = [ "systemd-networkd-wait-online.service" ];
preStart = ''
until ${pkg}/bin/pg_isready -h ${host}; do
sleep 0.5
done
'';
};
2022-02-19 22:55:53 +00:00
deploy-rs =
with types;
let
globalOpts = {
sshUser = nullOrOpt' str "Username deploy-rs will deploy with.";
user = nullOrOpt' str "Username deploy-rs will deploy with.";
sudo = nullOrOpt' str "Command to elevate privileges with (used if the deployment user != profile user).";
sshOpts = mkOpt' (listOf str) [ ]
2022-02-19 22:55:53 +00:00
"Options deploy-rs will pass to ssh. Note: overriding at a lower level _merges_ options.";
fastConnection = nullOrOpt' bool "Whether to copy the whole closure instead of using substitution.";
autoRollback = nullOrOpt' bool "Whether to roll back the profile if activation fails.";
magicRollback = nullOrOpt' bool "Whether to roll back the profile if connectivity to the deployer is lost.";
confirmTimeout = nullOrOpt' ints.u16 "Timeout for confirming activation succeeded.";
tempPath = nullOrOpt' str "Path that deploy-rs will use for temporary files.";
};
profileOpts = {
path = mkOpt' package "" "Derivation to build (should include activation script).";
profilePath = nullOrOpt' str "Path to profile location";
} // globalOpts;
profileType = submodule { options = profileOpts; };
2022-02-19 22:55:53 +00:00
nodeOpts = {
hostname = mkOpt' str "" "Hostname deploy-rs will connect to.";
profilesOrder = nullOrOpt' (listOf str)
"Order to deploy profiles in (remainder will be deployed in arbitrary order).";
profiles = mkOpt' (attrsOf profileType) { } "Profiles to deploy.";
2022-02-19 22:55:53 +00:00
} // globalOpts;
nodeType = submodule { options = nodeOpts; };
deployOpts = {
nodes = mkOption {
type = attrsOf nodeType;
default = { };
internal = true;
description = "deploy-rs node configurations.";
};
} // globalOpts;
deployType = submodule { options = deployOpts; };
2022-02-19 22:55:53 +00:00
in
{
inherit globalOpts;
node = mkOpt' nodeType { } "deploy-rs node configuration.";
deploy = mkOpt' deployType { } "deploy-rs configuration.";
2022-02-19 22:55:53 +00:00
filterOpts = filterAttrsRecursive (_: v: v != null);
};
2022-07-16 21:01:18 +01:00
nginx = {
proxyHeaders = ''
# Setting any proxy_header in a child (e.g. location) will nuke the parents...
proxy_set_header X-Origin-URI $request_uri;
proxy_set_header Host $host;
proxy_set_header X-Host $http_host;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Protocol $scheme;
proxy_set_header X-Scheme $scheme;
'';
};
nix = {
2022-07-17 02:56:26 +01:00
cacheKeys = [
"nix-cache.nul.ie-1:XofkqdHQSGFoPjB6aRohQbCU2ILKFqhNjWfoOdQgF5Y="
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
];
2022-07-16 21:01:18 +01:00
};
pubDomain = "nul.ie";
2022-08-01 22:55:59 +01:00
dockerNetAssignment =
assignments: name: with assignments."${name}".internal; "ip=${ipv4.address},ip=${ipv6.address}";
colony = rec {
domain = "ams1.int.${pubDomain}";
start = {
all = {
v4 = "10.100.";
v6 = "2a0e:97c0:4d2:1";
};
base = {
v4 = "${start.all.v4}0.";
v6 = "${start.all.v6}0::";
};
vms = {
v4 = "${start.all.v4}1.";
v6 = "${start.all.v6}1::";
};
ctrs = {
v4 = "${start.all.v4}2.";
v6 = "${start.all.v6}2::";
};
2022-08-01 17:44:08 +01:00
oci = {
v4 = "${start.all.v4}3.";
v6 = "${start.all.v6}3::";
};
2022-11-21 01:21:50 +00:00
vip1 = "94.142.241.22";
};
prefixes = {
all = {
v4 = "${start.base.v4}0/16";
v6 = "${start.base.v6}/60";
};
base.v6 = "${start.base.v6}/64";
vms = {
v4 = "${start.vms.v4}0/24";
v6 = "${start.vms.v6}/64";
};
ctrs = {
v4 = "${start.ctrs.v4}0/24";
v6 = "${start.ctrs.v6}/64";
};
2022-08-01 17:44:08 +01:00
oci = {
v4 = "${start.oci.v4}0/24";
v6 = "${start.oci.v6}/64";
};
2022-11-21 01:21:50 +00:00
vip1 = "${start.vip1}4/30";
};
2022-05-23 00:57:25 +01:00
};
2022-02-22 00:59:57 +00:00
sshKeyFiles = {
2022-06-11 23:51:37 +01:00
me = ../.keys/me.pub;
deploy = ../.keys/deploy.pub;
2022-02-22 00:59:57 +00:00
};
2022-02-13 13:10:21 +00:00
}