Install Openldap From Source And Configure Multi-Master Replication

Author: Nitin Bhadauria
Version: 1.0

Going forward to my previous document on setting up a Qmail Server with Openldap, I am now sharing a doc on how we can set up an Openldap in multi-master replication mode. So If you want more than one ldap-server for redundancy here we go:

 

1 Preliminary Note

In this tutorial I will use two demo servers, just to make steps simple, But you can replicate the same setup on more then two servers.

server1.example.com: IP address 192.168.0.100
server2.example.com: IP address 192.168.0.101

Because we will run all the steps from this tutorial with root privileges, you can either pretend all commands in this tutorial with the string sudo, or we become root right now by typing:

sudo su

Two servers should be able to resolve the other systems' hostnames. If this cannot be done through DNS, you should edit the /etc/hosts file so that it looks as follows on all three systems:

vi /etc/hosts
127.0.0.1      localhost.localdomain   localhost
192.168.0.100  server1.example.com     server1
192.168.0.101  server2.example.com     server2
 

 

2 Prerequisites

a. Before compiling we will install some dependencies:

yum install libacl-devel libblkid-devel gnutls-devel readline-devel python-devel autoconf gcc-c++ gcc glibc-devel glibc-headers kernel-headers libgomp libstdc++-devel openssl-devel e2fsprogs-devel keyutils-libs-devel krb5-devel libselinux-devel libsepol-devel libtool-ltdl-devel

b. Before installing Openldap we need to install latest Oracle Berkeley DB.

wget http://download.oracle.com/berkeley-db/db-4.7.25.tar.gz
tar xvf db-4.7.25.tar.gz
cd db-4.7.25
cd build_unix
../dist/configure
make
make install
ls /usr/local/BerkeleyDB.4.7/
cp -p /usr/local/BerkeleyDB.4.7/bin/db_* /usr/bin/
cp -p /usr/local/BerkeleyDB.4.7/lib/* /usr/lib
cp -p /usr/local/BerkeleyDB.4.7/include/* /usr/include/
mv /usr/lib/libdb-4.7.so /usr/lib/libdb-4.7.so.0.0.0
ln -s /usr/lib/libdb-4.7.so.0.0.0 /usr/lib/libdb-4.7.so
ldconfig

 

3 Install Openldap

a. install the OpenLDAP server from source:

wget ftp://ftp.openldap.org/pub/OpenLDAP/openldap-release/openldap-2.4.26.tgz
tar xvf openldap-2.4.26.tgz
cd openldap-2.4.26
./configure --prefix=/usr/local/openldap --enable-overlays=mod --enable-modules --enable-bdb --enable-accesslog --enable-auditlog --enable-collect --enable-memberof --enable-syncprov
make depend
make
make install

Try to start the service and check it started without any error. To make sure we are good to go.

/usr/local/openldap/libexec/slapd -d 5

Note: Press "ctrl + c"  to exit.

Now we will follow the same steps to install the Openldap on other server.

 

4 Configure Multi-Master Replication

Now we will configure the replication although i will include most of the important configuration just to make sure that the configuration are in correct order (which is important because you can’t just put any line anywhere in file).

On server1 (192.168.0.100):

vi /usr/local/openldap/etc/openldap/slapd.conf
pidfile /usr/local/openldap/var/run/slapd.pid
argsfile /usr/local/openldap/var/run/slapd.args

# Load the required modules
moduleload syncprov.la
moduleload accesslog.la
moduleload back_bdb.la

#Define the server ID.
serverID 1

# Make sure you change below configuration as your need

database bdb
suffix " dc=example,dc=com "
rootdn "cn=ldadmin,dc=example,dc=com "
rootpw {SSHA}MxGntcb+QdYimYqbly7IOCY2ZJ0SxqCZ # Generate password using "slappasswd"
directory /usr/local/openldap/var/openldap-data

# These are basic performances configuration required
checkpoint 10240 720 # check point whenever 10M data bytes written or 24Hr has elapsed whichever occurs first
cachesize 50000 # LDAP maintains 50,000 entries in memory

# These configurations are to set the default database parameters
dbconfig set_cachesize 0 524288000 1 # Set the database in memory cache size to 500 MB, Tuning this value can greatly effect your database performance.
dbconfig set_lk_max_locks 3000
dbconfig set_lk_max_objects 1500
dbconfig set_lk_max_lockers 1500
dbconfig set_lg_regionmax 262144
dbconfig set_lg_bsize 2097152

# Replication configuration, only things you may have to change here are provider, binddn, credentials and searchbase.
syncrepl rid=001
    provider=ldap://server2.example.com:389
    binddn="cn=ldadmin,dc=example,dc=com "
    bindmethod=simple
    credentials=secret
    searchbase=" dc=example,dc=com "
    type=refreshAndPersis
    interval=00:00:00:10
    retry="5 5 300 5"
    timeout=1

index objectClass eq

#Rest replication configuration goes to end of the file.
mirrormode TRUE
overlay syncprov
syncprov-nopresent TRUE
syncprov-reloadhint TRUE
syncprov-checkpoint 1000 60 

Now configure server2 (192.168.0.101):

vi /usr/local/openldap/etc/openldap/slapd.conf
pidfile /usr/local/openldap/var/run/slapd.pid
argsfile /usr/local/openldap/var/run/slapd.args
moduleload syncprov.la
moduleload accesslog.la
moduleload back_bdb.la
serverID 1

database bdb
suffix " dc=example,dc=com "
rootdn "cn=ldadmin,dc=example,dc=com "
rootpw {SSHA}MxGntcb+QdYimYqbly7IOCY2ZJ0SxqCZ # Generate password using “slappasswd”
directory /usr/local/openldap/var/openldap-data

checkpoint 10240 720
cachesize 50000
dbconfig set_cachesize 0 524288000 1
dbconfig set_lk_max_locks 3000
dbconfig set_lk_max_objects 1500
dbconfig set_lk_max_lockers 1500
dbconfig set_lg_regionmax 262144
dbconfig set_lg_bsize 2097152

syncrepl rid=002
    provider=ldap://server1.example.com:389
    binddn="cn=ldadmin,dc=example,dc=com "
    bindmethod=simple
    credentials=secret
    searchbase="dc=example,dc=com "
    type=refreshAndPersist
    interval=00:00:00:10
    retry="5 5 300 5"
    timeout=1

index objectClass eq

mirrormode TRUE
overlay syncprov
syncprov-nopresent TRUE
syncprov-reloadhint TRUE
syncprov-checkpoint 1000 60 

 

5 Configure Startup Script File

First create an account to run ldap service:

groupadd ldap
useradd -g ldap -d /usr/local/openldap/var/openldap-data/ -s /bin/false -p'*' ldap

As openldap didn't include any scripts in package we will create one:


vi /etc/init.d/ldap
#!/bin/bash
#
# ldap This shell script takes care of starting and stopping
# ldap servers (slapd and slurpd).
#
# chkconfig: - 27 73
# description: LDAP stands for Lightweight Directory Access Protocol, used \
# for implementing the industry standard directory services.
# processname: slapd
# config: /usr/local/openldap/etc/openldap/slapd.conf
# pidfile: /usr/local/openldap/var/run/slapd.pid

# Source function library.
. /etc/init.d/functions

# Source networking configuration and check that networking is up.
if [ -r /etc/sysconfig/network ] ; then
. /etc/sysconfig/network
[ ${NETWORKING} = "no" ] && exit 1
fi

# Source an auxiliary options file if we have one, and pick up OPTIONS,
# SLAPD_OPTIONS, SLURPD_OPTIONS, SLAPD_LDAPS, SLAPD_LDAPI, and maybe
# KRB5_KTNAME and SLURPD_KRB5CCNAME.
if [ -r /etc/sysconfig/ldap ] ; then
. /etc/sysconfig/ldap
fi

#slapd=/usr/sbin/slapd
slapd=/usr/local/openldap/libexec/slapd
slurpd=/usr/sbin/slurpd
slaptest=/usr/local/openldap/sbin/slaptest
[ -x ${slapd} ] || exit 1
[ -x ${slurpd} ] || exit 1

RETVAL=0

#
# Pass commands given in $2 and later to "test" run as user given in $1.
#
function testasuser() {
local user= cmd=
user="$1"
shift
cmd="[email protected]"
if test x"$user" != x ; then
if test x"$cmd" != x ; then
/sbin/runuser -f -m -s /bin/sh -c "test $cmd" -- "$user"
else
false
fi
else
false
fi
}

#
# Check for read-access errors for the user given in $1 for a service named $2.
# If $3 is specified, the command is run if "klist" can't be found.
#
function checkkeytab() {
local user= service= klist= default=
user="$1"
service="$2"
default="${3:-false}"
if test -x /usr/kerberos/bin/klist ; then
klist=/usr/kerberos/bin/klist
elif test -x /usr/bin/klist ; then
klist=/usr/bin/klist
fi
KRB5_KTNAME="${KRB5_KTNAME:-/etc/krb5.keytab}"
export KRB5_KTNAME
if test -s "$KRB5_KTNAME" ; then
if test x"$klist" != x ; then
if LANG=C $klist -k "$KRB5_KTNAME" | tail -n 4 | awk '{print $2}' | grep -q ^"$service"/ ; then
if ! testasuser "$user" -r ${KRB5_KTNAME:-/etc/krb5.keytab} ; then
true
else
false
fi
else
false
fi
else
$default
fi
else
false
fi
}

function configtest() {
local user= ldapuid= dbdir= file=
# Check for simple-but-common errors.
user=ldap
prog=`basename ${slapd}`
ldapuid=`id -u $user`
# Unaccessible database files.
for dbdir in `LANG=C egrep '^directory[[:space:]]+[[:print:]]+$' /usr/local/openldap/etc/openldap/slapd.conf | sed s,^directory,,` ; do
for file in `find ${dbdir}/ -not -uid $ldapuid -and \( -name "*.dbb" -or -name "*.gdbm" -or -name "*.bdb" -or -name "__db.*" \)` ; do
echo -n $"$file is not owned by \"$user\"" ; warning ; echo
done
done
# Unaccessible keytab with an "ldap" key.
if checkkeytab $user ldap ; then
file=${KRB5_KTNAME:-/etc/krb5.keytab}
echo -n $"$file is not readable by \"$user\"" ; warning ; echo
fi
# Unaccessible TLS configuration files.
tlsconfigs=`LANG=C egrep '^(TLS_CACERT|TLSCACertificateFile|TLSCertificateFile|TLSCertificateKeyFile)[[:space:]]' /usr/local/openldap/etc/openldap/slapd.conf /usr/local/openldap/etc/openldap/ldap.conf | awk '{print $2}'`
for file in $tlsconfigs ; do
if ! testasuser $user -r $file ; then
echo -n $"$file is not readable by \"$user\"" ; warning ; echo
fi
done
# Check the configuration file.
slaptestout=`/sbin/runuser -m -s "$slaptest" -- "$user" "-u" 2>&1`
slaptestexit=$?
if test $slaptestexit == 0 ; then
if echo "$slaptestout" | grep -v "config file testing succeeded" >/dev/null ; then
echo -n $"Checking configuration files for $prog: " ; warning ; echo
echo "$slaptestout"
fi
else
echo -n $"Checking configuration files for $prog: " ; failure ; echo
echo "$slaptestout"
if /sbin/runuser -m -s "$slaptest" -- "$user" "-u" &>/dev/null ; then
for directory in `LANG=C egrep '^directory[[:space:]]+[[:print:]]+$' /usr/local/openldap/etc/openldap/slapd.conf | sed s,^directory,,` ; do
if test -r $directory/__db.001 ; then
echo -n $"stale lock files may be present in $directory" ; warning ; echo
fi
done
fi
exit 1
fi
}

function start() {
configtest
# Define a couple of local variables which we'll need. Maybe.
user=ldap
prog=`basename ${slapd}`
if test x$SLAPD_LDAP = xyes ; then
harg="ldap:///"
fi
if grep -q ^TLS /usr/local/openldap/etc/openldap/slapd.conf || test x$SLAPD_LDAPS = xyes ; then
harg="$harg ldaps:///"
fi
if test x$SLAPD_LDAPI = xyes ; then
harg="$harg ldapi:///"
fi
# Start daemons.
echo -n $"Starting $prog: "
ulimit $ULIMIT_SETTINGS > /dev/null 2>&1
daemon --check=$prog ${slapd} -h \"$harg\" -u ${user} $OPTIONS $SLAPD_OPTIONS
RETVAL=$?
echo
if [ $RETVAL -eq 0 ]; then
if grep -q "^replogfile" /usr/local/openldap/etc/openldap/slapd.conf; then
prog=`basename ${slurpd}`
echo -n $"Starting $prog: "
if [ -n "$SLURPD_KRB5CCNAME" ]; then
export KRB5CCNAME="$SLURPD_KRB5CCNAME";
fi
daemon ${slurpd} $OPTIONS $SLURPD_OPTIONS
RETVAL=$?
echo
fi
fi
[ $RETVAL -eq 0 ] && touch /usr/local/openldap/var/lock/subsys/ldap
return $RETVAL
}

function stop() {
# Stop daemons.
prog=`basename ${slapd}`
echo -n $"Stopping $prog: "
killproc -d $STOP_DELAY ${slapd}
RETVAL=$?
echo
if [ $RETVAL -eq 0 ]; then
if grep -q "^replogfile" /usr/local/openldap/etc/openldap/slapd.conf; then
prog=`basename ${slurpd}`
echo -n $"Stopping $prog: "
killproc ${slurpd}
RETVAL=$?
echo
fi
fi
[ $RETVAL -eq 0 ] && rm -f /usr/local/openldap/var/lock/subsys/ldap /usr/local/openldap/var/run/slapd.args
return $RETVAL
}

# See how we were called.
case "$1" in
configtest)
configtest
;;
start)
start
RETVAL=$?
;;
stop)
stop
RETVAL=$?
;;
status)
status ${slapd}
RETVAL=$?
if grep -q "^replogfile" /usr/local/openldap/etc/openldap/slapd.conf ; then
status ${slurpd}
RET=$?
if [ $RET -ne 0 ] ; then
RETVAL=$RET;
fi
fi
;;
restart)
stop
start
;;
condrestart)
if [ -f /usr/local/openldap/var/lock/subsys/ldap ] ; then
stop
start
RETVAL=$?
fi
;;
*)
echo $"Usage: $0 {start|stop|restart|status|condrestart}"
RETVAL=1
esac

exit $RETVAL

You may have to make some aditional directory required:

mkdir -p /usr/local/openldap/var/{run,lock/subsys}
chown ldap: -R /usr/local/openldap

Now, make this script executable and change its default permissions:

chmod 700  /etc/init.d/ldap
chkconfig --add ldap
chkconfig --level 345 ldap on

Start your OpenLDAP Server manually with the following command:

/etc/init.d/ldap start

 

6 Migration

Only follow these steps if you are setting replication on already running Openldap server:

a. First copy all the schema used in your running setup, I would suggest sync the whole directory.

rsync -av /usr/local/openldap/etc/openldap/schema [email protected]:/usr/local/openldap/etc/openldap/schema

Now remember to include the these schema in your configuration:

vi /usr/local/openldap/etc/openldap/slapd.conf
include         /usr/local/openldap/etc/openldap/schema/core.schema
include         /usr/local/openldap/etc/openldap/schema/cosine.schema
include         /usr/local/openldap/etc/openldap/schema/inetorgperson.schema
include         /usr/local/openldap/etc/openldap/schema/nis.schema
include         /usr/local/openldap/etc/openldap/schema/qmail.schema

b. Now import all the data from server1 to server2.

on server1:

ldapsearch -x -b 'dc=example,dc=com' > master.ldif
scp master.ldif [email protected]:

on server2:

ldapmodify -cvx -D'cn=ldadmin,dc=example,dc=com' -W -f /root/master.ldif

Enter LDAP Password:

Now restart Ldap service simultaneously on both servers:

/etc/init.d/ldap restart

 

7 Configure Qmail And IMAP To Use Both servers

Now we will edit a qmail control file to define multiple ldap servers:  

vi /var/qmail/control/ldapserver
server1.example.com:389
server2.example.com:389

And courier-auth configuration to make imap use both the servers:

vi /etc/courier/authldaprc
LDAP_URI    ldap://server1.example.com, ldap://server2.example.com

Now just restart the services and all should be good :)

I will be publishing a doc to configure replication over SSL very soon...

Share this page:

Suggested articles

9 Comment(s)

Add comment

Comments

By:

Is it safe to have the root password hash in etc/openldap/slapd.conf ? You do not mention any further precautions like setting permission of slapd.conf!?

By:

thanks for pointing it, i will update the doc accordingly..

By: tvs

the syncrepl configuration in slapd.conf uses ldaadmin with password 'secret', while in the same file the rootdn is also defined as ldadmin but with a hashed password, isn't this wrong?

 

By: Anonymous

I have followed your instructions to a T and upon getting to the point where you run the init.d script, I noticed I was receiving no output.  Upon investigating the ldap service script, I noticed you check for slurpd and ensure it is located at/usr/sbin/slurpd.  However, I have had 0 luck in finding it at that or any other location on my machine.  I've searched the entire box using find as root and found 0 files named slurpd (including the the openldap build directory).  Any thoughts on how to get slurpd installed?

 Wait... I just noticed they removed slurpd in 2.4.... why would you reference using 2.4.6 then?

By: sekhar

Here my question is :

3 ldap servers in replication but we did not make any changes but on 2 servers its showing status error.

please help me with solution for this issue.

There are 3 replications of LDAP, they are on lkosscif1,lkosscif2 and lkossomsas1.

Found 2 error when check on lkosscif1 and lkossomsas1. Log as below.

No changed were done on them. The issue is still happening. Thanks.

 

Checking on lkosscif1

Replication Configuration Menu

 

1 Enable Domain Replication

2 Create Domain Replication Agreement

3 Check Status of Domain Replication Agreement

4 Initialize Domain Replication

5 Remove Domain Replication Agreement

6 List all Replication Agreements

7 Disable Domain Replication

8 Add Replica to LDAP Client Connection Profile

9 Exit

 

Enter option number: 6

 

INFO [Executing: /opt/SUNWdsee/ds6/bin/dsconf list-repl-agmts -i -D cn=directory manager]

 

dc=lkoss,dc=smartone,dc=com lkossomsas1.lkoss.smartone.com:636

dc=lkoss,dc=smartone,dc=com lkosscif2.lkoss.smartone.com:636

 

INFO Listing replication agreement was successful.

… …

 

Enter option number: 3

 

Enter Replication destination FQHN (e.g. server2.dns.companyname.com): lkosscif2.lkoss.smartone.com

 

INFO [Executing: /opt/SUNWdsee/ds6/bin/dsconf show-repl-agmt-status -D cn=directory manager dc=lkoss,dc=smartone,dc=com lkosscif2.lkoss.smartone.com:636]

Configuration Status : OK

Authentication Status : NOT OK

Initialization Status : OK

 

Status : Error Sending Updates

Last Message : Replication error updating replica: Could not bind to replica : transient error - Failed to bind to remote

Pending Changes : 14867

 

INFO Check replication status ran successfully.

 

Checking on lkossomsas1

Replication Configuration Menu

 

1 Enable Domain Replication

2 Create Domain Replication Agreement

3 Check Status of Domain Replication Agreement

4 Initialize Domain Replication

5 Remove Domain Replication Agreement

6 List all Replication Agreements

7 Disable Domain Replication

8 Add Replica to LDAP Client Connection Profile

9 Exit

 

Enter option number: 6

 

INFO [Executing: /opt/SUNWdsee/ds6/bin/dsconf list-repl-agmts -i -D cn=directory manager]

 

dc=lkoss,dc=smartone,dc=com lkosscif2.lkoss.smartone.com:636

dc=lkoss,dc=smartone,dc=com lkosscif1.lkoss.smartone.com:636

 

INFO Listing replication agreement was successful.

 

… …

Enter option number: 3

 

Enter Replication destination FQHN (e.g. server2.dns.companyname.com): lkosscif1.lkoss.smartone.com

 

INFO [Executing: /opt/SUNWdsee/ds6/bin/dsconf show-repl-agmt-status -D cn=directory manager dc=lkoss,dc=smartone,dc=com lkosscif1.lkoss.smartone.com:636]

Configuration Status : OK

Authentication Status : NOT OK

Initialization Status : OK

 

Status : Error Sending Updates

Last Message : Replication error updating replica: Could not bind to replica : transient error - Failed to bind to remote

Pending Changes : 1

 

INFO Check replication status ran successfully.

 

.

 

we know that the workaround to fix this issue is to recreate the replication agreements between sorce and destination.

but need the RCA for this issue.

Thanks in advance.

 

 

By: shashikanth.b

Can you please tell me whether syncrepl replicate the password policy on Ldap. and if yes , can you let me know the steps in implementing 

By: venu

Till 4th step the documentation is clear, I was wondered on which server I need to do these configurations after 4th step, You didn't mention on which server we need to perform other steps. I am new to this and I want to learn, so please help me out. And let me know how to check whether replication done or not

By: VG-hyd

When i am using rsynch operation on my EC2 instance getting an error like "Permanently added 'server2,x.x.x.x' (ECDSA) to the list of known hosts. Permission denied (publickey). rsync: connection unexpectedly closed (0 bytes received so far) [sender]"

How to solve this issue? Is there anybody to help me?

By: Abdeslam

Hello

 

This tutorial is out f date it is applicabel to the old versions of ldap