1 { pkgs, lib, config, ... }:
3 inherit (builtins) hasAttr;
4 inherit (builtins.extraBuiltins) pass-chomp;
5 inherit (config) networking;
6 inherit (config.services) openldap;
7 inherit (config.users) users groups;
8 inherit (pkgs.lib) unlines;
9 domainSuffix = openldap.domainSuffix;
13 , gidNumber ? uidNumber
16 , userPassword ? null # NOTE: doveadm pw -s SSHA -u $user -p $pass
19 , mailStorageDirectory ? null
20 , loginShell ? "/run/current-system/sw/bin/bash"
22 , mailForwardingAddress ? []
23 , domain ? networking.domain
24 }: "\n" + lib.concatStringsSep "\n\n" [
26 dn: uid=${uid},ou=accounts,ou=posix,${domainSuffix}
28 objectClass: posixAccount
29 objectClass: shadowAccount
30 objectClass: PostfixBookMailAccount
31 objectClass: PostfixBookMailForward
34 mail: ${uid}${lib.optionalString (networking.domain != "") "@${networking.domain}"}
35 mailEnabled: ${if mailEnabled then "TRUE" else "FALSE"}
36 #mailGroupMember: ${networking.domainBase}'']
37 ++ [ "uidNumber: ${toString uidNumber}" ]
38 ++ [ "gidNumber: ${toString gidNumber}" ]
39 ++ [ "homeDirectory: ${homeDirectory}" ]
40 ++ lib.optional (loginShell != null) "loginShell: ${loginShell}"
41 ++ lib.optional (userPassword != null) "userPassword: ${userPassword}"
42 ++ lib.optional (mailStorageDirectory != null) "mailStorageDirectory: ${mailStorageDirectory}"
43 ++ map (forward: "mailForwardingAddress: ${forward}") mailForwardingAddress
44 ++ map (alias: "mailAlias: ${alias}@${networking.domain}") mailAlias
45 ++ lib.optional (mailAlias == []) "mailAlias:"
46 # NOTE: required by PostfixBookMailForward
49 dn: cn=${uid},ou=groups,ou=posix,${domainSuffix}
51 objectClass: posixGroup
52 gidNumber: ${toString gidNumber}
58 config = lib.mkIf config.users.ldap.enable {
61 # echo "$(nixops show-option mermet -d production services.openldap.databases."dc=sourcephile,dc=fr".data)"
65 # WARNING: this deletes data.
70 # sudo ldapsearch -LLL -H ldapi:// -D cn=admin,cn=config -Y EXTERNAL -b 'olcDatabase={1}mdb,cn=config' -s sub
71 dn: olcBackend={1}mdb,cn=config
72 objectClass: olcBackendConfig
74 dn: olcDatabase={1}mdb,cn=config
75 objectClass: olcDatabaseConfig
76 objectClass: olcMdbConfig
77 # NOTE: checkpoint the database periodically in case of system failure
78 # and to speed slapd shutdown.
79 olcDbCheckpoint: 512 30
80 # Database max size is 1G
81 olcDbMaxSize: 1073741824
83 # NOTE: database superuser. Needed for syncrepl.
84 olcRootDN: cn=admin,${domainSuffix}
85 # NOTE: superuser password, generated with slappasswd -h "{SSHA}" -s "$password"
86 #olcRootPW: {SSHA}COkATGNe7rs/g8vWcYP5rqt4u5sWdMgP
88 olcDbIndex: objectClass eq
90 olcDbIndex: uidNumber,gidNumber eq
91 olcDbIndex: member,memberUid eq
93 olcDbIndex: mailAlias eq
94 olcDbIndex: mailEnabled eq
96 olcAccess: to attrs=userPassword
99 by dn="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write
101 olcAccess: to attrs=shadowLastChange
103 by dn="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" write
105 olcAccess: to dn.sub="ou=posix,${domainSuffix}"
107 by dn="gidNumber=${toString groups.nslcd.gid}+uidNumber=${toString users.nslcd.uid},cn=peercred,cn=external,cn=auth" read
108 ${lib.optionalString (hasAttr "postfix" users) ''by dn="gidNumber=${toString groups.postfix.gid}+uidNumber=${toString users.postfix.uid},cn=peercred,cn=external,cn=auth" read''}
109 by dn="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" read
110 # NOTE: dovecot/auth runs as root, hence the gidNumber=0+uidNumber=0
118 objectClass: dcObject
119 objectClass: organization
120 o: ${networking.domainBase}
122 dn: cn=admin,${domainSuffix}
123 objectClass: simpleSecurityObject
124 objectClass: organizationalRole
125 description: ${networking.domainBase} LDAP administrator
126 roleOccupant: ${domainSuffix}
128 #userPassword: {SSHA}NONVwwKnKsCBmFxkMqTCFekdu3SJQHc9
130 dn: ou=posix,${domainSuffix}
132 objectClass: organizationalUnit
134 dn: ou=accounts,ou=posix,${domainSuffix}
136 objectClass: organizationalUnit
138 dn: ou=groups,ou=posix,${domainSuffix}
140 objectClass: organizationalUnit
142 dn: cn=${networking.domainBase},ou=groups,ou=posix,${domainSuffix}
144 objectClass: posixGroup
150 + lib.concatMapStrings posixAccount [
152 uidNumber=users.julm.uid;
153 gidNumber=groups.julm.gid;
154 cn="Julien Moutinho"; sn="julm";
155 mailAlias = ["julien.moutinho"];
156 userPassword = pass-chomp "members/julm/mail/hashedPassword";
157 mailStorageDirectory = "maildir:/home/julm/Maildir/sourcephile.fr:UTF-8:LAYOUT=maildir++";
159 #{ uid="sevy"; uidNumber=10001; cn="Séverine Popek"; sn="sévy";
160 # mailAlias = ["severine.popek" "ouais-ouais"]; }
161 #{ uid="nomail"; uidNumber=10002; mailAlias = ["noalias"]; mailEnabled = false; }
162 #{ uid="post"; domain="friot"; mailForwardingAddress = ["ju@${networking.domain}"]; }
163 #{ uid="host"; mailForwardingAddress = ["ju@${networking.domain}"]; }