@ -1,150 +1,12 @@
{ pkgs , config , . . . }:
{ config , pkgs , . . . }:
with pkgs . lib ;
with pkgs ;
###### interface
let
inherit mkOption mkIf optionalString stringAfter singleton ;
cfg = config . users . ldap ;
options = {
users = {
ldap = {
enable = mkOption {
default = false ;
description = "
Whether to enable authentication against an LDAP server .
" ;
} ;
server = mkOption {
example = " l d a p : / / l d a p . e x a m p l e . o r g / " ;
description = "
The URL of the LDAP server .
" ;
} ;
base = mkOption {
example = " d c = e x a m p l e , d c = o r g " ;
description = "
The distinguished name of the search base .
" ;
} ;
useTLS = mkOption {
default = false ;
description = "
If enabled , use TLS ( encryption ) over an LDAP ( port 389 )
connection . The alternative is to specify an LDAPS server ( port
636 ) in <option> users . ldap . server < /option > or to forego
security .
" ;
} ;
timeLimit = mkOption {
default = 0 ;
type = types . int ;
description = "
Specifies the time limit ( in seconds ) to use when performing
searches . A value of zero ( 0 ) , which is the default , is to
wait indefinitely for searches to be completed .
" ;
} ;
daemon = {
enable = mkOption {
default = false ;
description = ''
Whether to let the nslcd daemon ( nss-pam-ldapd ) handle the
LDAP lookups for NSS and PAM . This can improve performance ,
and if you need to bind to the LDAP server with a password ,
it increases security , since only the nslcd user needs to
have access to the bindpw file , not everyone that uses NSS
and/or PAM . If this option is enabled , a local nscd user is
created automatically , and the nslcd service is started
automatically when the network get up .
'' ;
} ;
extraConfig = mkOption {
default = " " ;
type = types . string ;
description = ''
Extra configuration options that will be added verbatim at
the end of the nslcd configuration file ( nslcd . conf ) .
'' ;
} ;
} ;
bind = {
distinguishedName = mkOption {
default = " " ;
example = " c n = a d m i n , d c = e x a m p l e , d c = c o m " ;
type = types . string ;
description = "
The distinguished name to bind to the LDAP server with . If this
is not specified , an anonymous bind will be done .
" ;
} ;
password = mkOption {
default = " / e t c / l d a p / b i n d . p a s s w o r d " ;
type = types . string ;
description = "
The path to a file containing the credentials to use when binding
to the LDAP server ( if not binding anonymously ) .
" ;
} ;
timeLimit = mkOption {
default = 30 ;
type = types . int ;
description = "
Specifies the time limit ( in seconds ) to use when connecting
to the directory server . This is distinct from the time limit
specified in <literal> users . ldap . timeLimit < /literal > and affects
the initial server connection only .
" ;
} ;
policy = mkOption {
default = " h a r d _ o p e n " ;
type = types . string ;
description = "
Specifies the policy to use for reconnecting to an unavailable
LDAP server . The default is <literal> hard_open < /literal > , which
reconnects if opening the connection to the directory server
failed . By contrast , <literal> hard_init < /literal > reconnects if
initializing the connection failed . Initializing may not
actually contact the directory server , and it is possible that
a malformed configuration file will trigger reconnection . If
<literal> soft < /literal > is specified , then
<literal> nss_ldap < /literal > will return immediately on server
failure . All hard reconnect policies block with exponential
backoff before retrying .
" ;
} ;
} ;
extraConfig = mkOption {
default = " " ;
type = types . string ;
description = ''
Extra configuration options that will be added verbatim at
the end of the ldap configuration file ( ldap . conf ) .
If <literal> users . ldap . daemon < /literal > is enabled , this
configuration will not be used . In that case , use
<literal> users . ldap . daemon . extraConfig < /literal > instead .
'' ;
} ;
} ;
} ;
} ;
# Careful: OpenLDAP seems to be very picky about the indentation of
# this file. Directives HAVE to start in the first column!
ldapConfig = {
@ -186,63 +48,199 @@ let
in
###### implementation
mkIf cfg . enable {
require = [
options
] ;
environment . etc = if cfg . daemon . enable then [ nslcdConfig ] else [ ldapConfig ] ;
system . activationScripts = mkIf insertLdapPassword {
ldap = stringAfter [ " e t c " " g r o u p s " " u s e r s " ] ''
if test - f " ${ cfg . bind . password } " ; then
echo " b i n d p w " $ ( cat $ { cfg . bind . password } ) " " | cat $ { ldapConfig } - > /etc/ldap.conf.bindpw
mv - fT /etc/ldap.conf.bindpw /etc/ldap.conf
chmod 600 /etc/ldap.conf
fi
'' ;
} ;
{
system . nssModules = singleton (
if cfg . daemon . enable then nss_pam_ldapd else nss_ldap
) ;
###### interface
users = mkIf cfg . daemon . enable {
extraGroups . nslcd = {
gid = config . ids . gids . nslcd ;
} ;
options = {
users . ldap = {
enable = mkOption {
default = false ;
description = " W h e t h e r t o e n a b l e a u t h e n t i c a t i o n a g a i n s t a n L D A P s e r v e r . " ;
} ;
server = mkOption {
example = " l d a p : / / l d a p . e x a m p l e . o r g / " ;
description = " T h e U R L o f t h e L D A P s e r v e r . " ;
} ;
base = mkOption {
example = " d c = e x a m p l e , d c = o r g " ;
description = " T h e d i s t i n g u i s h e d n a m e o f t h e s e a r c h b a s e . " ;
} ;
useTLS = mkOption {
default = false ;
description = ''
If enabled , use TLS ( encryption ) over an LDAP ( port 389 )
connection . The alternative is to specify an LDAPS server ( port
636 ) in <option> users . ldap . server < /option > or to forego
security .
'' ;
} ;
timeLimit = mkOption {
default = 0 ;
type = types . int ;
description = ''
Specifies the time limit ( in seconds ) to use when performing
searches . A value of zero ( 0 ) , which is the default , is to
wait indefinitely for searches to be completed .
'' ;
} ;
daemon = {
enable = mkOption {
default = false ;
description = ''
Whether to let the nslcd daemon ( nss-pam-ldapd ) handle the
LDAP lookups for NSS and PAM . This can improve performance ,
and if you need to bind to the LDAP server with a password ,
it increases security , since only the nslcd user needs to
have access to the bindpw file , not everyone that uses NSS
and/or PAM . If this option is enabled , a local nscd user is
created automatically , and the nslcd service is started
automatically when the network get up .
'' ;
} ;
extraConfig = mkOption {
default = " " ;
type = types . string ;
description = ''
Extra configuration options that will be added verbatim at
the end of the nslcd configuration file ( nslcd . conf ) .
'' ;
} ;
} ;
bind = {
distinguishedName = mkOption {
default = " " ;
example = " c n = a d m i n , d c = e x a m p l e , d c = c o m " ;
type = types . string ;
description = ''
The distinguished name to bind to the LDAP server with . If this
is not specified , an anonymous bind will be done .
'' ;
} ;
password = mkOption {
default = " / e t c / l d a p / b i n d . p a s s w o r d " ;
type = types . string ;
description = ''
The path to a file containing the credentials to use when binding
to the LDAP server ( if not binding anonymously ) .
'' ;
} ;
timeLimit = mkOption {
default = 30 ;
type = types . int ;
description = ''
Specifies the time limit ( in seconds ) to use when connecting
to the directory server . This is distinct from the time limit
specified in <literal> users . ldap . timeLimit < /literal > and affects
the initial server connection only .
'' ;
} ;
policy = mkOption {
default = " h a r d _ o p e n " ;
type = types . string ;
description = ''
Specifies the policy to use for reconnecting to an unavailable
LDAP server . The default is <literal> hard_open < /literal > , which
reconnects if opening the connection to the directory server
failed . By contrast , <literal> hard_init < /literal > reconnects if
initializing the connection failed . Initializing may not
actually contact the directory server , and it is possible that
a malformed configuration file will trigger reconnection . If
<literal> soft < /literal > is specified , then
<literal> nss_ldap < /literal > will return immediately on server
failure . All hard reconnect policies block with exponential
backoff before retrying .
'' ;
} ;
} ;
extraConfig = mkOption {
default = " " ;
type = types . string ;
description = ''
Extra configuration options that will be added verbatim at
the end of the ldap configuration file ( ldap . conf ) .
If <literal> users . ldap . daemon < /literal > is enabled , this
configuration will not be used . In that case , use
<literal> users . ldap . daemon . extraConfig < /literal > instead .
'' ;
} ;
extraUsers . nslcd = {
uid = config . ids . uids . nslcd ;
description = " n s l c d u s e r . " ;
group = " n s l c d " ;
} ;
} ;
systemd . services = mkIf cfg . daemon . enable {
nslcd = {
wantedBy = [ " n s s - u s e r - l o o k u p . t a r g e t " ] ;
before = [ " n s s - u s e r - l o o k u p . t a r g e t " ] ;
after = [ " n e t w o r k . t a r g e t " ] ;
preStart = ''
mkdir - p /run/nslcd
rm - f /run/nslcd/nslcd.pid ;
chown nslcd . nslcd /run/nslcd
$ { optionalString ( cfg . bind . distinguishedName != " " ) ''
if test - s " ${ cfg . bind . password } " ; then
ln - sfT " ${ cfg . bind . password } " /run/nslcd/bindpw
fi
'' }
###### implementation
config = mkIf cfg . enable {
environment . etc = if cfg . daemon . enable then [ nslcdConfig ] else [ ldapConfig ] ;
system . activationScripts = mkIf insertLdapPassword {
ldap = stringAfter [ " e t c " " g r o u p s " " u s e r s " ] ''
if test - f " ${ cfg . bind . password } " ; then
echo " b i n d p w " $ ( cat $ { cfg . bind . password } ) " " | cat $ { ldapConfig } - > /etc/ldap.conf.bindpw
mv - fT /etc/ldap.conf.bindpw /etc/ldap.conf
chmod 600 /etc/ldap.conf
fi
'' ;
} ;
system . nssModules = singleton (
if cfg . daemon . enable then nss_pam_ldapd else nss_ldap
) ;
users = mkIf cfg . daemon . enable {
extraGroups . nslcd = {
gid = config . ids . gids . nslcd ;
} ;
extraUsers . nslcd = {
uid = config . ids . uids . nslcd ;
description = " n s l c d u s e r . " ;
group = " n s l c d " ;
} ;
} ;
serviceConfig = {
ExecStart = " ${ nss_pam_ldapd } / s b i n / n s l c d " ;
Type = " f o r k i n g " ;
PIDFile = " / r u n / n s l c d / n s l c d . p i d " ;
Restart = " a l w a y s " ;
systemd . services = mkIf cfg . daemon . enable {
nslcd = {
wantedBy = [ " n s s - u s e r - l o o k u p . t a r g e t " ] ;
before = [ " n s s - u s e r - l o o k u p . t a r g e t " ] ;
after = [ " n e t w o r k . t a r g e t " ] ;
preStart = ''
mkdir - p /run/nslcd
rm - f /run/nslcd/nslcd.pid ;
chown nslcd . nslcd /run/nslcd
$ { optionalString ( cfg . bind . distinguishedName != " " ) ''
if test - s " ${ cfg . bind . password } " ; then
ln - sfT " ${ cfg . bind . password } " /run/nslcd/bindpw
fi
'' }
'' ;
serviceConfig = {
ExecStart = " ${ nss_pam_ldapd } / s b i n / n s l c d " ;
Type = " f o r k i n g " ;
PIDFile = " / r u n / n s l c d / n s l c d . p i d " ;
Restart = " a l w a y s " ;
} ;
} ;
} ;
} ;
}