{ config, pkgs, lib, ... }: { options = { services.nginx.domain = lib.mkOption { type = lib.types.str; description = "The base domain name to append to virtual domain names"; }; services.nginx.virtualHosts = let autheliaDomain = "auth.${config.services.nginx.domain}"; extraLocationOptions = {config, ...}: { options = { enableAutheliaProxy = lib.mkEnableOption "Enable recommended authelia proxy settings"; enableAuthorization = lib.mkEnableOption "Enable authorization via authelia"; }; config = { recommendedProxySettings = lib.mkIf config.enableAutheliaProxy false; extraConfig = lib.concatStringsSep "\n" [ (lib.optionalString config.enableAutheliaProxy '' proxy_set_header Host $host; proxy_set_header X-Original-URL $scheme://$http_host$request_uri; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $http_host; proxy_set_header X-Forwarded-URI $request_uri; proxy_set_header X-Forwarded-Ssl on; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Connection ""; client_body_buffer_size 128k; proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; proxy_redirect http:// $scheme://; proxy_http_version 1.1; proxy_cache_bypass $cookie_session; proxy_no_cache $cookie_session; proxy_buffers 64 256k; real_ip_header X-Forwarded-For; real_ip_recursive on; send_timeout 5m; proxy_read_timeout 360; proxy_send_timeout 360; proxy_connect_timeout 360; '') (lib.optionalString config.enableAuthorization '' auth_request /authelia; set_escape_uri $target_url $scheme://$http_host$request_uri; auth_request_set $user $upstream_http_remote_user; auth_request_set $groups $upstream_http_remote_groups; auth_request_set $name $upstream_http_remote_name; auth_request_set $email $upstream_http_remote_email; proxy_set_header Remote-User $user; proxy_set_header Remote-Groups $groups; proxy_set_header Remote-Email $email; proxy_set_header Remote-Name $name; error_page 401 =302 https://${autheliaDomain}/?rd=$target_url; '') ]; }; }; extraVirtualHostOptions = { name, config, ... }: { options = { enableAuthorization = lib.mkEnableOption "Enable authorization via authelia"; enableHSTS = lib.mkEnableOption "Enable HSTS"; addAccessLog = lib.mkOption { type = lib.types.bool; default = true; description = '' Add special logging to `/var/log/nginx/''${serverName}` ''; }; locations = lib.mkOption { type = lib.types.attrsOf (lib.types.submodule extraLocationOptions); }; }; config = { extraConfig = lib.concatStringsSep "\n" [ (lib.optionalString config.enableHSTS '' add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always; '') (lib.optionalString config.addAccessLog '' access_log /var/log/nginx/${name}/access.log upstream_time; '') ]; locations = lib.mkIf config.enableAuthorization { "/".enableAuthorization = true; "/authelia" = { proxyPass = "http://127.0.0.1:9091/api/verify"; recommendedProxySettings = false; extraConfig = '' internal; proxy_set_header X-Original-URL $scheme://$http_host$request_uri; proxy_set_header X-Original-Method $request_method; proxy_set_header X-Forwarded-Method $request_method; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $http_host; proxy_set_header X-Forwarded-Uri $request_uri; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header Content-Length ""; proxy_set_header Connection ""; proxy_pass_request_body off; proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; proxy_redirect http:// $scheme://; proxy_http_version 1.1; proxy_cache_bypass $cookie_session; proxy_no_cache $cookie_session; proxy_buffers 4 32k; client_body_buffer_size 128k; send_timeout 5m; proxy_read_timeout 240; proxy_send_timeout 240; proxy_connect_timeout 240; ''; }; }; }; }; in lib.mkOption { type = lib.types.attrsOf (lib.types.submodule extraVirtualHostOptions); }; }; config = { # Don't attempt to run acme if the domain name is not tlater.net systemd.services = let confirm = ''[[ "tlater.net" = ${config.services.nginx.domain} ]]''; in lib.mapAttrs' (cert: _: lib.nameValuePair "acme-${cert}" { serviceConfig.ExecCondition = ''${pkgs.runtimeShell} -c '${confirm}' ''; }) config.security.acme.certs; }; }