mirror of
https://github.com/gensokyo-zone/infrastructure.git
synced 2026-02-09 12:29:19 -08:00
feat: abstractions rework
This commit is contained in:
parent
ec7571171b
commit
0a6085cb49
48 changed files with 798 additions and 1219 deletions
|
|
@ -1,77 +0,0 @@
|
|||
{ config, nixos, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
options.network = {
|
||||
enable = mkEnableOption "Use kat's network module?";
|
||||
addresses = mkOption {
|
||||
type = with types; attrsOf (submodule ({ name, ... }: {
|
||||
options = {
|
||||
enable = mkEnableOption "Is the system a part of the ${name} network?";
|
||||
ipv4 = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
};
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
};
|
||||
ipv6 = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
};
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
};
|
||||
prefix = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
domain = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
out = {
|
||||
identifierList = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = if config.enable then singleton config.domain ++ config.out.addressList else [ ];
|
||||
};
|
||||
addressList = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = if config.enable then concatMap (i: optional i.enable i.address) [ config.ipv4 config.ipv6 ] else [ ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
tf = {
|
||||
enable = mkEnableOption "Was the system provisioned by terraform?";
|
||||
ipv4_attr = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
ipv6_attr = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
};
|
||||
dns = {
|
||||
enable = mkEnableOption "Do you want DNS to be semi-managed through this module?";
|
||||
isRoot = mkEnableOption "Is this system supposed to be the @ for the domain?";
|
||||
email = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
zone = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
domain = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
dynamic = mkEnableOption "Enable Glauca Dynamic DNS Updater";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
network.addresses = nixos.network.addresses or {};
|
||||
network.tf = nixos.network.tf or {};
|
||||
network.dns = nixos.network.dns or {};
|
||||
};
|
||||
}
|
||||
|
|
@ -135,6 +135,7 @@ with lib;
|
|||
inputs.home-manager.nixosModules.home-manager
|
||||
meta.modules.nixos
|
||||
meta.modules.system
|
||||
meta.nixos.network
|
||||
meta.system
|
||||
];
|
||||
specialArgs = {
|
||||
|
|
|
|||
|
|
@ -1,82 +0,0 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.network.firewall;
|
||||
in
|
||||
{
|
||||
options.network.firewall = {
|
||||
public.tcp.ports = mkOption {
|
||||
type = types.listOf types.port;
|
||||
default = [ ];
|
||||
};
|
||||
public.udp.ports = mkOption {
|
||||
type = types.listOf types.port;
|
||||
default = [ ];
|
||||
};
|
||||
private.tcp.ports = mkOption {
|
||||
type = types.listOf types.port;
|
||||
default = [ ];
|
||||
};
|
||||
private.udp.ports = mkOption {
|
||||
type = types.listOf types.port;
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
public.tcp.ranges = mkOption {
|
||||
type = types.listOf (types.attrsOf types.port);
|
||||
default = [ ];
|
||||
};
|
||||
public.udp.ranges = mkOption {
|
||||
type = types.listOf (types.attrsOf types.port);
|
||||
default = [ ];
|
||||
};
|
||||
private.tcp.ranges = mkOption {
|
||||
type = types.listOf (types.attrsOf types.port);
|
||||
default = [ ];
|
||||
};
|
||||
private.udp.ranges = mkOption {
|
||||
type = types.listOf (types.attrsOf types.port);
|
||||
default = [ ];
|
||||
};
|
||||
|
||||
public.interfaces = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "Public firewall interfaces";
|
||||
default = [ ];
|
||||
};
|
||||
private.interfaces = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "Private firewall interfaces";
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
network.firewall = mkMerge (mapAttrsToList (_: user: user.network.firewall) config.home-manager.users);
|
||||
networking.firewall.interfaces =
|
||||
let
|
||||
fwTypes = {
|
||||
ports = "Ports";
|
||||
ranges = "PortRanges";
|
||||
};
|
||||
|
||||
interfaceDef = visibility:
|
||||
listToAttrs (flatten (mapAttrsToList
|
||||
(type: typeString:
|
||||
map
|
||||
(proto: {
|
||||
name = "allowed${toUpper proto}${typeString}";
|
||||
value = cfg.${visibility}.${proto}.${type};
|
||||
}) [ "tcp" "udp" ])
|
||||
fwTypes));
|
||||
|
||||
interfaces = visibility:
|
||||
listToAttrs
|
||||
(map (interface: nameValuePair interface (interfaceDef visibility))
|
||||
cfg.${visibility}.interfaces);
|
||||
in
|
||||
mkMerge (map (visibility: interfaces visibility) [ "public" "private" ]);
|
||||
};
|
||||
}
|
||||
|
|
@ -1,257 +0,0 @@
|
|||
{ config, lib, tf, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.network;
|
||||
in
|
||||
{
|
||||
options.network = {
|
||||
enable = mkEnableOption "Use kat's network module?";
|
||||
addresses = mkOption {
|
||||
type = with types; attrsOf (submodule ({ name, options, config, ... }: {
|
||||
options = {
|
||||
enable = mkEnableOption "Is it a member of the ${name} network?";
|
||||
nixos = {
|
||||
ipv4 = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = options.nixos.ipv4.address.isDefined;
|
||||
};
|
||||
selfaddress = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
};
|
||||
ipv6 = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = options.nixos.ipv6.address.isDefined;
|
||||
};
|
||||
selfaddress = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
};
|
||||
};
|
||||
tf = {
|
||||
ipv4 = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = options.tf.ipv4.address.isDefined;
|
||||
};
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
};
|
||||
ipv6 = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = options.tf.ipv6.address.isDefined;
|
||||
};
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
};
|
||||
};
|
||||
prefix = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
subdomain = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
domain = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "${config.subdomain}.${cfg.dns.domain}";
|
||||
};
|
||||
target = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = "${config.domain}.";
|
||||
};
|
||||
out = {
|
||||
identifierList = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = optionals config.enable (singleton config.domain ++ config.out.addressList);
|
||||
};
|
||||
addressList = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = optionals config.enable (concatMap (i: optional i.enable i.address) [ config.nixos.ipv4 config.nixos.ipv6 ]);
|
||||
};
|
||||
};
|
||||
};
|
||||
}));
|
||||
};
|
||||
extraCerts = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = { };
|
||||
};
|
||||
tf = {
|
||||
enable = mkEnableOption "Was the system provisioned by terraform?";
|
||||
ipv4_attr = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
ipv6_attr = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
dns = {
|
||||
enable = mkEnableOption "Do you want DNS to be semi-managed through this module?";
|
||||
isRoot = mkEnableOption "Is this system supposed to be the @ for the domain?";
|
||||
email = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
zone = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
domain = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config =
|
||||
let
|
||||
networks = cfg.addresses;
|
||||
networksWithDomains = filterAttrs (_: v: v.enable) networks;
|
||||
in
|
||||
mkIf cfg.enable {
|
||||
network = {
|
||||
dns = {
|
||||
domain = builtins.substring 0 ((builtins.stringLength cfg.dns.zone) - 1) cfg.dns.zone;
|
||||
};
|
||||
addresses = lib.mkMerge [
|
||||
(mkIf (!cfg.tf.enable) (genAttrs [ "private" "public" "yggdrasil" ] (network: {
|
||||
tf = {
|
||||
ipv4.address = mkIf (cfg.addresses.${network}.nixos.ipv4.enable) cfg.addresses.${network}.nixos.ipv4.address;
|
||||
ipv6.address = mkIf (cfg.addresses.${network}.nixos.ipv6.enable) cfg.addresses.${network}.nixos.ipv6.address;
|
||||
};
|
||||
})))
|
||||
(mkIf cfg.tf.enable (genAttrs ["yggdrasil" ] (network: {
|
||||
tf = {
|
||||
ipv4.address = mkIf (cfg.addresses.${network}.nixos.ipv4.enable) cfg.addresses.${network}.nixos.ipv4.address;
|
||||
ipv6.address = mkIf (cfg.addresses.${network}.nixos.ipv6.enable) cfg.addresses.${network}.nixos.ipv6.address;
|
||||
};
|
||||
})))
|
||||
(mkIf cfg.tf.enable {
|
||||
public = {
|
||||
tf = {
|
||||
ipv4.address = mkIf (cfg.tf.ipv4_attr != null) (tf.resources.${config.networking.hostName}.refAttr cfg.tf.ipv4_attr);
|
||||
ipv6.address = mkIf (cfg.tf.ipv6_attr != null) (tf.resources.${config.networking.hostName}.refAttr cfg.tf.ipv6_attr);
|
||||
};
|
||||
nixos = {
|
||||
ipv4.selfaddress = mkIf (tf.state.enable && cfg.tf.ipv4_attr != null) (tf.resources.${config.networking.hostName}.getAttr cfg.tf.ipv4_attr);
|
||||
ipv6.selfaddress = mkIf (tf.state.enable && cfg.tf.ipv6_attr != null) (tf.resources.${config.networking.hostName}.getAttr cfg.tf.ipv6_attr);
|
||||
ipv4.address = mkIf (tf.state.resources ? ${tf.resources.${config.networking.hostName}.out.reference} && cfg.tf.ipv4_attr != null) (tf.resources.${config.networking.hostName}.importAttr cfg.tf.ipv4_attr);
|
||||
ipv6.address = mkIf (tf.state.resources ? ${tf.resources.${config.networking.hostName}.out.reference} && cfg.tf.ipv6_attr != null) (tf.resources.${config.networking.hostName}.importAttr cfg.tf.ipv6_attr);
|
||||
};
|
||||
};
|
||||
})
|
||||
({
|
||||
private = {
|
||||
prefix = "int";
|
||||
subdomain = "${config.networking.hostName}.${cfg.addresses.private.prefix}";
|
||||
};
|
||||
yggdrasil = {
|
||||
enable = cfg.yggdrasil.enable;
|
||||
prefix = "ygg";
|
||||
subdomain = "${config.networking.hostName}.${cfg.addresses.yggdrasil.prefix}";
|
||||
};
|
||||
public = {
|
||||
subdomain = config.networking.hostName;
|
||||
};
|
||||
})
|
||||
(mkIf cfg.yggdrasil.enable {
|
||||
yggdrasil.nixos.ipv6.address = cfg.yggdrasil.address;
|
||||
})
|
||||
];
|
||||
};
|
||||
|
||||
|
||||
networking.domain = mkDefault (if cfg.addresses.public.enable then cfg.dns.domain
|
||||
else if cfg.addresses.private.enable then "${cfg.addresses.private.prefix}.${cfg.dns.domain}" else "");
|
||||
|
||||
deploy.tf.dns.records =
|
||||
let
|
||||
recordsV4 = mapAttrs'
|
||||
(n: v:
|
||||
nameValuePair "node_${n}_${config.networking.hostName}_v4" {
|
||||
inherit (v.tf.ipv4) enable;
|
||||
inherit (cfg.dns) zone;
|
||||
domain = v.subdomain;
|
||||
a = { inherit (v.tf.ipv4) address; };
|
||||
})
|
||||
networksWithDomains;
|
||||
recordsV6 = mapAttrs'
|
||||
(n: v:
|
||||
nameValuePair "node_${n}_${config.networking.hostName}_v6" {
|
||||
inherit (v.tf.ipv6) enable;
|
||||
inherit (cfg.dns) zone;
|
||||
domain = v.subdomain;
|
||||
aaaa = { inherit (v.tf.ipv6) address; };
|
||||
})
|
||||
networksWithDomains;
|
||||
in
|
||||
mkMerge (map (record: mkIf cfg.dns.enable record) [
|
||||
recordsV4
|
||||
recordsV6
|
||||
(mkIf cfg.dns.isRoot {
|
||||
"node_root_${config.networking.hostName}_v4" = {
|
||||
inherit (cfg.addresses.public) enable;
|
||||
inherit (cfg.dns) zone;
|
||||
a = { inherit (cfg.addresses.public.tf.ipv4) address; };
|
||||
};
|
||||
"node_root_${config.networking.hostName}_v6" = {
|
||||
inherit (cfg.addresses.public) enable;
|
||||
inherit (cfg.dns) zone;
|
||||
aaaa = { inherit (cfg.addresses.public.tf.ipv6) address; };
|
||||
};
|
||||
})
|
||||
]);
|
||||
|
||||
security.acme.certs = mkMerge (map (cert: mkIf cfg.dns.enable cert) [
|
||||
(mkIf config.services.nginx.enable (mapAttrs'
|
||||
(n: v:
|
||||
nameValuePair "${n}_${config.networking.hostName}" {
|
||||
inherit (v) domain;
|
||||
dnsProvider = "rfc2136";
|
||||
credentialsFile = config.secrets.files.dns_creds.path;
|
||||
group = mkDefault "nginx";
|
||||
})
|
||||
networksWithDomains))
|
||||
(mapAttrs'
|
||||
(n: v:
|
||||
nameValuePair "${n}" {
|
||||
domain = v;
|
||||
dnsProvider = "rfc2136";
|
||||
credentialsFile = config.secrets.files.dns_creds.path;
|
||||
group = mkDefault "nginx";
|
||||
})
|
||||
cfg.extraCerts)
|
||||
]);
|
||||
|
||||
services.nginx.virtualHosts = mkMerge (map (host: mkIf cfg.dns.enable host) [
|
||||
(mkIf config.services.nginx.enable (mapAttrs'
|
||||
(n: v:
|
||||
nameValuePair v.domain {
|
||||
useACMEHost = "${n}_${config.networking.hostName}";
|
||||
forceSSL = true;
|
||||
})
|
||||
networksWithDomains))
|
||||
(mapAttrs'
|
||||
(n: v:
|
||||
nameValuePair v {
|
||||
useACMEHost = "${n}";
|
||||
forceSSL = true;
|
||||
})
|
||||
cfg.extraCerts)
|
||||
]);
|
||||
|
||||
_module.args = { inherit (config.lib) kw; };
|
||||
};
|
||||
}
|
||||
|
|
@ -1,145 +0,0 @@
|
|||
{ config, meta, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.network.yggdrasil;
|
||||
calcAddr = pubkey: lib.readFile (pkgs.runCommandNoCC "calcaddr-${pubkey}" { } ''
|
||||
echo '{ SigningPublicKey: "${pubkey}" }' | ${config.services.yggdrasil.package}/bin/yggdrasil -useconf -address | tr -d '\n' > $out
|
||||
'').outPath;
|
||||
in
|
||||
{
|
||||
options.network.yggdrasil = {
|
||||
enable = mkEnableOption "Enable the yggdrasil-based private hexnet";
|
||||
pubkey = mkOption {
|
||||
type = types.str;
|
||||
description = "Public key of this node";
|
||||
};
|
||||
address = mkOption {
|
||||
type = types.str;
|
||||
#description = "Main Yggdrasil address. Set automatically";
|
||||
#default = calcAddr cfg.signingPubkey;
|
||||
default = "";
|
||||
};
|
||||
trust = mkOption {
|
||||
type = types.bool;
|
||||
description = "Open Firewall completely for the network";
|
||||
default = false;
|
||||
};
|
||||
listen = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
description = "Allow other hosts in the network to connect directly";
|
||||
default = false;
|
||||
};
|
||||
endpoints = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "Endpoints to listen on";
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
tunnel = {
|
||||
localV6 = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "v6 subnets to expose";
|
||||
default = [ ];
|
||||
};
|
||||
localV4 = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "v4 subnets to expose";
|
||||
default = [ ];
|
||||
};
|
||||
remoteV6 = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
description = "Extra v6 subnets to route";
|
||||
default = { };
|
||||
};
|
||||
remoteV4 = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
description = "Extra v4 subnets to route";
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
extra = {
|
||||
pubkeys = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
description = "Additional hosts to allow into the network. Keys won't be added to definition host.";
|
||||
default = { };
|
||||
example = { host = "0000000000000000000000000000000000000000000000000000000000000000"; };
|
||||
};
|
||||
addresses = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
internal = true;
|
||||
default = mapAttrs (_: c: calcAddr c) cfg.extra.pubkeys;
|
||||
};
|
||||
localV6 = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "v6 subnets to expose, but not route";
|
||||
default = [ ];
|
||||
};
|
||||
localV4 = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "v4 subnets to expose, but not route";
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
extern = {
|
||||
pubkeys = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
description = "Additional hosts to allow into the network. Keys won't be added to definition host.";
|
||||
default = { };
|
||||
example = { host = "0000000000000000000000000000000000000000000000000000000000000000"; };
|
||||
};
|
||||
endpoints = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = "Endpoints to listen on";
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable (
|
||||
let
|
||||
yggConfigs = filter
|
||||
(
|
||||
c: c.enable && (cfg.pubkey != c.pubkey)
|
||||
)
|
||||
(
|
||||
mapAttrsToList (_: node: node.network.yggdrasil or { enable = false; pubkey = null; }) meta.network.nodes.nixos
|
||||
);
|
||||
pubkeys = flatten ((filter (n: n != "0000000000000000000000000000000000000000000000000000000000000000") (attrValues cfg.extern.pubkeys)) ++ (map (c: [ c.pubkey ] ++ (attrValues c.extra.pubkeys)) yggConfigs));
|
||||
in
|
||||
{
|
||||
assertions = [
|
||||
{
|
||||
assertion = !(cfg.listen.enable && (cfg.listen.endpoints == [ ]));
|
||||
message = "Specify network.yggdrasil.listen.endpoints";
|
||||
}
|
||||
];
|
||||
|
||||
networking.firewall.trustedInterfaces = mkIf cfg.trust [ "yggdrasil" ];
|
||||
|
||||
services.yggdrasil = {
|
||||
enable = true;
|
||||
persistentKeys = true;
|
||||
config = {
|
||||
AllowedPublicKeys = pubkeys;
|
||||
IfName = "yggdrasil";
|
||||
Listen = cfg.listen.endpoints;
|
||||
Peers = lib.flatten (cfg.extern.endpoints ++ (map (c: c.listen.endpoints) (filter (c: c.listen.enable) yggConfigs)));
|
||||
};
|
||||
};
|
||||
|
||||
system.build.yggdrasilTemplate =
|
||||
let
|
||||
json = builtins.toJSON {
|
||||
inherit (config.services.yggdrasil.config) Peers SessionFirewall TunnelRouting;
|
||||
PublicKey = "";
|
||||
PrivateKey = "";
|
||||
};
|
||||
in
|
||||
pkgs.runCommandNoCC "yggdrasil-template.json" { }
|
||||
"echo '${json}' | ${config.services.yggdrasil.package}/bin/yggdrasil -useconf -normaliseconf > $out";
|
||||
}
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue