Partie 1 : Mise en place d’un serveur Unifi en Haute-Disponibilité

Le but de ce tutoriel est de réaliser par vous-même un cluster Unifi avec haute-disponibilité : a l’heure ou j’écris ces lignes, dans la roadmap Ubiquiti, cela n’existe pas. Pourtant, il s’agit d’un vrai manque car les situations ou avoir un serveur Unifi en haute-disponibilité sont nombreuses : portail captif, authentification Radius, continuité de service, etc … Unifi étant basée sur la base de données MongoDB, nous allons mettre en place ce cluster manuellement via une réplication entre deux instances MongoDB.

Le tutoriel suivant est inspiré de celui de “plon“, disponible ici : https://medium.com/@plon/how-i-made-my-unifi-controller-high-available-aa07df1d19c6. J’ai décidé de traduire et de compléter ce tutoriel afin d’avoir une vraie méthode, pas à pas, pour mettre en place un cluster. 

De même, la configuration de MongoDB utilisée ici est tirée de l’article correspondant sur le blog de Loïc Guilloishttp://www.loicguillois.fr/mettre-en-place-le-sharding-et-le-failover-avec-mongodb

Le tutoriel à été réalisé sous Ubuntu 16.04, et il a aussi été validé sous Debian 9.0 et Ubuntu 18.04. 

Le cadre dans lequel nous allons travailler est le suivant :

  • Deux serveurs dédiés, le serveur Unifi1 d’IP X.X.X.X et le serveur Unifi2 d’IP Y.Y.Y.Y
  • Une IP Failover Z.Z.Z.Z, qui peut être attribuée a un des deux serveurs selon le besoin.

Les IPs sont des IP Publiques, accessibles depuis Internet.
Nous avons aussi trois enregistrements DNS, sur le domaine de votre choix. Ici pour l’exemple, votredomaine.fr :

  • unifi1.votredomaine.fr pointant vers X.X.X.X,
  • unifi2.votredomaine.fr pointant vers Y.Y.Y.Y,
  • unifi.votredomaine.fr pointant vers Z.Z.Z.Z

Les deux serveurs sont hébergés chez Dedi-Online, ainsi que l’IP Failover. Il est tout à fait possible de l’héberger sur n’importe quel autre plateforme proposant des serveurs et des IP Failovers, il faudra juste adapter le tutoriel à votre configuration ! L’infrastructure peut être déployée aussi sur un réseau local, toutefois pour le bien du tutoriel nous utiliserons ici des serveurs dédiés accessibles publiquement pour rendre disponible notre cluster sur Internet.

Le tutoriel demande des compétences certaines sur les serveurs Unifi et sur les systèmes Unix : il est possible de suivre le tutoriel sans rien connaître de tout ça, toutefois vous risquez d’être très vite perdu. Je vous recommande d’avoir une base de connaissance dans ces domaines avant de vous attaquer à ce tutoriel 🙂 

L’infrastructure que nous allons déployer peut-être résumée de la façon suivante : 

Figure 1 : Schéma de l’infrastructure réseau utilisée dans le tutoriel

Sur le papier, l’architecture est assez simple : une réplication entre deux instances MongoDB sur deux serveurs différents, chacun disposant d’une interface Web Unifi connectée sur ce cluster MongoDB. Une IP Failover permet ensuite d’accéder au service Unifi, le but étant de travailler sur l’un ou l’autre des serveurs de façon transparente et avec une haute-disponibilité. C’est parti pour la pratique ! 

1. Installation d’Unifi

Première étape, nous allons devoir installer Unifi et MongoDB sur les deux serveurs. Pour pouvoir installer le plus facilement possible ces paquets, Glenn R. propose sur le forum Ubiquiti des scripts d’installation automatique qui réalise l’installation de A à Z, sans prise de tête ! On va donc le télécharger et l’exécuter sur nos deux serveurs afin d’installer Unifi et toutes ses dépendances, sans efforts et surtout sans conflits !
A noter qu’ici le script exécuté est la version pour Ubuntu 16.04, version d’Ubuntu choisie pour le tutoriel, toutefois d’autres versions sont disponibles sur le forum ainsi que les commandes relatives à son installation : https://community.ubnt.com/t5/UniFi-Wireless/UniFi-Installation-Scripts-Works-on-Ubuntu-18-04-and-16-04/td-p/2375150.
Au moment ou je rédige ce tutoriel, la version d’Unifi stable est la 5.9.29. De la même façon, adapter les commandes à la version en cours.

Sur les deux serveurs, on lance donc les commandes suivantes :

root@unifi1:~# apt-get install ca-certificates -y
root@unifi1:~# wget https://get.glennr.nl/unifi/5.9.29/U1604/unifi-5.9.29.sh; chmod +x unifi-5.9.29.sh
root@unifi1:~# ./unifi-5.9.29.sh
root@unifi2:~# apt-get install ca-certificates -y
root@unifi2:~# wget https://get.glennr.nl/unifi/5.9.29/U1604/unifi-5.9.29.sh; chmod +x unifi-5.9.29.sh
root@unifi2:~# ./unifi-5.9.29.sh

Le script se déroule automatiquement, et sans actions de votre part. Excepté une demande, ou vous devez sélectionner No pour la question “Would you like to update the controller version when running the following command?”
Cette question permet d’indiquer si on veut qu’Unifi soit mis à jour lorsqu’on met à jour les paquets du système. Pour éviter une future incompatibilité avec notre installation, il est préférable de faire les futures mises à jours d’Unifi manuellement pour ce cluster.

2. Création du service MongoDB

Unifi démarre une instance MongoDB automatiquement lorsque le service est lancé, au démarrage. On va créer une instance de MongoDB “extérieure” au service Unifi pour qu’elle démarre avec le système, et qu’on puisse la configurer pour la réplication.
Sur les deux serveurs, on créé donc le service mongodb avec les paramètres nécessaires pour qu’il se lance au démarrage :

root@unifi1:~# nano /etc/systemd/system/mongodb.service
[Unit]
Description=High-performance, schema-free document-oriented database
After=network.target

[Service]
User=mongodb
ExecStart=/usr/bin/mongod --quiet --config /etc/mongod.conf

[Install]
WantedBy=multi-user.target
root@unifi2:~# nano /etc/systemd/system/mongodb.service
[Unit]
Description=High-performance, schema-free document-oriented database
After=network.target

[Service]
User=mongodb
ExecStart=/usr/bin/mongod --quiet --config /etc/mongod.conf

[Install]
WantedBy=multi-user.target

Sur les deux serveurs, on créé ensuite le dossier de travail de MongoDB, qui n’existe pas forcément après l’installation d’Unifi :

root@unifi1:~# mkdir /var/run/mongodb/
root@unifi2:~# mkdir /var/run/mongodb/

Sur les deux serveurs, on va venir ensuite modifier le fichier de configuration de MongoDB. Les arguments à modifier sont les suivants :

root@unifi1:~# nano /etc/mongod.conf
root@unifi2:~# nano /etc/mongod.conf
# network interfaces
net:
  port: 27017
  bindIp: 0.0.0.0


#replication:
replication:
   replSetName: "HA"

BindIP doit être mis à “0.0.0.0” pour que MongoDB écoute sur tous les ports et pas juste localement, ce qui est nécessaire pour que chaque MongoDB puisse contacter l’autre serveur.
La réplication doit être activée, et le replSetName doit être configuré. Il s’agit de l’identifiant de réplication, vous pouvez mettre n’importe quel nom qui vous conviendra, il faudra le retenir pour plus tard. Ici nous appellerons notre cluster MongoDB “HA“. 

Puis, sur les deux serveurs, on active le service mongodb au démarrage et on le lance :

root@unifi1:~# systemctl enable mongodb
root@unifi1:~# service mongod start
root@unifi2:~# systemctl enable mongodb
root@unifi2:~# service mongod start

Vous pouvez vérifier que tout fonctionne bien via la commande “service mongod status

root@unifi1:~# service mongod status

3. Mise en place de la réplication

Notre service MongoDB est maintenant fonctionnel sur les deux serveurs. Pour pouvoir mettre en place la réplication entre nos deux MongoDB préalablement configurées, il suffit de lancer la commande “mongo” sur le serveur primaire :

root@unifi1:~# mongo

MongoDB shell version v3.4.18
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.18
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
        http://docs.mongodb.org/
Questions? Try the support group
        http://groups.google.com/group/mongodb-user
Server has startup warnings:
2018-11-20T14:09:14.685+0100 I STORAGE  [initandlisten]
2018-11-20T14:09:14.685+0100 I STORAGE  [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2018-11-20T14:09:14.685+0100 I STORAGE  [initandlisten] **          See http://dochub.mongodb.org/core/prodnotes-filesystem
2018-11-20T14:09:15.262+0100 I CONTROL  [initandlisten]
2018-11-20T14:09:15.262+0100 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2018-11-20T14:09:15.262+0100 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2018-11-20T14:09:15.262+0100 I CONTROL  [initandlisten]
2018-11-20T14:09:15.263+0100 I CONTROL  [initandlisten]
2018-11-20T14:09:15.263+0100 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2018-11-20T14:09:15.263+0100 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2018-11-20T14:09:15.263+0100 I CONTROL  [initandlisten]
>

Puis exécuter les deux commandes suivantes dans la console de MongoDB. Attention à modifier X.X.X.X et Y.Y.Y.Y par les IP de votre serveur primaire et secondaire . Idem, remplacer “HA par le replSetName défini un peu plus tôt, si vous l’avez modifié :

cfg = {
_id : "HA",
members : [
{ _id : 0, host : "X.X.X.X:27017"},
{ _id : 1, host : "Y.Y.Y.Y:27017"},
] }
rs.initiate(cfg)

Pour vérifier que la réplication est bien active, on peut utiliser la commande “db.isMaster()” dans la console Mongo, sur le serveur primaire ou sur le serveur secondaire :

HA:OTHER> db.isMaster()
{
        "hosts" : [
                "X.X.X.X:27017",
                "Y.Y.Y.Y:27017"
        ],
        "setName" : "HA",
        "setVersion" : 1,
        "ismaster" : true,
        "secondary" : false,
        "primary" : "X.X.X.X:27017",
        "me" : "Y.Y.Y.Y:27017",
        "electionId" : ObjectId("7fffffff0000000000000001"),
        "lastWrite" : {
                "opTime" : {
                        "ts" : Timestamp(1542719553, 1),
                        "t" : NumberLong(1)
                },
                "lastWriteDate" : ISODate("2018-11-20T13:12:33Z")
        },
        "maxBsonObjectSize" : 16777216,
        "maxMessageSizeBytes" : 48000000,
        "maxWriteBatchSize" : 1000,
        "localTime" : ISODate("2018-11-20T13:12:43.390Z"),
        "maxWireVersion" : 5,
        "minWireVersion" : 0,
        "readOnly" : false,
        "ok" : 1
}
HA:PRIMARY> exit
bye

root@unifi1:~#
root@unifi2:~# mongo

MongoDB shell version v3.4.18
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.18
Welcome to the MongoDB shell.
For interactive help, type "help".
For more comprehensive documentation, see
        http://docs.mongodb.org/
Questions? Try the support group
        http://groups.google.com/group/mongodb-user
Server has startup warnings:
2018-11-20T14:09:15.284+0100 I STORAGE  [initandlisten]
2018-11-20T14:09:15.284+0100 I STORAGE  [initandlisten] ** WARNING: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine
2018-11-20T14:09:15.284+0100 I STORAGE  [initandlisten] **          See http://dochub.mongodb.org/core/prodnotes-filesystem
2018-11-20T14:09:15.861+0100 I CONTROL  [initandlisten]
2018-11-20T14:09:15.861+0100 I CONTROL  [initandlisten] ** WARNING: Access control is not enabled for the database.
2018-11-20T14:09:15.861+0100 I CONTROL  [initandlisten] **          Read and write access to data and configuration is unrestricted.
2018-11-20T14:09:15.861+0100 I CONTROL  [initandlisten]
2018-11-20T14:09:15.861+0100 I CONTROL  [initandlisten]
2018-11-20T14:09:15.861+0100 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2018-11-20T14:09:15.861+0100 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2018-11-20T14:09:15.861+0100 I CONTROL  [initandlisten]

HA:SECONDARY> exit
bye

root@unifi2:~#

Le “prompt” de votre console MongoDB indique le statut de votre base de données, Primary ou Secondary. Notre réplication est maintenant fonctionnelle. 

4. Mise en place du Cluster UNIFI

Maintenant que nous avons correctement configuré MongoDB sur nos deux serveurs et que nous disposons d’une base de données répliquée, il faut indiquer à Unifi de travailler sur cette nouvelle base plutôt que sur l’instance sur laquelle il travaille habituellement. Un fichier de configuration est à notre disposition, qui est décrit sur la documentation Ubiquiti : https://help.ubnt.com/hc/en-us/articles/205202580-UniFi-system-properties-File-Explanation

Sur les deux serveurs, ajouter les lignes suivantes à la fin du fichier /usr/lib/unifi/data/system.properties (“X.X.X.X” est mon primaire, “Y.Y.Y.Y” est mon secondaire, “HA” est mon nom de replicationSet de MongoDB, défini dans la configuration précédemment).
Remplacer les IP par votre configuration et le nom du replicaSet par celui que vous avez défini, si vous l’avez modifié.

root@unifi1:~# nano /usr/lib/unifi/data/system.properties
root@unifi2:~# nano /usr/lib/unifi/data/system.properties
db.mongo.local=false
db.mongo.uri=mongodb\://X.X.X.X,Y.Y.Y.Y\:27017/unifi?replicaSet\=HA
reporter-uuid=bb2601fe-ba4c-44ee-b157-c8646bfecdec
statdb.mongo.uri=mongodb\://X.X.X.X,Y.Y.Y.Y\:27017/unifi?replicaSet\=HA
unifi.db.name=HA

Redémarrer le service Unifi sur les deux serveurs :

root@unifi1:~# service unifi restart
root@unifi2:~# service unifi restart

Se connecter via votre navigateur Web sur l’interface WEB des deux serveurs. Les URLS sont les suivantes (remplacer par les IP de vos serveurs) :

https://X.X.X.X:8443 
https://Y.Y.Y.Y:8443 


Sur chacun des serveurs, passer toutes les étapes de l’assistant de configuration Unifi, selon votre configuration souhaitée :


Indiquer votre pays ainsi que le fuseau horaire correspond pour votre serveur



Faire “Skip” directement, on ajoutera les équipements plus tard



Faire “Skip” directement, on configurera le Wifi plus tard

Ajouter un compte pour l’accès à l’interface Web, ainsi que pour l’accès SSH des équipements. C’est le compte qui servira à vous connecter par la suite.


Puis valider votre configuration.


Si besoin, entrez vos identifiants ubnt.com, sinon faites “Skip”.

Il est nécessaire de se connecter sur les deux serveurs via l’interface WEB, et de passer les assistants sur les deux serveurs en rentrant les mêmes informations, pour éviter les conflits dans le cluster. Une fois les assistants terminés, connectez / déconnecter vous au moins une fois sur l’interface de chaque serveur.

Figure 2 : Dashboard du serveur Unifi.

Puis redémarrer le service Unifi sur les deux serveurs :

root@unifi1:~# service unifi restart
root@unifi2:~# service unifi restart

Le cluster est maintenant fonctionnel. Toutefois, il est nécessaire de synchroniser les dossiers entre les deux serveurs pour éviter les conflits. Nous allons voir ça toute de suite.

5. Synchronisation des dossiers Unifi entre les deux serveurs

Nous allons pour cela utiliser le paquet Unix “unison” qui permet une synchronisation simple de deux dossiers, dans les deux sens. Y compris via SSH, puisque ici nous allons utiliser SSH pour synchroniser le même dossier mais sur deux serveurs distants.
Nous allons configurer le SSH pour permettre une connexion via le compte root entre le serveur primaire, et le serveur secondaire. Le dossier de travail d’Unifi sera synchronisé entre les deux serveurs via SSH, pour que les deux serveurs disposent des mêmes fichiers.

En premier lieu, installez les paquets suivants sur les deux serveurs :

root@unifi1:~# apt-get -y install unison openssh-server ssh
root@unifi2:~# apt-get -y install unison openssh-server ssh 

Mettre ensuite un mot de passe à l’utilisateur root sur les deux serveurs (ce n’est pas le cas par défaut, puisque nous sommes sur Ubuntu !).

root@unifi1:~# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
root@unifi2:~# passwd
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully

Nous allons aussi configurer le service SSH pour permettre à l’utilisateur root de se connecter. Sur les deux serveurs, ouvrez le fichier de configuration de SSH : 

root@unifi1:~# nano /etc/ssh/sshd_config
root@unifi2:~# nano /etc/ssh/sshd_config

Modifier la ligne “PermitRootLogin” en passant le paramètre à “yes” au lieu de “prohibit-password

# Authentication:
LoginGraceTime 120
PermitRootLogin yes
StrictModes yes

Puis redémarrer le service ssh sur les deux serveurs :

root@unifi1:~# service ssh reload
root@unifi2:~# service ssh reload

Sur le serveur primaire, exécuter la commande suivante (aux 3 questions, faire juste Entrée) :

root@unifi1:~# ssh-keygen

Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Created directory '/root/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:d0twWEH2Bzw7cjbBKN4fgyhMO6HoaHu46oFMjEt2y2Y root@unifi1
The key's randomart image is:
+---[RSA 2048]----+
|           .==.  |
|        o .+..=. |
|     . + +o+...+.|
|o   . . = oo+ O. |
|.= +    So. o= = |
|*.= o    . o ..  |
|o+ E        .    |
|  * .            |
|oo.o             |
+----[SHA256]-----+

Puis lancer la commande “ssh-copy-id root@Y.Y.Y.Y” sur votre serveur primaire, ou Y.Y.Y.Y est l’IP de votre serveur secondaire

root@unifi1:~# ssh-copy-id root@Y.Y.Y.Y

/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host 'Y.Y.Y.Y (Y.Y.Y.Y)' can't be established.
ECDSA key fingerprint is SHA256:mU2x0/iTNARkHD6oBKIcRXzBv6MA0KvDmArJmInRzPM.
Are you sure you want to continue connecting (yes/no)? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
root@51.15.172.29's password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@Y.Y.Y.Y'"
and check to make sure that only the key(s) you wanted were added.

Exécuter la commande suivante sur le serveur primaire, en remplaçant “Y.Y.Y.Y” par l’IP de votre serveur secondaire : 

root@unifi1:~# /usr/bin/unison -batch /usr/lib/unifi/data/sites/ ssh://root@Y.Y.Y.Y//usr/lib/unifi/data/sites/

La commande doit rendre ce genre d’informations :

root@unifi1:~# /usr/bin/unison -batch /usr/lib/unifi/data/sites/ ssh://root@Y.Y.Y.Y//usr/lib/unifi/data/sites/

Contacting server...
Connected [//unifi1//var/lib/unifi/sites -> //unifi2//var/lib/unifi/sites]
Looking for changes
Warning: No archive files were found for these roots, whose canonical names are:
        /var/lib/unifi/sites
        //unifi2//var/lib/unifi/sites
This can happen either
because this is the first time you have synchronized these roots,
or because you have upgraded Unison to a new version with a different
archive format.

Update detection may take a while on this run if the replicas are
large.

Unison will assume that the 'last synchronized state' of both replicas
was completely empty.  This means that any files that are different
will be reported as conflicts, and any files that exist only on one
replica will be judged as new and propagated to the other replica.
If the two replicas are identical, then no changes will be reported.

If you see this message repeatedly, it may be because one of your machines
is getting its address from DHCP, which is causing its host name to change
between synchronizations.  See the documentation for the UNISONLOCALHOSTNAME
environment variable for advice on how to correct this.

Donations to the Unison project are gratefully accepted:
http://www.cis.upenn.edu/~bcpierce/unison

  Waiting for changes from server
Reconciling changes
file     ---->            default/map/5bf52bbeeb0e001b540fc8fd
local        : file               modified on 2018-11-21 at 10:56:14  size 84596     rw-r-----
unifi2       : absent
         <---- file       default/map/5bf52bc42b14dd1c0704fc3a
local        : absent
unifi2       : file               modified on 2018-11-21 at 10:56:20  size 84596     rw-r-----
         <---- file       default/map/5bf52d402b14dd22b6b3825c
local        : absent
unifi2       : file               modified on 2018-11-21 at 11:02:40  size 84596     rw-r-----
file     ---->            default/map/5bf52d40eb0e0021d7a683c3
local        : file               modified on 2018-11-21 at 11:02:40  size 84596     rw-r-----
unifi2       : absent
Propagating updates
UNISON 2.48.3 started propagating changes at 11:06:23.66 on 21 Nov 2018
[BGN] Copying default/map/5bf52bbeeb0e001b540fc8fd from /var/lib/unifi/sites to //unifi2//var/lib/unifi/sites
[BGN] Copying default/map/5bf52bc42b14dd1c0704fc3a from //unifi2//var/lib/unifi/sites to /var/lib/unifi/sites
[BGN] Copying default/map/5bf52d402b14dd22b6b3825c from //unifi2//var/lib/unifi/sites to /var/lib/unifi/sites
[BGN] Copying default/map/5bf52d40eb0e0021d7a683c3 from /var/lib/unifi/sites to //unifi2//var/lib/unifi/sites
Shortcut: copied /var/lib/unifi/sites/default/map/5bf52bc42b14dd1c0704fc3a from local file /var/lib/unifi/sites/default/map/5bf52d40eb0e0021d7a683c3
Shortcut: copied /var/lib/unifi/sites/default/map/5bf52d402b14dd22b6b3825c from local file /var/lib/unifi/sites/default/map/.unison.5bf52bc42b14dd1c0704fc3a.5fa200cbec221d2964bc46cefa7db551.unison.tmp
Shortcut: copied /var/lib/unifi/sites/default/map/5bf52bbeeb0e001b540fc8fd from local file /var/lib/unifi/sites/default/map/5bf52d402b14dd22b6b3825c
Shortcut: copied /var/lib/unifi/sites/default/map/5bf52d40eb0e0021d7a683c3 from local file /var/lib/unifi/sites/default/map/.unison.5bf52bbeeb0e001b540fc8fd.e76285476404edf53d5259a1c9fdcf60.unison.tmp
[END] Copying default/map/5bf52bbeeb0e001b540fc8fd
[END] Copying default/map/5bf52bc42b14dd1c0704fc3a
[END] Copying default/map/5bf52d402b14dd22b6b3825c
[END] Copying default/map/5bf52d40eb0e0021d7a683c3
UNISON 2.48.3 finished propagating changes at 11:06:23.68 on 21 Nov 2018
Saving synchronizer state
Synchronization complete at 11:06:23  (4 items transferred, 0 skipped, 0 failed)

Pour s’assurer du bon fonctionnement de la synchronisation, créer le fichier test.txt sur le serveur secondaire. Puis exécuter à nouveau la commande de synchronisation sur le serveur primaire. Le fichier doit apparaître sur le serveur primaire.

root@unifi2:~# touch /usr/lib/unifi/data/sites/test.txt
root@unifi1:~# /usr/bin/unison -batch /usr/lib/unifi/data/sites/ ssh://root@Y.Y.Y.Y//usr/lib/unifi/data/sites/
Contacting server...
Connected [//unifi1//var/lib/unifi/sites -> //unifi2//var/lib/unifi/sites]
Looking for changes
  Waiting for changes from server
Reconciling changes
         <---- new file   test.txt
local        : absent
unifi2       : new file           modified on 2018-11-20 at 15:09:41  size 0         rw-r--r--
Propagating updates
UNISON 2.48.3 started propagating changes at 15:11:36.53 on 20 Nov 2018
[BGN] Copying test.txt from //unifi2//var/lib/unifi/sites to /var/lib/unifi/sites
[END] Copying test.txt
UNISON 2.48.3 finished propagating changes at 15:11:36.54 on 20 Nov 2018
Saving synchronizer state
Synchronization complete at 15:11:36  (1 item transferred, 0 skipped, 0 failed)

De même, en supprimant le fichier test.txt sur le serveur primaire et en synchronisant à nouveau, il doit disparaître des deux serveurs :

root@unifi1:~# rm /usr/lib/unifi/data/sites/test.txt

root@unifi1:~# /usr/bin/unison -batch /usr/lib/unifi/data/sites/ ssh://root@Y.Y.Y.Y//usr/lib/unifi/data/sites/
Contacting server...
Connected [//unifi1//var/lib/unifi/sites -> //unifi2//var/lib/unifi/sites]
Looking for changes
  Waiting for changes from server
Reconciling changes
deleted  ---->            test.txt
local        : deleted
unifi2       : unchanged file     modified on 2018-11-20 at 15:11:36  size 0         rw-r--r--
Propagating updates
UNISON 2.48.3 started propagating changes at 15:11:56.11 on 20 Nov 2018
[BGN] Deleting test.txt from //unifi2//var/lib/unifi/sites
[END] Deleting test.txt
UNISON 2.48.3 finished propagating changes at 15:11:56.11 on 20 Nov 2018
Saving synchronizer state
Synchronization complete at 15:11:56  (1 item transferred, 0 skipped, 0 failed)
root@unifi2:~# ls /usr/lib/unifi/data/sites/test.txt
ls: cannot access '/usr/lib/unifi/data/sites/test.txt': No such file or directory

Ajouter la ligne suivante dans la crontab root sur le serveur primaire via la commande “crontab -e

root@unifi1:~# crontab -e
no crontab for root - using an empty one

Select an editor.  To change later, run 'select-editor'.
  1. /bin/ed
  2. /bin/nano        <---- easiest
  3. /usr/bin/vim.tiny

Choose 1-3 [2]: 2
# m h  dom mon dow   command
*/2 * * * * /usr/bin/unison -batch /usr/lib/unifi/data/sites/ ssh://root@Y.Y.Y.Y//usr/lib/unifi/data/sites/

La synchronisation des dossiers Unifi est maintenant fonctionnelle.

Conclusion

Félicitations, vous avez maintenant un superbe cluster Unifi fonctionnel ! Vous avez donc deux serveurs Unifi sur deux adresses/enregistrements DNS différents, avec une IP Failover que vous pouvez basculer entre les deux. Les deux serveurs Unifi sont synchronisés en permanence via la réplication de leur base de données et de leurs fichiers.
Vous pouvez réaliser des modifications sur l’une ou l’autre interface, retourner sur l’autre serveur et retrouver ces modifications.

/!\ Attention : les équipements Unifi doivent êtres adoptées sur l’IP Failover. Ils basculent automatiquement entre l’un ou l’autre serveur selon vers lequel vous pointez l’IP Failover. Il est possible de se connecter en Web indifférement sur n’importe laquelle des deux interfaces, ou via l’IP Failover. Les données seront les mêmes car synchronisées entre les bases. /!\

Le cluster est fonctionnel, toutefois quelques effets secondaires subsistent. En premier lieu, un refresh (F5) de votre page Web Unifi peut être nécessaire quand vous modifiez sur un serveur et que vous retourner sur l’autre, Unifi n’étant pas forcément prévu pour ce genre de fonctionnement. De même, les Maps peuvent avoir quelques soucis quand on passe d’un serveur à l’autre, je n’ai pas encore réussi à trouver de solution pour qu’elle soient pleinement fonctionnelles. Si vous avez plus d’informations à ce propos, n’hésitez pas à me le faire savoir !

A noter que dans mon cas, il était aussi nécessaire de configurer une interface manuellement sur chaque serveur pour accueillir l’IP Failover. C’est une configuration propre aux serveurs Dedi Online, toutefois il est possible que pour accueillir l’IP Failover, une configuration particulière soit nécessaire, référer vous à la documentation liée à votre plateforme d’hébergement. 

Il est nécessaire de faire la bascule de l’IP Failover manuellement, mais heureusement nous verrons dans le prochain article la partie 2 de notre tuto, ou comment piloter automatiquement l’IP Failover et basculer automatiquement en cas de panne sur un des services Unifi ou MongoDB !

D’ici là n’hésitez pas à commenter si vous avez des questions ou si vous avez besoin de précisions ! @ +

0 0 votes
Évaluation de l'article
S’abonner
Notification pour
guest
2 Commentaires
Le plus ancien
Le plus récent Le plus populaire
Commentaires en ligne
Afficher tous les commentaires
Ghislain
11 juillet 2019 13 h 04 min

Bonjour, Avant tout excellent tutoriel, complet et très lisible. Une petite remarque concernant les replica set de mongo db. dans ma version (3.4.21) J’ai eu une surprise lorsque j’ai déconnecté unifi2 qui était SECONDARY dans ma config. Dans ce cas, lorsque je me connectais à unifi1, j’obtenais des internal server error, le contrôleur primaire ne fonctionnait plus. Après avoir fouillé un peu la doc mongo: https://docs.mongodb.com/manual/core/replica-set-architectures/ Je vois qu’un replica set doit être composé d’au moins trois membres sur 3 machines distinctes pour fonctionner. En effet un principe d’élection du PRIMARY fait qu’il faut plus de 50% des votants pour… Lire la suite »

JML
JML
18 avril 2020 20 h 21 min

Merci pour ce tuto très lisible 😉 Comme Ghislain, je m’oriente vers la mise en place d’un arbitre et 2 hosts. J’ai adapté la méthode pour permettre une synchro avec une autre user que root 😉 J’ai restauré une sauvegarde plutôt que de faire une nouvelle installation. 700 sites 😉 cela a pris un peu de temps à MongoDB. Mon hôte primaire a généré tout d’abord des erreurs webSocket après la connexion à unifi. Le second était opérationnel. Je l’ai laissé tourner un peu et tout est en rentré en ordre. Les 2 hôtes sont fonctionnels. Côté problème: Je montais… Lire la suite »