{
  config,
  lib,
  pkgs,
  ...
}:
let

  cfg = config.services.manticore;
  format = pkgs.formats.json { };

  toSphinx =
    {
      mkKeyValue ? lib.generators.mkKeyValueDefault { } "=",
      listsAsDuplicateKeys ? true,
    }:
    attrsOfAttrs:
    let
      # map function to string for each key val
      mapAttrsToStringsSep =
        sep: mapFn: attrs:
        lib.concatStringsSep sep (lib.mapAttrsToList mapFn attrs);
      mkSection =
        sectName: sectValues:
        ''
          ${sectName} {
        ''
        + lib.generators.toKeyValue { inherit mkKeyValue listsAsDuplicateKeys; } sectValues
        + ''}'';
    in
    # map input to ini sections
    mapAttrsToStringsSep "\n" mkSection attrsOfAttrs;

  configFile = pkgs.writeText "manticore.conf" (
    toSphinx {
      mkKeyValue = k: v: "  ${k} = ${v}";
    } cfg.settings
  );

in
{

  options = {
    services.manticore = {

      enable = lib.mkEnableOption "Manticoresearch";

      settings = lib.mkOption {
        default = {
          searchd = {
            listen = [
              "127.0.0.1:9312"
              "127.0.0.1:9306:mysql"
              "127.0.0.1:9308:http"
            ];
            log = "/var/log/manticore/searchd.log";
            query_log = "/var/log/manticore/query.log";
            pid_file = "/run/manticore/searchd.pid";
            data_dir = "/var/lib/manticore";
          };
        };
        description = ''
          Configuration for Manticoresearch. See
          <https://manual.manticoresearch.com/Server%20settings>
          for more information.
        '';
        type = lib.types.submodule {
          freeformType = format.type;
        };
        example = lib.literalExpression ''
          {
            searchd = {
                listen = [
                  "127.0.0.1:9312"
                  "127.0.0.1:9306:mysql"
                  "127.0.0.1:9308:http"
                ];
                log = "/var/log/manticore/searchd.log";
                query_log = "/var/log/manticore/query.log";
                pid_file = "/run/manticore/searchd.pid";
                data_dir = "/var/lib/manticore";
            };
          }
        '';
      };

    };
  };

  config = lib.mkIf cfg.enable {

    systemd = {
      packages = [ pkgs.manticoresearch ];
      services.manticore = {
        wantedBy = [ "multi-user.target" ];
        after = [ "network.target" ];
        serviceConfig = {
          ExecStart = [
            ""
            "${pkgs.manticoresearch}/bin/searchd --config ${configFile}"
          ];
          ExecStop = [
            ""
            "${pkgs.manticoresearch}/bin/searchd --config ${configFile} --stopwait"
          ];
          ExecStartPre = [ "" ];
          DynamicUser = true;
          LogsDirectory = "manticore";
          RuntimeDirectory = "manticore";
          StateDirectory = "manticore";
          ReadWritePaths = "";
          CapabilityBoundingSet = "";
          RestrictAddressFamilies = [
            "AF_UNIX"
            "AF_INET"
            "AF_INET6"
          ];
          RestrictNamespaces = true;
          PrivateDevices = true;
          PrivateUsers = true;
          ProtectClock = true;
          ProtectControlGroups = true;
          ProtectHome = true;
          ProtectKernelLogs = true;
          ProtectKernelModules = true;
          ProtectKernelTunables = true;
          SystemCallArchitectures = "native";
          SystemCallFilter = [
            "@system-service"
            "~@privileged"
          ];
          RestrictRealtime = true;
          LockPersonality = true;
          MemoryDenyWriteExecute = true;
          UMask = "0066";
          ProtectHostname = true;
        }
        // lib.optionalAttrs (cfg.settings.searchd.pid_file != null) {
          PIDFile = cfg.settings.searchd.pid_file;
        };
      };
    };

  };

  meta.maintainers = with lib.maintainers; [ onny ];

}
