{ config, lib, ... }: let hostNames = lib.attrNames config.services.nginx.virtualHosts; logPath = name: "/var/log/nginx/${name}/access.log"; logFormat = lib.concatStringsSep " " [ "$remote_addr - $remote_user [$time_local]" ''"$request" $status $body_bytes_sent'' ''"$http_referer" "$http_user_agent"'' ''rt=$request_time uct="$upstream_connect_time"'' ''uht="$upstream_header_time" urt="$upstream_response_time"'' ]; in { # Extend the default configuration for nginx virtual hosts; we'd # like to create log files for each of them, so that the prometheus # nginxlog exporter can process per-host logs. options.services.nginx.virtualHosts = lib.mkOption { type = lib.types.attrsOf ( lib.types.submodule ( { name, ... }: { config.extraConfig = '' access_log ${logPath name} upstream_time; ''; } ) ); }; config = { # Create directories for host-specific logs with systemd tmpfiles systemd.tmpfiles.settings."10-nginx-logs" = lib.listToAttrs ( map ( name: lib.nameValuePair "/var/log/nginx/${name}" { d = { inherit (config.services.nginx) user group; mode = "0750"; }; } ) hostNames ); services = { # Set the nginx-wide log format nginx.commonHttpConfig = '' log_format upstream_time '${logFormat}'; ''; # Set up nginxlog to read the file and log format defined above # for each virtual host prometheus.exporters.nginxlog = { enable = true; listenAddress = "127.0.0.1"; group = "nginx"; settings.namespaces = map (name: { inherit name; metrics_override.prefix = "nginxlog"; namespace_label = "vhost"; format = logFormat; source.files = [ (logPath name) ]; }) hostNames; }; logrotate.settings = { # Override the nginx module default, just keep fewer logs nginx.rotate = 6; # Configure logrotate for host-specific logs nginxVirtualHosts = { files = map logPath hostNames; frequency = "daily"; rotate = 2; compress = true; delaycompress = true; su = "${config.services.nginx.user} ${config.services.nginx.group}"; postrotate = "[ ! -f /var/run/nginx/nginx.pid ] || kill -USR1 `cat /var/run/nginx/nginx.pid`"; }; }; }; }; }