{ 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.routers.${serviceName}.service" = "${serviceName}"; "traefik.http.services.${serviceName}.loadbalancer.server.port" = "${toString port}"; } // oauthLabels // homepageLabels // extraLabels; }; in builtins.mapAttrs mkContainer config.virtualisation.web-containers.containers ); }; }