Intro
La gestion et la création d’un virtual host (VHOST) sur un serveur web peuvent vite devenir compliquées, surtout lorsque les utilisateurs ne sont pas formés pour cela… Heureusement, l’automatisation vient à la rescousse. 🤖
Dans cet article, nous allons voir comment utiliser systemd, pour surveiller automatiquement un répertoire (ici /var/www/
) et créer un VHOST Nginx dès qu’une modification y est détectée.
Pour résumer, voici ce que nous allons mettre en place :
Etape 0 : Le setup
Avant de jouer avec tout ça 🕹️, il va falloir préparer le terrain. Pour le lab, je suis parti d’une machine virtuelle EC2 AWS en Ubuntu 22.04 sur laquelle j’ai fait quelques actions :
- Installation de Nginx
- Création d’un user “dev”
- Ajout des droits sudo sur la commande
/usr/bin/systemctl restart nginx
pour l’utilisateur dev - Mettre les droits de lecture et écriture sur
/var/www
pour notre utilisateur
Si vous ne voulez pas vous prendre la tête, vous pouvez aveuglément exécuter ces commandes 🫣 :
$ sudo apt update && sudo apt install vim nginx -y
$ sudo adduser dev
$ sudo visudo #ajoutez cette ligne à la fin du fichier
dev ALL=(ALL : ALL) NOPASSWD: /usr/bin/systemctl restart nginx
$ sudo chown root:dev /var/www && sudo chmod 775 /var/www
Etape 1 : Script pour ajouter un nouveau VHOST
Comme je l’ai énoncé dans l’intro, le but est d’ajouter automatiquement un VHOST lorsque notre utilisateur crée un répertoire dans /var/www
. Nous allons faire un script qui va automatiser toutes ces étapes :sudo vim /opt/restarter.sh
Puis on colle le contenu suivant :
#!/bin/bash
web_dir="/var/www"
nginx_dir="/etc/nginx/sites-available"
# Loop on every directory in /var/www
for dir in "$web_dir"/*/; do
site_name=$(basename "$dir")
# Check if config file exist in /etc/nginx/sites-available
if [ ! -f "$nginx_dir/$site_name" ]; then
cp /etc/nginx/sites-available/default $nginx_dir/$site_name
sed -i '/^\s*#.*$/d' $nginx_dir/$site_name
sed -e 's/default_server//g' -i $nginx_dir/$site_name
sed -i "s|root /var/www/html;|root /var/www/$site_name/html;|g" $nginx_dir/$site_name
sed -i "s|server_name _;|server_name $site_name;|g" $nginx_dir/$site_name
ln -s $nginx_dir/$site_name /etc/nginx/sites-enabled
if nginx -t; then
systemctl restart nginx
else
echo "Nginx configuration test failed for $site_name." >&2
exit 1
fi
fi
done
⚠️N’oubliez pas de rendre le script exécutable :
chmod +x /opt/restarter.sh
Sans trop rentrer dans les détails, mon script crée et configure automatiquement les fichiers nécessaires pour que Nginx prenne en charge les nouveaux hôtes virtuels.
Pour ce faire, je parcours chaque sous-répertoire de /var/www
puis je vérifie si un fichier de configuration Nginx existe déjà en me basant sur le nom du VHOST créé (ils doivent donc être identiques).
Si ce n’est pas le cas, je copie le fichier de configuration Nginx par défaut en y appliquant quelques modifs :
- Suppression des commentaires et de l’instruction
default_server
- Adaptation du chemin pour aller chercher les fichiers HTML adéquats
- Définition du
server_name
avec le nom du VHOST - Test de la nouvelle configuration Nginx et redémarrage du service
Etape 2 : Créer un service pour redémarrer Nginx
Maintenant que nous avons notre script tout beau tout propre, il nous faut un service pour l’exécuter. Rien de plus simple, créons un fichier /etc/systemd/system/nginx-restarter.service
avec ce contenu :
[Unit]
Description=Add new VHOST to Nginx when /var/www directory is changing
After=network.target
[Service]
Type=oneshot
ExecStart=/bin/bash -c 'bash /opt/restarter.sh'
[Install]
WantedBy=multi-user.target
Etape 3 : Créer un fichier de type path systemd pour surveiller la création de nouveaux VHOSTS
Vu que l’on kiffe l’automatisation sur ce blog, la prochaine étape c’est de créer un fichier systemd de type path. Il aura pour mission de surveiller le répertoire /var/www
et de déclencher notre service nginx-restarter
dès qu’il y aura une modification.
Pour que ça fonctionne comme sur des roulettes 🛹, le nom des fichiers .service
et .path
doivent coïncider. Nous allons créer le fichier /etc/systemd/system/nginx-restarter.path
afin d’y ajouter ce contenu :
[Unit]
Description=Watch Nginx config directory for changes
[Path]
PathModified=/var/www/
[Install]
WantedBy=multi-user.target
Etape 4 : Activer et démarrer les unités systemd
Tout est prêt ✅
Enfin… Presque, il faut d’abord démarrer tout ce ptit’ monde :
$ sudo systemctl daemon-reload
$ sudo systemctl start nginx-restarter.path && sudo systemctl enable nginx-restarter.path
Si tout s’est bien passé, la commande sudo systemctl status nginx-restarter.path
doit vous retourner l’état du status : active (waiting)
● nginx-restarter.path - Watch Nginx config directory for changes
Loaded: loaded (/etc/systemd/system/nginx-restarter.path; enabled; vendor preset: enabled)
Active: active (waiting) since Sat 2024-06-08 06:54:58 UTC; 7s ago
Triggers: ● nginx-restarter.service
Etape 5 : Teeeeest
C’est moment de véritééééé ! 🥁🥁
Avec notre utilisateur préféré (sudo su - dev
), créons les répertoires mysite.com/html dans /var/www
:
dev$ mkdir -p /var/www/mysite.com/html
Je vous laisse admirer mes talents en HTML pour avoir un fichier index qui claque 😎 :
dev$ vim /var/www/mysite.com/html/index.html
<html>
<head>
<title>Welcome to mysite.com!</title>
</head>
<body>
<h1>Success! The mysite.com server block is working!</h1>
</body>
</html>
A présent, si l’on curl mysite.com
on tombe bel est bien sur notre Virtual Host (pensez à ajouter mysite.com dans votre /etc/hosts
si vous êtes en local sinon, ajouter une entrée DNS):
dev$ curl mysite.com
<html>
<head>
<title>Welcome to mysite.com!</title>
</head>
<body>
<h1>Success! The mysite.com server block is working!</h1>
</body>
</html>
🥳🥳🥳
Quelques conventions
Il y a quelques petites conventions à respecter pour que ça fonctionne. La première, c’est que le nom du répertoire créé dans /var/www
doit être identique à celui du VHOST. Par exemple, si je souhaite un site toto.com, je dois avoir un répertoire /var/www/toto.com
. La deuxième convention concerne la structure de l’arborescence. Pour chaque hôte virtuel, elle doit ressembler à celle-ci :
/var/www
├── html
│ └── index.nginx-debian.html
└── mysite.com
└── html
└── index.html
Conclusion
Ptit recap’ ? 🧐
Nous avons configuré un service systemd pour surveiller les modifications dans le répertoire /var/www/
et redémarrer automatiquement Nginx avec la configuration du nouveau Virtual Host
Cette approche, permet d’offrir une plus grande autonomie aux devs. Ils n’ont plus besoin d’apprendre à créer des VHOSTS. Ils peuvent se concentrer à 100% sur leur code. 💪
En axe d’amélioration, je pourrais prévoir la suppression des hôtes virtuels lorsque le répertoire n’est plus présent dans /var/www
(mais on verra ça pour une prochaine fois 😅)
Je terminerai cet article sur une note de sécurité. Notre utilisateur n’a plus besoin de redémarrer Nginx lui-même, nous pouvons lui retirer ses droits sudo, qui lui permettaient de réaliser cette action. En plus, cela lui simplifie grandement la vie parce que tout le process est automatisé et devient totalement transparent pour lui.
En relisant l’article, je me suis rendu compte que j’ai énormément axé celui-ci sur l’ajout de nouveaux VHOSTS. A la base, je souhaitais vous faire découvrir la mécanique de wachter et de trigger via systemd (avec les
.service
et.path
), j’espère tout de même que c’est chose faite 😅
A la prochaine 👋