Skip to content

Redémarrer automatiquement un service Systemd en cas de modification d’un répertoire

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 👋

Published inNon classé