diff --git a/system/features/web-containers.nix b/system/features/web-containers.nix new file mode 100644 index 0000000..3a2ed90 --- /dev/null +++ b/system/features/web-containers.nix @@ -0,0 +1,126 @@ +{ config, lib, ... }: +{ + options = + with lib; + with types; + { + virtualisation.web-containers = { + enable = mkEnableOption "web containers"; + containers = mkOption { + type = lazyAttrsOf (submodule { + options = + let + strOpt = mkOption { type = str; }; + intOpt = mkOption { type = int; }; + boolOpt = mkOption { + type = bool; + default = false; + }; + strList = mkOption { + type = listOf str; + default = [ ]; + }; + attrOpt = mkOption { + type = attrsOf str; + default = { }; + }; + in + { + image = strOpt; + hostname = strOpt; + port = intOpt; + homepageOpts = attrOpt; + dependsOn = strList; + domain = strOpt; + volumes = strList; + environment = attrOpt; + environmentFiles = strList; + public = boolOpt; + user = mkOption { + type = nullOr str; + default = null; + }; + extraOptions = strList; + oauthProxy = boolOpt; + extraLabels = attrOpt; + }; + }); + default = { }; + description = ""; + }; + }; + }; + + config = { + virtualisation.oci-containers.containers = lib.mkIf config.virtualisation.web-containers.enable ( + let + hostRule = host: domain: "Host(`${host}.${domain}`)"; + localNet = "192.168.0.0/16"; + dockerNet = "10.88.0.0/16"; + localNetRule = "(ClientIP(`${localNet}`) || ClientIP(`${dockerNet}`))"; + localHostRule = host: domain: "${localNetRule} && ${hostRule host domain}"; + mkContainer = + key: + { + image, + hostname, + port, + homepageOpts, + dependsOn, + domain, + volumes, + environment, + environmentFiles, + public, + user, + extraOptions, + oauthProxy, + extraLabels, + }: + let + fqn = "${hostname}.${domain}"; + serviceName = lib.strings.replaceChars [ "." ] [ "-" ] fqn; + routerRule = if public then hostRule hostname domain else localHostRule hostname domain; + homepageLabels = + if homepageOpts == { } then + { } + else + { + "homepage.group" = "${homepageOpts.group}"; + "homepage.name" = "${homepageOpts.name}"; + "homepage.icon" = "${homepageOpts.icon}"; + "homepage.href" = "https://${fqn}"; + "homepage.description" = "${homepageOpts.description}"; + }; + oauthLabels = + if oauthProxy then + { "traefik.http.routers.${serviceName}.middlewares" = "oidc-auth@file"; } + else + { }; + in + { + inherit + image + dependsOn + volumes + environment + environmentFiles + user + extraOptions + ; + autoStart = true; + labels = + { + "traefik.enable" = "true"; + "traefik.http.routers.${serviceName}.rule" = "${routerRule}"; + "traefik.http.services.${serviceName}.loadbalancer.server.port" = "${toString port}"; + } + // oauthLabels + // homepageLabels + // extraLabels; + }; + in + builtins.mapAttrs mkContainer config.virtualisation.web-containers.containers + ); + }; +} diff --git a/system/hosts/mcp/containers/dm-companion.nix b/system/hosts/mcp/containers/dm-companion.nix index 925a31f..6e1264e 100644 --- a/system/hosts/mcp/containers/dm-companion.nix +++ b/system/hosts/mcp/containers/dm-companion.nix @@ -81,7 +81,7 @@ in port = 8080; volumes = [ "/tank/web/dm.terakoda.com/pb_data:/pb/pb_data" - "/tank/web/dm.terakoda.com/pb_migrniations:/pb/pb_migrations:ro" + "/tank/web/dm.terakoda.com/pb_migrations:/pb/pb_migrations:ro" ]; environment = { }; extraLabels = { diff --git a/system/hosts/mcp/containers/goatcounter.nix b/system/hosts/mcp/containers/goatcounter.nix index c7bb998..87104e0 100644 --- a/system/hosts/mcp/containers/goatcounter.nix +++ b/system/hosts/mcp/containers/goatcounter.nix @@ -1,47 +1,58 @@ { config, ... }: let inherit (import ./lib.nix config) - mkContainer terakoda blazestar hostRule ; in { - virtualisation.oci-containers.containers.goatcounter-terakoda = mkContainer { - image = "arp242/goatcounter"; - hostName = "goatcounter"; - domain = terakoda; - public = true; - port = 8080; - volumes = [ - "goatcounter-data:/home/goatcounter/goatcounter-data" - ]; - extraLabels = { - # "traefik.http.middlewares.strip-analytics.stripprefix.prefixes" = "/analytics"; - # "traefik.http.routers.www-terakoda-com-goatcounter.middlewares" = "strip-analytics"; - # Host the script on www.terakoda.com so that it is easy to fetch - "traefik.http.routers.www-terakoda-com-goatcounter.rule" = - "PathPrefix(`/count`) && ${hostRule "www" terakoda}"; - "traefik.http.routers.www-terakoda-com-goatcounter.service" = "goatcounter"; - }; - }; - virtualisation.oci-containers.containers.goatcounter-blazestar = mkContainer { - image = "arp242/goatcounter"; - hostName = "goatcounter"; - domain = blazestar; - public = true; - port = 8080; - volumes = [ - "goatcounter-data:/home/goatcounter/goatcounter-data" - ]; - extraLabels = { - # "traefik.http.middlewares.strip-analytics.stripprefix.prefixes" = "/analytics"; - # "traefik.http.routers.www-blazestar-net-goatcounter.middlewares" = "strip-analytics"; - # Host the script on www.blazestar.net so that it is easy to fetch - "traefik.http.routers.www-blazestar-net-goatcounter.rule" = - "PathPrefix(`/count`) && ${hostRule "www" blazestar}"; - "traefik.http.routers.www-blazestar-net-goatcounter.service" = "goatcounter"; + imports = [ + ../../../features/web-containers.nix + ]; + + virtualisation.web-containers = { + enable = true; + containers = { + goatcounter-terakoda = { + image = "arp242/goatcounter"; + hostname = "goatcounter"; + domain = terakoda; + public = true; + port = 8080; + volumes = [ + "goatcounter-data:/home/goatcounter/goatcounter-data" + ]; + extraLabels = { + # "traefik.http.middlewares.strip-analytics.stripprefix.prefixes" = "/analytics"; + # "traefik.http.routers.www-terakoda-com-goatcounter.middlewares" = "strip-analytics"; + # Host the script on www.terakoda.com so that it is easy to fetch + "traefik.http.routers.www-terakoda-com-goatcounter.rule" = + "PathPrefix(`/count`) && ${hostRule "www" terakoda}"; + "traefik.http.routers.www-terakoda-com-goatcounter.entrypoints" = "websecure"; + "traefik.http.routers.www-terakoda-com-goatcounter.service" = "goatcounter-terakoda-com"; + }; + }; + + goatcounter-blazestar = { + image = "arp242/goatcounter"; + hostname = "goatcounter"; + domain = blazestar; + public = true; + port = 8080; + volumes = [ + "goatcounter-data-blazestar:/home/goatcounter/goatcounter-data" + ]; + extraLabels = { + # "traefik.http.middlewares.strip-analytics.stripprefix.prefixes" = "/analytics"; + # "traefik.http.routers.www-blazestar-net-goatcounter.middlewares" = "strip-analytics"; + # Host the script on www.blazestar.net so that it is easy to fetch + "traefik.http.routers.www-blazestar-net-goatcounter.rule" = + "PathPrefix(`/count`) && ${hostRule "www" blazestar}"; + "traefik.http.routers.www-blazestar-net-goatcounter.entrypoints" = "websecure"; + "traefik.http.routers.www-blazestar-net-goatcounter.service" = "goatcounter-blazestar-net@docker"; + }; + }; }; }; }