| # SPDX-FileCopyrightText: 2024 Clicks Codes |
| # |
| # SPDX-License-Identifier: GPL-3.0-only |
| |
| { lib, config, ... }: |
| let |
| cfg = config.clicks.services.nginx; |
| in |
| { |
| options.clicks.services.nginx = { |
| enable = lib.mkEnableOption "Enable Nginx routing"; |
| hosts = lib.options.mkOption { |
| type = lib.types.attrsOf (lib.clicks.types.nginx.host config); |
| description = "Attrset of web domain to host data"; |
| default = {}; |
| }; |
| defaultDnsProvider = lib.options.mkOption { |
| type = lib.types.nullOr lib.types.str; |
| description = "Default provider for getting web certificates"; |
| default = null; |
| }; |
| xClacksOverhead.enable = lib.options.mkOption { |
| type = lib.types.bool; |
| description = "Write the header `X-Clacks-Overhead: GNU Terry Pratchett` on all virtual host locations"; |
| default = true; |
| }; |
| }; |
| |
| config = lib.modules.mkIf cfg.enable (let |
| processedHosts = lib.clicks.nginx.http.internal.serviceTranslation cfg.hosts; |
| hostsList = lib.attrsets.attrsToList processedHosts; |
| nginxHosts = lib.attrsets.mapAttrs (_: host: lib.attrsets.removeAttrs host [ "authWith" "dnsProvider" ]) processedHosts; |
| acmeCerts = lib.attrsets.mapAttrs (_: host: { |
| inherit (host) dnsProvider; |
| webroot = if host.dnsProvider == null |
| then config.security.acme.defaults.webroot |
| else null; |
| }) processedHosts; |
| tailscaleAuthHosts = lib.pipe hostsList [ |
| (lib.lists.filter (host: host.value.authWith == "tailscale")) |
| (map (host: host.name)) |
| ]; |
| in { |
| services.nginx = { |
| enable = true; |
| enableReload = true; |
| virtualHosts = { |
| "default_server_ssl" = { |
| listen = [ |
| { |
| ssl = true; |
| port = 443; |
| addr = "0.0.0.0"; |
| extraParameters = [ |
| "default_server" |
| ]; |
| } |
| ]; |
| |
| rejectSSL = true; |
| }; |
| "default_server" = { |
| listen = [ |
| { |
| port = 80; |
| addr = "0.0.0.0"; |
| extraParameters = [ |
| "default_server" |
| ]; |
| } |
| ]; |
| |
| locations."/" = { |
| return = 444; |
| }; |
| }; |
| } // nginxHosts; |
| }; |
| |
| security.acme.certs = acmeCerts; |
| |
| clicks.services.tailscaleAuth = lib.mkIf (lib.lists.length tailscaleAuthHosts > 0) { |
| enable = true; |
| |
| hosts = tailscaleAuthHosts; |
| }; |
| |
| networking.firewall.allowedTCPPorts = [ 80 443 ]; |
| }); |
| } |