117 lines
3.6 KiB
Nix
117 lines
3.6 KiB
Nix
{
|
|
lib,
|
|
config,
|
|
...
|
|
}: let
|
|
state = builtins.import ../state.nix;
|
|
ty = {
|
|
ipv4 = lib.types.strMatching "(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}";
|
|
ipv6 = lib.types.strMatching "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))";
|
|
};
|
|
in {
|
|
options.state = with lib; {
|
|
vpn.ipv4 = mkOption {
|
|
type = ty.ipv4;
|
|
description = "VPN IPv4";
|
|
readOnly = true;
|
|
};
|
|
vpn.ipv6 = mkOption {
|
|
type = types.str;
|
|
description = "VPN IPv6";
|
|
readOnly = true;
|
|
};
|
|
vpn.machine = mkOption {
|
|
type = with types;
|
|
attrsOf (submodule {
|
|
options = {
|
|
ipv4 = mkOption {
|
|
type = ty.ipv4;
|
|
description = "VPN IPv4";
|
|
};
|
|
ipv6 = mkOption {
|
|
type = ty.ipv6;
|
|
description = "VPN IPv6";
|
|
};
|
|
};
|
|
});
|
|
description = "VPN IP definitions for all available machines";
|
|
readOnly = true;
|
|
};
|
|
vpn.dns = mkOption {
|
|
type = ty.ipv4;
|
|
description = "VPN internal DNS server address";
|
|
readOnly = true;
|
|
};
|
|
vpn.cnames = mkOption {
|
|
type = types.attrsOf types.str;
|
|
description = "CNAMES for our internal DNS server";
|
|
readOnly = true;
|
|
};
|
|
services = mkOption {
|
|
type = with types;
|
|
attrsOf (submodule {
|
|
options = {
|
|
host = mkOption {
|
|
type = str;
|
|
description = "Host where the service runs";
|
|
};
|
|
port = mkOption {
|
|
type = number;
|
|
description = "Port over which the service can be accessed";
|
|
};
|
|
external = mkOption {
|
|
type = nullOr bool;
|
|
description = "Whether this service should be exposed (outside of VPN)";
|
|
};
|
|
};
|
|
});
|
|
description = "Service settings";
|
|
readOnly = true;
|
|
};
|
|
};
|
|
|
|
config.state = let
|
|
host = config.networking.hostName;
|
|
in {
|
|
vpn.ipv4 =
|
|
if state ? vpn.${host}.v4
|
|
then state.vpn.${host}.v4
|
|
else builtins.throw "VPN IPv4 not defined for ${host}";
|
|
vpn.ipv6 =
|
|
if state ? vpn.${host}.v6
|
|
then state.vpn.${host}.v6
|
|
else builtins.throw "VPN IPv6 not defined for ${host}";
|
|
vpn.machine =
|
|
if state ? vpn
|
|
then
|
|
builtins.mapAttrs (_: conf: {
|
|
ipv4 = conf.v4;
|
|
ipv6 = conf.v6;
|
|
})
|
|
state.vpn
|
|
else builtins.throw "No VPN definitions";
|
|
vpn.dns =
|
|
if state ? services && state.services ? dns
|
|
then
|
|
(
|
|
if state ? vpn && state.vpn ? "${state.services.dns.host}"
|
|
then state.vpn.${state.services.dns.host}.v4
|
|
else builtins.throw "No VPN entry for DNS host"
|
|
)
|
|
else builtins.throw "No DNS service defined!";
|
|
vpn.cnames =
|
|
(
|
|
if state ? cnames
|
|
then state.cnames
|
|
else {}
|
|
)
|
|
// (
|
|
builtins.mapAttrs (_name: value: value.host) config.state.services
|
|
);
|
|
services =
|
|
if state ? services
|
|
then state.services
|
|
else {};
|
|
};
|
|
}
|