{ config, lib, pkgs, ... }: with lib; let cfg = config.services.openldap; openldap = pkgs.openldap; dataFile = pkgs.writeText "ldap-contents.ldif" cfg.declarativeContents; configFile = pkgs.writeText "slapd.conf" cfg.extraConfig; configOpts = if cfg.configDir == null then "-f ${configFile}" else "-F ${cfg.configDir}"; in { ###### interface options = { services.openldap = { enable = mkOption { type = types.bool; default = false; description = " Whether to enable the ldap server. "; }; user = mkOption { type = types.string; default = "openldap"; description = "User account under which slapd runs."; }; group = mkOption { type = types.string; default = "openldap"; description = "Group account under which slapd runs."; }; urlList = mkOption { type = types.listOf types.string; default = [ "ldap:///" ]; description = "URL list slapd should listen on."; example = [ "ldaps:///" ]; }; dataDir = mkOption { type = types.string; default = "/var/db/openldap"; description = "The database directory."; }; configDir = mkOption { type = types.nullOr types.path; default = null; description = "Use this optional config directory instead of using slapd.conf"; example = "/var/db/slapd.d"; }; extraConfig = mkOption { type = types.lines; default = ""; description = " slapd.conf configuration "; example = literalExample '' ''' include ${pkgs.openldap.out}/etc/schema/core.schema include ${pkgs.openldap.out}/etc/schema/cosine.schema include ${pkgs.openldap.out}/etc/schema/inetorgperson.schema include ${pkgs.openldap.out}/etc/schema/nis.schema database bdb suffix dc=example,dc=org rootdn cn=admin,dc=example,dc=org # NOTE: change after first start rootpw secret directory /var/db/openldap ''' ''; }; declarativeContents = mkOption { type = with types; nullOr lines; default = null; description = '' Declarative contents for the LDAP database, in LDIF format. Note a few facts when using it. First, the database must be stored in the directory defined by dataDir. Second, all dataDir will be erased when starting the LDAP server. Third, modifications to the database are not prevented, they are just dropped on the next reboot of the server. Finally, performance-wise the database and indexes are rebuilt on each server startup, so this will slow down server startup, especially with large databases. ''; example = '' dn: dc=example,dc=org objectClass: domain dc: example dn: ou=users,dc=example,dc=org objectClass = organizationalUnit ou: users # ... ''; }; }; }; ###### implementation config = mkIf cfg.enable { environment.systemPackages = [ openldap ]; systemd.services.openldap = { description = "LDAP server"; wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; preStart = '' mkdir -p /var/run/slapd chown -R "${cfg.user}:${cfg.group}" /var/run/slapd ${optionalString (cfg.declarativeContents != null) '' rm -Rf "${cfg.dataDir}" ''} mkdir -p "${cfg.dataDir}" ${optionalString (cfg.declarativeContents != null) '' ${openldap.out}/bin/slapadd ${configOpts} -l ${dataFile} ''} chown -R "${cfg.user}:${cfg.group}" "${cfg.dataDir}" ''; serviceConfig.ExecStart = "${openldap.out}/libexec/slapd -d 0 " + "-u '${cfg.user}' -g '${cfg.group}' " + "-h '${concatStringsSep " " cfg.urlList}' " + "${configOpts}"; }; users.extraUsers.openldap = { name = cfg.user; group = cfg.group; uid = config.ids.uids.openldap; }; users.extraGroups.openldap = { name = cfg.group; gid = config.ids.gids.openldap; }; }; }