Facebook Twitter E-mail RSS
magnify
formats

Utilize Lsyncd to sync multiple web servers

Published on October 16, 2011

This article will show the steps needed to install and utilize lsyncd to sync multiple web servers in a cloud environment. I have set this up in various production environments, from 2 to 12+ servers. This can be used for many purposes, for this article I will use it to sync a pair of wordpress web servers since its a very common application that I have setup for many of my clients. For this demo I will show you how to do it on CentOS.

First setup the file systems on all the web servers, including a user with same UID/GID to use for the ownership of the transferred locations (this part of the configuration is not required to make lsyncd work, but I think a uniform simplistic approach is best). For this example we will use a default web layout of /var/www/html owned by a regular user bob (UID 501, GID 501)

#adduser bob -d /var/www/html
#passwd bob
#chown -R bob:bob /var/www/html

Next we will setup passwordless SSH from master to slave system for user root (I don’t care for this part from a security standpoint, but have not figured out how to run demon as a regular user yet).

Generate SSH keypair on master:

# ssh-keygen -t rsa

Then copy /root/.ssh/id_rsa.pub on master to /root/.ssh/authorized_keys on the slave server

Then ensure the following lines are uncommitted in /etc/ssh/sshd_config on the slave server

PermitRootLogin yes
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile      .ssh/authorized_keys

Then make sure to restart SSH after making changes to the configuration. Then test SSH access from master to slave to ensure entry is working correctly.

Before we can install the demon you will need to ensure you have all the dependencies in place, most likely the following command will get everything you need.

# yum install lua lua-devel pkgconfig

Then grab the source from http://code.google.com/p/lsyncd/

Untar the file and run the standard ‘./configure && make && make install’ to create and install the binaries.

The source code install does not add the init.d script or configuration file by default, those have to be manually added after installation. Create the init.d script from template below.

/etc/init.d/lsyncd

#!/bin/bash
#
# lsyncd: Starts the lsync Daemon
#
# chkconfig: 345 99 90
# description: Lsyncd uses rsync to synchronize local directories with a remote
# machine running rsyncd. Lsyncd watches multiple directories
# trees through inotify. The first step after adding the watches
# is to, rsync all directories with the remote host, and then sync
# single file buy collecting the inotify events.
# processname: lsyncd

# . /etc/rc.d/init.d/functions 

config="/etc/lsyncd.lua"
lsyncd="/usr/local/bin/lsyncd"
lockfile="/var/lock/lsyncd"
prog="lsyncd" RETVAL=0
RETVAL=0

start() {
        if [ -f $lockfile ]; then
        echo -n $"$prog is already running: "
        echo
        else
        echo -n $"Starting $prog: "
        $lsyncd $config
        RETVAL=$?
        echo
        [ $RETVAL = 0 ] && touch $lockfile
        return $RETVAL
        fi
    }
stop() {
        echo -n $"Stopping $prog: "
        killall $lsyncd
        RETVAL=$?
        echo
        [ $RETVAL = 0 ] && rm -f $lockfile
        return $RETVAL
    }
case "$1" in
        start)
        start
        ;;
        stop)
        stop
        ;;
        restart)
        stop
        start
        ;;
        status)
        status $lsyncd
        ;;
        *)

        echo "Usage: lsyncd {start|stop|restart|status}"
        exit 1
    esac

    exit $?
 Set permissions and ownership on init.d file:
# chmod 775 /etc/init.d/lsyncd
# chown root:root /etc/init.d/lsyncd

Lsyncd configuration file examples. /etc/lsyncd.lua

Here is an example of a master, single slave configuration file (1.1.1.1 is the IP of the slave server).

settings = {
   logfile = "/var/log/lsyncd.log",
   statusFile = "/var/log/lsyncd-status.log",
   statusInterval = 20 }
sync{
   default.rsyncssh,
   source="/var/www/html",
   host="1.1.1.1",
   targetdir="/var/www/html",
   rsyncOpts="-avz" }

Here is an example for a master with two slave configuration (1.1.1.1 first slave, 2.2.2.2 second slave)

settings = {
   logfile = "/var/log/lsyncd.log",
   statusFile = "/var/log/lsyncd-status.log",
   statusInterval = 20 }
sync{
   default.rsyncssh,
   source="/var/www/html",
   host="1.1.1.1",
   targetdir="/var/www/html",
   rsyncOpts="-avz" }
sync{
   default.rsyncssh,
   source="/var/www/html",
   host="2.2.2.2",
   targetdir="/var/www/html",
   rsyncOpts="-avz" }

There is a huge amount that can be done using the configuration file, including execution of lau and bash scripts triggered by events in the configuration files. Here is the manual for configuration http://code.google.com/p/lsyncd/wiki/Lsyncd20Manual I will show you one example of its power to exclude files from sync. If you want to exclude a directory, use an exclude file and the excludeFrom directive:

Sample exclude file – /etc/lsyncd-excludes.txt:

cache/

uploads/

dontcopymebro/

Then a sample configuration file with the exclude file included – /etc/lsyncd.lua:

settings = {
   logfile = "/var/log/lsyncd.log",
   statusFile = "/var/log/lsyncd-status.log",
   statusInterval = 20 }
sync{
   default.rsyncssh,
   source="/var/www/html",
   host="1.1.1.1",
   targetdir="/var/www/html",
   excludeFrom="/etc/lsyncd-excludes.txt",
   rsyncOpts="-avz" }

 

Once the init script and the configuration file are in place, run the following command to setup run on boot:

chkconfig lsyncd on

Make sure to look over your log files to ensure that everything is working, the most common problem other than SSH login is running out of inodes if your file structure is large. This can be adjusted in /proc/sys/fs/inotify/max_user_watches .

Now I mentioned at the first of this article that this is a one way synchronization program so all disk writes have to be done on the master web server or this will break sync. Now using a CMS like wordpress this is pretty easy to do. The way I recommend to my clients is to force SSL login/admin access. by adding the following lines to your wp-config.php. In my opinion this is a good standard security step anyways.

define('FORCE_SSL_ADMIN', true);
define(‘FORCE_SSL_LOGIN’, true);

This forces all logins to the control panel, which is where all writes are done to SSL. Then you just have to configure whatever load balancing solution your using to send all SSL traffic to your master server only.

Now there are plenty of other things that need to be done to setup a multi-server CMS configuration such as session handling and Apache optimization but that’s another article.

Hope you find this article helpful.

- Nomad