From 9e1e3b288062abf37847307adeee17f3c8dddc42 Mon Sep 17 00:00:00 2001 From: Franz Pletz Date: Tue, 15 Nov 2016 04:40:33 +0100 Subject: [PATCH] clamav service: refactor * Sync systemd units with upstream. Upstream uses SIGUSR2 instead of SIGHUP to reload the clamd service. * Convert freshclam service to a oneshot service activated by a systemd timer. This way we can make clamd wait for freshclam to finish fetching the virus database before failing to start if the database doesn't exist yet. * Fixes console tools to work as expected as they require hardcoded config file locations. --- nixos/modules/rename.nix | 2 + nixos/modules/services/security/clamav.nix | 95 ++++++++++++++-------- pkgs/tools/security/clamav/default.nix | 11 +++ 3 files changed, 73 insertions(+), 35 deletions(-) diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix index 44e07f4618de..0d2e0f981db8 100644 --- a/nixos/modules/rename.nix +++ b/nixos/modules/rename.nix @@ -30,6 +30,8 @@ with lib; (mkRenamedOptionModule [ "services" "gitlab" "stateDir" ] [ "services" "gitlab" "statePath" ]) (mkRemovedOptionModule [ "services" "gitlab" "satelliteDir" ] "") + (mkRenamedOptionModule [ "services" "clamav" "updater" "config" ] [ "services" "clamav" "updater" "extraConfig" ]) + # Old Grub-related options. (mkRenamedOptionModule [ "boot" "initrd" "extraKernelModules" ] [ "boot" "initrd" "kernelModules" ]) (mkRenamedOptionModule [ "boot" "extraKernelParams" ] [ "boot" "kernelParams" ]) diff --git a/nixos/modules/services/security/clamav.nix b/nixos/modules/services/security/clamav.nix index 89ac1c01f521..b045e140546d 100644 --- a/nixos/modules/services/security/clamav.nix +++ b/nixos/modules/services/security/clamav.nix @@ -3,26 +3,37 @@ with lib; let clamavUser = "clamav"; stateDir = "/var/lib/clamav"; - runDir = "/var/run/clamav"; - logDir = "/var/log/clamav"; + runDir = "/run/clamav"; clamavGroup = clamavUser; cfg = config.services.clamav; + pkg = pkgs.clamav; + clamdConfigFile = pkgs.writeText "clamd.conf" '' DatabaseDirectory ${stateDir} LocalSocket ${runDir}/clamd.ctl - LogFile ${logDir}/clamav.log PidFile ${runDir}/clamd.pid + TemporaryDirectory /tmp User clamav + Foreground yes ${cfg.daemon.extraConfig} ''; - pkg = pkgs.clamav; + + freshclamConfigFile = pkgs.writeText "freshclam.conf" '' + DatabaseDirectory ${stateDir} + Foreground yes + Checks ${toString cfg.updater.frequency} + + ${cfg.updater.extraConfig} + + DatabaseMirror database.clamav.net + ''; in { options = { services.clamav = { daemon = { - enable = mkEnableOption "clamd daemon"; + enable = mkEnableOption "ClamAV clamd daemon"; extraConfig = mkOption { type = types.lines; @@ -34,16 +45,27 @@ in }; }; updater = { - enable = mkEnableOption "freshclam updater"; + enable = mkEnableOption "ClamAV freshclam updater"; frequency = mkOption { + type = types.int; default = 12; description = '' Number of database checks per day. ''; }; - config = mkOption { + interval = mkOption { + type = types.str; + default = "hourly"; + description = '' + How often freshclam is invoked. See systemd.time(7) for more + information about the format. + ''; + }; + + extraConfig = mkOption { + type = types.lines; default = ""; description = '' Extra configuration for freshclam. Contents will be added verbatim to the @@ -68,50 +90,53 @@ in gid = config.ids.gids.clamav; }; - services.clamav.updater.config = mkIf cfg.updater.enable '' - DatabaseDirectory ${stateDir} - Foreground yes - Checks ${toString cfg.updater.frequency} - DatabaseMirror database.clamav.net - ''; + environment.etc."clamav/freshclam.conf".source = freshclamConfigFile; + environment.etc."clamav/clamd.conf".source = clamdConfigFile; - systemd.services.clamd = mkIf cfg.daemon.enable { + systemd.services.clamav-daemon = mkIf cfg.daemon.enable { description = "ClamAV daemon (clamd)"; - path = [ pkg ]; - after = [ "network.target" "freshclam.service" ]; - requires = [ "freshclam.service" ]; + after = mkIf cfg.updater.enable [ "clamav-freshclam.service" ]; + requires = mkIf cfg.updater.enable [ "clamav-freshclam.service" ]; wantedBy = [ "multi-user.target" ]; + restartTriggers = [ clamdConfigFile ]; + preStart = '' - mkdir -m 0755 -p ${logDir} mkdir -m 0755 -p ${runDir} - chown ${clamavUser}:${clamavGroup} ${logDir} chown ${clamavUser}:${clamavGroup} ${runDir} ''; + serviceConfig = { - ExecStart = "${pkg}/bin/clamd --config-file=${clamdConfigFile}"; - Type = "forking"; - ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; - Restart = "on-failure"; - RestartSec = "10s"; - StartLimitInterval = "1min"; + ExecStart = "${pkg}/bin/clamd"; + ExecReload = "${pkgs.coreutils}/bin/kill -USR2 $MAINPID"; + PrivateTmp = "yes"; + PrivateDevices = "yes"; + PrivateNetwork = "yes"; }; }; - systemd.services.freshclam = mkIf cfg.updater.enable { - description = "ClamAV updater (freshclam)"; - after = [ "network.target" ]; - wantedBy = [ "multi-user.target" ]; - path = [ pkg ]; + systemd.timers.clamav-freshclam = mkIf cfg.updater.enable { + description = "Timer for ClamAV virus database updater (freshclam)"; + wantedBy = [ "timers.target" ]; + timerConfig = { + OnCalendar = cfg.updater.interval; + Unit = "clamav-freshclam.service"; + }; + }; + + systemd.services.clamav-freshclam = mkIf cfg.updater.enable { + description = "ClamAV virus database updater (freshclam)"; + restartTriggers = [ freshclamConfigFile ]; + preStart = '' mkdir -m 0755 -p ${stateDir} chown ${clamavUser}:${clamavGroup} ${stateDir} ''; + serviceConfig = { - ExecStart = "${pkg}/bin/freshclam --daemon --config-file=${pkgs.writeText "freshclam.conf" cfg.updater.config}"; - ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; - Restart = "on-failure"; - RestartSec = "10s"; - StartLimitInterval = "1min"; + Type = "oneshot"; + ExecStart = "${pkg}/bin/freshclam"; + PrivateTmp = "yes"; + PrivateDevices = "yes"; }; }; }; diff --git a/pkgs/tools/security/clamav/default.nix b/pkgs/tools/security/clamav/default.nix index 7473f056ce97..88df4d78d26b 100644 --- a/pkgs/tools/security/clamav/default.nix +++ b/pkgs/tools/security/clamav/default.nix @@ -10,11 +10,17 @@ stdenv.mkDerivation rec { sha256 = "0yh2q318bnmf2152g2h1yvzgqbswn0wvbzb8p4kf7v057shxcyqn"; }; + # don't install sample config files into the absolute sysconfdir folder + postPatch = '' + substituteInPlace Makefile.in --replace ' etc ' ' ' + ''; + buildInputs = [ zlib bzip2 libxml2 openssl ncurses curl libiconv libmilter pcre ]; configureFlags = [ + "--sysconfdir=/etc/clamav" "--with-zlib=${zlib.dev}" "--with-libbz2-prefix=${bzip2.dev}" "--with-iconv-dir=${libiconv}" @@ -26,6 +32,11 @@ stdenv.mkDerivation rec { "--enable-milter" ]; + postInstall = '' + mkdir $out/etc + cp etc/*.sample $out/etc + ''; + meta = with stdenv.lib; { homepage = http://www.clamav.net; description = "Antivirus engine designed for detecting Trojans, viruses, malware and other malicious threats";