{ pkgs, config, lib, ... }: with lib; let cfg = config.eboskma.caddy-proxy; proxyHost = types.submodule { options = { externalHostname = mkOption { description = "Hostname where this service should be reached"; type = types.str; }; proxyAddress = mkOption { description = "Internal address where this service is reachable"; type = types.str; }; external = mkEnableOption "Make this host externally reachable."; }; }; cloudflare-tls = '' tls { dns cloudflare {env.CF_API_TOKEN} } ''; mkProxyHost = target: { extraConfig = '' reverse_proxy ${target} ${cloudflare-tls} ''; }; mkLocalProxyHost = target: { extraConfig = '' @local_or_ts { remote_ip 10.0.0.0/24 100.64.0.0/10 } handle @local_or_ts { reverse_proxy ${target} } handle { error "Nope." 403 } ${cloudflare-tls} ''; }; in { options.eboskma.caddy-proxy = { enable = mkEnableOption "Caddy proxy"; package = mkPackageOption pkgs "caddy" { }; proxyHosts = mkOption { description = "Proxy hosts"; type = types.listOf proxyHost; }; }; config = mkIf cfg.enable { services.caddy = { enable = true; package = cfg.package; email = "erwin@datarift.nl"; acmeCA = "https://acme-v02.api.letsencrypt.org/directory"; virtualHosts = builtins.listToAttrs ( map ( host: let mkProxy = if host ? external && host.external then mkProxyHost else mkLocalProxyHost; in { name = host.externalHostname; value = mkProxy host.proxyAddress; } ) cfg.proxyHosts ); }; systemd.services.caddy.serviceConfig.EnvironmentFile = [ config.sops.secrets.caddy-env.path ]; networking.firewall.allowedTCPPorts = [ 80 443 ]; }; }