Vous pouvez naviguer parmi les posts en glissant votre doigt.

Automatiser le déploiement de plusieurs sites Jekyll sur le même serveur

12 août 2016 . category: code .
#jekyll #nginx #tutorial #deployment

Automatiser le déploiement de plusieurs sites Jekyll sur le même serveur

Jekyll est un framework assez puissant pour réaliser des sites statiques assez rapidement et très jolis & fonctionnels. Je m’en sers pour faire des sites rapidos qui n’ont pas besoin d’accès à des bases de données et qui peuvent être déployés sur une seule machine.

Comment ça va fonctionner: on bosse avec Jekyll sur son ordi, et quand on est content d’une version on l’envoie pour que les internautes puissent admirer le rendu. On va donc dans l’ordre:

  • générer le site en local;
  • configurer nginx;
  • écrire un script bash pour envoyer le site généré par Jekyll sur le serveur.

Ce qu’on peut donc obtenir:

  • pour un même site hébergé sur plusieurs serveurs, déployer une nouvelle version à partir de n’importe quelle machine appartenant à un contributeur du site;
  • pour plusieurs sites hébergés sur un même serveur, déployer l’un ou l’autre des sites à partir de n’importe quelle machine appartenant à un contributeur du site choisi;
  • la même chose avec plusieurs sites déployés sur plusieurs serveurs, si vous avez compris comment ça marche (ce que j’espère être le cas à la fin de ce tuto!).

Pourquoi pas git?

  • parce qu’on n’a pas forcément envie de déployer à chaque commit. On peut vouloir committer sans pour autant changer ce que les internautes vont voir;
  • parce qu’on n’a également pas forcément envie de devoir commiter pour déployer. Parfois, ce qu’on a déjà suffit amplement et on veut juste le déployer sur un nouvelle machine, par exemple;
  • parce que la méthode décrite sur le site de Jekyll nécessite deux choses qui me gênent: disposer de Jekyll sur le serveur, et tout committer pour effectuer un nouveau build. On l’a déjà le répertoire qu’il faut, autant garder celui-là!
  • il y a des chances qu’il faille déployer un site sur une machine sur laquelle on n’a que très peu de droits et pas de possibilité d’installer des git ou des jekyll;
  • parce qu’il faut selon moi bien distinguer le livrable (le site généré) et le travail et le matériau permettant d’obtenir ce livrable (le code versionné);
  • et puis également parce que c’est ce que tout le monde a l’air de faire, alors bon, soyons originaux (et faites tous comme moi dans ce tuto). Blague à part, je me suis penché sur plusieurs solutions (gulp, git avec hooks, scp, etc.) avant d’adopter cette solution. Elle a certainement des inconvénients (n’hésitez pas à m’en faire part), mais elle correspond pour l’instant tout à fait à mon besoin : faire simple et rapide.

Prérequis:

Avoir jekyll (et savoir faire des sites avec!) et rsync en local, nginx et rsync d’installé sur son serveur distant. rsync est installé par défaut sur certaines distributions; pour vérifier, il vous suffit de taper: rsync --version et si vous n’avez pas la version de rsync, bah sudo apt-get install rsync! Bien évidemment, ce que je vais décrire marche aussi avec apache, mais bon… Je préfère nginx. J’expliquerai certainement pourquoi un jour dans un billet. Certainement sa rapidité et sa facilité d’utilisation, je dirais.

Je vous suggère pour votre site d’acquérir un nom de domaine. Je n’ai pas d’endroit privilégié pour ça (je sais qu’amen en fait des pas chers), je varie moi-même les endroits où j’achète mes noms de domaine. Mettons dans tout ce tuto que votre nom de domaine soit vivecaesar.com (je ne vous empêche pas d’être fan, et je vous encourage vivement à multiplier les sites à la gloire de ma personne).

On y va!

Commençons déjà par créer notre site Jekyll sur votre ordinateur:

jekyll new site_vivecaesar

Je vous laisse ensuite faire ce que vous avez à faire sur le site. Ne pas oublier le petit jekyll build pour être bien sur d’avoir ce qu’il faut dans _site ou dans tout autre dossier que vous aurez configuré en tant que destination du livrable que vous allez exporter.

Maintenant il faut configurer le serveur. Sur celui-ci, il faut déjà créer le répertoire qui contiendra le site. Personnellement, et de manière très originale, je le mets dans /var/www/. Et il ne faut pas oublier de changer les droits sur le dossier:

cd /var/www
sudo mkdir site_vivecaesar
sudo chown -R www-data:www-data /var/www/site_vivecaesar/

Toujours sur le serveur, il faut ensuite configurer nginx pour qu’il redirige correctement l’utilisateur. Pour faire simple, on va copier une configuration de base et l’éditer:

sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/vivecaesar.com
sudo vi /etc/nginx/sites-available/vivecaesar.com

Dans ce fichier, voilà ce que vous allez mettre:

server {
        # écoute le port 80
        listen 80;

        # plusieurs valeurs possibles séparées par un espace
        server_name vivecaesar.com;

        # le répertoire racine où se trouve le site
        root /var/www/site_vivecaesar;

        # la page d'accueil
        index index.html;

        # les logs d'accès et d'erreur
        access_log /var/log/nginx/vivecaesar.access.log;
        error_log /var/log/nginx/vivecaesar.error.log;

        # renvoie 404 s'il ne trouve rien
        location / {
                try_files $uri $uri/ =404;
        }
}

Petite feinte: si c’est la première fois que vous utilisez nginx, il se peut que le serveur par défaut ne soit pas activé, ce qui fait que si vous tapez votre serveur par n’importe quelle url ou même juste avec l’IP, vous allez tomber sur un hôte virtuel que vous allez configurer, ce qui peut poser quelques problèmes… Pour remédier à ça, voilà ce qui redirigera le visiteur qui est venu sur la machine par un chemin qu’on ne voulait pas vers la page par défaut:

sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default

En tout état de cause, pour activer l’hôte virtuel de votre site, il faut créer un lien symbolique:

sudo ln -s /etc/nginx/sites-available/vivecaesar.com /etc/nginx/sites-enabled/vivecaesar.com

Il faut redémarrer nginx pour que les changements soient pris en compte:

sudo service nginx restart

Nginx est prêt et vous pouvez tester l’URL http://vivecaesar.com, vous arriverez sur votre site jekyll.

Automatisons le déploiement d’un seul script!

Ensuite, grâce à une simple commande, rsync, on va synchroniser tout le dossier _site (-r) ou le dossier configuré dans _config.yml avec le dossier cible sur le serveur, en prenant le soin d’effacer les fichiers devenus inutiles (--del) et en forçant l’écrasement des fichiers plus récents (--force). Je veux également savoir ce qu’il se passe lors du déploiement (-v) et vérifier la progression (-P).

Pour ça, j’ai créé un script deploy_jekyll.sh, que j’exécute dès que je suis content de moi. Par rapport au développement du site en question, je veux dire, parce qu’il m’arrive d’autres moments où je suis content de moi sans pour autant avoir envie de synchroniser mes sites. Le script va vérifier si dans votre configuration vous avez choisi une autre destination que _site comme dossier, afin de bien récupérer ce qu’il faut.

Voilà à quoi ressemble la bête, à mettre directement dans le répertoire de travail Jekyll de votre site (site_vivecaesar ici en l’occurrence). Vous pouvez récuprer la version que je maintiens à jour sur Github, et qui contient davantage d’options (elle est en anglais, cependant):

#!/bin/bash
url='vivecaesar.com'
dest_folder='/var/www/site_vivecaesar/'
site_folder='_site'
echo "Recherche d'une configuration particulière pour le dossier de destination construit par Jekyll"
folder=$(sed '/^#/d' _config.yml | grep '^destination:' | cut -d: -f2| sed -e 's/[[:space:]]//')
if [ -z "$folder" ]
then
  echo -e "[\e[33mINFO\e[0m] Pas de dossier particulier trouvé"
else
  echo -e "[\e[33mINFO\e[0m] Dossier particulier trouvé: \e[33m$folder\e[0m"
  site_folder=$folder
fi

rsync -rvP --del --force ./$site_folder/ $url:$dest_folder 2>rsync-errors
if  [ $? == 0 ]
then
  echo -e "[\e[32mOK\e[0m] Le site a bien été déployé sur \e[34m$url\e[0m dans le dossier $dest_folder"
else
  echo -e "[\e[31mERREUR\e[0m] Le site n'a pas été déployé sur \e[34m$url\e[0m dans le dossier $dest_folder \n\e[4mListe des erreurs:\e[24m"
  cat rsync-errors
fi

N’oubliez pas le traditionnel sudo chmod 777 deploy_jekyll.sh si vous voulez pouvoir exécuter le script. Je mets 777 parce que ce script, je le commit également avec git et je veux que les autres utilisateurs puissent l’exécuter et le modifier. Je suis partageur. Uniquement en code, je préfère vous prévenir, ma femme étant très belle je ne veux pas que vous vous fassiez d’illusion.

J’ai mis des couleurs dans le script pour que ce soit plus lisible, le vert signifiant que ça s’est bien passé et le rouge, bah… l’inverse ! Le site est mis en évidence en bleu. La liste des erreurs apparaît le cas échéant, et il y a deux paramètres (l’URL et le dossier de destination).

Attention lors de la première exécution, il peut y avoir ça:

The authenticity of host 'vivecaesar.com (88.123.12.1)' can't be established.
ECDSA key fingerprint is SHA256:yEIAo2duX9+abcds4d2Ttw6fYx6u7E6661yrKF5Et6g.
Are you sure you want to continue connecting (yes/no)?

Même si vous vous êtes déjà connecté à la machine distante en rentrant l’IP, là vous le faites avec un nom d’hôte particulier, donc il vous demande si vous voulez poursuivre. Écrivez yes et vous aurez le message:

Warning: Permanently added 'vivecaesar.com' (ECDSA) to the list of known hosts.
sending incremental file list

Dernier petit réglage: il ne faut pas que dans le build, Jekyll mette deploy_jekyll.sh et rsync_errors dans _site. Du coup, il faut ignorer ces deux fichiers en éditant _config.yml et en rajoutant: exclude: [deploy_jekyll.sh, rsync-errors].

Et voilà, c’est terminé ! Plutôt simple, non ? Pas d’usine à gaz, dix mille trucs à installer et à configurer. Vous pouvez développez, committer si ça vous fait plaisir, mais vous maîtrisez le déploiement. Un simple ./deploy_jekyll.sh dans le dossier de travail Jekyll et c’est bon!


Me

DJ Caësar 9114 est un DJ, qui code également. Il est trop feignant pour faire deux sites différents, alors il n'en a fait qu'un, qui unit ces deux passions.