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