aboutsummaryrefslogtreecommitdiff
path: root/modules/nixosModules/nginxProxy.nix
diff options
context:
space:
mode:
Diffstat (limited to 'modules/nixosModules/nginxProxy.nix')
-rw-r--r--modules/nixosModules/nginxProxy.nix217
1 files changed, 217 insertions, 0 deletions
diff --git a/modules/nixosModules/nginxProxy.nix b/modules/nixosModules/nginxProxy.nix
new file mode 100644
index 0000000..36fdc59
--- /dev/null
+++ b/modules/nixosModules/nginxProxy.nix
@@ -0,0 +1,217 @@
+{inputs, ...}: {
+ flake.nixosModules.nginxProxy = {
+ pkgs,
+ config,
+ lib,
+ ...
+ }:
+ with lib; let
+ vhostOptions = import (pkgs.path + "/nixos/modules/services/web-servers/nginx/vhost-options.nix");
+ locationOptions = import (pkgs.path + "/nixos/modules/services/web-servers/nginx/location-options.nix");
+ nginxOptions = import (pkgs.path + "/nixos/modules/services/web-servers/nginx/default.nix");
+
+ autheliaAuth = url: ''
+ auth_request /internal/authelia/authz;
+ auth_request_set $redirection_url $upstream_http_location;
+ error_page 401 =302 $redirection_url;
+
+ auth_request_set $user $upstream_http_remote_user;
+ auth_request_set $groups $upstream_http_remote_groups;
+ auth_request_set $email $upstream_http_remote_email;
+ auth_request_set $name $upstream_http_remote_name;
+
+ proxy_set_header Remote-User $user;
+ proxy_set_header Remote-Groups $groups;
+ proxy_set_header Remote-Email $email;
+ proxy_set_header Remote-Name $name;
+ '';
+
+ autheliaLocation = url: ''
+ internal;
+ set $upstream_authelia ${url}/api/authz/auth-request;
+ proxy_pass $upstream_authelia;
+
+ ## Headers
+ ## The headers starting with X-* are required.
+ proxy_set_header X-Original-Method $request_method;
+ proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
+ proxy_set_header X-Forwarded-For $remote_addr;
+ proxy_set_header Content-Length "";
+ proxy_set_header Connection "";
+
+ ## Basic Proxy Configuration
+ proxy_pass_request_body off;
+ proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; # Timeout if the real server is dead
+ 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;
+
+ ## Advanced Proxy Configuration
+ send_timeout 5m;
+ proxy_read_timeout 240;
+ proxy_send_timeout 240;
+ proxy_connect_timeout 240;
+ '';
+
+ cfg = config.nginxProxy;
+ in {
+ options.nginxProxy = {
+ enable = mkEnableOption "Enable nginxProxy";
+
+ domain = mkOption {
+ type = types.str;
+ description = ''
+ Domain to use with subdomains
+ '';
+ };
+
+ recommendedProxySettings = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Enables global recommended proxy settings
+ '';
+ };
+
+ subdomains = mkOption {
+ type = types.attrsOf (types.submodule (locationOptions {inherit config lib;}));
+ description = ''
+ Subdomains with nginx virtualHosts configuration
+ '';
+ };
+
+ extraVirtualHosts = mkOption {
+ type = types.attrsOf (types.submodule (vhostOptions {inherit config lib;}));
+ default = {};
+ };
+
+ home = {
+ virtualHosts = mkOption {
+ type = types.attrsOf (types.submodule (vhostOptions {inherit config lib;}));
+ default = {};
+ description = ''
+ Virtual hosts from another nginx configuration, that will be used to decrypt ssl and forward traffic to another server.
+ Make sure that the connection between the two is secure.
+ '';
+ };
+
+ subdomains = mkOption {
+ type = types.attrsOf (types.submodule (locationOptions {inherit config lib;}));
+ default = {};
+ description = ''
+ Subdomains from another nginx configuration, that will be used to decrypt ssl and forward traffic to another server.
+ Make sure that the connection between the two is secure.
+ '';
+ };
+
+ domain = mkOption {
+ type = types.str;
+ default = cfg.domain;
+ description = ''
+ Home domain, if no domain provided, the current will be used;
+ '';
+ };
+
+ url = mkOption {
+ type = types.str;
+ default = "";
+ description = ''
+ Url that requests would be passed to;
+ '';
+ };
+
+ authelia = mkOption {
+ type = types.submodule {
+ options = {
+ enable = mkOption {
+ type = types.bool;
+ default = true;
+ };
+ publicUrl = mkOption {
+ type = types.str;
+ default = "https://auth.${cfg.domain}/";
+ };
+ localUrl = mkOption {
+ type = types.str;
+ default = "http://127.0.0.1:9091";
+ };
+ };
+ };
+ default = {};
+ };
+ };
+
+ acme = {
+ enable = mkEnableOption "enable acme certs";
+ email = mkOption {
+ type = types.str;
+ default = "notspl3g+acme@duck.com";
+ };
+ };
+
+ extraConfig = mkOption {
+ type = types.attrsOf (types.submodule nginxOptions);
+ default = {};
+ description = ''
+ Extra nginx config.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ security.acme = mkIf cfg.acme.enable {
+ acceptTerms = true;
+ defaults.email = cfg.acme.email;
+ };
+
+ users.groups.nginx = mkIf cfg.acme.enable {};
+ users.users.nginx = mkIf cfg.acme.enable {
+ group = "nginx";
+ extraGroups = ["acme"];
+ isSystemUser = true;
+ };
+ services.nginx = let
+ ssl = {
+ forceSSL = cfg.acme.enable;
+ enableACME = cfg.acme.enable;
+ };
+
+ makeVhosts = domain: subdomains:
+ lib.concatMapAttrs
+ (name: value: {${name + "." + domain} = {locations."/" = value;} // ssl;})
+ subdomains;
+
+ homeRoutes = homeVirtualHosts: homeUrl:
+ builtins.mapAttrs
+ (name: value:
+ {
+ locations."/" =
+ value.locations."/"
+ // {
+ proxyPass = homeUrl;
+ recommendedProxySettings = true;
+ extraConfig = value.locations."/".extraConfig + (autheliaAuth cfg.home.authelia.publicUrl);
+ };
+ locations."/internal/authelia/authz" = mkIf cfg.home.authelia.enable {
+ extraConfig = autheliaLocation cfg.home.authelia.localUrl;
+ };
+ }
+ // ssl)
+ homeVirtualHosts;
+
+ vhosts = makeVhosts cfg.domain cfg.subdomains;
+ homeVhosts = homeRoutes ((makeVhosts (cfg.home.domain) cfg.home.subdomains) // cfg.home.virtualHosts) cfg.home.url;
+ in
+ {
+ enable = true;
+ recommendedProxySettings = cfg.recommendedProxySettings;
+
+ virtualHosts = vhosts // homeVhosts // cfg.extraVirtualHosts;
+ }
+ // cfg.extraConfig;
+ };
+ };
+}