at 23.11-pre 4.7 kB view raw
1{ config, lib, pkgs, ... }: 2with lib; 3let 4 clamavUser = "clamav"; 5 stateDir = "/var/lib/clamav"; 6 runDir = "/run/clamav"; 7 clamavGroup = clamavUser; 8 cfg = config.services.clamav; 9 pkg = pkgs.clamav; 10 11 toKeyValue = generators.toKeyValue { 12 mkKeyValue = generators.mkKeyValueDefault { } " "; 13 listsAsDuplicateKeys = true; 14 }; 15 16 clamdConfigFile = pkgs.writeText "clamd.conf" (toKeyValue cfg.daemon.settings); 17 freshclamConfigFile = pkgs.writeText "freshclam.conf" (toKeyValue cfg.updater.settings); 18in 19{ 20 imports = [ 21 (mkRemovedOptionModule [ "services" "clamav" "updater" "config" ] "Use services.clamav.updater.settings instead.") 22 (mkRemovedOptionModule [ "services" "clamav" "updater" "extraConfig" ] "Use services.clamav.updater.settings instead.") 23 (mkRemovedOptionModule [ "services" "clamav" "daemon" "extraConfig" ] "Use services.clamav.daemon.settings instead.") 24 ]; 25 26 options = { 27 services.clamav = { 28 daemon = { 29 enable = mkEnableOption (lib.mdDoc "ClamAV clamd daemon"); 30 31 settings = mkOption { 32 type = with types; attrsOf (oneOf [ bool int str (listOf str) ]); 33 default = { }; 34 description = lib.mdDoc '' 35 ClamAV configuration. Refer to <https://linux.die.net/man/5/clamd.conf>, 36 for details on supported values. 37 ''; 38 }; 39 }; 40 updater = { 41 enable = mkEnableOption (lib.mdDoc "ClamAV freshclam updater"); 42 43 frequency = mkOption { 44 type = types.int; 45 default = 12; 46 description = lib.mdDoc '' 47 Number of database checks per day. 48 ''; 49 }; 50 51 interval = mkOption { 52 type = types.str; 53 default = "hourly"; 54 description = lib.mdDoc '' 55 How often freshclam is invoked. See systemd.time(7) for more 56 information about the format. 57 ''; 58 }; 59 60 settings = mkOption { 61 type = with types; attrsOf (oneOf [ bool int str (listOf str) ]); 62 default = { }; 63 description = lib.mdDoc '' 64 freshclam configuration. Refer to <https://linux.die.net/man/5/freshclam.conf>, 65 for details on supported values. 66 ''; 67 }; 68 }; 69 }; 70 }; 71 72 config = mkIf (cfg.updater.enable || cfg.daemon.enable) { 73 environment.systemPackages = [ pkg ]; 74 75 users.users.${clamavUser} = { 76 uid = config.ids.uids.clamav; 77 group = clamavGroup; 78 description = "ClamAV daemon user"; 79 home = stateDir; 80 }; 81 82 users.groups.${clamavGroup} = 83 { gid = config.ids.gids.clamav; }; 84 85 services.clamav.daemon.settings = { 86 DatabaseDirectory = stateDir; 87 LocalSocket = "${runDir}/clamd.ctl"; 88 PidFile = "${runDir}/clamd.pid"; 89 TemporaryDirectory = "/tmp"; 90 User = "clamav"; 91 Foreground = true; 92 }; 93 94 services.clamav.updater.settings = { 95 DatabaseDirectory = stateDir; 96 Foreground = true; 97 Checks = cfg.updater.frequency; 98 DatabaseMirror = [ "database.clamav.net" ]; 99 }; 100 101 environment.etc."clamav/freshclam.conf".source = freshclamConfigFile; 102 environment.etc."clamav/clamd.conf".source = clamdConfigFile; 103 104 systemd.services.clamav-daemon = mkIf cfg.daemon.enable { 105 description = "ClamAV daemon (clamd)"; 106 after = optional cfg.updater.enable "clamav-freshclam.service"; 107 wantedBy = [ "multi-user.target" ]; 108 restartTriggers = [ clamdConfigFile ]; 109 110 preStart = '' 111 mkdir -m 0755 -p ${runDir} 112 chown ${clamavUser}:${clamavGroup} ${runDir} 113 ''; 114 115 serviceConfig = { 116 ExecStart = "${pkg}/bin/clamd"; 117 ExecReload = "${pkgs.coreutils}/bin/kill -USR2 $MAINPID"; 118 PrivateTmp = "yes"; 119 PrivateDevices = "yes"; 120 PrivateNetwork = "yes"; 121 }; 122 }; 123 124 systemd.timers.clamav-freshclam = mkIf cfg.updater.enable { 125 description = "Timer for ClamAV virus database updater (freshclam)"; 126 wantedBy = [ "timers.target" ]; 127 timerConfig = { 128 OnCalendar = cfg.updater.interval; 129 Unit = "clamav-freshclam.service"; 130 }; 131 }; 132 133 systemd.services.clamav-freshclam = mkIf cfg.updater.enable { 134 description = "ClamAV virus database updater (freshclam)"; 135 restartTriggers = [ freshclamConfigFile ]; 136 after = [ "network-online.target" ]; 137 preStart = '' 138 mkdir -m 0755 -p ${stateDir} 139 chown ${clamavUser}:${clamavGroup} ${stateDir} 140 ''; 141 142 serviceConfig = { 143 Type = "oneshot"; 144 ExecStart = "${pkg}/bin/freshclam"; 145 SuccessExitStatus = "1"; # if databases are up to date 146 PrivateTmp = "yes"; 147 PrivateDevices = "yes"; 148 }; 149 }; 150 }; 151}