Déployer un site Wagtail avec Gunicorn, Nginx et Supervisor

Ce tutoriel explique comment configurer Gunicorn, Nginx et Supervisor sur un serveur Linux pour servir un site Django Wagtail.

16 Juillet 2020 09:10
Thèmes: Déploiement

Dans un tutoriel précédent, on a configuré notre projet pour qu'il s'exécute localement sur un serveur DigitalOcean. On va maintenant installer Gunicorn et Nginx pour servir notre site sur Internet, comme cela est également décrit dans un didacticiel DigitalOcean. Cependant, notre configuration sera légèrement différente: on utilisera un fichier de configuration Gunicorn et utilisera Supervisor pour gérer à la fois Gunicorn et Nginx. Il existe d'autres didacticiels, tels que ce guide complet. Des tutoriels Linux peuvent être trouvés ici et ici.

Gunicorn servira de serveur d'applications, Nginx comme serveur Web et proxy inverse et Supervisor comme outil de gestion pour les exécuter. Gunicorn dirigera notre site et servira du contenu dynamique (à partir de la base de données) et sera installé dans le même environnement virtuel que notre site. Nginx servira du contenu statique (médias et images) et déléguera les demandes d'autres contenus à Gunicorn. Nginx sera installé sur le serveur, en dehors de l'environnement virtuel. Supervisor sera également installé sur le serveur et sera utilisé pour démarrer, arrêter et configurer à la fois Nginx et Gunicorn. Les étapes seront les suivantes:

  1. mettre à jour les paramètres de production
  2. installer et configurer Gunicorn
  3. installer et configurer Nginx
  4. installer et configurer Supervisor
  5. exécuter le site
1. Mettre à jour les paramètres de production

Jusqu'à présent, on n'a utilisé que les paramètres de développement de notre projet. Avec Gunicorn et Nginx, on utilisera les paramètres de production, où debug = False. On doit maintenant définir le paramètre ALLOWED_HOSTS, sinon Django générera une Bad Request error. On va modifier les paramètres sur notre ordinateur de développement, les pousser dans le référentiel et sur notre serveur les extraire de là. Dans votre fichier de paramètres production.py, ajoutez la ligne:

ALLOWED_HOSTS = ['pythoneatstail.com', 'www.pythoneatstail.com',]

Poussez la modification dans le référentiel:

git add .
git commit -m "added allowed hosts"
git push

Allez sur le serveur, activez l'environnement virtuel, entrez dans le répertoire du projet et tapez:

git pull origin master

Consultez le fichier production.py pour vérifier que la modification est effectuée. Collectons également tous les fichiers statiques dans le répertoire /static/, afin qu'ils puissent être récupérés par le serveur Web plus tard:

python3 manage.py collectstatic
2. Installer et configurer Gunicorn

Connectez-vous au serveur en tant qu'utilisateur qu'on a créé (utilisez votre propre adresse IP):

ssh usr_pet@165.22.199.4

Entrez dans l'environnement virtuel et installez Gunicorn:

source env/bin/activate 
pip3 install gunicorn

Pour tester que Gunicorn peut desservir le site, allez dans le répertoire de votre projet et tapez:

gunicorn --bind 0.0.0.0:8000 pet.wsgi

La visite de votre site avec le navigateur sur http://165.22.199.4:8000 (remplacez votre adresse IP) devrait donner le même résultat que dans le tutoriel précédent avec la commande runserver. Arrêtez Gunicorn avec ctrl-C.

Il existe plusieurs façons de définir la configuration de Gunicorn. On pourra créer un fichier de service pour la commande systemd, ou créer un script bash. Ici on va créer un fichier de configuration Gunicorn comme décrit dans la documentation de Gunicorn. On peut placer le fichier n'importe où; pour rester proche de l'organisation des fichiers de Linux, on va créer un répertoire /etc pour les fichiers de configuration avec un sous-répertoire /gunicorn:

mkdir -p ~/env/etc/gunicorn
cd ~/env/etc/gunicorn
touch conf.py

Le référentiel Gunicorn contient un exemple de fichier de configuration. On va copier certains des paramètres dont on a besoin. Commençons par quelques simples, qui sont expliqués dans l'exemple de fichier. Ouvrez conf.py avec vi ou un autre éditeur et ajoutez:

workers = 3
keepalive = 5
user = 'usr_pet'
proc_name = 'pet'

On ajoute également des informations sur la façon dont on veut enregistrer:

loglevel = 'error'
errorlog = '/home/usr_pet/env/var/log/gunicorn-error.log'
accesslog = '/home/usr_pet/env/var/log/gunicorn-access.log'

Les fichiers spécifiés n'existent pas encore. On n'a pas besoin de créer les fichiers, mais on doit s'assurer que le répertoire existe, alors quittez temporairement l'éditeur et créez un répertoire ~/env/var/log. Créez également un répertoire ~/env/run pour le fichier socket (voir ci-dessous).

mkdir -p ~/env/var/log
mkdir ~/env/run

Revenez à l'édition du fichier de configuration conf.py. Essentiel est le paramètre bind, qui indique à Gunicorn quelle est l'interface avec laquelle communiquer avec le monde extérieur. Ci-dessus, on a utilisé une adresse IP, maintenant on va utiliser un fichier (un fichier socket Unix) via lequel Gunicorn s'interfacera avec Nginx (qui à son tour se connectera à une adresse IP). Gunicorn créera ce fichier lui-même, mais le répertoire doit exister. La syntaxe est:

bind = 'unix:/home/usr_pet/env/run/gunicorn.sock'

On a besoin d'un moyen de dire à Gunicorn d'utiliser les paramètres de production de notre projet. Le paramètre Django pour cela est DJANGO_SETTINGS_MODULE et on peut le définir en utilisant le paramètre Gunicorn raw_env (voir aussi l'exemple de fichier):

raw_env = ['DJANGO_SETTINGS_MODULE=pet.settings.production',]

Pour s'assurer que Gunicorn peut trouver le fichier de paramètres Django, on doit spécifier le chemin Python:

pythonpath = '/home/usr_pet/pet'

Cela conclut le fichier de configuration de Gunicorn.

3. Installer et configurer Nginx

Quittez l'environnement virtuel si nécessaire et installez Nginx:

sudo apt-get update
sudo apt-get install nginx

Nginx crée un fichier de configuration générique dans /etc/nginx/nginx.conf et deux répertoires /sites-available et /sites-enabled. On va créer un fichier de configuration de bloc serveur dans le répertoire /sites-available. Créez le fichier (on l'appelle pet) et ouvrez-le avec votre éditeur (dans notre cas vi; utilisez sudo pour l'autorisation d'écriture):

sudo vi /etc/nginx/sites-available/pet

Dans ce fichier, on mettra un bloc serveur avec un certain nombre de paramètres (voir "Configure Nginx to Proxy Pass to Gunicorn"):

  • nom(s) de domaine du serveur
  • chemin d'accès aux fichiers journaux
  • blocs de location nous expliquant comment gérer différents uri

Mettez le contenu suivant et enregistrez le fichier; voir ci-dessous pour l'explication.

server {
    server_name pythoneatstail.com www.pythoneatstail.com;

    access_log /home/usr_pet/env/var/log/nginx-access.log;
    error_log /home/usr_pet/env/var/log/nginx-error.log;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        root /home/usr_pet/pet;
    }
    location /media/ {
        root /home/usr_pet/pet;
    }

    location / {
        include proxy_params;
        proxy_pass http://unix:/home/usr_pet/env/run/gunicorn.sock;
    }
}

La première ligne spécifie les noms de domaine de notre site, les deuxième et troisième les fichiers journaux. La première déclaration location indique à Nginx d'ignorer tout problème potentiel avec la recherche d'un favicon. Les deuxième et troisième instructions location spécifient l'emplacement des fichiers statiques et multimédias dans notre projet, afin que Nginx puisse les servir directement si cela est demandé. L'instruction finale correspond à toutes les autres demandes et pointe vers le fichier socket qu'on a créé plus tôt, procurant ainsi une requête proxy à Gunicorn. Il inclut un fichier de paramètres proxy_params créé lors de l'installation dans le répertoire /etc/nginx.

Les paramètres Nginx réels seront récupérés à partir du répertoire /sites-enabled, on fait donc un lien symbolique à partir de /sites-available pour y:

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

Testez la configuration Nginx pour les erreurs avec:

sudo nginx -t

Pour vérifier que Nginx est en cours d'exécution, utilisez la commande systemctl; il devrait afficher que Nginx est "active (running)".

sudo systemctl status nginx

On peut maintenant vérifier si Gunicorn et Nginx peuvent échanger des données via le fichier socket, en exécutant Gunicorn avec son fichier de configuration:

sudo /home/usr_pet/env/bin/gunicorn pet.wsgi:application --config /home/usr_pet/env/etc/gunicorn/conf.py

Ici, le premier chemin mène à l'exécutable Gunicorn, l'argument pet.wsgi:application est la variable application dans le fichier pet.wsgi de votre projet, et le deuxième chemin mène au fichier de configuration qu'on a créé ci-dessus. Cette commande lancera Gunicorn au premier plan, occupant temporairement la fenêtre de votre terminal. Dans votre navigateur, visitez votre domaine (www.pythoneatstail.com); si tout va bien, vous pourrez accéder à votre site. Vous pouvez vérifier que Gunicorn a créé le fichier socket en ouvrant un deuxième terminal et en listant le contenu du répertoire /home/usr_pet/env/run. Arrêtez le processus Gunicorn dans le premier terminal avec ctrl-C. Le fichier socket aura disparu.

4. Installer et configurer Supervisor

On utilisera Supervisor pour surveiller et contrôler à la fois le processus Gunicorn et le processus Nginx. Il est légèrement plus simple et plus convivial que le Systemd intégré et peut déléguer à des utilisateurs non root. Supervisor pourrait être installé dans l'environnement virtuel, mais comme on a l'intention de l'utiliser pour gérer Nginx, qui est installé sur le serveur, ce n'est pas très logique et nécessite plus de configuration. L'installation peut se faire via pip, mais on utilisera apt-get comme recommandé par DigitalOcean, malgré le fait qu'il nous donne une version plus ancienne:

sudo apt-get install supervisor

Supervisor a créé un fichier de configuration dans /etc/supervisor. Si vous l'inspectez, vous pouvez voir qu'il inclut tous les fichiers de configuration spécifiques à l'application dans le sous-répertoire /conf.d. Allez dans ce sous-répertoire, créez un fichier guni-pet.conf et collez le contenu suivant:

[program:guni-pet]
command=/home/usr_pet/env/bin/gunicorn pet.wsgi:application --config /home/usr_pet/env/etc/gunicorn/conf.py
user=usr_pet
autostart=true
autorestart=true

Tous les paramètres de configuration sont dans la documentation. La première ligne spécifie la commande d'exécution qu'on a utilisée auparavant, la deuxième ligne spécifie l'utilisateur et la troisième et la quatrième ligne indiquent à Supervisor de démarrer et redémarrer automatiquement le processus après une sortie. Pour Nginx, créez un fichier nginx-pet.conf et collez:

[program:nginx-pet]
command=/usr/sbin/nginx -g "daemon off;"
autostart=true
autorestart=true
stderr_logfile=/home/usr_pet/env/var/log/nginx-error.log
stdout_logfile=/home/usr_pet/env/var/log/nginx-access.log

Dans la commande, on définit "daemon off" avec le commutateur -g car Supervisor exige que les processus se déroulent au premier plan. Cette fois, on ne spécifie pas d'utilisateur, car Nginx a été installé par root et doit donc être exécuté par root. Pour la même raison, on répète les emplacements des fichiers journaux, pour nous assurer que les journaux s'y retrouvent.

Cela termine la configuration de Supervisor. La partie client en ligne de commande de Supervisor est supervisorctl. Ajoutez les nouvelles configurations à Supervisor avec:

sudo supervisorctl reread
sudo supervisorctl update
5. Exécuter le site

Cela devrait maintenant être aussi simple que:

sudo supervisorctl start all

qui démarre Gunicorn et Nginx. Accédez à votre adresse de domaine dans votre navigateur (dans notre cas www.pythoneatstail.com) et voyez si cela fonctionne. Arrêtez l'un des processus, redémarrez-les, vérifiez l'état, en utilisant les différentes commandes de Supervisor (avec <process-name> guni-pet ou nginx-pet):

sudo supervisorctl status [optional: <process-name>]
sudo supervisorctl start <process-name>
sudo supervisorctl stop <process-name>
sudo supervisorctl restart <process-name>

Si on n'a créé aucun contenu, notre site est toujours vide. On peut le remplir manuellement ou utiliser une sauvegarde; lire un autre tutoriel expliquant comment faire cela. On va également mettre en place un pare-feu, activer https et définir les clés d'accès ssh.

Commentez cet article (connectez-vous d'abord ou confirmez par nom et email ci-dessous)