diff --git a/flake.nix b/flake.nix
index 53ca564..cf2c29e 100644
--- a/flake.nix
+++ b/flake.nix
@@ -104,6 +104,7 @@ rec {
           flakeDefaults = import ./modules/flakeDefaults.nix;
           systemdNotify = import ./modules/systemdNotify.nix;
           inadyn = import ./modules/inadyn.nix;
+          nginx-authelia = import ./modules/nginx-authelia.nix;
         };
       };
       perSystem =
diff --git a/modules/nginx-authelia.nix b/modules/nginx-authelia.nix
new file mode 100644
index 0000000..c6662dc
--- /dev/null
+++ b/modules/nginx-authelia.nix
@@ -0,0 +1,145 @@
+{ config, lib, ... }:
+
+let
+  cfg = config.services.nginx-authelia;
+  vhostOptionsAuth =
+    { config, ... }:
+    {
+      options = {
+        enableAutheliaAuth = lib.mkEnableOption "Enable authelia auth";
+      };
+      config = lib.mkIf config.enableAutheliaAuth {
+        locations."/authelia".extraConfig = ''
+          set $upstream_authelia http://${cfg.host}:${toString cfg.port}/api/verify;
+
+          ## Essential Proxy Configuration
+          internal;
+          proxy_pass $upstream_authelia;
+
+          ## Headers
+          ## The headers starting with X-* are required.
+          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 "";
+
+          ## 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;
+        '';
+        locations."/".extraConfig = ''
+          ## Send a subrequest to Authelia to verify if the user is authenticated and has permission to access the resource.
+          auth_request /authelia;
+
+          ## Set the $target_url variable based on the original request.
+
+          ## Requires nginx http_set_misc module.
+          set_escape_uri $target_url $scheme://$http_host$request_uri;
+
+          ## Save the upstream response headers from Authelia to variables.
+          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;
+
+          ## Inject the response headers from the variables into the request made to the backend.
+          proxy_set_header Remote-User $user;
+          proxy_set_header Remote-Groups $groups;
+          proxy_set_header Remote-Name $name;
+          proxy_set_header Remote-Email $email;
+
+          ## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal.
+          error_page 401 =302 https://auth.zx.dev/?rd=$target_url;
+        '';
+      };
+    };
+
+  vhostOptionsProxy =
+    { config, ... }:
+    {
+      options = {
+        useAutheliaProxyConf = lib.mkEnableOption "Use recommended authelia proxy configuration";
+      };
+      config = lib.mkIf config.useAutheliaProxyConf {
+        locations."/".extraConfig = ''
+          ## Headers
+          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 "";
+
+          ## Basic Proxy Configuration
+          client_body_buffer_size 128k;
+          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 64 256k;
+
+          ## Trusted Proxies Configuration
+          ## Please read the following documentation before configuring this:
+          ##     https://www.authelia.com/integration/proxies/nginx/#trusted-proxies
+          # set_real_ip_from 10.0.0.0/8;
+          # set_real_ip_from 172.16.0.0/12;
+          # set_real_ip_from 192.168.0.0/16;
+          # set_real_ip_from fc00::/7;
+          real_ip_header X-Forwarded-For;
+          real_ip_recursive on;
+
+          ## Advanced Proxy Configuration
+          send_timeout 5m;
+          proxy_read_timeout 360;
+          proxy_send_timeout 360;
+          proxy_connect_timeout 360;
+        '';
+      };
+    };
+in
+{
+  options = {
+    services.nginx-authelia = {
+      host = lib.mkOption {
+        type = lib.types.str;
+        default = "localhost";
+      };
+      port = lib.mkOption {
+        type = lib.types.int;
+        default = 9091;
+      };
+    };
+
+    services.nginx.virtualHosts = lib.mkOption {
+      type = lib.types.attrsOf (
+        lib.types.submodule [
+          vhostOptionsAuth
+          vhostOptionsProxy
+        ]
+      );
+    };
+  };
+
+  config = { };
+}
diff --git a/services/authelia.nix b/services/authelia.nix
index 011bfb1..6209d9f 100644
--- a/services/authelia.nix
+++ b/services/authelia.nix
@@ -63,6 +63,8 @@ let
   smtpAccount = config.programs.msmtp.accounts.default;
 in
 {
+  imports = [ ../modules/nginx-authelia.nix ];
+
   age.secrets.authelia-jwt = {
     file = ../secrets/authelia/jwt.age;
     owner = cfg.user;
@@ -208,6 +210,10 @@ in
     "lldap.service"
   ];
 
+  services.nginx-authelia = {
+    inherit port;
+  };
+
   services.postgresql = {
     enable = true;
     ensureDatabases = [ cfg.user ];