{
  flake-inputs,
  pkgs,
  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`";
        };
      };
    };

    serviceTests =
      let
        testHostConfig =
          { config, ... }:
          {
            imports = [
              ./.
              ../../modules/serviceTests/mocks.nix
            ];

            networking.firewall.allowedTCPPorts = [ 80 ];

            services.nginx = {
              domain = "testHost";
              virtualHosts."${config.services.nginx.domain}".locations."/".return = "200 ok";
            };
          };
      in
      {
        nginxMetricsWork = pkgs.testers.runNixOSTest {
          name = "nginx-metrics-work";
          node.specialArgs = { inherit flake-inputs; };

          nodes = {
            testHost = testHostConfig;

            client =
              { pkgs, ... }:
              {
                environment.systemPackages = [ pkgs.curl ];
              };
          };

          testScript = ''
            import time

            start_all()

            testHost.wait_for_unit("nginx.service")
            client.succeed("curl --max-time 10 http://testHost")

            # Wait a bit for the prometheus exporter to scrape our logs
            time.sleep(5)

            res = testHost.succeed("curl localhost:${builtins.toString config.services.prometheus.exporters.nginxlog.port}/metrics")
            assert 'nginxlog_http_response_count_total{method="GET",status="200",vhost="testHost"} 1' in res, res
          '';
        };
      };
  };
}
