feat: i forgor o:

This commit is contained in:
Kat Inskip 2022-09-23 17:57:57 -07:00
parent 0eb5e3bdd7
commit 15519ad70d
Signed by: kat
GPG key ID: 465E64DECEA8CF0F
34 changed files with 552 additions and 265 deletions

View file

@ -10,8 +10,16 @@
type = nullOr str;
default = nixos.networking.hostName;
};
owner = mkOption {
type = str;
default = "nginx";
};
group = mkOption {
type = str;
default = "domain-auth";
};
network = mkOption {
type = nullOr str;
type = unspecified;
default = "internet";
};
type = mkOption {
@ -22,6 +30,10 @@
"cname"
];
};
create_cert = mkOption {
type = bool;
default = true;
};
domain = mkOption {
type = nullOr str;
default = "${nixos.networking.hostName}${if config.prefix != null then ".${config.prefix}" else ""}";
@ -42,7 +54,7 @@
type = nullOr str;
default = if (config.type == "cname" && config.host != nixos.networking.hostName) then
meta.network.nodes.nixos.${config.host}.networks.${config.network}.target
else "${config.domain}.${config.zone}";
else "${if config.domain == null then "" else "${config.domain}."}${config.zone}";
};
};
}));
@ -126,6 +138,11 @@
type = bool;
default = false;
};
extra_domains = mkOption {
type = listOf str;
description = "Domains to add to the certificate generated for this network.";
default = [];
};
domain = mkOption {
type = nullOr str;
default = "${nixos.networking.hostName}${if config.prefix != null then ".${config.prefix}" else ""}";
@ -146,13 +163,17 @@
}));
};
};
config = {
config = let
sane_networks = lib.filterAttrs (network: settings: settings.interfaces != []) config.networks;
in {
networks = {
internet = {
zone = mkDefault "kittywit.ch.";
create_domain = true;
};
chitei = {
create_domain = true;
zone = mkDefault "kittywit.ch.";
create_domain = false;
};
gensokyo = {
zone = mkDefault "gensokyo.zone.";
@ -182,8 +203,8 @@
domains' = map (family: mapAttrs' (name: settings: let
network = if settings.host != config.networking.hostName then
meta.network.nodes.nixos.${settings.host}.networks.${settings.network}
else config.networks.${settings.network};
in nameValuePair "${settings.network}-${if settings.type == "both" || settings.type == family then family else settings.type}-${settings.domain}-${settings.zone}" ({
else sane_networks.${settings.network};
in nameValuePair "${settings.network}-${if settings.type == "both" || settings.type == family then family else settings.type}-${if settings.domain == null then "root" else settings.domain}-${settings.zone}" ({
inherit (settings) domain zone;
enable = mkDefault false;
} // (optionalAttrs (settings.type == "cname" && family == "ipv4") {
@ -200,9 +221,21 @@
a.address = network.ipv4;
enable = mkForce network.ipv4_defined;
}))) domains) address_families;
networks = config.networks;
networks = sane_networks;
# Networks to actually create domains for
networks' = filterAttrs (_: settings: settings.create_domain) networks;
# Extra domains to automatically be cnamed
extraDomainedNetworks = filterAttrs (_: settings: settings.extra_domains != []) networks';
extraDomains = listToAttrs (concatLists (mapAttrsToList (network: settings:
map (domain: let
split_domain = splitString "." domain;
isRoot = (length split_domain) == 2;
in nameValuePair "${network}-cname-${if isRoot then "root" else elemAt split_domain (length split_domain -2)}-${concatStringsSep "." (sublist (length split_domain - 2) (length split_domain) split_domain)}." {
zone = "${concatStringsSep "." (sublist (length split_domain - 2) (length split_domain) split_domain)}.";
domain = if isRoot then null
else elemAt split_domain (length split_domain - 2);
cname = { inherit (settings) target; };
}) settings.extra_domains) extraDomainedNetworks));
# Merge the result of a map upon address_families to mapAttrs'
networks'' = map (family: mapAttrs' (network: settings:
nameValuePair "${network}-${family}-${settings.domain}-${settings.zone}" ({
@ -216,7 +249,7 @@
a.address = settings.ipv4;
})
)) networks') address_families;
in mkMerge (networks'' ++ domains');
in mkMerge (networks'' ++ domains' ++ [ extraDomains ]);
acme = let
home = meta.deploy.targets.home.tf;
@ -236,13 +269,13 @@
};
};
certs = let
hostnames = (attrValues (mapAttrs (network: settings: removeSuffix "." settings.target) config.networks))
++ (attrValues (mapAttrs (network: settings: removeSuffix "." settings.target) config.domains));
in listToAttrs (map (hostname:
nameValuePair hostname {
keyType = "4096";
dnsNames = singleton hostname;
}) hostnames);
nvP = network: settings: nameValuePair "${removeSuffix "." settings.target}" {
keyType = "4096";
dnsNames = [ (removeSuffix "." settings.target) ] ++ (lib.optionals (settings ? extra_domains) settings.extra_domains);
};
network_certs = mapAttrs' nvP sane_networks;
domain_certs = mapAttrs' nvP (filterAttrs (network: settings: settings.create_cert) config.domains);
in network_certs // domain_certs;
};
variables = {
@ -271,39 +304,60 @@
};
secrets.files = let
hostnames = (attrValues (mapAttrs (network: settings: removeSuffix "." settings.target) config.networks))
++ (attrValues (mapAttrs (network: settings: removeSuffix "." settings.target) config.domains));
in listToAttrs (map (hostname:
nameValuePair "${hostname}-cert" {
text = tf.acme.certs.${hostname}.out.refFullchainPem;
owner = "nginx";
group = "domain-auth";
}) hostnames) // listToAttrs (map (hostname:
nameValuePair "${hostname}-key" {
text = tf.acme.certs.${hostname}.out.refPrivateKeyPem;
owner = "nginx";
group = "domain-auth";
}) hostnames);
fixedTarget = settings: removeSuffix "." settings.target;
networks = mapAttrs' (network: settings:
nameValuePair "${fixedTarget settings}-cert" {
text = tf.acme.certs.${fixedTarget settings}.out.refFullchainPem;
owner = "nginx";
group = "domain-auth";
}
) sane_networks;
networks' = mapAttrs' (network: settings:
nameValuePair "${fixedTarget settings}-key" {
text = tf.acme.certs.${fixedTarget settings}.out.refPrivateKeyPem;
owner = "nginx";
group = "domain-auth";
}
) sane_networks;
domains = mapAttrs' (network: settings:
nameValuePair "${fixedTarget settings}-cert" {
text = tf.acme.certs.${fixedTarget settings}.out.refFullchainPem;
owner = settings.owner;
group = settings.group;
}
) (filterAttrs (network: settings: settings.create_cert) config.domains);
domains' = mapAttrs' (network: settings:
nameValuePair "${fixedTarget settings}-key" {
text = tf.acme.certs.${fixedTarget settings}.out.refPrivateKeyPem;
owner = settings.owner;
group = settings.group;
}
) (filterAttrs (network: settings: settings.create_cert) config.domains);
in networks // networks' // domains // domains';
services.nginx.virtualHosts = let
hostnames = (attrValues (mapAttrs (network: settings: removeSuffix "." settings.target) config.networks))
++ (attrValues (mapAttrs (network: settings: removeSuffix "." settings.target) config.domains));
in listToAttrs (map (hostname:
nameValuePair hostname {
forceSSL = true;
sslCertificate = config.secrets.files."${hostname}-cert".path;
sslCertificateKey = config.secrets.files."${hostname}-key".path;
}) hostnames);
networkVirtualHosts = concatLists (mapAttrsToList (network: settings: map(domain: nameValuePair domain {
forceSSL = true;
sslCertificate = config.secrets.files."${removeSuffix "." settings.target}-cert".path;
sslCertificateKey = config.secrets.files."${removeSuffix "." settings.target}-key".path;
}) ([ settings.target ] ++ settings.extra_domains)) sane_networks);
domainVirtualHosts = (attrValues (mapAttrs (network: settings: removeSuffix "." settings.target) config.domains));
domainVirtualHosts' = (map (hostname:
nameValuePair hostname {
forceSSL = true;
sslCertificate = config.secrets.files."${hostname}-cert".path;
sslCertificateKey = config.secrets.files."${hostname}-key".path;
}) domainVirtualHosts);
in listToAttrs (networkVirtualHosts ++ (lib.optionals config.services.nginx.enable domainVirtualHosts'));
users.groups.domain-auth = {
gid = 10600;
members = [ "nginx" "openldap" "keycloak" ];
};
networking.firewall = {
interfaces = mkMerge (mapAttrsToList (network: settings:
genAttrs settings.interfaces (_: { allowedTCPPortRanges = settings.tcp; allowedUDPPortRanges = settings.udp; })
) (removeAttrs config.networks ["tailscale"]));
) (removeAttrs sane_networks ["tailscale"]));
trustedInterfaces = [ "tailscale0" ];
allowedTCPPorts = [ 5200 ];
allowedUDPPorts = [ config.services.tailscale.port ];

View file

@ -1,24 +1,15 @@
{ meta, config, pkgs, lib, ... }: with lib; {
imports = with meta; [
hardware.x270
hardware.local
nixos.gui
nixos.light
nixos.network
services.nginx
home.gui
];
config = {
deploy.tf = {
resources.koishi = {
provider = "null";
type = "resource";
connection = {
port = head config.services.openssh.ports;
host = config.networks.gensokyo.ipv4;
};
};
};
programs.ssh.extraConfig = ''
Host daiyousei-build
HostName daiyousei.kittywit.ch
@ -102,6 +93,12 @@
gensokyo = {
interfaces = [ "enp1s0" "wlp3s0" ];
ipv4 = "10.1.1.65";
udp = [
# Chromecast
[ 32768 60999 ]
# MDNS
5353
];
};
};

View file

@ -49,6 +49,7 @@
networks = {
internet = {
zone = "kittywit.ch.";
ipv4 = "104.244.72.5";
ipv6 = "2605:6400:30:eed1:6cf7:bbfc:b4e:15c0";
interfaces = singleton "ens3";

View file

@ -0,0 +1,25 @@
{ config, tf,... }: {
networks.gensokyo = {
tcp = [ 8080 636 ];
};
services.kanidm = {
enableServer = true;
enablePam = false;
enableClient = true;
clientSettings = {
uri = "https://id.gensokyo.zone";
verify_ca = true;
verify_hostnames = true;
};
serverSettings = {
domain = "gensokyo.zone";
origin = "https://id.gensokyo.zone";
role = "WriteReplica";
log_level = "default";
db_fs_type = "zfs";
bindaddress = "${config.networks.tailscale.ipv4}:8080";
ldapbindaddress = "${config.networks.tailscale.ipv4}:636";
};
};
}

View file

@ -5,6 +5,8 @@
(modulesPath + "/installer/scan/not-detected.nix")
hardware.local
nixos.network
./kanidm.nix
./vouch.nix
./home-assistant.nix
./zigbee2mqtt.nix
./mosquitto.nix

View file

@ -0,0 +1,112 @@
{ config, pkgs, lib, tf, ... }: {
options = with lib; let
origin = "https://id.gensokyo.zone";
in {
services.vouch-proxy = {
settings = {
vouch = {
cookie = {
domain = mkOption {
type = types.nullOr types.str;
default = "gensokyo.zone";
};
};
port = mkOption {
type = lib.types.port;
default = 30746;
};
listen = mkOption {
type = types.nullOr types.str;
default = config.networks.tailscale.ipv4;
};
allowAllUsers = mkOption {
type = types.bool;
default = true;
};
};
oauth = {
auth_url = mkOption {
type = types.str;
default = "${origin}/ui/oauth2";
};
token_url = mkOption {
type = types.str;
default = "${origin}/oauth2/token";
};
user_info_url = mkOption {
type = types.str;
default = "${origin}/oauth2/openid/vouch/userinfo";
};
scopes = mkOption {
type = types.listOf types.str;
default = [ "openid" "email" "profile" ];
};
callback_url = mkOption {
type = types.str;
default = "https://login.gensokyo.zone/auth";
};
provider = mkOption {
type = types.nullOr types.str;
default = "oidc";
};
code_challenge_method = mkOption {
type = types.str;
default = "S256";
};
client_id = mkOption {
type = types.str;
default = "vouch";
};
};
};
};
};
config = {
kw.secrets.variables.gensokyo-id = {
path = "secrets/id.gensokyo.zone";
field = "client_secret";
};
kw.secrets.variables.gensokyo-jwt = {
path = "secrets/id.gensokyo.zone";
field = "jwt";
};
secrets.files.vouch-config = let
recursiveMergeAttrs = listOfAttrsets: lib.fold (attrset: acc: lib.recursiveUpdate attrset acc) {} listOfAttrsets;
in {
text = builtins.toJSON (recursiveMergeAttrs [
config.services.vouch-proxy.settings
{ oauth.client_secret = tf.variables.gensokyo-id.ref; vouch.jwt.secret = tf.variables.gensokyo-jwt.ref; }
]);
owner = "vouch-proxy";
group = "vouch-proxy";
};
systemd.services.vouch-proxy = {
description = "Vouch-proxy";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
serviceConfig = {
ExecStart =
''
${pkgs.vouch-proxy}/bin/vouch-proxy -config ${config.secrets.files.vouch-config.path}
'';
Restart = "on-failure";
RestartSec = 5;
WorkingDirectory = "/var/lib/vouch-proxy";
StateDirectory = "vouch-proxy";
RuntimeDirectory = "vouch-proxy";
User = "vouch-proxy";
Group = "vouch-proxy";
StartLimitBurst = 3;
};
};
users.users.vouch-proxy = {
isSystemUser = true;
group = "vouch-proxy";
};
users.groups.vouch-proxy = { };
};
}

View file

@ -1,6 +1,7 @@
{ meta, tf, config, pkgs, lib, ... }: with lib; {
imports = with meta; [
hardware.rm-310
hardware.local
nixos.network
nixos.arc
services.ha
@ -15,17 +16,6 @@
services.plex
];
deploy.tf = {
resources.yukari = {
provider = "null";
type = "resource";
connection = {
port = head config.services.openssh.ports;
host = config.network.addresses.private.nixos.ipv4.address;
};
};
};
boot.supportedFilesystems = singleton "zfs";
fileSystems = {