about summary refs log tree commit diff
diff options
context:
space:
mode:
authorArun Isaac2026-08-03 02:03:47 +0100
committerArun Isaac2026-08-04 13:24:53 +0100
commit3bf70c5c6d51ecdc9fc3671b483c00cf3a90ceb4 (patch)
tree4d6c3f7e88df298898a204cd84b97cdfbdc620e3
parentc3b28cdd8d2c80d7845ec011e388f6ff06564254 (diff)
downloadguix-forge-3bf70c5c6d51ecdc9fc3671b483c00cf3a90ceb4.tar.gz
guix-forge-3bf70c5c6d51ecdc9fc3671b483c00cf3a90ceb4.tar.lz
guix-forge-3bf70c5c6d51ecdc9fc3671b483c00cf3a90ceb4.zip
nginx: Add Anubis protection.
-rw-r--r--doc/forge.skb11
-rw-r--r--guix/forge/nginx.scm51
2 files changed, 59 insertions, 3 deletions
diff --git a/doc/forge.skb b/doc/forge.skb
index 986b7d7..4f184ae 100644
--- a/doc/forge.skb
+++ b/doc/forge.skb
@@ -418,6 +418,17 @@ cannot be found, nginx will send the list of files in the directory.])
          (record-field "try-files"
            [List of files whose existence is checked in the specified order.
 nginx will use the first file it finds to process the request.])
+         (record-field "anubis?"
+           [If ,(code [#t]), ,(ref :url
+"https://anubis.techaro.lol/docs/admin/configuration/subrequest-auth/" :text
+"Anubis subrequest authentication") locations are added to the server
+configuration. These are namely a ,(samp "/.within.website/") location and a
+,(samp "@redirectToAnubis") location. Locations to be protected by Anubis should
+specify ,(code "auth_request /.within.website/x/cmd/anubis/api/check; error_page
+401 = @redirectToAnubis;"). To use this feature, ,(code [nginx-service-type])
+must be configured with an nginx compiled with ,(samp
+[--with-http_auth_request_module]). The ,(code [nginx-with-auth-request])
+package is provided as a convenience for this purpose.])
          (record-field "raw-content"
            [List of strings or file-like objects to be appended to the server
 block. Each item is prefixed with indentation and suffixed with a new line.
diff --git a/guix/forge/nginx.scm b/guix/forge/nginx.scm
index abec390..87ad222 100644
--- a/guix/forge/nginx.scm
+++ b/guix/forge/nginx.scm
@@ -19,12 +19,16 @@
 
 (define-module (forge nginx)
   #:use-module (forge acme)
+  #:use-module (forge anubis)
   #:use-module (forge socket)
   #:use-module ((gnu packages admin) #:select (shepherd))
+  #:use-module ((gnu packages web) #:select (nginx))
   #:use-module (gnu services)
   #:use-module (gnu services web)
+  #:use-module (guix packages)
   #:use-module (guix gexp)
   #:use-module (guix records)
+  #:use-module (guix utils)
   #:use-module (ice-9 match)
   #:use-module (srfi srfi-1)
   #:export (<forge-nginx-configuration>
@@ -45,12 +49,22 @@
             forge-nginx-server-configuration-locations
             forge-nginx-server-configuration-index
             forge-nginx-server-configuration-try-files
+            forge-nginx-server-configuration-anubis?
             forge-nginx-server-configuration-raw-content
 
             nginx-socket->string
             socket->nginx-proxy-pass
             forge-nginx-service-type))
 
+(define-public nginx-with-auth-request
+  (package
+    (inherit nginx)
+    (arguments
+     (substitute-keyword-arguments (package-arguments nginx)
+       ((#:configure-flags flags '())
+        #~(cons "--with-http_auth_request_module"
+                #$flags))))))
+
 (define-record-type* <forge-nginx-configuration>
   forge-nginx-configuration make-forge-nginx-configuration
   forge-nginx-configuration?
@@ -84,6 +98,8 @@
          (default (list "index.html")))
   (try-files forge-nginx-server-configuration-try-files
              (default '()))
+  (anubis? forge-nginx-server-configuration-anubis?
+           (default #f))
   (raw-content forge-nginx-server-configuration-raw-content
                (default '())))
 
@@ -134,6 +150,28 @@ coerced into @code{<forge-nginx-server-configuration>} objects."
              server))
        (forge-nginx-configuration-server-blocks config)))
 
+(define (anubis-locations anubis-socket)
+  ;; This configuration is based on
+  ;; https://anubis.techaro.lol/docs/admin/configuration/subrequest-auth
+  (list (nginx-location-configuration
+          ;; Reverse proxy to Anubis for authorization and challenges. This
+          ;; location cannot be internal because clients need to request
+          ;; challenge pages.
+          (uri "/.within.website/")
+          (body (list (socket->nginx-proxy-pass anubis-socket)
+                      "proxy_set_header X-Real-IP $remote_addr;"
+                      "proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;"
+                      "proxy_set_header Host $http_host;"
+                      "proxy_pass_request_body off;"
+                      "proxy_set_header Content-Length \"\";")))
+        ;; Redirect to Anubis challenge if authorization failed. We may be
+        ;; listening locally on a non-standard port; do not expose that to the
+        ;; end user.
+        (nginx-named-location-configuration
+          (name "redirectToAnubis")
+          (body (list "port_in_redirect off;"
+                      "return 307 /.within.website/?redir=$scheme://$host$request_uri;")))))
+
 (define (forge-nginx-server-blocks config)
   "Return list of nginx server blocks to provision for forge-web service
 specified by @var{config}."
@@ -159,7 +197,7 @@ specified by @var{config}."
                      (body (list "add_header Strict-Transport-Security \"max-age=63072000; includeSubdomains; preload\";"
                                  "return 301 https://$host$request_uri;"))))))
           (map (match-record-lambda <forge-nginx-server-configuration>
-                 (server-name root locations index try-files anubis-uri-prefix raw-content)
+                 (server-name root locations index try-files anubis? raw-content)
                  (match server-name
                    ((name _ ...)
                     (nginx-server-configuration
@@ -171,7 +209,12 @@ specified by @var{config}."
                                         (list))))
                       (server-name server-name)
                       (root root)
-                      (locations locations)
+                      (locations
+                       (if anubis?
+                           (append (anubis-locations (forge-unix-socket
+                                                      (path %anubis-unix-socket)))
+                                   locations)
+                           locations))
                       (index index)
                       (try-files try-files)
                       (ssl-certificate (string-append acme-state-directory
@@ -211,7 +254,9 @@ forge-nginx service specified by @var{config}."
     (extensions (list (service-extension nginx-service-type
                                          forge-nginx-server-blocks)
                       (service-extension acme-service-type
-                                         forge-nginx-acme-certificates)))
+                                         forge-nginx-acme-certificates)
+                      (service-extension anubis-service-type
+                                         (const #t))))
     (compose concatenate)
     (extend (lambda (config server-blocks)
               (forge-nginx-configuration