at 24.11-pre 8.4 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.awstats; 7 package = pkgs.awstats; 8 configOpts = {name, config, ...}: { 9 options = { 10 type = mkOption{ 11 type = types.enum [ "mail" "web" ]; 12 default = "web"; 13 example = "mail"; 14 description = '' 15 The type of log being collected. 16 ''; 17 }; 18 domain = mkOption { 19 type = types.str; 20 default = name; 21 description = "The domain name to collect stats for."; 22 example = "example.com"; 23 }; 24 25 logFile = mkOption { 26 type = types.str; 27 example = "/var/log/nginx/access.log"; 28 description = '' 29 The log file to be scanned. 30 31 For mail, set this to 32 ``` 33 journalctl $OLD_CURSOR -u postfix.service | ''${pkgs.perl}/bin/perl ''${pkgs.awstats.out}/share/awstats/tools/maillogconvert.pl standard | 34 ``` 35 ''; 36 }; 37 38 logFormat = mkOption { 39 type = types.str; 40 default = "1"; 41 description = '' 42 The log format being used. 43 44 For mail, set this to 45 ``` 46 %time2 %email %email_r %host %host_r %method %url %code %bytesd 47 ``` 48 ''; 49 }; 50 51 hostAliases = mkOption { 52 type = types.listOf types.str; 53 default = []; 54 example = [ "www.example.org" ]; 55 description = '' 56 List of aliases the site has. 57 ''; 58 }; 59 60 extraConfig = mkOption { 61 type = types.attrsOf types.str; 62 default = {}; 63 example = literalExpression '' 64 { 65 "ValidHTTPCodes" = "404"; 66 } 67 ''; 68 description = "Extra configuration to be appended to awstats.\${name}.conf."; 69 }; 70 71 webService = { 72 enable = mkEnableOption "awstats web service"; 73 74 hostname = mkOption { 75 type = types.str; 76 default = config.domain; 77 description = "The hostname the web service appears under."; 78 }; 79 80 urlPrefix = mkOption { 81 type = types.str; 82 default = "/awstats"; 83 description = "The URL prefix under which the awstats pages appear."; 84 }; 85 }; 86 }; 87 }; 88 webServices = filterAttrs (name: value: value.webService.enable) cfg.configs; 89in 90{ 91 imports = [ 92 (mkRemovedOptionModule [ "services" "awstats" "service" "enable" ] "Please enable per domain with `services.awstats.configs.<name>.webService.enable`") 93 (mkRemovedOptionModule [ "services" "awstats" "service" "urlPrefix" ] "Please set per domain with `services.awstats.configs.<name>.webService.urlPrefix`") 94 (mkRenamedOptionModule [ "services" "awstats" "vardir" ] [ "services" "awstats" "dataDir" ]) 95 ]; 96 97 options.services.awstats = { 98 enable = mkEnableOption "awstats, a real-time logfile analyzer"; 99 100 dataDir = mkOption { 101 type = types.path; 102 default = "/var/lib/awstats"; 103 description = "The directory where awstats data will be stored."; 104 }; 105 106 configs = mkOption { 107 type = types.attrsOf (types.submodule configOpts); 108 default = {}; 109 example = literalExpression '' 110 { 111 "mysite" = { 112 domain = "example.com"; 113 logFile = "/var/log/nginx/access.log"; 114 }; 115 } 116 ''; 117 description = "Attribute set of domains to collect stats for."; 118 }; 119 120 updateAt = mkOption { 121 type = types.nullOr types.str; 122 default = null; 123 example = "hourly"; 124 description = '' 125 Specification of the time at which awstats will get updated. 126 (in the format described by {manpage}`systemd.time(7)`) 127 ''; 128 }; 129 }; 130 131 132 config = mkIf cfg.enable { 133 environment.systemPackages = [ package.bin ]; 134 135 environment.etc = mapAttrs' (name: opts: 136 nameValuePair "awstats/awstats.${name}.conf" { 137 source = pkgs.runCommand "awstats.${name}.conf" 138 { preferLocalBuild = true; } 139 ('' 140 sed \ 141 '' 142 # set up mail stats 143 + optionalString (opts.type == "mail") 144 '' 145 -e 's|^\(LogType\)=.*$|\1=M|' \ 146 -e 's|^\(LevelForBrowsersDetection\)=.*$|\1=0|' \ 147 -e 's|^\(LevelForOSDetection\)=.*$|\1=0|' \ 148 -e 's|^\(LevelForRefererAnalyze\)=.*$|\1=0|' \ 149 -e 's|^\(LevelForRobotsDetection\)=.*$|\1=0|' \ 150 -e 's|^\(LevelForSearchEnginesDetection\)=.*$|\1=0|' \ 151 -e 's|^\(LevelForFileTypesDetection\)=.*$|\1=0|' \ 152 -e 's|^\(LevelForWormsDetection\)=.*$|\1=0|' \ 153 -e 's|^\(ShowMenu\)=.*$|\1=1|' \ 154 -e 's|^\(ShowSummary\)=.*$|\1=HB|' \ 155 -e 's|^\(ShowMonthStats\)=.*$|\1=HB|' \ 156 -e 's|^\(ShowDaysOfMonthStats\)=.*$|\1=HB|' \ 157 -e 's|^\(ShowDaysOfWeekStats\)=.*$|\1=HB|' \ 158 -e 's|^\(ShowHoursStats\)=.*$|\1=HB|' \ 159 -e 's|^\(ShowDomainsStats\)=.*$|\1=0|' \ 160 -e 's|^\(ShowHostsStats\)=.*$|\1=HB|' \ 161 -e 's|^\(ShowAuthenticatedUsers\)=.*$|\1=0|' \ 162 -e 's|^\(ShowRobotsStats\)=.*$|\1=0|' \ 163 -e 's|^\(ShowEMailSenders\)=.*$|\1=HBML|' \ 164 -e 's|^\(ShowEMailReceivers\)=.*$|\1=HBML|' \ 165 -e 's|^\(ShowSessionsStats\)=.*$|\1=0|' \ 166 -e 's|^\(ShowPagesStats\)=.*$|\1=0|' \ 167 -e 's|^\(ShowFileTypesStats\)=.*$|\1=0|' \ 168 -e 's|^\(ShowFileSizesStats\)=.*$|\1=0|' \ 169 -e 's|^\(ShowBrowsersStats\)=.*$|\1=0|' \ 170 -e 's|^\(ShowOSStats\)=.*$|\1=0|' \ 171 -e 's|^\(ShowOriginStats\)=.*$|\1=0|' \ 172 -e 's|^\(ShowKeyphrasesStats\)=.*$|\1=0|' \ 173 -e 's|^\(ShowKeywordsStats\)=.*$|\1=0|' \ 174 -e 's|^\(ShowMiscStats\)=.*$|\1=0|' \ 175 -e 's|^\(ShowHTTPErrorsStats\)=.*$|\1=0|' \ 176 -e 's|^\(ShowSMTPErrorsStats\)=.*$|\1=1|' \ 177 '' 178 + 179 # common options 180 '' 181 -e 's|^\(DirData\)=.*$|\1="${cfg.dataDir}/${name}"|' \ 182 -e 's|^\(DirIcons\)=.*$|\1="icons"|' \ 183 -e 's|^\(CreateDirDataIfNotExists\)=.*$|\1=1|' \ 184 -e 's|^\(SiteDomain\)=.*$|\1="${name}"|' \ 185 -e 's|^\(LogFile\)=.*$|\1="${opts.logFile}"|' \ 186 -e 's|^\(LogFormat\)=.*$|\1="${opts.logFormat}"|' \ 187 '' 188 + 189 # extra config 190 concatStringsSep "\n" (mapAttrsToList (n: v: '' 191 -e 's|^\(${n}\)=.*$|\1="${v}"|' \ 192 '') opts.extraConfig) 193 + 194 '' 195 < '${package.out}/wwwroot/cgi-bin/awstats.model.conf' > "$out" 196 ''); 197 }) cfg.configs; 198 199 # create data directory with the correct permissions 200 systemd.tmpfiles.rules = 201 [ "d '${cfg.dataDir}' 755 root root - -" ] ++ 202 mapAttrsToList (name: opts: "d '${cfg.dataDir}/${name}' 755 root root - -") cfg.configs ++ 203 [ "Z '${cfg.dataDir}' 755 root root - -" ]; 204 205 # nginx options 206 services.nginx.virtualHosts = mapAttrs'(name: opts: { 207 name = opts.webService.hostname; 208 value = { 209 locations = { 210 "${opts.webService.urlPrefix}/css/" = { 211 alias = "${package.out}/wwwroot/css/"; 212 }; 213 "${opts.webService.urlPrefix}/icons/" = { 214 alias = "${package.out}/wwwroot/icon/"; 215 }; 216 "${opts.webService.urlPrefix}/" = { 217 alias = "${cfg.dataDir}/${name}/"; 218 extraConfig = '' 219 autoindex on; 220 ''; 221 }; 222 }; 223 }; 224 }) webServices; 225 226 # update awstats 227 systemd.services = mkIf (cfg.updateAt != null) (mapAttrs' (name: opts: 228 nameValuePair "awstats-${name}-update" { 229 description = "update awstats for ${name}"; 230 script = optionalString (opts.type == "mail") 231 '' 232 if [[ -f "${cfg.dataDir}/${name}-cursor" ]]; then 233 CURSOR="$(cat "${cfg.dataDir}/${name}-cursor" | tr -d '\n')" 234 if [[ -n "$CURSOR" ]]; then 235 echo "Using cursor: $CURSOR" 236 export OLD_CURSOR="--cursor $CURSOR" 237 fi 238 fi 239 NEW_CURSOR="$(journalctl $OLD_CURSOR -u postfix.service --show-cursor | tail -n 1 | tr -d '\n' | sed -e 's#^-- cursor: \(.*\)#\1#')" 240 echo "New cursor: $NEW_CURSOR" 241 ${package.bin}/bin/awstats -update -config=${name} 242 if [ -n "$NEW_CURSOR" ]; then 243 echo -n "$NEW_CURSOR" > ${cfg.dataDir}/${name}-cursor 244 fi 245 '' + '' 246 ${package.out}/share/awstats/tools/awstats_buildstaticpages.pl \ 247 -config=${name} -update -dir=${cfg.dataDir}/${name} \ 248 -awstatsprog=${package.bin}/bin/awstats 249 ''; 250 startAt = cfg.updateAt; 251 }) cfg.configs); 252 }; 253 254} 255