Aller au contenu

Apache

TP4 : équilibrage de charge

allez voir : Doc de Beber le Goat

TP5 : Haute disponibilité et équilibrage de charge

Architecture à mettre en place

alt text

Création des machines virtuelles

Fichiers de config utiles : - /etc/network/interfaces -> pour les interfaces

1. Ncc-load-balancer

Récupérée du server-front du TP4.
Machines avec deux interfaces :
Interface Qamu -> 192.168.122.50
Interface interne -> 10.20.1.10

2. ncc-webserver1

Interface interne -> 10.20.1.20

iface enp1s0 inet static
address 10.20.1.20
netmask 255.255.255.0
gateway 10.20.1.10

Création user ncc :

sudo groupadd -g 110 ncc
sudo useradd -u 110 -g 110 -s /bin/bash ncc

3. ncc-webserver2

Interface interne -> 10.20.1.30

iface enp1s0 inet static
address 10.20.1.30
netmask 255.255.255.0
gateway 10.20.1.10

Création user ncc :

sudo groupadd -g 110 ncc
sudo useradd -u 110 -g 110 -s /bin/bash ncc

4. ncc-database

Interface interne -> 10.20.1.40

iface enp1s0 inet static
address 10.20.1.40
netmask 255.255.255.0
gateway 10.20.1.10

Création user ncc sans shell :

sudo groupadd -g 110 ncc
sudo useradd -u 110 -g 110 -s /sbin/nologin ncc

5. ncc-redis

Interface interne -> 10.20.1.50

iface enp1s0 inet static
address 10.20.1.50
netmask 255.255.255.0
gateway 10.20.1.10

Configuration de la machine ncc-database

Attention - Bind address

Mettre à 0.0.0.0 dans /etc/mysql/mariadb.conf.d/50-server.cnf :

bind-address = 0.0.0.0

Activer le port TCP par défaut 3306

Dans /etc/mysql/mariadb.cnf, décommenter la ligne :

port = 3306
sudo systemctl restart mariadb

Ajout des informations de configuration

Dans le répertoire /etc/mysql/mariadb.conf.d/

Dans 50-server.cnf :

[server]
skip_name_resolve = 1
innodb_buffer_pool_size = 128M
# innodb_buffer_pool_instances = 1
innodb_flush_log_at_trx_commit = 2
innodb_log_buffer_size = 32M
innodb_max_dirty_pages_pct = 90
query_cache_type = 1
query_cache_limit = 2M
query_cache_min_res_unit = 2k
query_cache_size = 64M
tmp_table_size= 64M
max_heap_table_size= 64M
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1

[mariadbd]
character_set_server = utf8mb4
collation_server = utf8mb4_general_ci
transaction_isolation = READ-COMMITTED
binlog_format = ROW

Dans 50-client.cnf :

[client]
default-character-set = utf8mb4

Répertoire de log

sudo mkdir -p /var/log/mysql
sudo chown -R mysql:mysql /var/log/mysql
sudo systemctl restart mariadb
sudo systemctl status mariadb

Configuration SQL

sudo mariadb
CREATE DATABASE IF NOT EXISTS nextcloud COMMENT 'nextcloud database';
CREATE USER IF NOT EXISTS ncc@localhost IDENTIFIED BY 'toto';
CREATE ROLE IF NOT EXISTS nccuser;
GRANT ALL ON nextcloud.* TO nccuser;
GRANT nccuser TO ncc@localhost;
GRANT nccuser TO ncc@'10.20.1.20' IDENTIFIED BY 'toto';
GRANT nccuser TO ncc@'10.20.1.30' IDENTIFIED BY 'toto';
SET DEFAULT ROLE nccuser FOR ncc@localhost;
SET DEFAULT ROLE nccuser FOR ncc@'10.20.1.20';
SET DEFAULT ROLE nccuser FOR ncc@'10.20.1.30';
FLUSH PRIVILEGES;

Vérifier les droits :

SHOW GRANTS FOR ncc@localhost;
SHOW GRANTS FOR ncc@'10.20.1.20';
SHOW GRANTS FOR ncc@'10.20.1.30';

Configuration de la machine ncc-redis

Configuration NFS

sudo apt install apache2 nfs-kernel-server

💡 On installe apache2 directement pour récupérer automatiquement l'utilisateur www-data avec le bon UID/GID, sans avoir à le créer manuellement.

Désactiver Apache sur ncc-redis (il ne doit pas tourner ici) :

sudo systemctl stop apache2
sudo systemctl disable apache2

Créer le répertoire partagé :

sudo mkdir -p /srv/nfs/ncshare
sudo chown -R www-data:www-data /srv/nfs/ncshare

Dans /etc/exports :

/srv/nfs/ncshare 10.20.1.20(rw,sync) 10.20.1.30(rw,sync)

Appliquer la configuration :

sudo exportfs -a
sudo systemctl restart nfs-kernel-server

Configuration Redis

sudo apt install redis

Dans /etc/redis/redis.conf, modifier les lignes suivantes :

# Remplacer la ligne bind existante par (retirer 127.0.0.1) :
bind 10.20.1.50

# Décommenter et mettre à systemd :
supervised systemd

# Décommenter et mettre à no :
protected-mode no

⚠️ Bien supprimer 127.0.0.1 de la ligne bind, on ne veut écouter que sur l'interface réseau interne.

sudo systemctl restart redis
sudo systemctl status redis

Configuration commune ncc-webserver1 et ncc-webserver2

⚠️ Tout ce qui suit est à faire sur les deux webservers. L'astuce est de tout faire sur ncc-webserver1 puis de cloner l'image disque pour obtenir ncc-webserver2, en pensant à changer l'adresse IP après le clonage.

Installation des paquets PHP et Apache

sudo apt install apache2 php-fpm php-pear
sudo apt install php-curl php-gd php-mbstring php-zip php-intl php-mysql php-apcu php-redis php-imagick

Configuration des modules Apache

Désactiver les modules incompatibles avec le mode FPM :

sudo a2dismod mpm_prefork
# Désactiver php[X.Y] si présent (sur Debian 13 c'est probablement déjà le cas)
sudo a2dismod php8.2   # adapter la version si nécessaire

Activer les modules nécessaires :

sudo a2enmod mpm_event proxy_fcgi setenvif rewrite headers env dir mime

Activer la configuration PHP-FPM (adapter la version) :

sudo a2enconf php8.2-fpm   # adapter la version

Commandes utiles Apache :

Action Commande
Activer un module sudo a2enmod [module]
Désactiver un module sudo a2dismod [module]
Activer une config sudo a2enconf [config]
Désactiver une config sudo a2disconf [config]

ℹ️ Si certains modules ou configs n'existent pas, ce n'est pas grave — ils ne sont pas indispensables au fonctionnement du TP.

Configuration PHP

Dans /etc/php/X.Y/fpm/php.ini (adapter X.Y à la version installée) :

memory_limit = 512M

Dans /etc/php/X.Y/fpm/pool.d/www.conf, décommenter les lignes suivantes pour que les variables d'environnement soient disponibles en mode FCGI :

env[PATH] = /usr/local/bin:/usr/bin:/bin
env[TMP] = /tmp
env[TMPDIR] = /tmp
env[TEMP] = /tmp

Hôte virtuel Nextcloud

Créer /etc/apache2/sites-available/nextcloud.conf :

# nextcloud virtual host

<VirtualHost *:80>
  DocumentRoot /var/www/nextcloud/
  ServerName  dav.mycloud.net

  <Directory /var/www/nextcloud/>
    Require all granted
    AllowOverride All
    Options FollowSymLinks MultiViews

    <IfModule mod_dav.c>
      Dav off
    </IfModule>
  </Directory>

  ProxyFCGIBackendType FPM
  <FilesMatch remote.php>
    SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
  </FilesMatch>

  # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
  # error, crit, alert, emerg.
  #LogLevel info ssl:warn
  ErrorLog ${APACHE_LOG_DIR}/dav-error.log
  CustomLog ${APACHE_LOG_DIR}/dav-access.log vhost_combined

</VirtualHost>

Activer le site et redémarrer Apache :

sudo a2ensite nextcloud
sudo a2dissite 000-default   # désactiver le site par défaut
sudo systemctl restart apache2

Montage NFS

sudo apt install nfs-common
sudo mkdir -p /srv/nfs/ncshare

Ajouter dans /etc/fstab pour que le montage soit persistant au redémarrage :

10.20.1.50:/srv/nfs/ncshare /srv/nfs/ncshare nfs rw,bg,intr 0 0

Monter le partage immédiatement et vérifier :

sudo mount /srv/nfs/ncshare
df -h | grep ncshare

Installation de Nextcloud sur ncc-webserver1

Téléchargement

Depuis le VDI, aller sur ce site et télécharger le fichier ZIP, puis l'envoyer sur webserver1 :

# D'abord sur le loadbalancer :
scp nextcloud-*.zip qamu@192.168.122.50:
# Puis depuis le loadbalancer vers webserver1 :
scp nextcloud-*.zip qamu@10.20.1.20:

💡 Si vous avez configuré ~/.ssh/config avec ProxyJump, une seule commande suffit depuis le VDI : scp nextcloud-*.zip webserver1:

Installation sur webserver1

sudo mv nextcloud-*.zip /var/www/
cd /var/www/
sudo unzip nextcloud-*.zip
sudo chown -R www-data:www-data nextcloud

Initialisation via OCC

⚠️ Les serveurs ncc-database et ncc-redis doivent être démarrés et le partage NFS monté avant de lancer cette commande.

cd /var/www/nextcloud
sudo -E -u www-data php occ maintenance:install \
     --database 'mysql' \
     --database-name 'nextcloud' \
     --database-host '10.20.1.40' \
     --database-user 'ncc' \
     --database-pass 'votre_mot_de_passe_bdd' \
     --admin-pass 'votre_mot_de_passe_admin' \
     --data-dir '/srv/nfs/ncshare'

✅ Si tout s'est bien passé, un message de confirmation s'affiche.
❌ En cas d'erreur de connexion à la base, vérifier le bind-address dans MariaDB (0.0.0.0) et relancer sudo systemctl restart mariadb.

Ajustement de config.php

Dans /var/www/nextcloud/config/config.php, ajouter les clés suivantes sans écraser ce qui existe déjà :

// Ajouter dav.mycloud.net aux domaines de confiance
'trusted_domains' =>
array (
  0 => 'localhost',
  1 => 'dav.mycloud.net',
),

// Cache local APCu
'memcache.local' => '\\OC\\Memcache\\APCu',

// Cache distribué Redis
'memcache.distributed' => '\\OC\\Memcache\\Redis',
'redis' => [
    'host' => '10.20.1.50',
    'port' => 6379,
    'timeout' => 0.0,
    'read_timeout' => 0.0,
],

// Proxy de confiance (le load balancer)
'trusted_proxies' => [ '10.20.1.10', ],

Test temporaire depuis le load balancer

Sur ncc-load-balancer, ajouter temporairement dans /etc/hosts :

10.20.1.20    dav.mycloud.net

Tester :

curl http://dav.mycloud.net

⚠️ Commenter ou supprimer cette ligne après le test, sinon la suite ne fonctionnera pas correctement.


Mécanisme de réplication ncc-webserver1 → ncc-webserver2

On ne réinstalle pas Nextcloud sur ncc-webserver2 manuellement : les valeurs de passwordsalt et secret générées lors de l'install seraient différentes, rendant les comptes utilisateurs incompatibles entre les deux serveurs. On réplique donc directement depuis webserver1.

1. Génération des clés SSH (sur webserver2, user ncc)

sudo su - ncc
ssh-keygen -t rsa   # Appuyer Entrée × 3 pour une clé sans passphrase
ssh-copy-id ncc@10.20.1.20

2. Script de filtrage SSH (sur webserver1)

Créer /home/ncc/filtre_ssh.sh :

#!/bin/bash

case $SSH_ORIGINAL_COMMAND in
    *\|*|*\;*|*\&)
        echo "UNAUTHORIZED COMMAND"
        ;;
    rsync*)
        $SSH_ORIGINAL_COMMAND
        ;;
    sudo\ rsync*)
        $SSH_ORIGINAL_COMMAND
        ;;
    *)
        echo "UNAUTHORIZED COMMAND"
        ;;
esac
chmod +x /home/ncc/filtre_ssh.sh

Dans /home/ncc/.ssh/authorized_keys sur webserver1, ajouter devant la clé publique de webserver2 la restriction suivante (tout sur une seule ligne) :

command="/home/ncc/filtre_ssh.sh",no-port-forwarding,no-X11-forwarding,no-agent-forwarding ssh-rsa AAAA... ncc@ncc-webserver2

3. Sudo sans mot de passe pour rsync (sur les DEUX webservers)

sudo visudo

Ajouter à la fin :

ncc     ALL=(root) NOPASSWD: /usr/bin/rsync

💡 Pourquoi sudo des deux côtés ? Côté webserver1, rsync doit lire des fichiers appartenant à www-data. Côté webserver2, il doit écrire dans /var/www/ qui appartient à root. Sans sudo, rsync n'aurait pas les droits suffisants des deux côtés.

4. Script de synchronisation (sur webserver2, user ncc)

mkdir -p /home/ncc/log

Créer /home/ncc/synchro.sh :

#!/bin/bash
sudo rsync -avz -e 'ssh -l ncc -i /home/ncc/.ssh/id_rsa' \
    --rsync-path="sudo rsync" \
    10.20.1.20:/var/www/nextcloud /var/www >> /home/ncc/log/synchro.log
chmod +x /home/ncc/synchro.sh

Tester la synchronisation :

/home/ncc/synchro.sh
cat /home/ncc/log/synchro.log   # vérifier que tout s'est bien passé
ls /var/www/nextcloud            # le dossier doit être présent

5. Crontab (sur webserver2, user ncc)

Installer exim4 pour la gestion des mails internes générés par cron :

sudo apt install exim4

Ajouter la tâche cron (en tant que user ncc) :

crontab -e
*/30 * * * * /home/ncc/synchro.sh

Configuration de ncc-load-balancer — HAProxy

Installation

sudo apt install haproxy

⚠️ Si vous avez récupéré la machine server-front du TP4, pensez à désactiver et arrêter Apache :

sudo systemctl stop apache2
sudo systemctl disable apache2

Configuration /etc/haproxy/haproxy.cfg

Ajouter à la fin du fichier :

frontend nextfront
    bind :80
    mode http
    default_backend webservers

backend webservers
    mode http
    balance roundrobin
    cookie SERVER insert indirect nocache
    server web1 10.20.1.20:80 check cookie web1
    server web2 10.20.1.30:80 check cookie web2
sudo systemctl restart haproxy
sudo systemctl status haproxy

💡 Comprendre la gestion de session : sans le mécanisme de cookie SERVER, un utilisateur authentifié sur web1 pourrait voir sa requête suivante traitée par web2 qui ne connaît pas sa session. HAProxy insère un cookie côté client indiquant sur quel serveur sa session a été ouverte, et toutes ses requêtes suivantes sont redirigées vers ce même serveur.


Test final depuis la machine cliente

Sur la machine cliente Debian, ajouter dans /etc/hosts :

192.168.122.50    dav.mycloud.net

Ouvrir Firefox et aller sur http://dav.mycloud.net. Se connecter avec le compte admin (mot de passe défini lors de l'installation OCC).

Surveiller les logs Apache en temps réel sur les deux webservers pour observer la répartition de charge :

# Sur webserver1 :
tail -f /var/log/apache2/dav-access.log

# Sur webserver2 :
tail -f /var/log/apache2/dav-access.log

Créer un second compte utilisateur depuis l'interface Nextcloud (menu Administrateur → Utilisateurs).

Ouvrir un second navigateur (ex: Chromium) et se connecter avec ce compte. Les requêtes doivent se répartir entre les deux webservers, visible dans les logs.