1{ config, lib, pkgs, ... }: 2with lib; 3let 4 clamavUser = "clamav"; 5 stateDir = "/var/lib/clamav"; 6 runDir = "/var/run/clamav"; 7 logDir = "/var/log/clamav"; 8 clamavGroup = clamavUser; 9 cfg = config.services.clamav; 10 clamdConfigFile = pkgs.writeText "clamd.conf" '' 11 DatabaseDirectory ${stateDir} 12 LocalSocket ${runDir}/clamd.ctl 13 LogFile ${logDir}/clamav.log 14 PidFile ${runDir}/clamd.pid 15 User clamav 16 17 ${cfg.daemon.extraConfig} 18 ''; 19in 20{ 21 options = { 22 services.clamav = { 23 daemon = { 24 enable = mkEnableOption "clamd daemon"; 25 26 extraConfig = mkOption { 27 type = types.lines; 28 default = ""; 29 description = '' 30 Extra configuration for clamd. Contents will be added verbatim to the 31 configuration file. 32 ''; 33 }; 34 }; 35 updater = { 36 enable = mkEnableOption "freshclam updater"; 37 38 frequency = mkOption { 39 default = 12; 40 description = '' 41 Number of database checks per day. 42 ''; 43 }; 44 45 config = mkOption { 46 default = ""; 47 description = '' 48 Extra configuration for freshclam. Contents will be added verbatim to the 49 configuration file. 50 ''; 51 }; 52 }; 53 }; 54 }; 55 56 config = mkIf cfg.updater.enable or cfg.daemon.enable { 57 environment.systemPackages = [ pkgs.clamav ]; 58 users.extraUsers = singleton { 59 name = clamavUser; 60 uid = config.ids.uids.clamav; 61 description = "ClamAV daemon user"; 62 home = stateDir; 63 }; 64 65 users.extraGroups = singleton { 66 name = clamavGroup; 67 gid = config.ids.gids.clamav; 68 }; 69 70 services.clamav.updater.config = mkIf cfg.updater.enable '' 71 DatabaseDirectory ${stateDir} 72 Foreground yes 73 Checks ${toString cfg.updater.frequency} 74 DatabaseMirror database.clamav.net 75 ''; 76 77 systemd.services.clamd = mkIf cfg.daemon.enable { 78 description = "ClamAV daemon (clamd)"; 79 path = [ pkgs.clamav ]; 80 after = [ "network.target" "freshclam.service" ]; 81 requires = [ "freshclam.service" ]; 82 wantedBy = [ "multi-user.target" ]; 83 preStart = '' 84 mkdir -m 0755 -p ${logDir} 85 mkdir -m 0755 -p ${runDir} 86 chown ${clamavUser}:${clamavGroup} ${logDir} 87 chown ${clamavUser}:${clamavGroup} ${runDir} 88 ''; 89 serviceConfig = { 90 ExecStart = "${pkgs.clamav}/bin/clamd --config-file=${clamdConfigFile}"; 91 Type = "forking"; 92 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 93 Restart = "on-failure"; 94 RestartSec = "10s"; 95 StartLimitInterval = "1min"; 96 }; 97 }; 98 99 systemd.services.freshclam = mkIf cfg.updater.enable { 100 description = "ClamAV updater (freshclam)"; 101 after = [ "network.target" ]; 102 wantedBy = [ "multi-user.target" ]; 103 path = [ pkgs.clamav ]; 104 preStart = '' 105 mkdir -m 0755 -p ${stateDir} 106 chown ${clamavUser}:${clamavGroup} ${stateDir} 107 ''; 108 serviceConfig = { 109 ExecStart = "${pkgs.clamav}/bin/freshclam --daemon --config-file=${pkgs.writeText "freshclam.conf" cfg.updater.config}"; 110 ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID"; 111 Restart = "on-failure"; 112 RestartSec = "10s"; 113 StartLimitInterval = "1min"; 114 }; 115 }; 116 }; 117}