nixos-config/modules/system/services/caddy.nix

99 lines
2.7 KiB
Nix

{
config,
pkgs,
lib,
...
}:
let
caddyWithTailscale = pkgs.caddy.withPlugins {
plugins = [ "github.com/tailscale/caddy-tailscale@v0.0.0-20250207163903-69a970c84556" ];
hash = "sha256-wt3+xCsT83RpPySbL7dKVwgqjKw06qzrP2Em+SxEPto=";
};
virtualHosts =
config.custom.services.caddy.virtualHosts |> lib.filterAttrs (_: value: value.enable);
isTailscaleDomain = domain: domain |> lib.hasSuffix config.custom.services.tailscale.domain;
tailscaleHostsExist = lib.any (v: isTailscaleDomain v.domain) (lib.attrValues virtualHosts);
nonTailscaleHostsExist = lib.any (v: !isTailscaleDomain v.domain) (lib.attrValues virtualHosts);
getSubdomain = domain: domain |> lib.splitString "." |> lib.head;
mkVirtualHostConfig = domain: port: {
logFormat = "output file ${config.services.caddy.logDir}/access-${domain}.log { mode 640 }";
extraConfig = ''
${lib.optionalString (isTailscaleDomain domain) "bind tailscale/${getSubdomain domain}"}
reverse_proxy localhost:${toString port}
'';
};
ports = [
80
443
];
in
{
options.custom.services.caddy.virtualHosts = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
};
domain = lib.mkOption {
type = lib.types.nonEmptyStr;
default = name;
};
port = lib.mkOption {
type = lib.types.port;
default = null;
};
};
}
)
);
default = { };
};
config = lib.mkIf (virtualHosts != { }) (
lib.mkMerge [
{
meta = {
ports.list = lib.mkIf nonTailscaleHostsExist ports;
domains.list = lib.mapAttrsToList (_: value: value.domain) virtualHosts;
};
networking.firewall.allowedTCPPorts = lib.mkIf nonTailscaleHostsExist ports;
services.caddy = {
enable = true;
enableReload = false;
virtualHosts =
virtualHosts
|> lib.mapAttrs' (
_: value: lib.nameValuePair value.domain (mkVirtualHostConfig value.domain value.port)
);
};
}
(lib.mkIf tailscaleHostsExist {
sops.secrets."service-tailscale-auth-key".owner = config.services.caddy.user;
services.caddy = {
package = caddyWithTailscale;
globalConfig = ''
admin off
tailscale {
auth_key {file.${config.sops.secrets."service-tailscale-auth-key".path}}
}
'';
};
})
]
);
}