Création d’un CHATONS – 2/5 : déploiement du LAPP

Après avoir décrit les grandes lignes de la mission qui nous incombe dans l’épisode précédent Création d’un CHATONS – 1 / 5 : Généralités, nous allons à présent nous attaquer au vif du sujet sur le plan technique pour le déploiement et la configuration des divers services à mettre en place pour constituer un serveur de type L.A.P.P. requis pour le fonctionnement de NextCloud.

[ez-toc]

Système d’exploitation : Debian

Debian est l’une des plus anciennes distribution GNU/Linux.

Debian se distingue de la plupart des distributions fondées sur elle par son caractère non commercial et par le mode de gouvernance coopératif de l’association qui gère la distribution.

Installation

Installation standard Debian netinst 11 sans X-Windows sur la carte microSD installée (/dev/sde), en s’appuyant sur le document de référence fourni par le fondation Debian : Manuel d’installation pour la distribution Debian GNU/Linux

Outils administrateurs

Bases :

sudo apt-get update
sudo apt install dnsutils net-tools htop iftop screen etckeeper mercurial git vim mailutils ethtool debian-goodies pwgen

Aussi

sudo apt-get install ca-certificates apt-transport-https software-properties-common wget curl lsb-release

EtcKeeper

Afin de garder un historique des modifications effectuées dans l’arborescence /etc/* ; il faut à chaque changement soumettre ses modifications à EctKeeper qui s’appuie sur le système de versioning Mercurial.

Une fois les changements validés, il est demandé de soumettre les modifs :

sudo etckeeper commit

Si l’on souhaite savoir où on en est :

cd /etc/ && sudo hg status

Ou encore obtenir le log des modifs :

cd /etc/ && sudo hg log
 changeset: 0:09a9c9ebb03a
 tag: tip
 user: bastien@kane.landinux.lan
 date: Wed May 03 19:10:24 2023 +0200
 summary: INIT

Grappe de disques RAID

Nous choisissons le RAID de niveau 5, étant donné que nous avons 4 disques et que c’est le mode proposant un ratio capacité/sécurité le plus optimal.

Nous nous baserons sur ces deux tutoriaux/documentations :

Tout d’abord, créer les partitions sur chaque disque :

Création des partitions

Ce tutoriel décris assez bien les bases du partitionnement via la ligne de commande :

Nous allons donc initialiser les 4 tables de partitions pour les 4 disques /dev/sda, sdb, sdc et sdd :

sudo fdisk /dev/sdX

La taille importante des disques impose la création d’une table de partitions de type GPT. Il faut ensuite changer le type pour « Linux RAID ». Au final nous devons avoir ceci pour sda, sdb, sdc et sdd :

Disque /dev/sda : 3,64 TiB, 4000787030016 octets, 7814037168 secteurs
Modèle de disque : TOSHIBA HDWT840 
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 4096 octets
taille d'E/S (minimale / optimale) : 4096 octets / 4096 octets
Type d'étiquette de disque : gpt
Identifiant de disque : 88172725-B843-AA44-BA0C-F7F0A65BE5C1

Périphérique Début Fin Secteurs Taille Type
/dev/sda1 2048 7814037134 7814035087 3,6T RAID Linux

Il faudra donc répéter l’opération pour les 4 disques …

Création de l’aire RAID

Nous installons mdadm :

sudo apt install mdadm

Pour pouvoir créer l’aire RAID5 sur les 4 disques de 4To chacuns :

sudo mdadm --create /dev/md0 --level=5 --raid-devices=4 /dev/sda1 /dev/sdb1 /dev/sdc1 /dev/sdd1

L’exécution est immédiate :

mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.

La construction de l’aire RAID prend beaucoup, beaucoup, beaucoup de temps (presque 6 heures dans le cas présent). Nous pouvons en observer l’évolution via /proc/mdadm :

cat /proc/mdstat 
Personalities : [linear] [multipath] [raid0] [raid1] [raid6] [raid5] [raid4] [raid10] 
md0 : active raid5 sdd1[4] sdc1[2] sdb1[1] sda1[0]
11720655360 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/3] [UUU_]
[>....................] recovery = 0.0% (329756/3906885120) finish=1184.6min speed=54959K/sec
bitmap: 30/30 pages [120KB], 65536KB chunk

unused devices: <none>

L’opération est terminée une fois que nous avons cette sortie [4/4] [UUUU] :

md0 : active raid5 sdd1[4] sdc1[2] sdb1[1] sda1[0]
11720655360 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
bitmap: 0/30 pages [0KB], 65536KB chunk

unused devices: <none>

À ce moment, il est fortement recommandé de redémarrer le serveur avant d’utiliser la nouvelle aire RAID. Pour une raison que j’ignore /dev/md0 est renommé en /dev/md127

Nous pouvons à présent créer et formater la partition :

$ sudo fdisk /dev/md127
Le périphérique ne contient pas de table de partitions reconnue.
La taille du disque est 10,9 TiB (12001951088640 octets). Ce format de table de partitions DOS ne peut pas être utilisé sur des disques pour des volumes plus grands que 2199023255040 octets pour des secteurs de 512 octets. Utilisez le format de table de partitions à GUID (GPT).

Création d'une nouvelle étiquette pour disque de type DOS avec identifiant de disque 0xf15aa0ee.

Commande (m pour l'aide) : g
Une nouvelle étiquette de disque GPT a été créée (GUID : E52DF8C1-70EF-464B-B3F2-F1E19A22D459).

Nous pouvons créer la partition à proprement parler :

Commande (m pour l'aide) : n
Numéro de partition (1-128, 1 par défaut) : 
Premier secteur (3072-23441310686, 3072 par défaut) : 
Dernier secteur, +/-secteurs ou +/-taille{K,M,G,T,P} (3072-23441310686, 23441310686 par défaut) :

Une nouvelle partition 1 de type « Linux filesystem » et de taille 10,9 TiB a été créée.

Et vérifier avant de valider les modifications :

Commande (m pour l'aide) : p
Disque /dev/md127 : 10,92 TiB, 12001951088640 octets, 23441310720 secteurs
Unités : secteur de 1 × 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 4096 octets
taille d'E/S (minimale / optimale) : 524288 octets / 1572864 octets
Type d'étiquette de disque : gpt
Identifiant de disque : E52DF8C1-70EF-464B-B3F2-F1E19A22D459

Périphérique Début Fin Secteurs Taille Type
/dev/md127p1 3072 23441310686 23441307615 10,9T Système de fichiers Linux

Nous pouvons quitter en écrivant la table de partitions déjà crée :

Commande (m pour l'aide) : w
La table de partitions a été altérée.
Appel d'ioctl() pour relire la table de partitions.
Synchronisation des disques.

Maintenant, nous formatons cette vaste partition au standard ext4 :

$ sudo mkfs.ext4 /dev/md127p1 
mke2fs 1.46.2 (28-Feb-2021)
Creating filesystem with 2930163451 4k blocks and 366272512 inodes
Filesystem UUID: 46f704a2-911b-4ec9-882a-f37c2c7b0cec
Superblock backups stored on blocks: 
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968, 
102400000, 214990848, 512000000, 550731776, 644972544, 1934917632, 
2560000000

Allocating group tables: done 
Writing inode tables: done 
Creating journal (262144 blocks): done
Writing superblocks and filesystem accounting information: done

Ensuite, nous sauvegardons les données utilisateur qui pourraient être présentes dans le dossier /home actuel.
Fermer toutes les sessions utilisateur et se connecter directement en root. Au préalable, vérifier qu’il n’y ait pas d’autres sessions ouvertes :

w
14:37:20 up 1:00, 1 user, load average: 0,00, 0,01, 0,05
UTIL. TTY DE LOGIN@ IDLE JCPU PCPU QUOI
root pts/0 192.168.69.69 14:37 0.00s 0.00s 0.00s w

Nous comparons l’espace disponible dans le répertoire de destination et le poids du dossier /home :

df -h /
Sys. de fichiers Taille Utilisé Dispo Uti% Monté sur
/dev/sde3 50G 1,9G 45G 4% /
du -hs /home
48K /home

Nous pouvons sauvegarder ce répertoire très léger :

cp -Ra /home /root/

Et puis, après avoir vérifié qu’il ne contenait pas de fichiers cachés, supprimer tout le contenu de /home :

ls -a /home/
. ..
rm -R /home/*

Nous récupérons l’ID de la partition :

sudo blkid /dev/md127p1 
/dev/md127p1: UUID="46f704a2-911b-4ec9-882a-f37c2c7b0cec" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="55c3e13e-fd2e-fd4a-b3c8-6f2f84322128"

Il est temps de la monter dans le répertoire /home en ajoutant ces lignes à la configuration des montages : /etc/fstab :

# /home is RAID area /dev/md127
UUID=46f704a2-911b-4ec9-882a-f37c2c7b0cec /home ext4 defaults 0 2

Nous n’avons pas besoin de redémarrer, cependant ça peut être utile pour s’assurer que le montage s’effectue correctement au boot.

sudo mount /home
sudo df -h /home
Sys. de fichiers Taille Utilisé Dispo Uti% Monté sur
/dev/md127p1 11T 28K 11T 1% /home

sudo reboot

C’est tout bon : La grappe de disques est à présent pleinement fonctionnelle !

Serveur SSH

Afin de s’épargner une masse importante de tentatives de connections intempestives ; il est choisi de modifier le port SSH par défaut 22 pour, par exemple, 2402 :

/etc/ssh/sshd_config :

Port 2424
#Port 22

Appliquer les changements en redémarrant le service (à noter que celui-ci à la délicatesse de garder les sessions déjà ouvertes sur le port 22)

sudo service ssh restart

Pare-feu

Afin de se simplifier la vie, nous allons utiliser l’interface de gestion de pare-feu netfilter/iptables Uncomplicated Firewall, plus connu sous le diminutif ufw.

https://www.it-connect.fr/configurer-un-pare-feu-local-sous-debian-11-avec-ufw/

Config. provisoire UFW

sudo apt install ufw

Ensuite, l’établissement des règles est assez simple, du moins pour l’instant, nous souhaitons ouvrir en entrée les services/ports suivants :

  • HTTP : 80
  • HTTPS : 443
  • SSH : 2424 (port 22 par défaut modifié juste au dessus)
  • NFS : 2049
  • LDAP : 389
# Interdire tous le traffic entrant
sudo ufw default deny incoming
# Autoriser tous le traffic sortant
sudo ufw default allow outgoing

# Autoriser certains services :
# HTTP
sudo ufw allow http
# HTTPS
sudo ufw allow https
# SSH (port non-standard : 2424)
sudo ufw allow 2424/tcp
# NFS
sudo ufw allow nfs
# LDAP
sudo ufw allow ldap

# Lancer le tout !
sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

Nous pouvons activer cette configuration :

sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
Firewall is active and enabled on system startup

Nous pouvons vérifier le résultat :

sudo ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 2049                       ALLOW IN    Anywhere                  
[ 2] 389                        ALLOW IN    Anywhere                  
[ 3] 80/tcp                     ALLOW IN    Anywhere                  
[ 4] 443                        ALLOW IN    Anywhere                  
[ 5] 389 (v6)                   ALLOW IN    Anywhere (v6)             
[ 6] 80/tcp (v6)                ALLOW IN    Anywhere (v6)             
[ 7] 443 (v6)                   ALLOW IN    Anywhere (v6)             
[ 8] 2049 (v6)                  ALLOW IN    Anywhere (v6)

Si l’on souhaite supprimer l’une des régles, il faut indiquer son numéro présenté dans la liste précédente, par exemple :

sudo ufw delete 8

La modification est immédiate !
Éventuellement … :

sudo ufw reload

Tests fonctionnels

Depuis un autre hôte présent sur le LAN, nous allons effectuer quelques vérifications …

La base : vérifier si ça répond aux pings :

ping -c 2 cloud.landinux.lan
PING cloud.landinux.lan (192.168.69.10) 56(84) bytes of data.
64 octets de cloud.landinux.lan (192.168.69.10) : icmp_seq=1 ttl=64 temps=0.205 ms
64 octets de cloud.landinux.lan (192.168.69.10) : icmp_seq=2 ttl=64 temps=0.178 ms

--- statistiques ping cloud.landinux.lan ---
2 paquets transmis, 2 reçus, 0 % paquets perdus, temps 1026 ms
rtt min/moy/max/mdev = 0,178/0,191/0,205/0,013 ms

Et surtout faire un scan de ports :

nmap -p 0-4096 cloud.bastbalt.lan
Starting Nmap 7.80 ( https://nmap.org ) at 2023-05-06 18:28 CEST
Nmap scan report for cloud.bastbalt.lan (192.168.69.10)
Host is up (0.00024s latency).
Not shown: 4093 filtered ports
PORT     STATE  SERVICE
80/tcp   open   http
389/tcp  open   ldap
443/tcp  closed https
2049/tcp open   nfs

Nmap done: 1 IP address (1 host up) scanned in 12.40 seconds

Lors de la prochaine mise en production …

En dernier lieu, lors de la mise en production, il faudra redéfinir ces règles en fonction de l’architecture réseau et du contexte dans lequel le serveur va être placé. Notamment, dédier chaque port ethernet à une branche réseau, une interface devant être réservée au LAN et l’autre au WAN.

Sauvegardes

Blabla …

Quelques Extras

Résolutions des noms : contexte DNS

Durant l’installation et la configuration, nous souhaitons être accessible uniquement à l’intérieur du LAN.

Ainsi il convient que la résolution des noms soit correctement configurées sur le DNS utilisé sur le LAN. Un vrai routeur saurait être trop conseillé pour ce faire …

Il conviendra d’y renseigner un enregistrement de type A dans la config DNS utilisé sur le LAN, par exemple sur un routeur OpenWRT : /etc/hosts :

192.168.69.10 cloud.landinux.lan
/etc/init.d/dnsmasq restart

Serveur de dossiers partagés NFS

L’installation et la configuration sont assez simples !

sudo apt install nfs-common nfs-kernel-server
sudo systemctl start nfs-kernel-server.service

Il faudra éditer le fichiers /etc/exports :

# Example for NFSv4:
#/home 192.168.69.0/24 (rw,no_root_squash,no_subtree_check,async)
/home 192.168.69.0/24(rw,sync,no_subtree_check)

Nous appliquons cette config :

sudo exportfs -a

Serveur de mail Postfix

RelayHost

Annuaire des utilisateurs : OpenLDAP

Basé sur cette série de tutoriaux : http://tutoriels.meddeb.net/category/openldap-tutorial/

Openldap tutorial – Installation et configuration de base

/etc/pam.d/common-{auth,account,password,session

Le L.A.P.P.

Base de donnée : PostgreSQL

sudo apt install postgresql-all

Nous allons pouvoir créer la base et l’utilisateur dédié à Nextcloud :

sudo -u postgres psql -d template1
template1=# CREATE USER nextcloud CREATEDB;
template1=# CREATE DATABASE nextcloud OWNER nextcloud TEMPLATE template0 ENCODING 'UTF8';
template1=# GRANT CREATE ON SCHEMA public TO nextcloud; template1=# ALTER ROLE nextcloud WITH PASSWORD 'V1Vfl!TDElVx';

On se garde cette partie de la doc officielle NextCloud sous le coude : Database configuration

Serveur www Apache2

Nous pourrions aussi nous amuser avec NGinx, qui présente certains avantages tout autant qu’il est moins répandu, donc moins connu des techniciens.

Donc nous allons nous contenter du bon vieux Apache2.

Installation du serveur www Apache2 + PHP8-FPM

Les dernières version de NextCloud exigeant la version 8 de PHP ; on installe donc Apache2, PHP8.1-FPM (mode réputé le plus performant) et tout le bazar de modules PHP :

sudo apt install php8.1 php8.1-bcmath php8.1-bz2 php8.1-cgi php8.1-cli php8.1-common php8.1-curl php8.1-dev php8.1-fpm php8.1-gd php8.1-gmp php8.1-imagick php8.1-intl php8.1-ldap php8.1-mcrypt php8.1-mbstring php8.1-memcache php8.1-memcached php8.1-pgsql php8.1-soap php8.1-xml php8.1-zip php-imagick

Et aussi !

sudo apt install php8.1-pgsql php8.1-ldap

Configuration du serveur www Apache2

Configuration de PHP8.1-FPM pour PostgreSQL

Comme indiqué dans la documentation NextCloud, vérifier : /etc/php/8.1/mods-available/pdo_pgsql.ini

# configuration for PHP PostgreSQL module
extension=pdo_pgsql.so
extension=pgsql.so

[PostgresSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0

On en profite pour relancer le service php7.4-fpm :

sudo service php8.1-fpm restart

Et ajouter la conf à Apache2 :

sudo a2enconf php8.1-fpm
Activation des modules Apache2

Nous allons devoir activer un certain nombre de modules d’Apache2 requis par NextCloud :

sudo a2enmod rewrite
sudo a2enmod headers
sudo a2enmod env
sudo a2enmod dir
sudo a2enmod mime
sudo a2enmod setenvif

Ainsi que :

sudo a2enmod vhost_alias
sudo a2enmod proxy_fcgi
sudo a2enmod socache_shmcb

Et puis évidemment relancer le serveur www :

sudo service apache2 restart
Ajout de l’hôte virtuel

Dans un premier temps, nous nous contentons de créer un VirtualHost www en HTTP sur le LAN simple à l’aide du script :

/usr/local/sbin/apache2-vhost.sh cloud.landinux.lan

Ensuite, il est conseillé de copier-coller les commandes indiquées

Enfin, nous modifions le fichier de config Apache2 généré en prenant note des recommandations données dans la doc de NextCloud, ainsi que l’utilisation de PHP7.4-FPM : /etc/apache2/sites-available/cloud.landinux.lan.conf :

<VirtualHost *:80>
  Include "conf-available/php8.1-fpm.conf"
  ServerAdmin bastien@landinux.org
  ServerName cloud.landinux.lan
  #ServerAlias www.cloud.landinux.lan
  DocumentRoot /var/www/vhosts/cloud.landinux.lan
  <FilesMatch "\.(cgi|shtml|phtml|php)$">
    SetHandler "proxy:unix:/run/php/php8.1-fpm.sock|fcgi://localhost"
  </FilesMatch>
  <Directory /usr/lib/cgi-bin>
    SetHandler "proxy:unix:/run/php/php8.1-fpm.sock|fcgi://localhost"
  </Directory>
  <Directory /var/www/vhosts/cloud.landinux.lan>
    Require all granted
    AllowOverride All
    Options FollowSymLinks MultiViews
  <IfModule mod_dav.c>
    Dav off
  </IfModule>
  </Directory>

  # Logs
  LogFormat "%h %l %u %t \"%r\" %>s %b" cloud.bastbalt.lan
  CustomLog ${APACHE_LOG_DIR}/cloud.bastbalt.lan.access.log cloud.bastbalt.lan
  ErrorLog ${APACHE_LOG_DIR}/cloud.landinux.lan.error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined
  #LogLevel warn
</VirtualHost>

On l’ajoute aux sites-enabled :

cd /etc/apache2/sites-enabled && sudo ln -s ../sites-available/cloud.landinux.lan.conf .

On vérifie la config :

sudo apache2ctl configtest
Syntax OK

Enfin on peut redémarrer le service www :

sudo service apache2 restart

Test fonctionnels

Nous allons pouvoir vérifier si le VirtualHost fonctionne correctement :

D’abord créer un fichier /var/www/vhosts/cloud.landinux.lan/test.php contenant :

<?php phpinfo(); ?>

Ensuite, utiliser un navigateur pour se connecter à cette URL LAN :
http://cloud.landinux.lan/test.php

Et normalement, on obtient une belle page phpinfo() qui nous confirme, entres-autres, que le mode FPM/FastCGI est bien utilisé:

La suite … 3/5 : NextCloud server

À présent que tous les pré-requis sont remplis, nous allons enfin pouvoir installer le cœur de métier de notre CHATONS ; à savoir l’installation à proprement parler de l’applicatif NextCloud dans l’épisode suivant …

Création d’un CHATONS – 3/5 : NextCloud server –>