{ pkgs, lib, config, ... }:
let
  inherit (builtins) baseNameOf readFile;
  inherit (lib) types;
  inherit (pkgs.lib) unlinesAttrs;
  inherit (config) networking;
  inherit (config.services) openldap;
  inherit (config.users) ldap;
  domainSuffix = "dc=" + lib.concatStringsSep ",dc=" (lib.splitString "." networking.domain);
in
{
imports = [
  openldap/sourcephile.fr.nix
  openldap/autogeree.net.nix
];
config = {
users.ldap = {
  enable = false;
  server = "ldapi:///";
  base = "ou=posix,${domainSuffix}";
  bind = {
    #distinguishedName = "cn=admin,${domainSuffix}";
  };
  daemon = {
    enable = false;
    extraConfig = ''
      log syslog info

      sasl_mech EXTERNAL
      # NOTE: nslcd cannot use SASL to bind to rootpwmoddn
      # which is the DN used by nslcd when passwd is run by root
      # to change the userPassword of an LDAP user.
      # SEE: https://www.reddit.com/r/linuxadmin/comments/53sxpl/how_do_i_configure_nslcd_to_use_a_sasl_external/d7w9awd/
      # Thus, use: ldappasswd -H ldapi:// -Y EXTERNAL uid=$user,ou=accounts,ou=posix,dc=sourcephile,dc=fr
    '';
  };
};
services.openldap = {
  enable    = true;
  dataDir   = "/var/db/ldap";
  configDir = "/var/db/slapd";
  urlList   = [ "ldapi:///" ]; # UNIX socket
  # sudo ldapsearch -LLL -H ldapi:// -D cn=admin,cn=config -Y EXTERNAL -b "" -s base supportedControl
  cnConfig = ''
    dn: cn=config
    objectClass: olcGlobal
    olcLogLevel: none
    # The tool-threads parameter sets the actual amount of CPU's
    # that is used for indexing.
    olcToolThreads: ${toString config.nix.maxJobs}

    dn: cn={0}module,cn=config
    objectClass: olcModuleList
    olcModulePath: ${pkgs.openldap}/lib/modules
    #olcModuleLoad: pw-sha2
    #olcModuleLoad: pw-pbkdf2
    olcModuleLoad: back_mdb

    # The first database is the special frontend database
    # whose settings are applied globally to all the other databases.
    # Beware that cn={0}module,cn=config must appear before
    # for enabling password schemes provided by the modules in olcPasswordHash.
    # ldapsearch -LLL -H ldapi:// -D cn=admin,cn=config -Y EXTERNAL -b 'olcDatabase={-1}frontend,cn=config' -s sub '*'
    dn: olcDatabase={-1}frontend,cn=config
    objectClass: olcDatabaseConfig
    objectClass: olcFrontendConfig
    # The maximum number of entries that is returned for a search operation
    olcSizeLimit: 500
    # Allow unlimited access to local connection from the local root user
    olcAccess: to *
      by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
      by * break
    # Allow unauthenticated read access for schema and base DN autodiscovery
    olcAccess: to dn.exact=""
      by * read
    olcAccess: to dn.base="cn=Subschema"
      by * read
    # Hash algorithm to be used by LDAP Password Modify Extended Operation or the ppolicy overlay
    #olcPasswordHash: {PBKDF2-SHA256}
    olcPasswordHash: {SSHA}

    dn: olcDatabase={0}config,cn=config
    objectClass: olcDatabaseConfig
    olcRootDN: cn=admin,cn=config
    # Access to cn=config, system root can be manager
    # with SASL mechanism (-Y EXTERNAL) over unix socket (-H ldapi://)
    olcAccess: to *
      by dn.exact="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage
      by * break

    dn: cn=schema,cn=config
    objectClass: olcSchemaConfig

    dn: olcBackend=mdb,cn=config
    objectClass: olcBackendConfig

    include: file://${pkgs.openldap}/etc/schema/core.ldif
    include: file://${pkgs.openldap}/etc/schema/cosine.ldif
    include: file://${pkgs.openldap}/etc/schema/nis.ldif
    include: file://${pkgs.openldap}/etc/schema/inetorgperson.ldif
    include: file://${openldap/schema/postfix-book.ldif}
  '';
};
};
}