From 98cb84c4d0ec41b647a418da03767a0a64bcb83f Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 4 Jul 2024 01:57:36 +0200 Subject: [PATCH 01/10] cluster/services/ways: init --- cluster/services/ways/default.nix | 16 +++++++ cluster/services/ways/host.nix | 58 +++++++++++++++++++++++ cluster/services/ways/options/default.nix | 8 ++++ cluster/services/ways/options/way.nix | 34 +++++++++++++ 4 files changed, 116 insertions(+) create mode 100644 cluster/services/ways/default.nix create mode 100644 cluster/services/ways/host.nix create mode 100644 cluster/services/ways/options/default.nix create mode 100644 cluster/services/ways/options/way.nix diff --git a/cluster/services/ways/default.nix b/cluster/services/ways/default.nix new file mode 100644 index 0000000..786499d --- /dev/null +++ b/cluster/services/ways/default.nix @@ -0,0 +1,16 @@ +{ config, lib, ... }: + +{ + imports = [ + ./options + ]; + + services.ways = { + nodes.host = config.services.websites.nodes.host; + nixos.host = ./host.nix; + }; + + dns.records = lib.mapAttrs (name: cfg: { + consulService = "${name}.ways-proxy"; + }) (lib.filterAttrs (_: cfg: !cfg.internal) config.ways); +} diff --git a/cluster/services/ways/host.nix b/cluster/services/ways/host.nix new file mode 100644 index 0000000..884fcf1 --- /dev/null +++ b/cluster/services/ways/host.nix @@ -0,0 +1,58 @@ +{ cluster, depot, lib, ... }: + +let + inherit (depot.lib.meta) domain; + + externalWays = lib.filterAttrs (_: cfg: !cfg.internal) cluster.config.ways; +in + +{ + services.nginx.virtualHosts = lib.mapAttrs' (name: cfg: { + name = if cfg.internal then "${name}.internal.${domain}" else "${name}.${domain}"; + value = { ... }: { + imports = [ + cfg.extras + { + forceSSL = true; + enableACME = !cfg.internal; + useACMEHost = lib.mkIf cfg.internal "internal.${domain}"; + locations = lib.mkMerge [ + { + "/".proxyPass = cfg.target; + "${cfg.healthCheckPath}".extraConfig = "access_log off;"; + } + { + "/.well-known/ways/internal-health-check" = { + return = ''200 "INTERNAL_OK\n"''; + extraConfig = "access_log off;"; + }; + } + ]; + } + ]; + }; + }) cluster.config.ways; + + security.acme.certs = lib.mapAttrs' (name: cfg: { + name = "${name}.${domain}"; + value = { + dnsProvider = "exec"; + webroot = lib.mkForce null; + }; + }) externalWays; + + consul.services.ways-proxy = { + unit = "nginx"; + mode = "external"; + definition = { + name = "ways-proxy"; + address = depot.reflection.interfaces.primary.addrPublic; + port = 443; + checks = lib.singleton { + interval = "60s"; + tcp = "127.0.0.1:80"; + }; + tags = lib.attrNames externalWays; + }; + }; +} diff --git a/cluster/services/ways/options/default.nix b/cluster/services/ways/options/default.nix new file mode 100644 index 0000000..abbf0a6 --- /dev/null +++ b/cluster/services/ways/options/default.nix @@ -0,0 +1,8 @@ +{ lib, ... }: + +{ + options.ways = lib.mkOption { + type = lib.types.attrsOf (lib.types.submodule ./way.nix); + default = {}; + }; +} diff --git a/cluster/services/ways/options/way.nix b/cluster/services/ways/options/way.nix new file mode 100644 index 0000000..8561902 --- /dev/null +++ b/cluster/services/ways/options/way.nix @@ -0,0 +1,34 @@ +{ lib, name, ... }: + +with lib; + +{ + options = { + internal = mkOption { + description = "Whether to only make this Way available internally. Will use the internal subdomain."; + type = types.bool; + default = false; + }; + + name = mkOption { + description = "Subdomain name to use."; + type = types.str; + default = name; + }; + + target = mkOption { + type = types.str; + }; + + healthCheckPath = mkOption { + type = types.path; + default = "/.well-known/ways/internal-health-check"; + }; + + extras = mkOption { + description = "Extra configuration to pass to the nginx virtual host submodule."; + type = types.deferredModule; + default = {}; + }; + }; +} -- 2.45.2 From 01f113046f1f39183941796dbfa704508a00578b Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 4 Jul 2024 04:06:20 +0200 Subject: [PATCH 02/10] cluster/lib: implement meshLinks --- cluster/default.nix | 3 ++- cluster/lib/mesh.nix | 15 +++++++++++++++ cluster/lib/service-module.nix | 19 ++++++++++++++++++- 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 cluster/lib/mesh.nix diff --git a/cluster/default.nix b/cluster/default.nix index 118341f..7a7653f 100644 --- a/cluster/default.nix +++ b/cluster/default.nix @@ -14,7 +14,8 @@ lib.evalModules { ./lib/services.nix ./lib/inject-nixos-config.nix ./lib/port-magic-multi.nix + ./lib/mesh.nix ./import-services.nix ]; -} \ No newline at end of file +} diff --git a/cluster/lib/mesh.nix b/cluster/lib/mesh.nix new file mode 100644 index 0000000..821512c --- /dev/null +++ b/cluster/lib/mesh.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +{ + hostLinks = lib.pipe config.services [ + (lib.filterAttrs (_: svc: svc.meshLinks != {})) + (lib.mapAttrsToList (svcName: svc: lib.mapAttrsToList (name: cfg: lib.genAttrs svc.nodes.${name} (hostName: { + ${cfg.name} = { ... }: { + imports = [ cfg.link ]; + ipv4 = config.vars.mesh.${hostName}.meshIp; + }; + })) svc.meshLinks)) + (map lib.mkMerge) + lib.mkMerge + ]; +} diff --git a/cluster/lib/service-module.nix b/cluster/lib/service-module.nix index 4f15370..c8f3558 100644 --- a/cluster/lib/service-module.nix +++ b/cluster/lib/service-module.nix @@ -1,8 +1,9 @@ -{ config, lib, ... }: +{ config, lib, name, ... }: with lib; let filterGroup = group: hostName: builtins.filter (x: x != hostName) group; + serviceName = name; in { @@ -31,6 +32,22 @@ in type = with types; attrs; default = {}; }; + meshLinks = mkOption { + description = "Create host links on the mesh network."; + type = types.attrsOf (types.submodule ({ name, ... }: { + options = { + name = mkOption { + type = types.str; + default = "${serviceName}-${name}"; + }; + link = mkOption { + type = types.deferredModule; + default = {}; + }; + }; + })); + default = {}; + }; }; config.otherNodes = builtins.mapAttrs (const filterGroup) config.nodes; } -- 2.45.2 From c484a2cf0201a3902319dce4c79752cfec6f5284 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 4 Jul 2024 04:25:56 +0200 Subject: [PATCH 03/10] cluster/services/forge: switch to ways --- cluster/services/forge/default.nix | 10 +++++++--- cluster/services/forge/server.nix | 6 +----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cluster/services/forge/default.nix b/cluster/services/forge/default.nix index 9693e02..e46d925 100644 --- a/cluster/services/forge/default.nix +++ b/cluster/services/forge/default.nix @@ -4,11 +4,15 @@ services.forge = { nodes.server = [ "VEGAS" ]; nixos.server = ./server.nix; + meshLinks.server = { + name = "forge"; + link.protocol = "http"; + }; }; - dns.records.forge.target = map - (node: depot.hours.${node}.interfaces.primary.addrPublic) - config.services.forge.nodes.server; + ways.forge.target = let + host = builtins.head config.services.forge.nodes.server; + in config.hostLinks.${host}.forge.url; garage = { keys.forgejo = { }; diff --git a/cluster/services/forge/server.nix b/cluster/services/forge/server.nix index ce4cefc..434f5d9 100644 --- a/cluster/services/forge/server.nix +++ b/cluster/services/forge/server.nix @@ -9,7 +9,7 @@ let host = "forge.${domain}"; - link = config.links.forge; + link = cluster.config.hostLinks.${config.networking.hostName}.forge; exe = lib.getExe config.services.forgejo.package; in @@ -43,8 +43,6 @@ in }; }; - links.forge.protocol = "http"; - services.forgejo = { enable = true; package = depot.packages.forgejo; @@ -101,8 +99,6 @@ in }; }; - services.nginx.virtualHosts."${host}" = vhosts.proxy link.url; - systemd.services.forgejo.preStart = let providerName = "PrivateVoidAccount"; args = lib.escapeShellArgs [ -- 2.45.2 From a39ef182d4942d7700c6ac3439fbdecaf5af823d Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 4 Jul 2024 17:03:39 +0200 Subject: [PATCH 04/10] cluster/services/ways: support multiple backends via consul services --- cluster/services/ways/host.nix | 89 +++++++++++++++++++-------- cluster/services/ways/options/way.nix | 25 +++++++- 2 files changed, 87 insertions(+), 27 deletions(-) diff --git a/cluster/services/ways/host.nix b/cluster/services/ways/host.nix index 884fcf1..84bf0f4 100644 --- a/cluster/services/ways/host.nix +++ b/cluster/services/ways/host.nix @@ -1,37 +1,47 @@ -{ cluster, depot, lib, ... }: +{ cluster, config, depot, lib, pkgs, ... }: let inherit (depot.lib.meta) domain; 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 { - services.nginx.virtualHosts = lib.mapAttrs' (name: cfg: { - name = if cfg.internal then "${name}.internal.${domain}" else "${name}.${domain}"; - value = { ... }: { - imports = [ - cfg.extras - { - forceSSL = true; - enableACME = !cfg.internal; - useACMEHost = lib.mkIf cfg.internal "internal.${domain}"; - locations = lib.mkMerge [ - { - "/".proxyPass = cfg.target; - "${cfg.healthCheckPath}".extraConfig = "access_log off;"; - } - { - "/.well-known/ways/internal-health-check" = { - return = ''200 "INTERNAL_OK\n"''; - extraConfig = "access_log off;"; - }; - } - ]; - } - ]; - }; - }) cluster.config.ways; + services.nginx = { + virtualHosts = lib.mapAttrs' (name: cfg: { + name = if cfg.internal then "${name}.internal.${domain}" else "${name}.${domain}"; + value = { ... }: { + imports = [ + cfg.extras + { + forceSSL = true; + enableACME = !cfg.internal; + useACMEHost = lib.mkIf cfg.internal "internal.${domain}"; + locations = lib.mkMerge [ + { + "/".proxyPass = cfg.target; + "${cfg.healthCheckPath}".extraConfig = "access_log off;"; + } + { + "/.well-known/ways/internal-health-check" = { + return = ''200 "INTERNAL_OK\n"''; + extraConfig = "access_log off;"; + }; + } + ]; + } + ]; + }; + }) cluster.config.ways; + + appendHttpConfig = lib.mkIf (consulServiceWays != {}) '' + include /run/consul-template/nginx-ways-*.conf; + ''; + }; security.acme.certs = lib.mapAttrs' (name: cfg: { name = "${name}.${domain}"; @@ -41,6 +51,33 @@ in }; }) 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 = { unit = "nginx"; mode = "external"; diff --git a/cluster/services/ways/options/way.nix b/cluster/services/ways/options/way.nix index 8561902..6bd3428 100644 --- a/cluster/services/ways/options/way.nix +++ b/cluster/services/ways/options/way.nix @@ -1,4 +1,4 @@ -{ lib, name, ... }: +{ lib, name, options, ... }: with lib; @@ -20,15 +20,38 @@ with lib; type = types.str; }; + consulService = mkOption { + type = types.str; + }; + healthCheckPath = mkOption { type = types.path; 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 { description = "Extra configuration to pass to the nginx virtual host submodule."; type = types.deferredModule; 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}"; + }) + ]; } -- 2.45.2 From a2cbfb9c258df7048367f3a624a60e9eca48d87e Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 4 Jul 2024 17:31:59 +0200 Subject: [PATCH 05/10] cluster/services/monitoring: switch to ways --- cluster/services/monitoring/default.nix | 5 +++- cluster/services/monitoring/grafana-ha.nix | 31 +++------------------- 2 files changed, 8 insertions(+), 28 deletions(-) diff --git a/cluster/services/monitoring/default.nix b/cluster/services/monitoring/default.nix index 03e5318..2753a27 100644 --- a/cluster/services/monitoring/default.nix +++ b/cluster/services/monitoring/default.nix @@ -85,5 +85,8 @@ in }; }; - dns.records.monitoring.consulService = "grafana"; + ways.monitoring = { + consulService = "grafana"; + extras.locations."/".proxyWebsockets = true; + }; } diff --git a/cluster/services/monitoring/grafana-ha.nix b/cluster/services/monitoring/grafana-ha.nix index 85b2154..6451617 100644 --- a/cluster/services/monitoring/grafana-ha.nix +++ b/cluster/services/monitoring/grafana-ha.nix @@ -8,8 +8,6 @@ let inherit (config.networking) hostName; - svc = cluster.config.services.monitoring; - iniList = lib.concatStringsSep " "; login = x: "https://login.${domain}/auth/realms/master/protocol/openid-connect/${x}"; @@ -93,36 +91,15 @@ in }; }; - services.nginx = { - upstreams.grafana-ha.servers = lib.mapAttrs' (_: links: lib.nameValuePair links.grafana.tuple {}) (lib.getAttrs (svc.nodes.grafana) hostLinks); - - virtualHosts."monitoring.${domain}" = lib.recursiveUpdate (depot.lib.nginx.vhosts.proxy "http://grafana-ha") { - locations."/".proxyWebsockets = true; - }; - }; - - security.acme.certs."monitoring.${domain}" = { - dnsProvider = "exec"; - webroot = lib.mkForce null; - }; - consul.services.grafana = { mode = "manual"; - definition = rec { + definition = { name = "grafana"; - address = depot.reflection.interfaces.primary.addrPublic; - port = 443; + address = hostLinks.${hostName}.grafana.ipv4; + port = hostLinks.${hostName}.grafana.port; checks = [ - rec { - name = "Frontend"; - id = "service:grafana:frontend"; - interval = "30s"; - http = "https://${address}/healthz"; - tls_server_name = "monitoring.${domain}"; - header.Host = lib.singleton tls_server_name; - } { - name = "Backend"; + name = "Grafana"; id = "service:grafana:backend"; interval = "5s"; http = "${hostLinks.${hostName}.grafana.url}/healthz"; -- 2.45.2 From ac047b189dc088dfd36f16f92cf20c6d668425d8 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 4 Jul 2024 18:12:52 +0200 Subject: [PATCH 06/10] cluster/services/ways: support wildcards --- cluster/services/ways/default.nix | 6 +-- cluster/services/ways/host.nix | 15 +++++--- cluster/services/ways/options/default.nix | 8 +++- cluster/services/ways/options/way.nix | 46 +++++++++++++++++++++-- 4 files changed, 61 insertions(+), 14 deletions(-) diff --git a/cluster/services/ways/default.nix b/cluster/services/ways/default.nix index 786499d..eb4f3c1 100644 --- a/cluster/services/ways/default.nix +++ b/cluster/services/ways/default.nix @@ -10,7 +10,7 @@ nixos.host = ./host.nix; }; - dns.records = lib.mapAttrs (name: cfg: { - consulService = "${name}.ways-proxy"; - }) (lib.filterAttrs (_: cfg: !cfg.internal) config.ways); + dns.records = lib.mapAttrs' + (_: cfg: lib.nameValuePair cfg.dnsRecord.name ({ ... }: { imports = [ cfg.dnsRecord.value ]; })) + config.ways; } diff --git a/cluster/services/ways/host.nix b/cluster/services/ways/host.nix index 84bf0f4..2c1a902 100644 --- a/cluster/services/ways/host.nix +++ b/cluster/services/ways/host.nix @@ -1,8 +1,6 @@ { cluster, config, depot, lib, pkgs, ... }: let - inherit (depot.lib.meta) domain; - externalWays = lib.filterAttrs (_: cfg: !cfg.internal) cluster.config.ways; consulServiceWays = lib.filterAttrs (_: cfg: cfg.useConsul) cluster.config.ways; @@ -13,14 +11,17 @@ in { services.nginx = { virtualHosts = lib.mapAttrs' (name: cfg: { - name = if cfg.internal then "${name}.internal.${domain}" else "${name}.${domain}"; + name = cfg.name; value = { ... }: { imports = [ cfg.extras { forceSSL = true; - enableACME = !cfg.internal; - useACMEHost = lib.mkIf cfg.internal "internal.${domain}"; + enableACME = !cfg.internal && !cfg.wildcard; + useACMEHost = lib.mkMerge [ + (lib.mkIf cfg.internal cfg.domainSuffixInternal) + (lib.mkIf cfg.wildcard "${name}.${cfg.domainSuffix}") + ]; locations = lib.mkMerge [ { "/".proxyPass = cfg.target; @@ -44,10 +45,12 @@ in }; security.acme.certs = lib.mapAttrs' (name: cfg: { - name = "${name}.${domain}"; + name = "${name}.${cfg.domainSuffix}"; value = { + domain = lib.mkIf cfg.wildcard "*.${name}.${cfg.domainSuffix}"; dnsProvider = "exec"; webroot = lib.mkForce null; + group = "nginx"; }; }) externalWays; diff --git a/cluster/services/ways/options/default.nix b/cluster/services/ways/options/default.nix index abbf0a6..c2b8212 100644 --- a/cluster/services/ways/options/default.nix +++ b/cluster/services/ways/options/default.nix @@ -1,8 +1,12 @@ -{ lib, ... }: +{ lib, depot, ... }: { options.ways = lib.mkOption { - type = lib.types.attrsOf (lib.types.submodule ./way.nix); + type = lib.types.attrsOf (lib.types.submodule { + imports = [ ./way.nix ]; + domainSuffixExternal = depot.lib.meta.domain; + domainSuffixInternal = "internal.${depot.lib.meta.domain}"; + }); default = {}; }; } diff --git a/cluster/services/ways/options/way.nix b/cluster/services/ways/options/way.nix index 6bd3428..34ca4bf 100644 --- a/cluster/services/ways/options/way.nix +++ b/cluster/services/ways/options/way.nix @@ -1,4 +1,4 @@ -{ lib, name, options, ... }: +{ config, lib, name, options, ... }: with lib; @@ -11,15 +11,39 @@ with lib; }; name = mkOption { - description = "Subdomain name to use."; + description = "Domain name to use."; type = types.str; - default = name; + default = let + basename = "${name}.${config.domainSuffix}"; + in if config.wildcard then "~^(.+)\.${lib.escapeRegex basename}$" else basename; + }; + + dnsRecord = { + name = mkOption { + description = "DNS record name for this Way."; + type = types.str; + default = if config.wildcard then "^[^_].+\\.${lib.escapeRegex name}" else name; + }; + + value = mkOption { + description = "DNS record value for this Way."; + type = types.deferredModule; + default = { + consulService = "${name}.ways-proxy"; + rewrite.type = lib.mkIf config.wildcard "regex"; + }; + }; }; target = mkOption { type = types.str; }; + wildcard = mkOption { + type = types.bool; + default = false; + }; + consulService = mkOption { type = types.str; }; @@ -40,6 +64,22 @@ with lib; internal = true; }; + domainSuffixInternal = mkOption { + type = types.str; + internal = true; + }; + + domainSuffixExternal = mkOption { + type = types.str; + internal = true; + }; + + domainSuffix = mkOption { + type = types.str; + internal = true; + default = if config.internal then config.domainSuffixInternal else config.domainSuffixExternal; + }; + extras = mkOption { description = "Extra configuration to pass to the nginx virtual host submodule."; type = types.deferredModule; -- 2.45.2 From e2397ac94661edb9398e8f9e4a7e58d51a9cd503 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 4 Jul 2024 18:30:38 +0200 Subject: [PATCH 07/10] cluster/services/ipfs: switch to ways --- cluster/services/ipfs/default.nix | 35 ++++++++++++++--- cluster/services/ipfs/gateway.nix | 56 +++------------------------- cluster/services/ipfs/node.nix | 8 ++-- cluster/services/ipfs/remote-api.nix | 4 +- 4 files changed, 40 insertions(+), 63 deletions(-) diff --git a/cluster/services/ipfs/default.nix b/cluster/services/ipfs/default.nix index 77e48cc..b82f24a 100644 --- a/cluster/services/ipfs/default.nix +++ b/cluster/services/ipfs/default.nix @@ -29,6 +29,10 @@ io-tweaks = [ "VEGAS" ]; remote-api = [ "VEGAS" ]; }; + meshLinks.gateway = { + name = "ipfsGateway"; + link.protocol = "http"; + }; nixos = { node = [ ./node.nix @@ -51,18 +55,37 @@ }; dns.records = { - p2p.consulService = "ipfs-gateway"; - pin.consulService = "ipfs-gateway"; "ipfs.admin".target = map (node: depot.hours.${node}.interfaces.primary.addrPublic) config.services.ipfs.nodes.remote-api; - "^[^_].+\\.ipfs" = { + pin.consulService = "ipfs-gateway"; + }; + + ways = { + p2p = { consulService = "ipfs-gateway"; - rewrite.type = "regex"; + extras.locations."/routing" = { + extraConfig = '' + add_header X-Content-Type-Options ""; + add_header Access-Control-Allow-Origin *; + ''; + }; }; - "^[^_].+\\.ipns" = { + ipfs = { consulService = "ipfs-gateway"; - rewrite.type = "regex"; + wildcard = true; + extras.extraConfig = '' + add_header X-Content-Type-Options ""; + add_header Access-Control-Allow-Origin *; + ''; + }; + ipns = { + consulService = "ipfs-gateway"; + wildcard = true; + extras.extraConfig = '' + add_header X-Content-Type-Options ""; + add_header Access-Control-Allow-Origin *; + ''; }; }; } diff --git a/cluster/services/ipfs/gateway.nix b/cluster/services/ipfs/gateway.nix index b5bbe4d..823b2d3 100644 --- a/cluster/services/ipfs/gateway.nix +++ b/cluster/services/ipfs/gateway.nix @@ -1,8 +1,7 @@ -{ config, depot, lib, ... }: -with depot.lib.nginx; +{ cluster, config, depot, lib, ... }: let inherit (depot.lib.meta) domain; - gw = config.links.ipfsGateway; + gw = cluster.config.hostLinks.${config.networking.hostName}.ipfsGateway; cfg = config.services.ipfs; metrics = config.links.ipfsMetrics; in @@ -34,42 +33,6 @@ in locations."/".return = "204"; locations."${metrics.path}".proxyPass = "http://unix:/run/ipfs/ipfs-api.sock:"; }; - "p2p.${domain}" = vhosts.basic // { - locations."/".return = "204"; - locations."/routing" = { - proxyPass = gw.url; - extraConfig = '' - add_header X-Content-Type-Options ""; - add_header Access-Control-Allow-Origin *; - ''; - }; - }; - }; - security.acme.certs."ipfs.${domain}" = { - domain = "*.ipfs.${domain}"; - extraDomainNames = [ "*.ipns.${domain}" ]; - dnsProvider = "exec"; - group = "nginx"; - }; - - security.acme.certs."p2p.${domain}" = { - dnsProvider = "exec"; - webroot = lib.mkForce null; - }; - - services.nginx.virtualHosts."ipfs.${domain}" = vhosts.basic // { - serverName = "~^(.+)\.(ip[fn]s)\.${domain}$"; - enableACME = false; - useACMEHost = "ipfs.${domain}"; - locations = { - "/" = { - proxyPass = gw.url; - extraConfig = '' - add_header X-Content-Type-Options ""; - add_header Access-Control-Allow-Origin *; - ''; - }; - }; }; services.ipfs.extraConfig.Gateway.PublicGateways = { @@ -88,20 +51,11 @@ in consul.services.ipfs-gateway = { mode = "external"; unit = "ipfs"; - definition = rec { + definition = { name = "ipfs-gateway"; - address = depot.reflection.interfaces.primary.addrPublic; - port = 443; + address = gw.ipv4; + port = gw.port; checks = [ - rec { - name = "Frontend"; - id = "service:ipfs-gateway:frontend"; - interval = "60s"; - http = "https://${address}/"; - tls_server_name = "bafybeiczsscdsbs7ffqz55asqdf3smv6klcw3gofszvwlyarci47bgf354.ipfs.${domain}"; # empty directory - header.Host = lib.singleton tls_server_name; - method = "HEAD"; - } { name = "IPFS Node"; id = "service:ipfs-gateway:ipfs"; diff --git a/cluster/services/ipfs/node.nix b/cluster/services/ipfs/node.nix index d71c42b..4d46288 100644 --- a/cluster/services/ipfs/node.nix +++ b/cluster/services/ipfs/node.nix @@ -4,7 +4,7 @@ let cfg = config.services.ipfs; apiAddress = "/unix/run/ipfs/ipfs-api.sock"; ipfsApi = pkgs.writeTextDir "api" apiAddress; - gw = config.links.ipfsGateway; + gw = cluster.config.hostLinks.${config.networking.hostName}.ipfsGateway; ipfsPort = 110; nameservers = lib.unique config.networking.nameservers; in @@ -13,8 +13,6 @@ in depot.nixosModules.ipfs ]; - links.ipfsGateway.protocol = "http"; - networking.firewall = { allowedTCPPorts = [ ipfsPort 4001 ]; allowedUDPPorts = [ ipfsPort 4001 ]; @@ -157,7 +155,9 @@ in "fc00::/7" "fe80::/10" ]; - IPAddressAllow = nameservers; + IPAddressAllow = nameservers ++ [ + cluster.config.vars.meshNet.cidr + ]; }; postStart = "chmod 660 /run/ipfs/ipfs-api.sock"; }; diff --git a/cluster/services/ipfs/remote-api.nix b/cluster/services/ipfs/remote-api.nix index 75e0ede..386b683 100644 --- a/cluster/services/ipfs/remote-api.nix +++ b/cluster/services/ipfs/remote-api.nix @@ -1,9 +1,9 @@ -{ config, depot, ... }: +{ cluster, config, depot, ... }: with depot.lib.nginx; let inherit (depot.lib.meta) domain; cfg = config.services.ipfs; - gw = config.links.ipfsGateway; + gw = cluster.config.hostLinks.${config.networking.hostName}.ipfsGateway; in { users.users.nginx.extraGroups = [ cfg.group ]; -- 2.45.2 From c358714cbe69713d2f0d977ebf3d4d106d859791 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 4 Jul 2024 19:42:08 +0200 Subject: [PATCH 08/10] cluster/services/ways: unique upstreams --- cluster/services/ways/host.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cluster/services/ways/host.nix b/cluster/services/ways/host.nix index 2c1a902..f5033fb 100644 --- a/cluster/services/ways/host.nix +++ b/cluster/services/ways/host.nix @@ -69,7 +69,7 @@ in {{end}} } '') consulServiceWays; - in pkgs.writeText "ways-upstreams.ctmpl" (lib.concatStringsSep "\n" upstreams); + in pkgs.writeText "ways-upstreams.ctmpl" (lib.concatStringsSep "\n" (lib.unique upstreams)); destination = "/run/consul-template/nginx-ways-upstreams.conf"; exec.command = [ "${config.services.nginx.package}/bin/nginx" -- 2.45.2 From b8067c6a33463825b9e34958fcdeed8d9b1af260 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 4 Jul 2024 19:57:05 +0200 Subject: [PATCH 09/10] cluster/services/ways: serialize acme cert updates --- cluster/services/ways/host.nix | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cluster/services/ways/host.nix b/cluster/services/ways/host.nix index f5033fb..040f552 100644 --- a/cluster/services/ways/host.nix +++ b/cluster/services/ways/host.nix @@ -54,6 +54,11 @@ in }; }) externalWays; + systemd.services = lib.mapAttrs' (name: cfg: { + name = "acme-${name}.${cfg.domainSuffix}"; + value.distributed.enable = true; + }) externalWays; + services.consul-template.instances.ways = lib.mkIf (consulServiceWays != {}) { user = "nginx"; group = "nginx"; -- 2.45.2 From c81aec9b9a00185309b7c3f36b53da1419972fd9 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 4 Jul 2024 20:23:50 +0200 Subject: [PATCH 10/10] cluster/services/storage: switch garage to ways --- cluster/services/storage/default.nix | 18 ++++-- cluster/services/storage/garage-gateway.nix | 66 ++------------------- 2 files changed, 20 insertions(+), 64 deletions(-) diff --git a/cluster/services/storage/default.nix b/cluster/services/storage/default.nix index 615bb73..5f39ca8 100644 --- a/cluster/services/storage/default.nix +++ b/cluster/services/storage/default.nix @@ -88,9 +88,19 @@ in }; }; - dns.records.garage.consulService = "garage"; - dns.records."^[^_].+\\.web\\.garage" = { - consulService = "garage-web"; - rewrite.type = "regex"; + ways = { + garage = { + consulService = "garage"; + extras.extraConfig = '' + client_max_body_size 4G; + ''; + }; + "web.garage" = { + consulService = "garage-web"; + wildcard = true; + extras.locations."/".extraConfig = '' + proxy_set_header Host "$1.${config.links.garageWeb.hostname}"; + ''; + }; }; } diff --git a/cluster/services/storage/garage-gateway.nix b/cluster/services/storage/garage-gateway.nix index a87ee0f..fa209e3 100644 --- a/cluster/services/storage/garage-gateway.nix +++ b/cluster/services/storage/garage-gateway.nix @@ -1,8 +1,8 @@ { config, cluster, depot, lib, ... }: let - linkS3 = cluster.config.links.garageS3; - linkWeb = cluster.config.links.garageWeb; + linkS3 = cluster.config.hostLinks.${config.networking.hostName}.garageS3; + linkWeb = cluster.config.hostLinks.${config.networking.hostName}.garageWeb; in { @@ -10,60 +10,14 @@ in services.garage.settings.admin.api_bind_addr = config.links.garageMetrics.tuple; - services.nginx.virtualHosts = { - ${linkS3.hostname} = depot.lib.nginx.vhosts.basic // { - locations = { - "/".proxyPass = cluster.config.hostLinks.${config.networking.hostName}.garageS3.url; - - "= /health".proxyPass = config.links.garageMetrics.url; - }; - extraConfig = "client_max_body_size 4G;"; - }; - "${linkWeb.hostname}" = depot.lib.nginx.vhosts.basic // { - serverName = "~^(.+)\.${lib.escapeRegex linkWeb.hostname}$"; - enableACME = false; - useACMEHost = linkWeb.hostname; - locations = { - "/" = { - proxyPass = cluster.config.hostLinks.${config.networking.hostName}.garageWeb.url; - extraConfig = '' - proxy_set_header Host "$1.${linkWeb.hostname}"; - ''; - }; - - "= /.internal-api/garage/health" = { - proxyPass = "${config.links.garageMetrics.url}/health"; - }; - }; - }; - }; - security.acme.certs = { - ${linkS3.hostname} = { - dnsProvider = "exec"; - webroot = lib.mkForce null; - }; - ${linkWeb.hostname} = { - domain = "*.${linkWeb.hostname}"; - dnsProvider = "exec"; - group = "nginx"; - }; - }; consul.services = { garage = { mode = "external"; - definition = rec { + definition = { name = "garage"; - address = depot.reflection.interfaces.primary.addrPublic; + address = linkS3.ipv4; inherit (linkS3) port; checks = [ - { - name = "Frontend"; - id = "service:garage:frontend"; - interval = "60s"; - http = "https://${address}/health"; - tls_server_name = linkS3.hostname; - header.Host = lib.singleton linkS3.hostname; - } { name = "Garage Node"; id = "service:garage:node"; @@ -76,19 +30,11 @@ in garage-web = { mode = "external"; unit = "garage"; - definition = rec { + definition = { name = "garage-web"; - address = depot.reflection.interfaces.primary.addrPublic; + address = linkWeb.ipv4; inherit (linkWeb) port; checks = [ - { - name = "Frontend"; - id = "service:garage-web:frontend"; - interval = "60s"; - http = "https://${address}/.internal-api/garage/health"; - tls_server_name = "healthcheck.${linkWeb.hostname}"; - header.Host = lib.singleton "healthcheck.${linkWeb.hostname}"; - } { name = "Garage Node"; id = "service:garage-web:node"; -- 2.45.2