Ways #98
2 changed files with 87 additions and 27 deletions
|
@ -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";
|
||||||
|
|
|
@ -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}";
|
||||||
|
})
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue