Toggle diff (336 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 3124ed2ef8..6f22edba2e 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -26259,6 +26259,130 @@ The file which should store the logging output of Agate.
@end table
@end deftp
+@subsubheading darkhttpd
+
+@cindex darkhttpd
+@uref{https://unix4lyfe.org/darkhttpd/, darkhttpd} is a web server with a
+focus on security and having a small memory footprint.
+
+Some security features are the following:
+
+@itemize
+@item Logging accesses, including Referer and User-Agent.
+@item Can chroot.
+@item Can drop privileges.
+@item Impervious to /../ sniffing.
+@item Times out idle connections.
+@item Drops overly long requests.
+@end itemize
+
+@deffn {Scheme Variable} darkhttpd-service-type
+This is the type of the darkhttpd service, whose value should be a
+@code{darkhttpd-service-type} object, as in this example:
+
+@lisp
+(service darkhttpd-service-type
+ (darkhttpd-configuration
+ (content "/var/www/localhost/blog")
+ (port 4567)
+ (no-server-id? #t)
+ (enable-ipv6? #t)
+ (chroot? #f)))
+@end lisp
+
+The example above shows @code{content} directory modified as
+well as @code{port}, @code{no-server-id?}, and @code{enable-ipv6?}
+enabled and @code{chroot?} disabled.
+
+A minimal config might look like the following:
+
+@lisp
+(service darkhttpd-service-type)
+@end lisp
+
+@deftp {Data Type} darkhttpd-configuration
+Data type representing the configuration of darkhttpd.
+
+@table @asis
+@item @code{package} (default: @code{darkhttpd})
+The package object of the darkhttpd server.
+
+@item @code{content} (default: @file{"/srv/gemini"})
+The directory from which Agate will serve files.
+
+@item @code{port} (default: @code{"80"})
+Specifies which port to listen on for connections.
+Assign 0 to let the system choose any free port for you.
+
+@item @code{address} (default: @code{"all"})
+If multiple interfaces are present, specifies
+which one to bind the listening port to.
+
+@item @code{maximum-connections} (default: @code{#f})
+Specifies how many concurrent connections to accept.
+
+@item @code{log-file} (default: @file{"/var/log/darkhttpd.log"})
+The file which should store the logging output of @code{darkhttpd}.
+
+@item @code{chroot?} (default: @code{#t})
+Locks the web server into the content directory for added security.
+
+@item @code{daemonize?} (default: @code{#t})
+Detach from the controlling terminal and run in the background.
+
+@item @code{index-file} (default: @code{"index.html"})
+Default file to serve when a directory is requested.
+
+@item @code{do-not-serve-listing?} (default: @code{#f})
+Do not serve listing if directory is requested.
+
+@item @code{mimetypes} (default: @code{#f})
+This option is optional. @code{mimetypes} parses the
+specified file for extension-MIME associations.
+
+@item @code{default-mimetype} (default: @code{"application/octet-stream"})
+Files with unknown extensions are served as this mimetype.
+
+@item @code{drop-user-privileges?} (default: @code{#t})
+Drops privileges to given uid after initialization.
+
+@item @code{drop-group-privileges?} (default: @code{#t})
+Drops privileges to given gid after initialization.
+
+@item @code{write-pid-file} (default: @code{#f})
+Write PID to the specified file. Note that if you are
+using @{chroot?}, then the pidfile will be set relative
+to the directory set with the @{content} option.
+
+@item @code{disable-keep-alive?} (default: @code{#f})
+Disables HTTP Keep-Alive functionality.
+
+@item @code{forward} (default: @code{#f})
+By default, @{darkhttpd} does not forward requests.
+This option allows requests to the host to be redirected
+to the corresponding url given as an argument.
+@{forward} may be specified multiple times, in which case
+the host is matched in order of appearance.
+
+@item @code{forward-all} (default: @code{#f})
+@{forward-all} is similar to @{forward} but all
+requests are redirected to the url given as an argument.
+
+@item @code{no-server-id?} (default: @code{#f})
+Do not identify the server type in headers or
+directory listings.
+
+@item @code{enable-ipv6?} (default: @code{#f})
+Listen on IPv6 address.
+
+@item @code{user} (default: @code{"darkhttpd"})
+Owner of the @code{darkhttpd} process.
+
+@item @code{group} (default: @code{"darkhttpd"})
+Owner's group of the @code{darkhttpd} process.
+
+@end table
+@end deftp
@node Certificate Services
@subsection Certificate Services
diff --git a/gnu/services/web.scm b/gnu/services/web.scm
index bb42eacf83..68afba3cad 100644
--- a/gnu/services/web.scm
+++ b/gnu/services/web.scm
@@ -281,8 +281,35 @@
agate-configuration-group
agate-configuration-log-file
- agate-service-type))
-
+ agate-service-type
+
+ darkhttpd-configuration
+ darkhttpd-configuration?
+ darkhttpd-configuration-package
+ darkhttpd-configuration-content
+ darkhttpd-configuration-port
+ darkhttpd-configuration-address
+ darkhttpd-configuration-maximum-connections
+ darkhttpd-configuration-log-file
+ darkhttpd-configuration-chroot
+ darkhttpd-configuration-daemonize
+ darkhttpd-configuration-index-file
+ darkhttpd-configuration-do-not-serve-listing
+ darkhttpd-configuration-mimetypes
+ darkhttpd-configuration-default-mimetype
+ darkhttpd-configuration-drop-user-privileges
+ darkhttpd-configuration-drop-group-privileges
+ darkhttpd-configuration-write-pid-file
+ darkhttpd-configuration-disable-keep-alive
+ darkhttpd-configuration-forward
+ darkhttpd-configuration-forward-all
+ darkhttpd-configuration-no-server-id
+ darkhttpd-configuration-enable-ipv6
+ darkhttpd-configuration-user
+ darkhttpd-configuration-group
+
+ darkhttpd-service-type))
+
;;; Commentary:
;;;
;;; Web services.
@@ -1993,3 +2020,156 @@ root=/srv/gemini
(service-extension shepherd-root-service-type
agate-shepherd-service)))
(default-value (agate-configuration))))
+
+(define-record-type* <darkhttpd-configuration>
+ darkhttpd-configuration make-darkhttpd-configuration
+ darkhttpd-configuration?
+ (package darkhttpd-configuration-package
+ (default darkhttpd))
+ (content darkhttpd-configuration-content
+ (default "/var/www/localhost/htdocs"))
+ (port darkhttpd-configuration-port
+ (default "80"))
+ (address darkhttpd-configuration-address
+ (default "all"))
+ (maximum-connections darkhttpd-configuration-maximum-connections
+ (default #f))
+ (log-file darkhttpd-configuration-log-file
+ (default "access.log"))
+ (chroot? darkhttpd-configuration-chroot
+ (default #t))
+ (daemonize? darkhttpd-configuration-daemonize
+ (default #t))
+ (index-file darkhttpd-configuration-index-file
+ (default "index.html"))
+ (do-not-serve-listing? darkhttpd-configuration-do-not-serve-listing
+ (default #f))
+ (mimetypes darkhttpd-configuration-mimetypes
+ (default #f))
+ (default-mimetype darkhttpd-configuration-default-mimetype
+ (default "application/octet-stream"))
+ (drop-user-privileges? darkhttpd-configuration-drop-user-privileges
+ (default #t))
+ (drop-group-privileges? darkhttpd-configuration-drop-group-privileges
+ (default #t))
+ (write-pid-file darkhttpd-configuration-write-pid-file
+ (default #f))
+ (disable-keep-alive? darkhttpd-configuration-disable-keep-alive
+ (default #f))
+ (forward darkhttpd-configuration-forward
+ (default #f))
+ (forward-all darkhttpd-configuration-forward-all
+ (default #f))
+ (no-server-id? darkhttpd-configuration-no-server-id
+ (default #f))
+ (enable-ipv6? darkhttpd-configuration-enable-ipv6
+ (default #f))
+ (user darkhttpd-configuration-user
+ (default "darkhttpd"))
+ (group darkhttpd-configuration-group
+ (default "www-data")))
+
+(define darkhttpd-shepherd-service
+ (match-lambda
+ (($ <darkhttpd-configuration> package content port address
+ maximum-connections log-file chroot?
+ daemonize? index-file do-not-serve-listing?
+ mimetypes default-mimetype
+ drop-user-priviledges drop-group-priviledges
+ write-pid-file disable-keep-alive?
+ forward forward-all
+ no-server-id? enable-ipv6?
+ user group)
+ (list (shepherd-service
+ (provision '(darkhttpd))
+ (requirement '(networking))
+ (documentation "Run the darkhttpd web server.")
+ (start (let ((darkhttpd (file-append package "/bin/darkhttpd")))
+ #~(make-forkexec-constructor
+ (list #$darkhttpd
+ #$content
+ #$@(if port
+ (list "--port" (number->string port))
+ '())
+ #$@(if address
+ (list "--addr" address)
+ '())
+ #$@(if maximum-connections
+ (list "--maxconn" maximum-connections)
+ '())
+ #$@(if log-file
+ (list "--log"
+ (string-append "/var/log/darkhttpd/"
+ log-file)
+ '()))
+ #$@(if chroot? '("--chroot") '())
+ #$@(if daemonize? '("--daemon") '())
+ #$@(if index-file
+ (list "--index" index-file)
+ '())
+ #$@(if do-not-serve-listing?
+ (list "--no-listing"
+ do-not-serve-listing?)
+ '())
+ #$@(if mimetypes '("--mimetypes" mimetypes) '())
+ #$@(if default-mimetype
+ (list "--default-mimetype"
+ default-mimetype)
+ '())
+ #$@(if drop-user-privileges?
+ '("--uid" user) '())
+ #$@(if drop-group-privileges?
+ '("--gid" group) '())
+ ;; if using --chroot, then the pidfile must be
+ ;; relative to, and inside the wwwroot.
+ #$@(if write-pid-file
+ "--pidfile"
+ (if (and chroot? write-pid-file)
+ '(string-append content
+ "/"
+ write-pid-file)
+ write-pid-file)
+ '())
+ #$@(if disable-keep-alive?
+ (list "--no-keepalive"
+ disable-keep-alive?)
+ '())
+ #$@(if forward '("--forward" forward) '())
+ #$@(if forward-all
+ (list "--forward-all" forward-all)
+ '())
+ #$@(if no-server-id? '("--no-server-id") '())
+ #$@(if enable-ipv6? '("--ipv6") '())
+ #:user #$user #:group #$group))))
+ (stop #~(make-kill-destructor)))))))
+
+(define darkhttpd-accounts
+ (match-lambda
+ (($ <darkhttpd-configuration> _ _ _ _ _ _ _ _
+ _ _ _ _ _ _ _ _
+ _ _ user group)
+ `(,@(if (equal? group "darkhttpd")
+ '()
+ (list (user-group (name "darkhttpd") (system? #t))))
+ ,(user-group
+ (name group)
+ (system? #t))
+ ,(user-account
+ (name user)
+ (group group)
+ (supplementary-groups '("darkhttpd"))
+ (system? #t)
+ (comment "darkhttpd server user")
+ (home-directory "/var/empty")
+ (shell (file-append shadow "/sbin/nologin")))))))
+
+(define darkhttpd-service-type
+ (service-type
+ (name 'guix)
+ (extensions
+ (list (service-extension account-service-type
+ darkhttpd-accounts)
+ (service-extension shepherd-root-service-type
+ darkhttpd-shepherd-service)))
+ (default-value (darkhttpd-configuration))))
+
--
2.33.0