python3Packages.orjson: Disable failing tests on 32 bit
[NixPkgs.git] / nixos / modules / services / logging / awstats.nix
blob708775bfcf03a9953ac860bde98c3aee6f274012
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
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 = lib.mdDoc ''
15           The type of log being collected.
16         '';
17       };
18       domain = mkOption {
19         type = types.str;
20         default = name;
21         description = lib.mdDoc "The domain name to collect stats for.";
22         example = "example.com";
23       };
25       logFile = mkOption {
26         type = types.str;
27         example = "/var/log/nginx/access.log";
28         description = lib.mdDoc ''
29           The log file to be scanned.
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       };
38       logFormat = mkOption {
39         type = types.str;
40         default = "1";
41         description = lib.mdDoc ''
42           The log format being used.
44           For mail, set this to
45           ```
46           %time2 %email %email_r %host %host_r %method %url %code %bytesd
47           ```
48         '';
49       };
51       hostAliases = mkOption {
52         type = types.listOf types.str;
53         default = [];
54         example = [ "www.example.org" ];
55         description = lib.mdDoc ''
56           List of aliases the site has.
57         '';
58       };
60       extraConfig = mkOption {
61         type = types.attrsOf types.str;
62         default = {};
63         example = literalExpression ''
64           {
65             "ValidHTTPCodes" = "404";
66           }
67         '';
68         description = lib.mdDoc "Extra configuration to be appended to awstats.\${name}.conf.";
69       };
71       webService = {
72         enable = mkEnableOption (lib.mdDoc "awstats web service");
74         hostname = mkOption {
75           type = types.str;
76           default = config.domain;
77           description = lib.mdDoc "The hostname the web service appears under.";
78         };
80         urlPrefix = mkOption {
81           type = types.str;
82           default = "/awstats";
83           description = lib.mdDoc "The URL prefix under which the awstats pages appear.";
84         };
85       };
86     };
87   };
88   webServices = filterAttrs (name: value: value.webService.enable) cfg.configs;
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   ];
97   options.services.awstats = {
98     enable = mkEnableOption (lib.mdDoc "awstats");
100     dataDir = mkOption {
101       type = types.path;
102       default = "/var/lib/awstats";
103       description = lib.mdDoc "The directory where awstats data will be stored.";
104     };
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 = lib.mdDoc "Attribute set of domains to collect stats for.";
118     };
120     updateAt = mkOption {
121       type = types.nullOr types.str;
122       default = null;
123       example = "hourly";
124       description = lib.mdDoc ''
125         Specification of the time at which awstats will get updated.
126         (in the format described by {manpage}`systemd.time(7)`)
127       '';
128     };
129   };
132   config = mkIf cfg.enable {
133     environment.systemPackages = [ package.bin ];
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;
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 - -" ];
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;
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   };