about summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--hosts/tahoe/services.nix14
-rw-r--r--modules/services/gitea/default.nix12
-rw-r--r--modules/services/nginx/default.nix291
3 files changed, 13 insertions, 304 deletions
diff --git a/hosts/tahoe/services.nix b/hosts/tahoe/services.nix
index 8846eae..8481bd0 100644
--- a/hosts/tahoe/services.nix
+++ b/hosts/tahoe/services.nix
@@ -19,19 +19,7 @@ in {
     };
     rclone = { enable = true; };
     traefik = { enable = false; };
-    nginx = {
-      enable = true;
-      acme = { credentialsFile = secrets."acme/dns-key".path; };
-      sso = {
-        authKeyFile = secrets."sso/auth-key".path;
-        users = {
-          fcuny = {
-            passwordHashFile = secrets."sso/fcuny/password-hash".path;
-          };
-        };
-        groups = { root = [ "fcuny" ]; };
-      };
-    };
+    nginx = { enable = true; };
     transmission = { enable = true; };
     metrics-exporter = { enable = true; };
     backup = {
diff --git a/modules/services/gitea/default.nix b/modules/services/gitea/default.nix
index 6828439..6259c30 100644
--- a/modules/services/gitea/default.nix
+++ b/modules/services/gitea/default.nix
@@ -37,10 +37,14 @@ in {
       };
     };
 
-    my.services.nginx.virtualHosts = [{
-      subdomain = "gitea";
-      port = 8002;
-    }];
+    services.nginx.virtualHosts."git.fcuny.net" = {
+      forceSSL = true;
+      enableACME = true;
+      locations."/" = {
+        proxyPass = "http://127.0.0.1:8002";
+        proxyWebsockets = true;
+      };
+    };
 
     my.services.backup = { paths = [ cfg.stateDir ]; };
   };
diff --git a/modules/services/nginx/default.nix b/modules/services/nginx/default.nix
index 0020111..9fb5cbd 100644
--- a/modules/services/nginx/default.nix
+++ b/modules/services/nginx/default.nix
@@ -1,177 +1,8 @@
-# A simple abstraction layer for almost all of my services' needs
 { config, lib, pkgs, ... }:
-let
-  cfg = config.my.services.nginx;
-  virtualHostOption = with lib;
-    types.submodule {
-      options = {
-        subdomain = mkOption {
-          type = types.str;
-          example = "dev";
-          description = ''
-            Which subdomain, under config.networking.domain, to use
-            for this virtual host.
-          '';
-        };
-        port = mkOption {
-          type = with types; nullOr port;
-          default = null;
-          example = 8080;
-          description = ''
-            Which port to proxy to, through 127.0.0.1, for this virtual host.
-            This option is incompatible with `root`.
-          '';
-        };
-        root = mkOption {
-          type = with types; nullOr path;
-          default = null;
-          example = "/var/www/blog";
-          description = ''
-            The root folder for this virtual host.  This option is incompatible
-            with `port`.
-          '';
-        };
-        sso = { enable = mkEnableOption "SSO authentication"; };
-        extraConfig = mkOption {
-          type = types.attrs; # FIXME: forward type of virtualHosts
-          example = litteralExample ''
-            {
-              locations."/socket" = {
-                proxyPass = "http://127.0.0.1:8096/";
-                proxyWebsockets = true;
-              };
-            }
-          '';
-          default = { };
-          description = ''
-            Any extra configuration that should be applied to this virtual host.
-          '';
-        };
-      };
-    };
+let cfg = config.my.services.nginx;
 in {
-  imports = [ ./sso ];
-  options.my.services.nginx = with lib; {
-    enable = mkEnableOption "Nginx";
-    monitoring = {
-      enable = my.mkDisableOption "monitoring through grafana and prometheus";
-    };
-    virtualHosts = mkOption {
-      type = types.listOf virtualHostOption;
-      default = [ ];
-      example = litteralExample ''
-        [
-          {
-            subdomain = "gitea";
-            port = 8080;
-          }
-          {
-            subdomain = "dev";
-            root = "/var/www/dev";
-          }
-          {
-            subdomain = "jellyfin";
-            port = 8096;
-            extraConfig = {
-              locations."/socket" = {
-                proxyPass = "http://127.0.0.1:8096/";
-                proxyWebsockets = true;
-              };
-            };
-          }
-        ]
-      '';
-      description = ''
-        List of virtual hosts to set-up using default settings.
-      '';
-    };
-    sso = {
-      authKeyFile = mkOption {
-        type = types.str;
-        example = "/var/lib/nginx-sso/auth-key.txt";
-        description = ''
-          Path to the auth key.
-        '';
-      };
-      subdomain = mkOption {
-        type = types.str;
-        default = "login";
-        example = "auth";
-        description = "Which subdomain, to use for SSO.";
-      };
-      port = mkOption {
-        type = types.port;
-        default = 8082;
-        example = 8080;
-        description = "Port to use for internal webui.";
-      };
-      users = mkOption {
-        type = types.attrsOf (types.submodule {
-          options = {
-            passwordHashFile = mkOption {
-              type = types.str;
-              example = "/var/lib/nginx-sso/alice/password-hash.txt";
-              description = "Path to file containing the user's password hash.";
-            };
-          };
-        });
-        example = litteralExample ''
-          {
-            alice = {
-              passwordHashFile = "/var/lib/nginx-sso/alice/password-hash.txt";
-            };
-          }
-        '';
-        description = "Definition of users";
-      };
-      groups = mkOption {
-        type = with types; attrsOf (listOf str);
-        example = litteralExample ''
-          {
-            root = [ "alice" ];
-            users = [ "alice" "bob" ];
-          }
-        '';
-        description = "Groups of users";
-      };
-    };
-  };
+  options.my.services.nginx = with lib; { enable = mkEnableOption "Nginx"; };
   config = lib.mkIf cfg.enable {
-    assertions = [ ] ++ (lib.flip builtins.map cfg.virtualHosts
-      ({ subdomain, ... }@args:
-        let
-          conflicts = [ "port" "root" ];
-          optionsNotNull = builtins.map (v: args.${v} != null) conflicts;
-          optionsSet = lib.filter lib.id optionsNotNull;
-        in {
-          assertion = builtins.length optionsSet == 1;
-          message = ''
-            Subdomain '${subdomain}' must have exactly one of ${
-              lib.concatStringsSep ", " (builtins.map (v: "'${v}'") conflicts)
-            } configured.
-          '';
-        })) ++ (let
-          ports = lib.my.mapFilter (v: v != null) ({ port, ... }: port)
-            cfg.virtualHosts;
-          portCounts = lib.my.countValues ports;
-          nonUniquesCounts = lib.filterAttrs (_: v: v != 1) portCounts;
-          nonUniques = builtins.attrNames nonUniquesCounts;
-          mkAssertion = port: {
-            assertion = false;
-            message = "Port ${port} cannot appear in multiple virtual hosts.";
-          };
-        in map mkAssertion nonUniques) ++ (let
-          subs = map ({ subdomain, ... }: subdomain) cfg.virtualHosts;
-          subsCounts = lib.my.countValues subs;
-          nonUniquesCounts = lib.filterAttrs (_: v: v != 1) subsCounts;
-          nonUniques = builtins.attrNames nonUniquesCounts;
-          mkAssertion = v: {
-            assertion = false;
-            message = ''
-              Subdomain '${v}' cannot appear in multiple virtual hosts.
-            '';
-          };
-        in map mkAssertion nonUniques);
     services.nginx = {
       enable = true;
       statusPage = true; # For monitoring scraping.
@@ -179,133 +10,19 @@ in {
       recommendedOptimisation = true;
       recommendedTlsSettings = true;
       recommendedProxySettings = true;
-      virtualHosts = let
-        domain = "fcuny.net";
-        mkVHost = ({ subdomain, ... }@args:
-          lib.nameValuePair "${subdomain}.${domain}" (lib.my.recursiveMerge [
-            # Base configuration
-            {
-              forceSSL = true;
-              useACMEHost = domain;
-            }
-            # Proxy to port
-            (lib.optionalAttrs (args.port != null) {
-              locations."/".proxyPass =
-                "http://127.0.0.1:${toString args.port}";
-            })
-            # Serve filesystem content
-            (lib.optionalAttrs (args.root != null) { inherit (args) root; })
-            # VHost specific configuration
-            args.extraConfig
-            # SSO configuration
-            (lib.optionalAttrs args.sso.enable {
-              extraConfig = (args.extraConfig.extraConfig or "") + ''
-                error_page 401 = @error401;
-              '';
-              locations."@error401".return = ''
-                302 https://${cfg.sso.subdomain}.fcuny.net/login?go=$scheme://$http_host$request_uri
-              '';
-              locations."/" = {
-                extraConfig = (args.extraConfig.locations."/".extraConfig or "")
-                  + ''
-                    # Use SSO
-                    auth_request /sso-auth;
-                    # Set username through header
-                    auth_request_set $username $upstream_http_x_username;
-                    proxy_set_header X-User $username;
-                    # Renew SSO cookie on request
-                    auth_request_set $cookie $upstream_http_set_cookie;
-                    add_header Set-Cookie $cookie;
-                  '';
-              };
-              locations."/sso-auth" = {
-                proxyPass = "http://localhost:${toString cfg.sso.port}/auth";
-                extraConfig = ''
-                  # Do not allow requests from outside
-                  internal;
-                  # Do not forward the request body
-                  proxy_pass_request_body off;
-                  proxy_set_header Content-Length "";
-                  # Set X-Application according to subdomain for matching
-                  proxy_set_header X-Application "${subdomain}";
-                  # Set origin URI for matching
-                  proxy_set_header X-Origin-URI $request_uri;
-                '';
-              };
-            })
-          ]));
-      in lib.my.genAttrs' cfg.virtualHosts mkVHost;
-      sso = {
-        enable = true;
-        configuration = {
-          listen = {
-            addr = "127.0.0.1";
-            inherit (cfg.sso) port;
-          };
-          audit_log = {
-            target = [ "fd://stdout" ];
-            events = [
-              "access_denied"
-              "login_success"
-              "login_failure"
-              "logout"
-              "validate"
-            ];
-            headers = [ "x-origin-uri" "x-application" ];
-          };
-          cookie = {
-            domain = ".fcuny.net";
-            secure = true;
-            authentication_key = { _secret = cfg.sso.authKeyFile; };
-          };
-          login = {
-            title = "fcuny.net's SSO";
-            default_method = "simple";
-            hide_mfa_field = false;
-            names = { simple = "Username / Password"; };
-          };
-          providers = {
-            simple = let applyUsers = lib.flip lib.mapAttrs cfg.sso.users;
-            in {
-              users = applyUsers (_: v: { _secret = v.passwordHashFile; });
-              inherit (cfg.sso) groups;
-            };
-          };
-          acl = {
-            rule_sets = [{
-              rules = [{
-                field = "x-application";
-                present = true;
-              }];
-              allow = [ "@root" ];
-            }];
-          };
-        };
-      };
     };
 
-    my.services.nginx.virtualHosts = [{
-      subdomain = "login";
-      inherit (cfg.sso) port;
-    }];
-
     networking.firewall.allowedTCPPorts = [ 80 443 ];
 
     # Nginx needs to be able to read the certificates
     users.users.nginx.extraGroups = [ "acme" ];
 
     security.acme = {
-      defaults.email = "franck@fcuny.net";
+      email = "franck@fcuny.net";
       acceptTerms = true;
     };
 
-    services.grafana.provision.dashboards = lib.mkIf cfg.monitoring.enable [{
-      name = "NGINX";
-      options.path = pkgs.nur.repos.alarsyo.grafanaDashboards.nginx;
-      disableDeletion = true;
-    }];
-
-    services.prometheus = lib.mkIf cfg.monitoring.enable {
+    services.prometheus = {
       exporters.nginx = {
         enable = true;
         listenAddress = "127.0.0.1";