{ config, lib, ... }: let inherit (lib) attrsToList concatStringsSep filterAttrs getAttr mapAttrs mapAttrs' mkEnableOption mkIf mkOption nameValuePair recursiveUpdate ; inherit (lib.types) attrs attrsOf bool port str submodule ; cfg = config.dgn-web; in { options.dgn-web = { enable = mkEnableOption "sane defaults for web services."; internalPorts = mkOption { type = attrsOf port; default = { }; description = '' Map from the web services to their internal ports, it should avoid port clashes. ''; }; simpleProxies = mkOption { type = attrsOf (submodule { options = { port = mkOption { type = port; description = '' Port where the service will listen. ''; }; host = mkOption { type = str; description = '' Hostname of the service. ''; }; proxyWebsockets = mkOption { type = bool; default = false; description = '' Whether to support proxying websocket connections with HTTP/1.1. ''; }; vhostConfig = mkOption { type = attrs; default = { }; description = '' Additional virtualHost settings. ''; }; }; }); default = { }; description = '' A set of simple localhost redirections. ''; }; }; config = mkIf cfg.enable { assertions = [ ( let duplicates = builtins.attrValues ( builtins.mapAttrs (p: serv: "${p}: ${concatStringsSep ", " serv}") ( filterAttrs (_: ls: builtins.length ls != 1) ( builtins.foldl' ( rev: { name, value }: let str = builtins.toString value; in rev // { ${str} = (rev.${str} or [ ]) ++ [ name ]; } ) { } (attrsToList cfg.internalPorts) ) ) ); in { assertion = duplicates == [ ]; message = '' Internal ports cannot be used for multiple services, the clashes are: ${concatStringsSep "\n " duplicates} ''; } ) ]; dgn-web.internalPorts = mapAttrs (_: getAttr "port") cfg.simpleProxies; services.nginx = { enable = true; virtualHosts = mapAttrs' ( _: { host, port, proxyWebsockets, vhostConfig, }: nameValuePair host ( recursiveUpdate { forceSSL = true; enableACME = true; locations."/" = { proxyPass = "http://127.0.0.1:${builtins.toString port}"; inherit proxyWebsockets; }; } vhostConfig ) ) cfg.simpleProxies; recommendedBrotliSettings = true; recommendedGzipSettings = true; recommendedOptimisation = true; recommendedProxySettings = true; recommendedTlsSettings = true; recommendedZstdSettings = true; }; networking.firewall.allowedTCPPorts = [ 80 443 ]; }; }