Ways #98

Merged
max merged 10 commits from pr-cluster-reverse-proxy into master 2024-07-04 22:05:22 +03:00
2 changed files with 87 additions and 27 deletions
Showing only changes of commit a39ef182d4 - Show all commits

View file

@ -1,37 +1,47 @@
{ cluster, depot, lib, ... }: { cluster, config, depot, lib, pkgs, ... }:
let let
inherit (depot.lib.meta) domain; inherit (depot.lib.meta) domain;
externalWays = lib.filterAttrs (_: cfg: !cfg.internal) cluster.config.ways; externalWays = lib.filterAttrs (_: cfg: !cfg.internal) cluster.config.ways;
consulServiceWays = lib.filterAttrs (_: cfg: cfg.useConsul) cluster.config.ways;
consulHttpAddr = "${config.services.consul.extraConfig.addresses.http or "127.0.0.1"}:${toString (config.services.consul.extraConfig.ports.http or 8500)}";
in in
{ {
services.nginx.virtualHosts = lib.mapAttrs' (name: cfg: { services.nginx = {
name = if cfg.internal then "${name}.internal.${domain}" else "${name}.${domain}"; virtualHosts = lib.mapAttrs' (name: cfg: {
value = { ... }: { name = if cfg.internal then "${name}.internal.${domain}" else "${name}.${domain}";
imports = [ value = { ... }: {
cfg.extras imports = [
{ cfg.extras
forceSSL = true; {
enableACME = !cfg.internal; forceSSL = true;
useACMEHost = lib.mkIf cfg.internal "internal.${domain}"; enableACME = !cfg.internal;
locations = lib.mkMerge [ useACMEHost = lib.mkIf cfg.internal "internal.${domain}";
{ locations = lib.mkMerge [
"/".proxyPass = cfg.target; {
"${cfg.healthCheckPath}".extraConfig = "access_log off;"; "/".proxyPass = cfg.target;
} "${cfg.healthCheckPath}".extraConfig = "access_log off;";
{ }
"/.well-known/ways/internal-health-check" = { {
return = ''200 "INTERNAL_OK\n"''; "/.well-known/ways/internal-health-check" = {
extraConfig = "access_log off;"; return = ''200 "INTERNAL_OK\n"'';
}; extraConfig = "access_log off;";
} };
]; }
} ];
]; }
}; ];
}) cluster.config.ways; };
}) cluster.config.ways;
appendHttpConfig = lib.mkIf (consulServiceWays != {}) ''
include /run/consul-template/nginx-ways-*.conf;
'';
};
security.acme.certs = lib.mapAttrs' (name: cfg: { security.acme.certs = lib.mapAttrs' (name: cfg: {
name = "${name}.${domain}"; name = "${name}.${domain}";
@ -41,6 +51,33 @@ in
}; };
}) externalWays; }) externalWays;
services.consul-template.instances.ways = lib.mkIf (consulServiceWays != {}) {
user = "nginx";
group = "nginx";
settings = {
consul.address = "http://${consulHttpAddr}";
template = [
{
source = let
upstreams = lib.mapAttrsToList (_: cfg: ''
upstream ${cfg.nginxUpstreamName} {
{{ range $i, $e := service "${cfg.consulService}~_agent" -}}
server {{ .Address }}:{{ .Port }}{{ if ne $i 0 }} backup{{ end }};
{{end}}
}
'') consulServiceWays;
in pkgs.writeText "ways-upstreams.ctmpl" (lib.concatStringsSep "\n" upstreams);
destination = "/run/consul-template/nginx-ways-upstreams.conf";
exec.command = [
"${config.services.nginx.package}/bin/nginx"
"-s" "reload"
"-g" "pid /run/nginx/nginx.pid;"
];
}
];
};
};
consul.services.ways-proxy = { consul.services.ways-proxy = {
unit = "nginx"; unit = "nginx";
mode = "external"; mode = "external";

View file

@ -1,4 +1,4 @@
{ lib, name, ... }: { lib, name, options, ... }:
with lib; with lib;
@ -20,15 +20,38 @@ with lib;
type = types.str; type = types.str;
}; };
consulService = mkOption {
type = types.str;
};
healthCheckPath = mkOption { healthCheckPath = mkOption {
type = types.path; type = types.path;
default = "/.well-known/ways/internal-health-check"; default = "/.well-known/ways/internal-health-check";
}; };
useConsul = mkOption {
type = types.bool;
internal = true;
default = false;
};
nginxUpstreamName = mkOption {
type = types.str;
internal = true;
};
extras = mkOption { extras = mkOption {
description = "Extra configuration to pass to the nginx virtual host submodule."; description = "Extra configuration to pass to the nginx virtual host submodule.";
type = types.deferredModule; type = types.deferredModule;
default = {}; default = {};
}; };
}; };
config = lib.mkMerge [
(lib.mkIf options.consulService.isDefined {
useConsul = true;
nginxUpstreamName = "ways_upstream_${builtins.hashString "md5" options.consulService.value}";
target = "http://${options.nginxUpstreamName.value}";
})
];
} }