aaaaa
This commit is contained in:
parent
414e830efa
commit
d3a93fd115
35 changed files with 1832 additions and 228 deletions
|
|
@ -1,9 +1,160 @@
|
|||
{ pkgs, lib, config, ... }:
|
||||
let cfg = config.xyno.services.authentik; in
|
||||
{
|
||||
options.xyno.services.authentik.enable = lib.mkEnableOption "enables the authentik SSO thing";
|
||||
config = lib.mkIf cfg.enable {
|
||||
pkgs,
|
||||
inputs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.xyno.services.authentik;
|
||||
defaultAppOptions = {
|
||||
options = {
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
group = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
groups = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
};
|
||||
meta_description = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
meta_icon = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
meta_launch_url = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
meta_publisher = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
terrraformStateDir = "/var/lib/authentik-terraform-config";
|
||||
environmentFileDir = "/run/authentik-terraform-config";
|
||||
terranixConfig = inputs.terranix.lib.terranixConfiguration {
|
||||
system = pkgs.system;
|
||||
modules = [
|
||||
./authentik/provider.nix
|
||||
{
|
||||
inherit (cfg) oauthApps ldapApps proxyApps;
|
||||
stateFile = "${terrraformStateDir}/state.tfstate";
|
||||
}
|
||||
];
|
||||
};
|
||||
in
|
||||
{
|
||||
options.xyno.services.authentik.enable = mkEnableOption "enables the authentik SSO thing";
|
||||
options.xyno.services.authentik.oauthApps = mkOption {
|
||||
default = { };
|
||||
type = types.attrsOf (
|
||||
types.submodule (
|
||||
{ name, ... }:
|
||||
({
|
||||
options = {
|
||||
environmentFile = mkOption {
|
||||
type = types.str;
|
||||
default = "${environmentFileDir}/${name}_environment";
|
||||
};
|
||||
}
|
||||
// defaultAppOptions.options;
|
||||
})
|
||||
)
|
||||
);
|
||||
};
|
||||
options.xyno.services.authentik.ldapApps = mkOption {
|
||||
default = { };
|
||||
type = types.attrsOf (types.submodule (defaultAppOptions));
|
||||
};
|
||||
options.xyno.services.authentik.proxyApps = mkOption {
|
||||
default = { };
|
||||
type = types.attrsOf (
|
||||
types.submodule ({
|
||||
options = {
|
||||
externalHost = mkOption {
|
||||
type = types.str;
|
||||
};
|
||||
}
|
||||
// defaultAppOptions.options;
|
||||
})
|
||||
);
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
environment.etc."authentik-config/config.tf.json".source = terranixConfig;
|
||||
xyno.impermanence.directories = [
|
||||
terrraformStateDir
|
||||
];
|
||||
services.authentik = {
|
||||
enable = true;
|
||||
createDatabase = true;
|
||||
environmentFile = config.sops.secrets."authentik/env".path;
|
||||
};
|
||||
systemd.services.authentik-ldap.after = [ "authentik-config.service" ];
|
||||
services.authentik-ldap = {
|
||||
environmentFile = "${environmentFileDir}/ldap_config";
|
||||
enable = true;
|
||||
};
|
||||
systemd.services.authentik-proxy.after = [ "authentik-config.service" ];
|
||||
services.authentik-proxy = {
|
||||
enable = true;
|
||||
environmentFile = "${environmentFileDir}/proxy_config";
|
||||
};
|
||||
|
||||
systemd.services.authentik-config = {
|
||||
after = [ "authentik.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
StateDirectory = terrraformStateDir;
|
||||
};
|
||||
script = ''
|
||||
umask u=rw,go=
|
||||
export PATH=$PATH:${pkgs.opentofu}/bin
|
||||
cd terrraformStateDir
|
||||
cp ${terranixConfig} ./main.tf.json
|
||||
source ${config.services.authentik.environmentFile}
|
||||
export AUTHENTIK_URL=http://localhost:9000
|
||||
export AUTHENTIK_TOKEN=$AUTHENTIK_BOOTSTRAP_TOKEN
|
||||
|
||||
tofu init
|
||||
tofu validate || exit 1
|
||||
tofu apply
|
||||
|
||||
tofu output -raw proxy_config > ${environmentFileDir}/proxy_config
|
||||
tofu output -raw ldap_config > ${environmentFileDir}/ldap_config
|
||||
${concatStringsSep "\n" (
|
||||
mapAttrsToList (n: v: "tofu output -raw ${n}_environment > ${v.environmentFile}") cfg.oauthApps
|
||||
)}
|
||||
'';
|
||||
|
||||
};
|
||||
sops.secrets."authentik/env" = {
|
||||
|
||||
};
|
||||
|
||||
services.caddy.extraConfig = ''
|
||||
(reverse_proxy_auth) {
|
||||
route {
|
||||
# always forward outpost path to actual outpost
|
||||
reverse_proxy /outpost.goauthentik.io/* http://[::1]:9000 {
|
||||
}
|
||||
forward_auth http://[::1]:9000 {
|
||||
uri /outpost.goauthentik.io/auth/caddy
|
||||
copy_headers X-Authentik-Username X-Copyparty-Group X-Authentik-Groups X-Authentik-Entitlements X-Authentik-Email X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt X-Authentik-Meta-Jwks X-Authentik-Meta-Outpost X-Authentik-Meta-Provider X-Authentik-Meta-App X-Authentik-Meta-Version X-Grafana-Role
|
||||
}
|
||||
reverse_proxy {args[:]}
|
||||
}
|
||||
'';
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
|||
0
modules/services/authentik/appOptions.nix
Normal file
0
modules/services/authentik/appOptions.nix
Normal file
144
modules/services/authentik/provider.nix
Normal file
144
modules/services/authentik/provider.nix
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
{ lib, config, ... }:
|
||||
with lib;
|
||||
let
|
||||
|
||||
# { ldapApps = { appName = { name = str?; group = str?; meta_desc = str?; meta_icon = str?; meta_launch_url = str?; meta_publisher = str?; }; }; oauthApps = { appName = {}; ] }; proxyApps = { appName = { externalHost = ""; }; }; }
|
||||
|
||||
authorizationFlow = tfRef "data.authentik_flow.default-authorization-flow.id";
|
||||
authenticationFlow = tfRef "data.authentik_flow.default-authentication-flow.id";
|
||||
genApp = provider: n: v: {
|
||||
protocol_provider = provider;
|
||||
slug = n;
|
||||
inherit (v)
|
||||
name
|
||||
group
|
||||
meta_description
|
||||
meta_icon
|
||||
meta_launch_url
|
||||
meta_publisher
|
||||
;
|
||||
};
|
||||
in
|
||||
{
|
||||
options = {
|
||||
stateFile = mkOption { type = types.str; };
|
||||
oauthApps = mkOption { type = types.attrs; };
|
||||
proxyApps = mkOption { type = types.attrs; };
|
||||
ldapApps = mkOption { type = types.attrs; };
|
||||
|
||||
};
|
||||
config = {
|
||||
terraform.backend.local.path = config.stateFile;
|
||||
provider.authentik = { };
|
||||
data.authentik_flow."default-authorization-flow" = {
|
||||
slug = "default-provider-authorization-implicit-consent";
|
||||
};
|
||||
data."authentik_flow"."default-authentication-flow" = {
|
||||
slug = "default-authentication-flow";
|
||||
};
|
||||
resource.authentik_outpost.proxy = {
|
||||
name = "proxy";
|
||||
type = "proxy";
|
||||
protocol_providers = mapAttrsToList (
|
||||
n: v: (tfRef "authentik_provider_proxy.${n}.id")
|
||||
) config.proxyApps;
|
||||
};
|
||||
resource.authentik_outpost.ldap = {
|
||||
name = "ldap";
|
||||
type = "ldap";
|
||||
protocol_providers = mapAttrsToList (
|
||||
n: v: (tfRef "authentik_provider_ldap.${n}.id")
|
||||
) config.ldapApps;
|
||||
};
|
||||
|
||||
resource.authentik_provider_oauth2 = mapAttrs (n: v: {
|
||||
name = n;
|
||||
client_id = n;
|
||||
authorization_flow = authorizationFlow;
|
||||
}) config.oauthApps;
|
||||
data.authentik_provider_oauth2_config = mapAttrs (n: v: {
|
||||
provider_id = tfRef "resource.authentik_provider_oauth2.${n}.id";
|
||||
}) config.oauthApps;
|
||||
|
||||
resource.authentik_provider_proxy = mapAttrs (n: v: {
|
||||
name = n;
|
||||
mode = "forward-single";
|
||||
external_host = v.externalHost;
|
||||
authorization_flow = authorizationFlow;
|
||||
}) config.proxyApps;
|
||||
resource.authentik_provider_ldap = mapAttrs (n: v: {
|
||||
name = n;
|
||||
base_dn = "dc=ldap,dc=goauthentik,dc=io";
|
||||
bind_flow = authenticationFlow;
|
||||
}) config.ldapApps;
|
||||
output =
|
||||
(mapAttrs' (
|
||||
n: v:
|
||||
nameValuePair ("${n}_environment") ({
|
||||
value =
|
||||
let
|
||||
val = val: tfRef "resource.authentik_provider_oauth2.${n}.${val}";
|
||||
cfgVal = val: tfRef "data.authentik_provider_oauth2_config.${n}.${val}";
|
||||
in
|
||||
''
|
||||
CLIENT_ID=${val "client_id"}
|
||||
CLIENT_SECRET=${val "client_secret"}
|
||||
USER_INFO_URL=${cfgVal "user_info_url"}
|
||||
TOKEN_URL=${cfgVal "token_url"}
|
||||
AUTHORIZE_URL=${cfgVal "authorize_url"}
|
||||
'';
|
||||
})
|
||||
) config.oauthApps)
|
||||
// {
|
||||
proxy_config.value = tfRef "resource.authentik_outpost.proxy.config";
|
||||
ldap_config.value = tfRef "resource.authentik_outpost.ldap.config";
|
||||
};
|
||||
|
||||
resource.authentik_application = mkMerge [
|
||||
(mapAttrs (n: v: genApp (tfRef "authentik_provider_oauth2.${n}.id") n v) config.oauthApps)
|
||||
(mapAttrs (n: v: genApp (tfRef "authentik_provider_proxy.${n}.id") n v) config.proxyApps)
|
||||
(mapAttrs (n: v: genApp (tfRef "authentik_provider_ldap.${n}.id") n v) config.ldapApps)
|
||||
];
|
||||
|
||||
# group stuff
|
||||
resource.authentik_group.admin = {
|
||||
name = "admin";
|
||||
};
|
||||
resource.authentik_application_entitlement =
|
||||
let
|
||||
genEnts =
|
||||
apps:
|
||||
mapAttrs (n: v: {
|
||||
name = "${n}-ent";
|
||||
application = tfRef "authentik_application.${n}.uuid";
|
||||
}) (filterAttrs (n: v: (builtins.length v.groups) > 0) apps);
|
||||
in
|
||||
mkMerge [
|
||||
(genEnts config.oauthApps)
|
||||
(genEnts config.proxyApps)
|
||||
(genEnts config.ldapApps)
|
||||
];
|
||||
resource.authentik_policy_binding =
|
||||
let
|
||||
genEnts =
|
||||
apps:
|
||||
lib.flatten (
|
||||
mapAttrsToList (
|
||||
n: v:
|
||||
(map (g: {
|
||||
"${n}-${g}-access" = {
|
||||
target = tfRef "authentik_application_entitlement.${n}.uuid";
|
||||
group = tfRef "authentik_group.${g}.id";
|
||||
order = 0;
|
||||
};
|
||||
}) v.groups)
|
||||
) apps
|
||||
);
|
||||
in
|
||||
mkMerge [
|
||||
(genEnts config.oauthApps)
|
||||
(genEnts config.proxyApps)
|
||||
(genEnts config.ldapApps)
|
||||
];
|
||||
};
|
||||
}
|
||||
102
modules/services/caddy.nix
Normal file
102
modules/services/caddy.nix
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.xyno.services.caddy;
|
||||
wildcardMatcherStr = wildcard: hostName: content: ''
|
||||
@${hostName} host ${hostName}.${wildcard}
|
||||
handle @${hostName} {
|
||||
${content.extraConfig}
|
||||
}
|
||||
|
||||
'';
|
||||
genOneWildcard = wildcard: host: {
|
||||
extraConfig = ''
|
||||
# extra pre
|
||||
${host.extraConfigPre}
|
||||
# block bots
|
||||
${optionalString host.blockBots "import blockBots"}
|
||||
# hosts handler
|
||||
${concatStrings (mapAttrsToList (n: v: wildcardMatcherStr wildcard n v) host.hosts)}
|
||||
# extra post
|
||||
${host.extraConfigPost}
|
||||
abort
|
||||
'';
|
||||
};
|
||||
genVHostsFromWildcard = mapAttrs' (
|
||||
n: v: nameValuePair "*.${n}" (genOneWildcard n v)
|
||||
) cfg.wildcardHosts;
|
||||
in
|
||||
{
|
||||
options.xyno.services.caddy.enable = mkEnableOption "enables caddy with the desec plugin";
|
||||
options.xyno.services.caddy.wildcardHosts = mkOption {
|
||||
example = {
|
||||
"hailsatan.eu" = {
|
||||
blockBots = true;
|
||||
hosts.md.extraConfig = ''reverse_proxy ...'';
|
||||
};
|
||||
};
|
||||
default = { };
|
||||
type =
|
||||
with types;
|
||||
attrsOf (submodule {
|
||||
options = {
|
||||
blockBots = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
};
|
||||
extraConfigPre = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
extraConfigPost = mkOption {
|
||||
type = str;
|
||||
default = "";
|
||||
};
|
||||
hosts = attrsOf (submodule {
|
||||
options = {
|
||||
extraConfig = mkOption { type = lines; };
|
||||
};
|
||||
});
|
||||
};
|
||||
});
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
networking.firewall.allowedTCPPorts = [ 80 443 ];
|
||||
networking.firewall.allowedUDPPorts = [ 443 ];
|
||||
services.caddy = {
|
||||
enable = true;
|
||||
package = pkgs.caddy-desec;
|
||||
virtualHosts = genVHostsFromWildcard;
|
||||
email = mkDefault "ssl@xyno.systems";
|
||||
acmeCA = mkDefault "https://acme-v02.api.letsencrypt.org/directory";
|
||||
globalConfig = ''
|
||||
metrics {
|
||||
per_host
|
||||
}
|
||||
admin ${config.xyno.monitoring.ip}:2019
|
||||
'';
|
||||
extraConfig = ''
|
||||
(blockBots) {
|
||||
@botForbidden header_regexp User-Agent "(?i)AdsBot-Google|Amazonbot|anthropic-ai|Applebot|Applebot-Extended|AwarioRssBot|AwarioSmartBot|Bytespider|CCBot|ChatGPT|ChatGPT-User|Claude-Web|ClaudeBot|cohere-ai|DataForSeoBot|Diffbot|FacebookBot|Google-Extended|GPTBot|ImagesiftBot|magpie-crawler|omgili|Omgilibot|peer39_crawler|PerplexityBot|YouBot"
|
||||
|
||||
handle @botForbidden {
|
||||
redir https://hil-speed.hetzner.com/10GB.bin
|
||||
}
|
||||
handle /robots.txt {
|
||||
respond <<TXT
|
||||
User-Agent: *
|
||||
Disallow: /
|
||||
TXT 200
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
xyno.services.monitoring.exporters.caddy = 2019;
|
||||
|
||||
};
|
||||
}
|
||||
|
|
@ -2,21 +2,88 @@
|
|||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
instanceConfig,
|
||||
instanceConfigs,
|
||||
# inputs,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.xyno.services.monitoring;
|
||||
|
||||
firstInstanceWithPromServer = (builtins.head (
|
||||
builtins.filter (x: x ? prometheusServer && x.prometheusServer) (attrValues instanceConfigs)
|
||||
)).hostName;
|
||||
vmBasicAuthUsername = "xyno-monitoring";
|
||||
in
|
||||
{
|
||||
options.xyno.services.monitoring.enable =
|
||||
lib.mkEnableOption "enables monitoring (prometheus exporters and stuff)";
|
||||
options.xyno.services.monitoring.ip = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "::1";
|
||||
description = "the ip prometheus exporters should listen to";
|
||||
mkEnableOption "enables monitoring (prometheus exporters and stuff)";
|
||||
options.xyno.services.monitoring.remoteWriteUrl = mkOption {
|
||||
type = types.str;
|
||||
default = "http://${firstInstanceWithPromServer}.${config.xyno.services.wireguard.monHostsDomain}:8428/api/v1/write";
|
||||
description = "where prometheus metrics should be pushed to";
|
||||
};
|
||||
options.xyno.services.monitoring.exporters = mkOption {
|
||||
type = types.attrsOf (types.either types.int types.str);
|
||||
description = "names of exporters and their ports (to open fw and generate prometheus config)";
|
||||
example = ''
|
||||
{
|
||||
node = 9100;
|
||||
postgres = "unix:///run/postgres-exporter.sock";
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
config = mkMerge [
|
||||
(mkIf cfg.enable {
|
||||
services.prometheus.exporters.node = {
|
||||
enable = true;
|
||||
enabledCollectors = [ "systemd" ];
|
||||
};
|
||||
xyno.services.monitoring.exporters.node = config.services.prometheus.exporters.node.port;
|
||||
services.vmagent = {
|
||||
remoteWrite.url = cfg.remoteWriteUrl;
|
||||
remoteWrite.basicAuthUsername = vmBasicAuthUsername;
|
||||
remoteWrite.basicAuthPasswordFile = config.sops.secrets."victoriametrics/basicAuthPassword".path;
|
||||
|
||||
};
|
||||
prometheusConfig.scrape_configs = mapAttrsToList (name: value: {
|
||||
job_name = "${name}-exporter";
|
||||
metrics_path = "/metrics";
|
||||
staticConfigs = [
|
||||
{
|
||||
targets = [ (if ((builtins.typeOf value) == "string") then value else "[::1]:${toString value}") ];
|
||||
labels.type = name;
|
||||
labels.host = config.networking.hostName;
|
||||
}
|
||||
];
|
||||
}) cfg.exporters;
|
||||
};
|
||||
sops.secrets."victoriametrics/basicAuthPassword" = {
|
||||
reloadUnits = [ "vmagent.service" ];
|
||||
};
|
||||
|
||||
})
|
||||
(mkIf (cfg.enable && instanceConfig ? prometheusServer && instanceConfig.prometheusServer) {
|
||||
xyno.impermanence.directories = [ "/var/lib/${config.services.victoriametrics.stateDir}" ];
|
||||
sops.secrets."victoriametrics/basicAuthPassword" = {
|
||||
reloadUnits = [ "victoriametrics.service" ];
|
||||
};
|
||||
networking.firewall.extraInputRules = ''tcp dport 8428 ip6 daddr ${config.xyno.services.wireguard.monIp6}/128 accept comment "victoriametrics-http"'';
|
||||
systemd.services.victoriametrics.serviceConfig.LoadCredential = [
|
||||
"basic_auth_pw:${config.sops.secrets."victoriametrics/basicAuthPassword".path}"
|
||||
];
|
||||
services.victoriametrics = {
|
||||
enable = true;
|
||||
listenAddress = "${config.xyno.services.wireguard.monIp6}:8428";
|
||||
extraOptions = [
|
||||
"-httpAuth.username=${vmBasicAuthUsername}"
|
||||
"-httpAuth.password=file://\${CREDENTIALS_DIRECTORY}/basic_auth_pw"
|
||||
];
|
||||
};
|
||||
|
||||
services.grafana.declarativePlugins = with pkgs.grafanaPlugins; [ victoriametrics-metrics-datasource ];
|
||||
|
||||
})
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,8 @@ in
|
|||
};
|
||||
services.prometheus.exporters.postgres = lib.mkIf config.xyno.services.monitoring.enable {
|
||||
enable = true;
|
||||
listenAddress = config.xyno.services.monitoring.ip;
|
||||
port = 9187;
|
||||
};
|
||||
xyno.services.monitoring.exporters.postgres = config.services.prometheus.exporters.postgres.port;
|
||||
|
||||
xyno.impermanence.extraDirectories = [ "/var/lib/postgresql" ];
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,9 @@
|
|||
...
|
||||
}:
|
||||
let
|
||||
wgServer = instanceConfig?wg.server && instanceConfig.wg.server;
|
||||
cfg = config.xyno.services.wireguard;
|
||||
ula = "fd68:b6a4:36e4";
|
||||
ula = cfg.ula;
|
||||
ulaPrefix = "${ula}:1337"; # /64 for normal vpn
|
||||
monitoringUlaPrefix = "${ula}:2337"; # /64 for monitoring
|
||||
|
||||
|
|
@ -17,55 +18,84 @@ let
|
|||
prefix: hostName:
|
||||
let
|
||||
hostHash = builtins.hashString "sha512" hostName;
|
||||
localParts = map (n: builtins.substring (n * 4) 4 hostHash) hostHash;
|
||||
localParts = map (n: builtins.substring (n * 4) 4 hostHash) (lib.range 0 3);
|
||||
localPart = lib.concatStringsSep ":" localParts;
|
||||
in
|
||||
"${prefix}:${localPart}";
|
||||
# peers list for networkd
|
||||
wgPeers = map (
|
||||
filteredConfigs = builtins.filter (x: x.hostName != config.networking.hostName ) (lib.attrValues instanceConfigs);
|
||||
wgPeersLists = map (
|
||||
c:
|
||||
(
|
||||
(lib.optionals (lib.hasAttr c "publicHostname") {
|
||||
(lib.optional (c?publicHostname) {
|
||||
# if peer is publicly on the internet
|
||||
AllowedIPs =
|
||||
(lib.optionals (c.wgServer) [
|
||||
(lib.optionals (c.wg.server) [
|
||||
"${ulaPrefix}::/48" # all traffic in the ula shall be sent to the server
|
||||
])
|
||||
++ (lib.optionals (!c.wgServer) [
|
||||
++ (lib.optionals (!c.wg.server) [
|
||||
"${genUlaForHost ulaPrefix c.hostName}/128" # if a host is reachable but shouldn't play server, send only to the hosts ip
|
||||
]);
|
||||
Endpoint = "${c.publicHostname}:51820";
|
||||
PersistentKeepalive = 25;
|
||||
PublicKey = c.wgPubKey;
|
||||
})
|
||||
++ (lib.optionals (!(lib.hasAttr c "publicHostname") && instanceConfig.wgServer && (lib.hasAttr c "wgPubKey")) {
|
||||
# if this is the server and the peer isn't reachable on the internet
|
||||
AllowedIPs = [
|
||||
"${genUlaForHost ulaPrefix c.hostName}/128"
|
||||
"${genUlaForHost monitoringUlaPrefix c.hostName}/128"
|
||||
];
|
||||
PublicKey = c.wgPubKey;
|
||||
# TODO: preshared keys
|
||||
PublicKey = c.wg.pubKey;
|
||||
})
|
||||
++ (lib.optional
|
||||
((!c?publicHostname) && wgServer && (c?wg.pubKey))
|
||||
{
|
||||
# if this is the server and the peer isn't reachable on the internet
|
||||
AllowedIPs = [
|
||||
"${genUlaForHost ulaPrefix c.hostName}/128"
|
||||
"${genUlaForHost monitoringUlaPrefix c.hostName}/128"
|
||||
];
|
||||
PublicKey = c.wg.pubKey;
|
||||
PresharedKeyFile = config.sops.secrets."wg/psk".path; # TODO
|
||||
}
|
||||
)
|
||||
)
|
||||
) instanceConfigs;
|
||||
) filteredConfigs;
|
||||
wgPeers = lib.flatten wgPeersLists;
|
||||
in
|
||||
{
|
||||
options.xyno.services.wireguard.enable = lib.mkEnableOption "enables wireguard";
|
||||
options.xyno.services.wireguard.hostsDomain = lib.mkOpion { type = lib.types.str; default = "wg.hailsatan.eu"; };
|
||||
options.xyno.services.wireguard.monHostsDomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "mon.wg.hailsatan.eu";
|
||||
};
|
||||
options.xyno.services.wireguard.hostsDomain = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "wg.hailsatan.eu";
|
||||
};
|
||||
options.xyno.services.wireguard.ula = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "fd68:b6a4:36e4";
|
||||
};
|
||||
options.xyno.services.wireguard.ip6 = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = genUlaForHost ulaPrefix config.networking.hostName;
|
||||
};
|
||||
options.xyno.services.wireguard.monIp6 = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = genUlaForHost monitoringUlaPrefix config.networking.hostName;
|
||||
};
|
||||
config = lib.mkIf cfg.enable {
|
||||
xyno.services.monitoring.ip = genUlaForHost monitoringUlaPrefix config.networking.hostName;
|
||||
networking.hosts = lib.mapAttrs' (
|
||||
networking.hosts = (lib.mapAttrs' (
|
||||
n: v: {
|
||||
name = "${v.hostName}.${cfg.hostsDomain}";
|
||||
value = [ (genUlaForHost ulaPrefix v.hostName) ];
|
||||
value = ["${v.hostName}.${cfg.hostsDomain}"];
|
||||
name = (genUlaForHost ulaPrefix v.hostName);
|
||||
}
|
||||
);
|
||||
networking.firewall.allowedUDPPorts = lib.mkIf instanceConfig.wgServer [ 51820 ];
|
||||
) instanceConfigs) // (lib.mapAttrs' (
|
||||
n: v: {
|
||||
value = ["${v.hostName}.${cfg.monHostsDomain}"];
|
||||
name = (genUlaForHost monitoringUlaPrefix v.hostName);
|
||||
}
|
||||
) instanceConfigs);
|
||||
networking.firewall.allowedUDPPorts = lib.optional wgServer [ 51820 ];
|
||||
networking.firewall.interfaces."wg0".allowedUDPPorts = lib.optional wgServer [ 53 ];
|
||||
systemd.network.netdevs."wg0" = {
|
||||
wireguardConfig = {
|
||||
ListenPort = lib.mkIf instanceConfig.wgServer 51820;
|
||||
PrivateKeyFile = config.sops.secrets.wg_privkey.path; # TODO
|
||||
ListenPort = lib.mkIf wgServer 51820;
|
||||
PrivateKeyFile = config.sops.secrets."wg/privkey".path; # TODO
|
||||
};
|
||||
wireguardPeers = wgPeers;
|
||||
};
|
||||
|
|
@ -79,8 +109,28 @@ in
|
|||
"${(genUlaForHost monitoringUlaPrefix config.networking.hostName)}/128"
|
||||
];
|
||||
};
|
||||
services.prometheus.exporters.wireguard = lib.mkIf (wgServer && config.xyno.services.monitoring.enable) {
|
||||
enable = true;
|
||||
interfaces = [ "wg0" ];
|
||||
};
|
||||
|
||||
sops.secrets.wg_privkey = {
|
||||
services.coredns = lib.mkIf wgServer { # for non nixos devices to be able to resolve vpn hostnames
|
||||
enable = true;
|
||||
config = ''
|
||||
. {
|
||||
bind wg0
|
||||
prometheus
|
||||
hosts ${cfg.hostsDomain}
|
||||
forward . /etc/resolv.conf
|
||||
}
|
||||
'';
|
||||
};
|
||||
xyno.services.monitoring.exporters.coredns = lib.mkIf wgServer 9153;
|
||||
xyno.services.monitoring.exporters.wireguard = lib.mkIf wgServer config.services.prometheus.exporters.wireguard.port;
|
||||
sops.secrets."wg/privkey" = {
|
||||
reloadUnits = [ "systemd-networkd.service" ];
|
||||
};
|
||||
sops.secrets."wg/psk" = {
|
||||
reloadUnits = [ "systemd-networkd.service" ];
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue