128 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
	
		
			3.9 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
{
 | 
						|
  lib,
 | 
						|
  config,
 | 
						|
  ...
 | 
						|
}: let
 | 
						|
  dataDir = "/var/lib/acme";
 | 
						|
  httpPort = 80;
 | 
						|
  httpsPort = 443;
 | 
						|
in {
 | 
						|
  options.host.reverse_proxy = {
 | 
						|
    enable = lib.mkEnableOption "turn on the reverse proxy";
 | 
						|
    hostname = lib.mkOption {
 | 
						|
      type = lib.types.str;
 | 
						|
      description = "what host name are we going to be proxying from";
 | 
						|
    };
 | 
						|
    forceSSL = lib.mkOption {
 | 
						|
      type = lib.types.bool;
 | 
						|
      description = "force connections to use https";
 | 
						|
      default = config.host.reverse_proxy.enableACME;
 | 
						|
    };
 | 
						|
    enableACME = lib.mkOption {
 | 
						|
      type = lib.types.bool;
 | 
						|
      description = "auto renew certificates";
 | 
						|
      default = true;
 | 
						|
    };
 | 
						|
    subdomains = lib.mkOption {
 | 
						|
      type = lib.types.attrsOf (lib.types.submodule ({name, ...}: {
 | 
						|
        options = {
 | 
						|
          subdomain = lib.mkOption {
 | 
						|
            type = lib.types.str;
 | 
						|
            description = "what is the default subdomain to be used for this application to be used for";
 | 
						|
            default = name;
 | 
						|
          };
 | 
						|
          extraSubdomains = lib.mkOption {
 | 
						|
            type = lib.types.listOf lib.types.str;
 | 
						|
            description = "extra domains that should be configured for this domain";
 | 
						|
            default = [];
 | 
						|
          };
 | 
						|
 | 
						|
          target = lib.mkOption {
 | 
						|
            type = lib.types.str;
 | 
						|
            description = "what url will all traffic to this application be forwarded to";
 | 
						|
          };
 | 
						|
 | 
						|
          websockets.enable = lib.mkEnableOption "should the default config proxy websockets";
 | 
						|
 | 
						|
          forwardHeaders.enable = lib.mkEnableOption "should the default config contain forward headers";
 | 
						|
 | 
						|
          extraConfig = lib.mkOption {
 | 
						|
            type = lib.types.lines;
 | 
						|
            default = "";
 | 
						|
            description = ''
 | 
						|
              These lines go to the end of the upstream verbatim.
 | 
						|
            '';
 | 
						|
          };
 | 
						|
        };
 | 
						|
      }));
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  config = lib.mkIf config.host.reverse_proxy.enable (lib.mkMerge [
 | 
						|
    {
 | 
						|
      security.acme = lib.mkIf config.host.reverse_proxy.enableACME {
 | 
						|
        acceptTerms = true;
 | 
						|
        defaults.email = "jan-leila@protonmail.com";
 | 
						|
      };
 | 
						|
 | 
						|
      services.nginx = {
 | 
						|
        enable = true;
 | 
						|
        virtualHosts = lib.mkMerge (
 | 
						|
          lib.lists.flatten (
 | 
						|
            lib.attrsets.mapAttrsToList (
 | 
						|
              name: value: let
 | 
						|
                hostConfig = {
 | 
						|
                  forceSSL = config.host.reverse_proxy.forceSSL;
 | 
						|
                  enableACME = config.host.reverse_proxy.enableACME;
 | 
						|
                  locations = {
 | 
						|
                    "/" = {
 | 
						|
                      proxyPass = value.target;
 | 
						|
                      proxyWebsockets = value.websockets.enable;
 | 
						|
                      recommendedProxySettings = value.forwardHeaders.enable;
 | 
						|
                      extraConfig =
 | 
						|
                        value.extraConfig;
 | 
						|
                    };
 | 
						|
                  };
 | 
						|
                };
 | 
						|
              in (
 | 
						|
                [
 | 
						|
                  {
 | 
						|
                    ${"${value.subdomain}.${config.host.reverse_proxy.hostname}"} = hostConfig;
 | 
						|
                  }
 | 
						|
                ]
 | 
						|
                ++ builtins.map (subdomain: {${"${subdomain}.${config.host.reverse_proxy.hostname}"} = hostConfig;})
 | 
						|
                value.extraSubdomains
 | 
						|
              )
 | 
						|
            )
 | 
						|
            config.host.reverse_proxy.subdomains
 | 
						|
          )
 | 
						|
        );
 | 
						|
      };
 | 
						|
 | 
						|
      networking.firewall.allowedTCPPorts = [
 | 
						|
        httpPort
 | 
						|
        httpsPort
 | 
						|
      ];
 | 
						|
    }
 | 
						|
    (lib.mkIf config.host.impermanence.enable {
 | 
						|
      # TODO: figure out how to write an assertion for this
 | 
						|
      # assertions = [
 | 
						|
      #   {
 | 
						|
      #     assertion = security.acme.certs.<name>.directory == dataDir;
 | 
						|
      #     message = "postgres data directory does not match persistence";
 | 
						|
      #   }
 | 
						|
      # ];
 | 
						|
      environment.persistence."/persist/system/root" = {
 | 
						|
        enable = true;
 | 
						|
        hideMounts = true;
 | 
						|
        directories = [
 | 
						|
          {
 | 
						|
            directory = dataDir;
 | 
						|
            user = "acme";
 | 
						|
            group = "acme";
 | 
						|
          }
 | 
						|
        ];
 | 
						|
      };
 | 
						|
    })
 | 
						|
  ]);
 | 
						|
}
 |