Message ID | 20210929004633.17158-1-jgart@dismail.de |
---|---|
State | Accepted |
Headers | show |
Series | [bug#50882] services: Add darkhttpd service. | expand |
Context | Check | Description |
---|---|---|
cbaines/comparison | success | View comparision |
cbaines/git branch | success | View Git branch |
cbaines/applying patch | success | View Laminar job |
cbaines/issue | success | View issue |
cbaines/comparison | success | View comparision |
cbaines/git branch | success | View Git branch |
cbaines/applying patch | success | View Laminar job |
cbaines/issue | success | View issue |
cbaines/comparison | success | View comparision |
cbaines/git branch | success | View Git branch |
cbaines/applying patch | success | View Laminar job |
cbaines/issue | success | View issue |
cbaines/comparison | success | View comparision |
cbaines/git branch | success | View Git branch |
cbaines/applying patch | success | View Laminar job |
cbaines/issue | success | View issue |
cbaines/comparison | success | View comparision |
cbaines/git branch | success | View Git branch |
cbaines/applying patch | success | View Laminar job |
cbaines/issue | success | View issue |
Hi, jgart <jgart@dismail.de> skribis: > * gnu/services/web.scm (<darkhttpd-configuration>): New record type. > (darkhttpd-accounts, darkhttpd-shepherd-service): New procedures. > (darkhttpd-service-type): New variable. > * doc/guix.texi (Web Services): Adds documentation for darkhttpd. Overall LGTM! Some comments and suggestions below. > +@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 I’d replace the bullet list with a simple sentence like: “Among other things, it can change root directories, drop privileges, it times out on idle connections and can drop overly long requests.” > +@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 Please don’t use tabs. > +@end table > +@end deftp > @node Certificate Services Missing newline before @node. :-) > + (mimetypes darkhttpd-configuration-mimetypes > + (default #f)) > + (default-mimetype darkhttpd-configuration-default-mimetype Rather ‘mime-type’ (two words). > +(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) Rather use ‘match-record’ here, to make sure we’re getting the right fields. > +(define darkhttpd-accounts > + (match-lambda > + (($ <darkhttpd-configuration> _ _ _ _ _ _ _ _ > + _ _ _ _ _ _ _ _ > + _ _ user group) In such a case, simply call ‘darkhttpd-configuration-user’ and ‘darkhttpd-configuration-group’; it’s much less error-prone! > +(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)))) Please add a ‘description’ field. Could you also add a system test, under (gnu tests web)? You can start by copying the nginx test; it should take around ~20 lines. TIA! Ludo’.
tag 50882 moreinfo thanks Hello jgart, Ludovic Courtès <ludo@gnu.org> writes: > Hi, > > jgart <jgart@dismail.de> skribis: > >> * gnu/services/web.scm (<darkhttpd-configuration>): New record type. >> (darkhttpd-accounts, darkhttpd-shepherd-service): New procedures. >> (darkhttpd-service-type): New variable. >> * doc/guix.texi (Web Services): Adds documentation for darkhttpd. > > Overall LGTM! Some comments and suggestions below. > >> +@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 > > I’d replace the bullet list with a simple sentence like: “Among other > things, it can change root directories, drop privileges, it times out on > idle connections and can drop overly long requests.” > >> +@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 > > Please don’t use tabs. > >> +@end table >> +@end deftp >> @node Certificate Services > > Missing newline before @node. :-) > >> + (mimetypes darkhttpd-configuration-mimetypes >> + (default #f)) >> + (default-mimetype darkhttpd-configuration-default-mimetype > > Rather ‘mime-type’ (two words). > >> +(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) > > Rather use ‘match-record’ here, to make sure we’re getting the right > fields. > >> +(define darkhttpd-accounts >> + (match-lambda >> + (($ <darkhttpd-configuration> _ _ _ _ _ _ _ _ >> + _ _ _ _ _ _ _ _ >> + _ _ user group) > > In such a case, simply call ‘darkhttpd-configuration-user’ and > ‘darkhttpd-configuration-group’; it’s much less error-prone! > >> +(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)))) > > Please add a ‘description’ field. > > Could you also add a system test, under (gnu tests web)? You can start > by copying the nginx test; it should take around ~20 lines. Friendly ping about the above requests from Ludovic :-). Thanks, Maxim
On Thu, 07 Jul 2022 14:02:36 -0400 Maxim Cournoyer <maxim.cournoyer@gmail.com> wrote: > tag 50882 moreinfo > thanks > > Hello jgart, > > Ludovic Courtès <ludo@gnu.org> writes: > > > Hi, > > > > jgart <jgart@dismail.de> skribis: > > > >> * gnu/services/web.scm (<darkhttpd-configuration>): New record type. > >> (darkhttpd-accounts, darkhttpd-shepherd-service): New procedures. > >> (darkhttpd-service-type): New variable. > >> * doc/guix.texi (Web Services): Adds documentation for darkhttpd. > > > > Overall LGTM! Some comments and suggestions below. > > > >> +@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 > > > > I’d replace the bullet list with a simple sentence like: “Among other > > things, it can change root directories, drop privileges, it times out on > > idle connections and can drop overly long requests.” > > > >> +@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 > > > > Please don’t use tabs. > > > >> +@end table > >> +@end deftp > >> @node Certificate Services > > > > Missing newline before @node. :-) > > > >> + (mimetypes darkhttpd-configuration-mimetypes > >> + (default #f)) > >> + (default-mimetype darkhttpd-configuration-default-mimetype > > > > Rather ‘mime-type’ (two words). > > > >> +(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) > > > > Rather use ‘match-record’ here, to make sure we’re getting the right > > fields. > > > >> +(define darkhttpd-accounts > >> + (match-lambda > >> + (($ <darkhttpd-configuration> _ _ _ _ _ _ _ _ > >> + _ _ _ _ _ _ _ _ > >> + _ _ user group) > > > > In such a case, simply call ‘darkhttpd-configuration-user’ and > > ‘darkhttpd-configuration-group’; it’s much less error-prone! > > > >> +(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)))) > > > > Please add a ‘description’ field. > > > > Could you also add a system test, under (gnu tests web)? You can start > > by copying the nginx test; it should take around ~20 lines. > > Friendly ping about the above requests from Ludovic :-). Arun Isaac convinced me to not write a service for this one since it's common usage is for quick serving by simply running `darkhttpd ...` from the command line. I think that guile bindings for every CLI feature of darkhttpd doesn't add to that aim. I might change my mind later on this. Feel free to close this one for now. It was a fun exercise though. Ludo, thanks for the review. It was much appreciated! all best, jgart https://whereis.みんな/
Hello, [...] >> Friendly ping about the above requests from Ludovic :-). > > Arun Isaac convinced me to not write a service for this one since it's > common usage is for quick serving by simply running `darkhttpd ...` from > the command line. I think that guile bindings for every CLI feature of > darkhttpd doesn't add to that aim. I might change my mind later on this. > Feel free to close this one for now. > > It was a fun exercise though. > > Ludo, thanks for the review. It was much appreciated! OK, if you do reopen a ticket for it, please incorporate Ludovic's and others comments in this issue in the to be submitted code, to avoid duplicating efforts. Closing; thanks! Maxim
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)))) +