From 6c009a6f424379028512c1378506bc31296c5982 Mon Sep 17 00:00:00 2001 From: Eric Bavier Date: Tue, 28 Mar 2017 18:03:21 -0500 Subject: [PATCH 4/4] gnu: services: Add ClamAV service. * gnu/services/antivirus.scm: New file. * gnu/local.mk (GNU_SYSTEM_MODULES): Add it. * gnu/packages/antivirus.scm (%clamav-database-directory): New variable. (clamav)[arguments]: Use it. --- gnu/local.mk | 1 + gnu/packages/antivirus.scm | 5 +- gnu/services/antivirus.scm | 195 +++++++++++++++++++++++++++++++++++++ 3 files changed, 199 insertions(+), 2 deletions(-) create mode 100644 gnu/services/antivirus.scm diff --git a/gnu/local.mk b/gnu/local.mk index be27be6df..44f234e74 100644 --- a/gnu/local.mk +++ b/gnu/local.mk @@ -465,6 +465,7 @@ GNU_SYSTEM_MODULES = \ \ %D%/services.scm \ %D%/services/admin.scm \ + %D%/services/antivirus.scm \ %D%/services/audio.scm \ %D%/services/avahi.scm \ %D%/services/base.scm \ diff --git a/gnu/packages/antivirus.scm b/gnu/packages/antivirus.scm index f117e3080..1b01fae41 100644 --- a/gnu/packages/antivirus.scm +++ b/gnu/packages/antivirus.scm @@ -40,6 +40,8 @@ #:use-module (gnu packages web) #:use-module (gnu packages xml)) +(define-public %clamav-database-directory "/var/db/clamav") + (define-public clamav (package (name "clamav") @@ -107,8 +109,7 @@ "--enable-bzip2" "--enable-check" "--sysconfdir=/etc/clamav" - ;; Default database directory needs to be writeable - "--with-dbdir=/var/db/clamav")) + ,(string-append "--with-dbdir=" %clamav-database-directory))) ;; install sample .conf files to %output/etc rather than /etc/clamav #:make-flags (list (string-append "sysconfdir=" %output "/etc")) #:phases (modify-phases %standard-phases diff --git a/gnu/services/antivirus.scm b/gnu/services/antivirus.scm new file mode 100644 index 000000000..69566ffa2 --- /dev/null +++ b/gnu/services/antivirus.scm @@ -0,0 +1,195 @@ +;;; GNU Guix --- Functional package management for GNU +;;; Copyright © 2017 Eric Bavier +;;; +;;; This file is part of GNU Guix. +;;; +;;; GNU Guix is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; GNU Guix is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of thye GNU General Public License +;;; along with GNU Guix. If not, see . + +(define-module (gnu services antivirus) + #:use-module (ice-9 format) + #:use-module (gnu packages admin) + #:use-module (gnu packages antivirus) + #:use-module (gnu packages bash) + #:use-module (gnu services) + #:use-module (gnu services shepherd) + #:use-module (gnu system shadow) + #:use-module (guix build-system trivial) + #:use-module (guix packages) + #:use-module (guix records) + #:use-module (guix gexp) + #:export (clamav-configuration + clamav-configuration? + ;; clamav-service + clamav-service-type + + freshclam-configuration + freshclam-configuration? + freshclam-service-type)) + +(define-record-type* + freshclam-configuration make-freshclam-configuration + freshclam-configuration? + (clamav freshclam-configuration-clamav + (default clamav)) + (log-file freshclam-configuration-log-file + (default #f)) + (database-mirror freshclam-configuration-database-mirror + (default "database.clamav.net"))) + +(define-record-type* + clamav-configuration make-clamav-configuration + clamav-configuration? + (clamav clamav-configuration-clamav ;package + (default clamav)) + (local-socket clamav-configuration-local-socket + (default "/var/run/clamd.socket")) + (pid-file clamav-configuration-pid-file (default #f)) + (log-file clamav-configuration-log-file (default #f)) + (log-file-max-size clamav-configuration-log-file-max-size (default #f)) + (freshclam clamav-configuration-freshclam + (default (freshclam-configuration))) + (exclude-path clamav-configuration-exclude-path (default '()))) ;list + +;;; TODO: Accounts and groups can be configured by the user, so we probably +;;; should derive these from the configuration. +(define %clamd-accounts + ;; User account and group for clamd + (list (user-group + (name "clamav") + (system? #t)) + (user-account + (name "clamav") + (system? #t) + (group "clamav") + (comment "Clam AntiVirus") + (home-directory "/var/empty") + (shell (file-append shadow "/sbin/nologin"))))) + +(define (freshclam-configuration-file config) + "Returns a @file{/etc} entry for @file{freshclam.conf} based on CONFIG, a +." + `(("freshclam.conf" + ,(plain-file "freshclam.conf" + (format #f "~ +## Automatically generated from your GuixSD configuration. Any changes +## will be lost upon reboot or reconfiguration. + +~@[LogFile ~a~%~]~ +~@[DatabaseMirror ~a~%~]" + (freshclam-configuration-log-file config) + (freshclam-configuration-database-mirror config)))))) + +(define (clamd-configuration-file config) + "Returns a @file{/etc} entry for @file{clamd.conf} based on CONFIG, a +." + `(("clamd.conf" + ,(plain-file "clamd.conf" + (format #f "~ +## Automatically generated from your GuixSD configuration. Any changes +## will be lost upon reboot or reconfiguration. + +~@[LogFile ~a~%~]~ +~@[LogFileMaxSize ~a~%~]~ +~@[PidFile ~a~%~]~ +~@[LocalSocket ~a~%~]~ +~@[~{ExcludePath ~a~^~%~}~]" + (clamav-configuration-log-file config) + (clamav-configuration-log-file-max-size config) + (clamav-configuration-pid-file config) + (clamav-configuration-local-socket config) + (clamav-configuration-exclude-path config)))))) + +(define (freshclam-shepherd-service config) + "Return a list of for CONFIG, a +." + (shepherd-service + (documentation "Run the ClamAV virus database updater.") + (provision '(freshclam)) + (requirement '(networking)) + (start #~(make-forkexec-constructor + (list (string-append #$clamav "/bin/freshclam")) + #:user "clamav" + #:group "clamav")) + (stop #~(make-kill-destructor)))) + +(define (clamd-shepherd-service config) + "Return a list of for CONFIG, a ." + (let* ((freshclam? (clamav-configuration-freshclam config))) + (shepherd-service + (documentation "Run the ClamAV daemon.") + (provision '(clamd)) + (requirement (if freshclam? '(freshclam) '())) + (start #~(lambda () + ;; Wait until freshclam has had a chance to successfully + ;; run. freshclam always writes a "mirrors.dat" file. + (let ((pid (primitive-fork))) + (case pid + ((0) + (let wait () + (unless (file-exists? + (string-append + %clamav-database-directory "/mirrors.dat")) + (usleep 500000) + (wait))) + (exec-command + (list (string-append #$clamav "/sbin/clamd")))) + (else #t))) + #:user "clamav" + #:group "clamav")) + (stop #~(make-kill-destructor))))) + +(define clamav-activation + ;; Actions to take before starting clamd or freshclam + (with-imported-modules '((guix build utils)) + #~(begin + (use-modules (guix build utils)) + (mkdir-p #$%clamav-database-directory) + (chmod #$%clamav-database-directory #o660) + (let ((uid (passwd:uid (getpw "clamav"))) + (gid (group:gid (getgr "clamav")))) + (chown #$%clamav-database-directory uid gid))))) + +(define clamav-service-type + (service-type + (name 'clamav) + (extensions + (list (service-extension account-service-type (const %clamd-accounts)) + (service-extension activation-service-type (const clamav-activation)) + (service-extension + shepherd-root-service-type + (lambda (config) + (cons (clamd-shepherd-service config) + (or (and=> (clamav-configuration-freshclam config) + (compose list freshclam-shepherd-service)) + '())))) + (service-extension + etc-service-type + (lambda (config) + (append (clamd-configuration-file config) + ;; Include default etc even if freshclam disabled so that + ;; users can run `freshclam`. + (freshclam-configuration-file + (or (clamav-configuration-freshclam config) + (freshclam-configuration)))))))))) + +(define freshclam-service-type + (service-type + (name 'freshclam) + (extensions + (list (service-extension account-service-type (const %clamd-accounts)) + (service-extension account-service-type (const clamav-activation)) + (service-extension shepherd-root-service-type + freshclam-shepherd-service) + (service-extension etc-service-type + freshclam-configuration-file))))) -- 2.19.1