* gnu/services/web.scm (anonip-configuration): New record type.
(anonip-configuration?, anonip-configuration-anonip,
anonip-configuration-input, anonip-configuration-output,
anonip-configuration-skip-private?, anonip-configuration-column,
anonip-configuration-replacement, anonip-configuration-ipv4mask,
anonip-configuration-ipv6mask, anonip-configuration-increment,
anonip-configuration-delimiter, anonip-configuration-regex): New procedures.
(anonip-service-type): New service type.
* doc/guix.texi (Log Rotation): Add subheading for Anonip Service.
doc/guix.texi | 71 +++++++++++++++++++++++++++-
gnu/services/web.scm | 110 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 179 insertions(+), 2 deletions(-)
Toggle diff (226 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index cf373b6cbd..a22a7f59ec 100644
@@ -30,7 +30,7 @@ Copyright @copyright{} 2015, 2016 Mathieu Lirzin@*
Copyright @copyright{} 2014 Pierre-Antoine Rault@*
Copyright @copyright{} 2015 Taylan Ulrich Bayırlı/Kammer@*
Copyright @copyright{} 2015, 2016, 2017, 2019, 2020, 2021 Leo Famulari@*
-Copyright @copyright{} 2015, 2016, 2017, 2018, 2019, 2020, 2021 Ricardo Wurmus@*
+Copyright @copyright{} 2015, 2016, 2017, 2018, 2019, 2020, 2021, 2022 Ricardo Wurmus@*
Copyright @copyright{} 2016 Ben Woodcroft@*
Copyright @copyright{} 2016, 2017, 2018, 2021 Chris Marusich@*
Copyright @copyright{} 2016, 2017, 2018, 2019, 2020, 2021, 2022 Efraim Flashner@*
@@ -18700,6 +18700,75 @@ String or gexp denoting the corresponding mcron job schedule
+@cindex logging, anonymization
+@subheading Anonip Service
+Anonip is a privacy filter that removes IP address from web server logs.
+This service creates a FIFO and filters any written lines with anonip
+before writing the filtered log to a target file.
+The following example sets up the FIFO
+@file{/var/run/anonip/https.access.log} and writes the filtered log file
+@file{/var/log/anonip/https.access.log}.
+(service anonip-service-type
+ (input "/var/run/anonip/https.access.log")
+ (output "/var/log/anonip/https.access.log")))
+Configure your web server to write its logs to the FIFO at
+@file{/var/run/anonip/https.access.log} and collect the anonymized log
+file at @file{/var/web-logs/https.access.log}.
+@deftp {Data Type} anonip-configuration
+This data type represents the configuration of anonip.
+It has the following parameters:
+@item @code{anonip} (default: @code{anonip})
+The anonip package to use.
+The file name of the input log file to process. The service creates a
+FIFO of this name. The web server should write its logs to this FIFO.
+The file name of the processed log file.
+The following optional settings may be provided:
+@item @code{skip-private?}
+When @code{#true} do not mask addresses in private ranges.
+A 1-based indexed column number. Assume IP address is in the specified
+@item @code{replacement}
+Replacement string in case address parsing fails, e.g. @code{"0.0.0.0"}.
+Number of bits to mask in IPv4 addresses.
+Number of bits to mask in IPv6 addresses.
+Increment the IP address by the given number. By default this is zero.
+Regular expression for detecting IP addresses. Use this instead of @code{column}.
@subsection Networking Setup
diff --git a/gnu/services/web.scm b/gnu/services/web.scm
index 4434fecf02..1480a751e2 100644
--- a/gnu/services/web.scm
+++ b/gnu/services/web.scm
;;; Copyright © 2018 Pierre-Antoine Rouby <pierre-antoine.rouby@inria.fr>
;;; Copyright © 2018 Marius Bakke <mbakke@fastmail.com>
;;; Copyright © 2019, 2020 Florian Pelz <pelzflorian@pelzflorian.de>
-;;; Copyright © 2020 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2020, 2022 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2020 Tobias Geerinckx-Rice <me@tobias.gr>
;;; Copyright © 2020 Arun Isaac <arunisaac@systemreboot.net>
;;; Copyright © 2020 Oleg Pykhalov <go.wigust@gmail.com>
@@ -205,6 +205,21 @@ (define-module (gnu services web)
+ anonip-configuration-anonip
+ anonip-configuration-input
+ anonip-configuration-output
+ anonip-configuration-skip-private?
+ anonip-configuration-column
+ anonip-configuration-replacement
+ anonip-configuration-ipv4mask
+ anonip-configuration-ipv6mask
+ anonip-configuration-increment
+ anonip-configuration-delimiter
+ anonip-configuration-regex
varnish-configuration-package
@@ -1355,6 +1370,99 @@ (define tailon-service-type
(default-value (tailon-configuration))))
+(define-record-type* <anonip-configuration>
+ anonip-configuration make-anonip-configuration
+ (anonip anonip-configuration-anonip ;file-like
+ (input anonip-configuration-input) ;string
+ (output anonip-configuration-output) ;string
+ (skip-private? anonip-configuration-skip-private? ;boolean
+ (column anonip-configuration-column ;number
+ (replacement anonip-configuration-replacement ;string
+ (ipv4mask anonip-configuration-ipv4mask ;number
+ (ipv6mask anonip-configuration-ipv6mask ;number
+ (increment anonip-configuration-increment ;number
+ (delimiter anonip-configuration-delimiter ;string
+ (regex anonip-configuration-regex ;string
+(define (anonip-activation config)
+ (with-imported-modules '((guix build utils))
+ (use-modules (guix build utils))
+ (chmod directory #o755))
+ (list (dirname #$(anonip-configuration-input config))
+ (dirname #$(anonip-configuration-output config)))))))
+(define (anonip-shepherd-service config)
+ (let ((input (anonip-configuration-input config))
+ (output (anonip-configuration-output config)))
+ (list (shepherd-service
+ (provision (list (symbol-append 'anonip- (string->symbol output))))
+ (requirement '(user-processes))
+ (documentation "Anonimyze the given log file location with anonip.")
+ (lambda (accessor option)
+ (or (and=> (accessor config)
+ option (accessor config)))))
+ (unless (file-exists? input)
+ (mknod input 'fifo #o600 0))
+ (let ((pid (fork+exec-command
+ (list #$(file-append (anonip-configuration-anonip config)
+ (string-append "--input=" input)
+ (string-append "--output=" output))
+ (if (anonip-configuration-skip-private? config)
+ '("--skip-private") (list))
+ (optional anonip-configuration-column "--column")
+ (optional anonip-configuration-ipv4mask "--ipv4mask")
+ (optional anonip-configuration-ipv6mask "--ipv6mask")
+ (optional anonip-configuration-increment "--increment")
+ (optional anonip-configuration-replacement "--replacement")
+ (optional anonip-configuration-delimiter "--delimiter")
+ (optional anonip-configuration-regex "--regex"))
+ ;; Run in a UTF-8 locale
+ #:environment-variables
+ (list (string-append "GUIX_LOCPATH=" #$glibc-utf8-locales
+ "LC_ALL=en_US.utf8"))))
+ (stop #~(make-kill-destructor))))))
+(define anonip-service-type
+ (list (service-extension shepherd-root-service-type
+ anonip-shepherd-service)
+ (service-extension activation-service-type
+ "Provide web server log anonymization with @command{anonip}.")))