Pour Commencer
Il est important d'avoir à l'esprit qu'il faut un minimum de connaissance des commandes du système d'exploitation choisit pour s'en sortir. Dans mon cas il s'agira de FreeBSD mais cela vaut pour les distribution Linux courantes.
Identifier les objectifs
Dans un premier temps il faut identifier "de quel(s) service(s) j'ai besoin". Cela permet d'identifier les applications à mettre en place et donc les ressources nécessaire au serveur.
Dans notre cas nous partirons sur Drupal, Nexcloud, PostFix et Dovecot.
Choisir son hébergeur
Il est toujours possible de se dire que l'on va héberger dans son garage mais cela a plusieurs inconvénients : la sécurité physique, électrique et incendie du local sont à assurer. Cela devient vite compliqué dans un garage ou un placard.
Choisir son système d'exploitation
Là un grand débat pourrait s'engager : FreeBSD, Linux Debian, Linux Ubuntu, Linux OpenSuse. Une bonne approche reste avant tout d'utiliser les images proposées par votre hébergeur, en effet s'engager dans des installations exotiques peuvent être chronophages et décourager.
Installation de Base
Déployer l'OS
Dans un premier temps il est nécessaire dès l'installation de mettre le plus à jour possible le système, celui sera bien entendu installé sans interface graphique.
Idéalement si votre hébergeur le permet, dans le partitionnement nous pendrons soins de créer une partition système et une partition pour les données. Il ne faut pas hésiter à utiliser les système de fichier btrs, openzfs qui s'avèrent aujourd'hui mature surtout pour notre usage. Cela semble désuet avec la virtualisation et l'explosion des ressources mais d'expérience, il peut toujours y avoir une action ou des utilisateurs trop gourmands qui vont saturer le disque.
Pour du FreeBSD, comme il respecte les concepts des Unix ( pour ceux qui ne comprennent pas, il y plusieurs répertoire etc, a savoir /etc et /usr/local/etc ) /usr/local/srv/webcontent pour ensuite avoir les sous-répertoires suivants :
- Site Drupal : /usr/local/srv/webcontent/web
- Site Nexcloud : /usr/local/srv/webcontent/cloud
- Les données Nexcloud : /usr/local/srv/webcontent/cloud_data
- Les données de base de données : /usr/local/srv/databases
Ces noms ne sont pas fixe, vous pouvez les adapter en fonction de vos habitudes.
Gestion des Comptes
Personellement je n'utilise jamais le compte root, toujours du sudo. Il faut donc l'ajouter, sous FreeBSD cela donne :
pkg install sudo
Il faut ensuite éditer le paramétrage avec la commande visudo
.
Là en général il faut ajouter un groupe avec les droits sudo, cela peut-être le groupe sudo / wheel / adm
en fonction des distributions.
%wheel ALL=(ALL:ALL) ALL
%sudo ALL=(ALL:ALL) ALL
Il peut y avoir un débat sur l'option NOPASSWD:ALL
qui permet de ne pas redemander le mot de passe lorsque l'on tape une commande précédée de sudo, personnellement je trouve cela dangereux. Pour une ou deux commandes si vraiment il y a besoin, je l'entends mais pour toutes les commandes, attention.
Pensez aussi au durcissement du système, avec la version pour Linux et la version pour FreeBSD.
Mettre en place SSH
Voir le sous article concernant la mise en place de l'accès distant par SSH.
Mettre en place le mur de feu
Voir le sous article concernant la mise en place du mur de feu.
Mettre en place Fail2Ban
Fail2Ban permet d'éviter les attaques par force brut sur les service tel que SSH et SMTP ou IMAP. Pour un serveur en cloud public la mise ne place d'un outil capable de bloquer les attaques est une obligation, Fail2Ban peut être remplace par Suricata en mode IPS.
Sous FreeBSD le package est précédé par la version de Python, par exemple: py311-fail2ban. Le fichier de configuration par défaut est /usr/local/etc/fail2ban/jail.conf
qu'il ne faut pas modifier mais créer un fichier /jail.local
juste à coté. Il faut penser à ajouter dans le fichier pf.conf à la fin la ligne :
anchor "f2b/*"
Dans la documentation PF sur les ancres il est bien stipulé que lorsque PF arrive sur la définition de l'ancre il va traiter toute les règles contenues dans le point d'ancrage. Selon le fonctionnement de PF, il faut donc le mettre à la fin du fichier pour être certain que la règle soit la dernière appliqué.
[DEFAULT]
bantime = 10m
bantime.increment = true
bantime.maxtime = 48h
ignoreip = 127.0.0.1/8 ::1
#banaction = pf
banaction = pf[actiontype=<multiport>]
banaction_allports = pf[actiontype=<allports>]
[sshd]
enabled = true
[apache-auth]
enabled = true
port = http,https
filter = apache-auth
logpath = /var/log/*error.log
maxretry = 3
findtime = 600
[apache-noscript]
enabled = true
port = http,https
filter = apache-noscript
logpath = /var/log/*error.log
maxretry = 3
findtime = 600
[apache-overflows]
enabled = true
port = http,https
filter = apache-overflows
logpath = /var/log/*error.log
maxretry = 2
findtime = 600
[apache-badbots]
enabled = true
port = http,https
filter = apache-badbots
logpath = /var/log/*error.log
maxretry = 2
findtime = 600
[postfix]
enabled = true
port = stmp,smtps
filter = postfix
logpath = /var/log/maillog
[dovecot-pop3imap]
enabled = true
port = imaps,imaps, pop3, pop3s
filter = dovecot
logpath = /var/log/maillog
Pour activer le service automatiquement au démarrage : sysrc fail2ban_enable="YES"
Pour démarrer le service : service fail2ban start
Pour vérifier le status du Fail2ban : fail2ban-client status
Pour voir le contenu des tables:
pfctl -a "f2b/sshd" -t f2b-sshd -Ts
pfctl -a "f2b/postfix" -t f2b-postfix -Ts
Sources :
https://cmcenroe.me/2016/06/04/freebsd-pf-fail2ban.html
https://lab.neuronfarm.net/nomad/wiki-system/wiki/PF-and-Fail2ban-on-FreeBSD
https://www.purplehat.org/?page_id=566
Installation des applications Web
Mettre en place PHP-FPM
PHP FPM permet de mieux gérer la mémoire et le CPU en démarrant un certain nombre de processus de traitement qui seront utilisés pour traiter les différentes requêtes PHP. Cette configuration permet aussi de passer Apache en mode event qui implémente un serveur hybride multi-processus et multi-threads rendant Apache aussi efficace que ses concurrent. Aussi aujourd'hui il parait désuet de continuer à déployer PHP en tant que module Apache.
Extensions
Voici la liste des extension à installer pour Drupal et Nexcloud : ctype, cURL, dom, fileinfo, gd, json, mbstring, opensssl, pdo_pgsql, pgsql, posix, session, SimpleXML, tokenizer, xml, XMLReader, XMLWriter, zip, zlib
Il est préférable d'ajouter : acpu, exif, imagik, memcached,
Pour les serveurs les plus puissant : ffmpeg
Paramétrage PHP
Pour assurer un minimum la confidentialité pensez à paramétrer dans le php.ini :
session.cookie_samesite = Strict
Configuration du pool Drupal
Augmenter la tailler mémoire :
memory_limit = 256M
Fichier de configuration du Pool :
[www]
user = www
group = www
listen.mode = 0660
listen = /var/run/php-fpm-www.sock
listen.owner = www
listen.group = www
pm = dynamic
pm.max_children = 10
pm.start_server = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
Configuration du pool Nextcloud
Fichier de configuration du Pool :
[cloud]
user = www
group = www
listen.mode = 0660
listen = /var/run/php-fpm-cloud.sock
listen.owner = www
listen.group = www
pm = dynamic
pm.max_children = 10
pm.start_server = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
Mettre en place Apache 2
Pour éviter d'augmenter artificiellement la complexité de l'installation, la version fournie avec la distribution installée et largement suffisante.
Pour FreeBSD
Sous FreeBSD il faut activer des modules du noyau utilisé par Apache pour traiter les requêtes. Pour vérifier dans un premier temps il est possible de les charger directement :
kldload accf_http.ko
kldload accf_data.ko
Maintenant pour que le paramétrage perdure après un redémarrage il faut ajouter dans le fichier /boot/loader.conf
les lignes :
accf_data_load="YES"
accf_http_load="YES"
Optimisation
Pour des environnements très sollicité les valeurs suivantes peuvent être adaptées :
ServerLimit , ThreadLimit, MaxRequestWorkers, ThreadsPerChild
Attention à ces valeurs qui doivent prendre en considération les autres services, les limites du systèmes ( nombre max de file descriptor ) car en car de dépassement c'est le système qui peu devenir instable ou Apache peut tout simplement refuser de démarrer ( cf doc Apache 2 ThreadLimit )
Cacher les informations de serveur
Par défaut Apache va indiquer sa version et le système d'exploitation sous-jacent. Pour cacher ces informations il suffit d'ajouter dans le fichier conf.d/security.conf ou équivalent selon la distribution Linux utilisée les lignes :
ServerSignature Off ServerTokens Prod
Installer les modules
Afin d'assurer le bon fonctionnement des applicatifs il faut que les modules suivants soit présent et actifs dans apache : mod_rewrite, mod_headers, mod_env, mod_dir, mod_mime et comme nous allons utiliser mod_fcgi il nous faut aussi mod_setenvif
a2enmod rewrite
a2enmod headers
a2enmod env
a2enmod dirMettre en place le mail
a2enmod mime
a2enmod fcgi
a2enmod setenvif
Virtual Host Drupal
Dans notre cas Drupal va servir le site racine, nous allons donc utiliser _default_
dans la définition des Virtual Host.
<VirtualHost _default_:80>
ServerAdmin <email webmaster>
ServerName <hostname>
ServerAlias <alias>
Redirect permanent / https://<hostname>/
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}
</IfModule>
ErrorLog "/var/log/apache-www-error.log"
CustomLog "/var/log/apache-www-access.log" common
</VirtualHost>
<VirtualHost _default_:443>
ServerAdmin <email webmaster>
ServerName <hostname>
ServerAlias <alias>
DocumentRoot "/usr/local/srv/webcontent/www/web"
SSLEngine On
SSLCertificateFile "/usr/local/etc/letsencrypt/live/XXXXX/fullchain.pem"
SSLCertificateKeyFile "/usr/local/etc/letsencrypt/live/XXXXX/privkey.pem"
<FilesMatch ".+\.ph(ar|p)$">
<If "-f %{REQUEST_FILENAME}">
SetHandler "proxy:unix:/var/run/php/phpfpm-www.sock|fcgi://localhost"
</If>
</FilesMatch>
<Directory /usr/local/srv/webcontent/www/web>
Require all granted
AllowOverride All
Options FollowSymLinks MultiViews
</Directory>
ErrorLog "/var/log/apache-www-error.log"
CustomLog "/var/log/apache-www-access.log" common
</VirtualHost>
Virtual Host Nextcloud
Pour ma part j'ai eut quelques surprises pour faire fonctionner correctement la synchronisation Nextcloud et PHP-FPM. Vous trouverez la configuration qui fonctionne.
<VirtualHost *:80>
ServerAdmin <email webmaster>
ServerName <hostname>
Redirect permanent / https://<hostname>/
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI}
</IfModule>
ErrorLog "/var/log/apache-cloud-error.log"
CustomLog "/var/log/apache-cloud-access.log" common
</VirtualHost>
<VirtualHost *:443>
ServerAdmin <email webmaster>
ServerName <hostname>
DocumentRoot "/usr/local/srv/webcontent/cloud"
SSLEngine On
SSLCertificateFile "/usr/local/etc/letsencrypt/live/XXXXX/fullchain.pem"
SSLCertificateKeyFile "/usr/local/etc/letsencrypt/live/XXXXX/privkey.pem"
<FilesMatch ".+\.ph(ar|p)$">
<If "-f %{REQUEST_FILENAME}">
SetHandler "proxy:unix:/var/run/php/phpfpm-cloud.sock|fcgi://localhost"
</If>
</FilesMatch>
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
</IfModule>
<IfModule mod_headers.c>
Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains"
</IfModule>
<Directory /usr/local/srv/webcontent/cloud>
Require all granted
AllowOverride All
Options FollowSymLinks MultiViews
<IfModule mod_dav.c>
Dav off
</IfModule>
</Directory>
<Directory /usr/local/srv/webcontent/cloud_data>
Require all granted
AllowOverride All
Options FollowSymLinks MultiViews
</Directory>
ErrorLog "/var/log/apache-cloud-error.log"
CustomLog "/var/log/apache-cloud-access.log" common
</VirtualHost>
Mettre en place Postgres
Postgres est une excellente base de données très robuste. Elle peut paraître plus lourde à mettre en place mais en charge, il n'y a pas de perte de données.
Il faut d'abor initialiser le répertoir de Postgres :
initdb /usr/local/srv/databases/ --encoding=UTF8 --locale="fr_FR.UTF-8"
Pour les système de fichier capables de gérer les sommes de contrôle comme le ZFS on utilisera :
initdb --data-checksums /usr/local/srv/databases/ --encoding=UTF8 --locale="fr_FR.UTF-8"
Pour créer la base Drupal on utilisera :
CREATE USER user_drupal_user WITH NOCREATEROLE NOCREATEDB NOSUPERUSER LOGIN PASSWORD '<password>';
CREATE DATABASE db_drupal OWNER user_drupal;
Pour créer la base Nextcloud on utilisera :
CREATE USER user_nextcloud WITH NOCREATEROLE NOCREATEDB NOSUPERUSER LOGIN PASSWORD '<password>
';
CREATE DATABASE db_nextcloud OWNER user_nextcloud TEMPLATE template0 ENCODING 'UTF8';
GRANT CREATE ON SCHEMA public TO user_nextcloud;
Mettre en place Drupal
Pour déployer Durpal on utilisera la méthode officielle avec Composer disponible ici.
Pour durcir Drupal pensez à changer la valeur suivante dans le fichier <Drupal>/web/sites/default/default.services.yml
cookie_samesite: Strict
Autre élément, pensez à désactiver le formulaire d'inscription car vous allez rapidement avoir de nombreuses tentative de création de comptes à votre insu. A la page https://<votre url Drupal>/admin/config/people/accounts dans la section "Inscription et annulation" à la question "Qui peut enregistrer des comptes ?" sélectionnez "Administrateurs seulement"
Tester la sécurité de Dupal
Il existe un projet OpenSource qui permet d'auditer l'installation du Drupal : Droopescan
Il est présent dans Exegol.
Mettre en place Nextcloud
Pour le déploiement de Nextcloud je préconise le téléchargement directement des sources sur le serveur. Elles sont disponibles ici.
Pretty URL
Le site étant hébergé sur le sous domaine cloud.mondomaine.org soit https://cloud.mondomaine.org/
on ajoutera dans le fichier config.php de Nextcloud:
'overwrite.cli.url' => 'https://cloud.mondomaine.org/',
'htaccess.RewriteBase' => '/',
Commentaires