Simple Apache failover cluster on Ubuntu with config synchronization

In my previous post, I was explaining how to setup a simple failover cluster using Ucarp on Ubuntu.

In this article we are going to cover the same topic but this time we’ll have an Apache server running and we, of course, want to synchronize its configuration.

This time again, we are going to keep things simple. We are going to use Ucarp to provide the IP failover mechanism (read my previous article if it is not clear), and a little script to synchronize Apache configuration and content (including httpd.conf, sites, ssl certificates, web sites, …).

Here is an overall picture of what we want to achieve :

Step 1 : Setup your two Apache servers

You’ll need two Apache servers, it can be virtual servers. In my case, I’m using Ubuntu 10.04 LTS, one machine is physical, and the second one is virtual (but you can do whatever you want). Simply install Apache on both servers, and make sure you configure at least the master server (Apache #1) so that Apache runs correctly. Keep in mind that you need to run the same version of Apache on both servers (I even recommend the same version of Operating System) :

sudo apt-get install apache2

Then, install Ucarp on both servers as well :

sudo apt-get install ucarp

Step 2 : Configure Ucarp

Ucarp is our IP failover mechanism. It will bascially allow us to have a “virtual IP” address that will “point” to Apache #1 if the server is up, and to Apache #2 in case the first server is down (again, see my previous article if you want to know more).

Here is the network configuration for Apache #1 :

sudo nano /etc/network/interfaces

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
        ################################
        # standard network configuration
        ################################
        address 172.20.1.26
        netmask 255.255.240.0
        network 172.20.0.0
        broadcast 172.20.15.255
        gateway 172.20.1.250

        ################################
        # ucarp configuration
        ################################
        # vid : The ID of the virtual server [1-255]
        ucarp-vid 1
        # vip : The virtual address
        ucarp-vip 172.20.1.16
        # password : A password used to encrypt Carp communications
        ucarp-password secret
        # advskew : Advertisement skew [1-255]
        ucarp-advskew 1
        # advbase : Interval in seconds that advertisements will occur
        ucarp-advbase 1
        # master : determine if this server is the master
        ucarp-master yes

# The carp network interface, on top of eth0
iface eth0:ucarp inet static
        address 172.20.1.16
        netmask 255.255.240.0

And here is the network configuration for Apache #2 :

sudo nano /etc/network/interfaces

The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
auto eth0
iface eth0 inet static
        ################################
        # standard network configuration
        ################################
        address 172.20.1.36
        netmask 255.255.240.0
        network 172.20.0.0
        broadcast 172.20.15.255
        gateway 172.20.1.250

        ################################
        # ucarp configuration
        ################################
        # vid : The ID of the virtual server [1-255]
        ucarp-vid 1
        # vip : The virtual address
        ucarp-vip 172.20.1.16
        # password : A password used to encrypt Carp communications
        ucarp-password secret
        # advskew : Advertisement skew [1-255]
        ucarp-advskew 100
        # advbase : Interval in seconds that advertisements will occur
        ucarp-advbase 1
        # master : determine if this server is the master
        ucarp-master no

# The carp network interface, on top of eth0
iface eth0:ucarp inet static
        address 172.20.1.16
        netmask 255.255.240.0

Once you have finished, restart the network interfaces on both servers :

sudo /etc/init.d/networking restart

You’ll then be able to see that if both servers are up, the virtual IP (172.20.1.16) is assigned to the Apache #1 server. If you shutdown the Apache #1 server, the Apache #2 server will get the virtual IP. To test, simply look at the result of the following command on each servers :

sudo ifconfig

eth0      Link encap:Ethernet  HWaddr b8:ac:6f:90:31:19
          inet addr:172.20.1.26  Bcast:172.20.15.255  Mask:255.255.240.0
          inet6 addr: fe80::baac:6fff:fe90:3119/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:739943 errors:0 dropped:0 overruns:0 frame:0
          TX packets:593742 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:668890196 (668.8 MB)  TX bytes:717991771 (717.9 MB)
          Interrupt:16 Memory:da000000-da012800

eth0:ucarp Link encap:Ethernet  HWaddr b8:ac:6f:90:31:19
          inet addr:172.20.1.16  Bcast:172.20.15.255  Mask:255.255.240.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          Interrupt:16 Memory:da000000-da012800

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:3 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:312 (312.0 B)  TX bytes:312 (312.0 B)

Step 3 : Synchronizing the two servers

The server Apache #1 is called our master server. We will basically replicate any Apache related changes made on that server to the second server Apache #2. This means if you want to modify the apache config of your failover farm, you’ll have to perform those changes on the server Apache #1.

Create a new file :

sudo echo "dummy content" > /root/sync-apache-conf.sh

Give the file execution permissions :

sudo chmod 744 /root/sync-apache-conf.sh

Open it with nano, and copy the following content into it

sudo nano /root/sync-apache-conf.sh

#!/usr/bin/env bash

#############################################################
#
# Synchronizes the apache configuration and related stuff
# accross the network using rsync. The master server is
# bepscnet26, we grab everything from there...
#
# H@cked by Laurent Bel in April 2012
#
# Credits :
# - http://tech.tomgoren.com/archives/214
# - http://laurentbel.com/?p=230
############################################################

# Variables (change it accordingly)
master_server="172.20.1.26"
current_date=$(date)
log_file="/var/log/sync-apache-conf.log"

# We sync the apache config, the ssl certificates, and the hosts file, www folder
result=$(rsync -ai --delete --force ${master_server}:/etc/apache2/ /etc/apache2/)
rsync -ai --delete --force ${master_server}:/etc/ssl/ /etc/ssl/
rsync -ai --delete --force ${master_server}:/etc/hosts /etc/hosts
rsync -ai --delete --force ${master_server}:/var/www/ /var/www/

# if nothing to do, the result variable will be empty, in which case the
# changes variable will be equal to 0
changes=$(echo -ne "$result" | wc -m)

# We some changes were performed, we need to reload the apache config
if [[ $changes > 0 ]]; then
        # We log
        echo "$current_date - Apache Conf Sync : Changes were found, we reload apache" >> $log_file
        # We reload apache
        /etc/init.d/apache2 reload
else
        #  We log
        echo "$current_date - Apache Conf Sync : No changes were found, we don't do anything" >> $log_file
fi

The script is quite well documented and self explanatory. Long story short, we are using rsync to copy files (apache config, ssl certificates, hosts file, and www folder) from Apache #1 to Apache #2. If some changes are detected in the apache config, we then perform a “reload” of the apache server. You’ll note the variables at the beginning of the script that you can change according to your needs.

We now can run the synchronization manually. You can test the script by changing something on Apache #1 and then run :

sudo /root/sync-apache-conf.sh

This should update the files on Apache #2 and perform if needed an Apache reload.

You can view the logs by typing

sudo cat /var/log/sync-apache-conf.log

Important note : If the script does not work, or if rsync keeps prompting for a password (it will !), just follow those steps to get rid of the password prompting.

Step 4 : Automate the synchronization to run every 5 minutes

Now we are going to automate this synchronization (we are lazy…) using crontab. The synchronization will run every 5 minutes.

Let’s start crontab and insert a new scheduled tasks :

sudo crontab -e

Append the following lines to the file

# We synchronize the apache conf every 5 minutes
*/5 * * * * /root/sync-apache-conf.sh

Step 5 : Test !

Now let’s test a little. First of all, check in the log file if your scheduled task is running correctly every 5 minutes :

sudo cat /var/log/sync-apache-conf.log

Try to shutdown the server Apache #1 and see if the second one is taking over correctly.

Try to modify the config (anything, apache, or a web site) on Server Apache #1 and wait 5 minutes to see if it gets synchronized on Apache #2.

Once you are confident that it works fine, just release your work to production. And you are done !

Conclusion :

In roughly half a day (overall, including testing), you can setup a simple Apache failover cluster with automatic synchronization of the config (you might have to adjust the sync script to perform any other action you want). It is simple, efficient… everything you need.

Note that in a more complex environments, you might want to achieve something similar using Puppet. It allows you to synchronize configuration across several servers and it is of course much more powerful than our little script, but it is also more complex and time consuming to setup.

Colorier la synthaxe PHP de l’éditeur nano sur Ubuntu

Ceux qui, comme moi, utilisent souvent le célèbre éditeur de texte nano pour éditer des fichiers PHP, trouveront dans cet article un moyen simple et efficace de donner des couleurs (très pratiques) à leur code.

En suivant les étapes ci-dessous, vous obtiendrez une synthaxe coloriée pour vos codes sources en php.

  • Pour commencer voici le résultat final :


  • Et voici comment faire pour le mettre en place sur nano

- Etape 1 : Créer un fichier de définition nano pour PHP en tappant le code ci-dessous
sudo nano /usr/share/nano/php.nanorc

- Etape 2 : Copier le code ci-dessous dans le fichier créé lors de l’étape 1 puis sauvegarder :

## PHP syntax highlighting
##
syntax "php" "\.php$" "\.php[2345s]$" "\.phtml$"
#functions
color brightmagenta "([A-Za-z0-9])"
#numbers
color brightblue "[0-9]"
#special
color blue "(^|[^A-Za-z0-9])(|var|and|or|default|class|extends|true|false|global|function|new|switch|case|break|next|prev|elseif|if|else|foreach|for|as|do|while|exit|die|declare|require_once|require|include_once|include|return|echo|static|array|isset)([^A-Za-z0-9])"
#types
color brightred "([^A-Za-z0-9])|[^A-Za-z](null|int|string|float|bool|object|resource)[^A-Za-z0-9_]+[^A-Za-z]"
#strings
color brightyellow ""(\\.|[^\"])*""
color brightyellow "'(\\.|[^\'])*'"
#Variables
color brightcyan "\$[]\[A-Za-z0-9_'\"]*"
#comments
color green "//.*"
color green "#.*"
color green start="/\*" end="\*/"

- Etape 3 : Configurez nano pour utiliser le fichier créé lors de étapes précédentes.

Il suffit pour cela d’éditer le fichier de configuration de nano :
sudo nano /etc/nanorc

et d’y ajouter les lignes suivantes (à la fin du fichier par exemple) :
## PHP
include "/usr/share/nano/php.nanorc"

- Etape 4 : C’est terminé. Si vous ouvrez un fichier php avec nano, vous constaterez que la synthaxe php est coloriée rendant la lecture plus facile.

Si vous avez regardé un petit peu la configuration présente dans le fichier /etc/nanorc, vous aurez peut être remarqué que vous pouvez activer la coloration synthaxique pour d’autres languages. Il suffit pour cela de décommenter les lignes commencant par “include” vers la fin du fichier.

Bon code php !

Tutoriel : Backup Manager sur Ubuntu

Vous disposez d’un serveur Ubuntu (ou Debian) que vous souhaitez sauvegarder (backup) régulièrement et surtout automatiquement : cet article est pour vous.

  • Objectifs du tutoriel

Télécharger, installer, configurer et faire fonctionner l’outil Backup-Manager afin de sauvegarder automatiquement vos données sur Serveur Ubuntu.

  • Présentation de Backup-Manager

Backup-Manager est un superbe outil en ligne de commande pour GNU/Linux.
Il permet de sauvegarder facilement:
- Fichiers
- Bases de données MySQL
- Repository SubVersion (SVN)

La destination des sauvegarde peut passer par :
- Un simple répertoire local
- Un CD /DVD
- FTP
- SCP
- SSH
- RSYNC
- S3

Le tout compressé au format : zip, tar.gz, tar.bz2, tar, (et quelques autres).

Un superbe outil, dont je ne peux honnêtement plus me passer aujourd’hui. Si vous décidez de suivre ce tutoriel, vous deviendrez vous aussi mordu de backup manager, vous êtes prévenu.

Le site officiel : http://www.backup-manager.org/

  • Pré-requis

- Une distribution Ubuntu ou Debian (ce sera très similaire pour n’importe quelle distribution Linux). Dans mon cas, Ubuntu Server “Hardy”.

- Un éditeur de texte (VI, Nano, …). Dans mon cas, Nano sera utilisé. Dans le doute, vous pouvez l’installer en tappant :
sudo apt-get install nano

Et hop, c’est parti !

  • Etape 1 : Télécharger et installer Backup-Manager

Backup-Manager fait partie des packages standards d’universe. Avant de pouvoir utiliser ces packages, il vous faut ajouter quelques lignes dans votre fichier sources.list.

Editez le fichier /etc/apt/sources.list :
sudo nano /etc/apt/sources.list

Vérifiez la présence (et ajouter si nécessaire) les lignes suivantes :
deb http://archive.ubuntu.com/ubuntu/ hardy universe
deb-src http://archive.ubuntu.com/ubuntu/ hardy universe

Note : Vous devez remplacer hardy par le nom de votre distribution Ubuntu (dapper, feisty, …)

Installez désormais backup-manager :
sudo apt-get install backup-manager

Et voilà l’installation est terminée. Jusque là, “easy”, et je vous rassure cela va le rester.

  • Etape 2 : Configurer Backup-Manager

Il suffit pour cela d’éditer un seul et unique fichier :
sudo nano /etc/backup-manager.conf

La technique consiste à prendre votre temps et à parcourir dans l’ordre le fichier pour réaliser le paramétrage. Si vous ne savez pas quoi mettre, laissez la valeur par défaut. L’aide en ligne peut s’avérer très utile même si le fichier de configuration est très bien documenté.

Fixez le répertoire dans lequel les archives seront copiés :
export BM_REPOSITORY_ROOT="/var/archives"

Précisez le temps pendant lequel les archives seront conservées (ici 5 jours) :
export BM_ARCHIVE_TTL="5"

Selectionnez le type de backup à effectuer. Ici nous optons pour des backups incrémentales pour le fichiers + backup MySQL :
export BM_ARCHIVE_METHOD="tarball-incremental mysql"

Choisissez le format des backup (zip, tar, gz). Dans notre cas nous optons pour du zip (et oui, j’ai aussi des OS Windows…) :
export BM_TARBALL_FILETYPE="zip"

Préciser les répertoires de votre disque que vous souhaitez sauvegarder. Ici nous sauvegardons le “home” du mon utilisateur, apache2 (pour les fichiers de conf), php5 (toujours pour la conf), et tous les sites web hébergés par mon serveur :
export BM_TARBALL_DIRECTORIES="/home/toto /etc/apache2 /etc/php5 /var/www/"

Préciser la fréquence des FULL backup (backup complète permettant ensuite d’effectuer des backup incrémentales). Perso j’aime bien l’idée d’avoir quelque chose de frais toutes les semaines, le lundi dans l’exemple :
export BM_TARBALLINC_MASTERDATETYPE="weekly"
export BM_TARBALLINC_MASTERDATEVALUE="1"

Note : Pour une Full backup le premier jour de chaque mois. Saisissez simplement :
# BM_TARBALLINC_MASTERDATETYPE="monthly"
# BM_TARBALLINC_MASTERDATEVALUE="1"

Préciser les bases de données MYSQL que vous souhaitez sauvegarder (dans notre cas, on sauvegarde tout), ainsi le compte MYSQL à utiliser :
export BM_MYSQL_DATABASES="__ALL__"
export BM_MYSQL_ADMINLOGIN="compte administrateur ici"
export BM_MYSQL_ADMINPASS="mot de passe ici"
export BM_MYSQL_HOST="localhost"
export BM_MYSQL_PORT="3306"
export BM_MYSQL_FILETYPE="gzip"

Note : Si vous n’avez pas de base MYSQL, ne touchez rien

Dans notre cas, nous avons choisi d’uploader les fichiers par FTP simple sur un serveur distant dans le répertoire backup :
export BM_UPLOAD_METHOD="ftp"
export BM_UPLOAD_FTP_SECURE="false"
export BM_UPLOAD_FTP_PASSIVE="true"
export BM_UPLOAD_FTP_USER="compte ftp ici"
export BM_UPLOAD_FTP_PASSWORD="mot de passe ftp ici"
export BM_UPLOAD_FTP_HOSTS="ftp.monserveur.com"
export BM_UPLOAD_FTP_PURGE="true"
export BM_UPLOAD_FTP_DESTINATION="backup"

Attention : Vous devrez créer manuellement le répertoire backup sur votre serveur FTP, sinon cela ne fonctionnera pas

Et voilà, la configuration est terminée ! Vous aurez notez au passage qu’il est très facile de configurer Backup-Manager pour utiliser un flux SSH, RSYNC ou encore sauvegarder vos fichiers SubVersion (SVN).

  • Etape 3 : Automatisez le lancement de vos backups

Vous pouvez, pour tester lancer manuellement une première fois Backup-Manager :
sudo /usr/sbin/backup-manager

Note : Si vous relancer à nouveau les backups, vous constaterez sans doute que certaines archives seront ignorées car marquées comme déjà existantes : Et oui, vous venez de le faire tourner…

Nous allons ensuite créer un fichier qui sera exécuté tous les jours :
sudo nano /etc/cron.daily/backup-manager

Copier / Coller ensuite le contenu ci-dessous dans votre fichier :
#!/bin/sh
# cron script for backup-manager
test -x /usr/sbin/backup-manager || exit 0
/usr/sbin/backup-manager

Vérifions maintenant les permissions sur le fichier que nous venons de créer avec de s’assurer qu’il sera exécuté correctement :
sudo chown root:root /etc/cron.daily/backup-manager
sudo chmod 755 /etc/cron.daily/backup-manager

  • Conclusion

C’est tout ! Votre système de backup est en place vous permettant de sauvegarder vos fichiers, vos bases MySQL et d’uploader le tout sur un serveur FTP distant de manière quotidienne.

N’hésitez pas à me faire vos retours pour que je puisse adapter cet article.

Sources pour écrire cet article :
http://packages.ubuntu.com/search?searchon=names&keywords=backup-manager
http://documentation.dedibox.fr/doku.php?id=gestion:dedibackup2
http://www.backup-manager.org