Configurer Debian, Nginx et Gunicorn pour un projet Django



Bonne journée à tous.

Il y avait une tâche pour élever le serveur Debian sur Nginx pour les projets Django 3.x. Casser un tas d'informations sur Internet, j'ai réussi à le faire en combinant les recommandations de plusieurs sites différents. Si vous êtes intéressé à lire comment configurer votre premier serveur pour un projet Django, alors bienvenue.

Je vais vous parler un peu de vous pour que vous compreniez qui je suis. Je ne suis ni développeur, ni programmeur, ni administrateur système, ni même diplômé en informatique. Je suis professeur d'informatique. Mais au travail, je dois expliquer aux étudiants certains points qui sont très éloignés du cursus scolaire en informatique, dont l'un est le développement de projets sur Django.

Paramètres de base


Pour commencer, nous avons déjà un serveur avec Debian 10 installé, il ne devrait pas y avoir de problème pour installer Debian. J'ai eu une installation propre, sans paramètres supplémentaires, alors je suis allé sur mon serveur via root et j'ai commencé à installer certains des principaux composants pour moi.

apt-get update
apt-get install -y sudo htop git curl wget unzip zip gcc build-essential make
apt-get install -y tree redis-server nginx  libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python3-dev python-pil ython3-pil 
apt-get install -y python3-lxml libxslt-dev python-libxml2 python-libxslt1 python-dev gnumeric libpq-dev libxml2-dev libxslt1-dev libjpeg-dev libfreetype6-dev libcurl4-openssl-dev supervisor libgdbm-dev libnss3-dev ufw

Vous pouvez mettre tout cela dans une seule installation, mais j'ai eu une erreur, et dans cet ordre, tout s'est bien passé.

Ensuite, créez un nouvel utilisateur et ajoutez-le au groupe sudo afin qu'il puisse démarrer des processus au nom du superutilisateur.

adduser username 
usermod -aG sudo username

oĂą nom d'utilisateur est le nom d'utilisateur que vous utiliserez Ă  l'avenir.
Installez la dernière version de Python à partir des sources. Au moment de la rédaction de ce rapport, c'était 3.8.2 .

cd /home/username
curl -O https://www.python.org/ftp/python/3.8.2/Python-3.8.2.tar.xz
tar -xf Python-3.8.2.tar.xz
cd Python-3.8.2

Explication des actions
cd — , change directory;
curl — URL. ;
tar — .

Après avoir téléchargé la dernière version de Python et être passé dans le répertoire source, nous exécutons:

./configure --enable-optimizations
make -j 2

Cela nous permettra de préparer tout le nécessaire pour installer Python. Ici, le nombre 2, c'est le nombre de cœurs de processeur. Vous pouvez le découvrir avec la commande nproc .
Nous commençons l'installation.
make altinstall

Vous pouvez vérifier que Python a installé en utilisant la commande:

python3.8 -V

Il produira une version de Python .
Après cela, nous mettons à jour pip et installons les packages les plus couramment utilisés pour Python .
python3.8 -m pip install -U pip
python3.8 -m pip install -U setuptools
python3.8 -m pip install pillow
python3.8 -m pip install virtualenv

Configuration de Django


Nous redémarrons le système et passons sous l'utilisateur que vous avez créé. Allons dans le répertoire / var / www et téléchargeons notre projet, qui est téléchargé sur GitHub .

cd /var/www
sudo git clone LINK_TO_PROJECT

Configurez les droits pour un fonctionnement normal avec le répertoire / var / www
sudo chown -R www-data:www-data /var/www
sudo usermod -aG www-data username
sudo chmod go-rwx /var/www
sudo chmod go+x /var/www
sudo chgrp -R www-data /var/www
sudo chmod -R go-rwx /var/www
sudo chmod -R g+rwx /var/www

Il peut sembler que nous effectuons certaines actions, puis les annulons, mais le fait est que nous supprimons d'abord toutes les autorisations pour tout le monde, puis les attribuons à un utilisateur ou un groupe spécifique.

Nous allons à notre projet, créons un environnement virtuel et l'exécutons:

cd djangoprojectname/
virtualenv env
source ./env/bin/activate

Si tout est activé, il y aura une ligne du formulaire: (env) username @ server.

Nous livrerons / mettrons Ă  jour les principaux packages dont nous avons besoin pour notre projet.

pip install -U pip
pip install -U setuptools
pip install -U pillow

Nous avons mis Django, Gunicorn et un adaptateur pour PostgreSQL.

pip install django gunicorn psycopg2-binary

Vous pouvez également mettre les packages nécessaires à votre projet, j'utilise summernote pour le texte:

pip install django-summernote

Nous avons mis en place un pare-feu, nous devons donc créer une exception pour celui-ci sur le port 8000 (nous l'utilisons par défaut, si nous prévoyons d'en utiliser un autre, alors spécifiez-le):

sudo ufw allow 8000

L'étape requise consiste à vérifier l'intégrité du serveur:

python3.8 manage.py runserver 0.0.0.0:8000

Et accédez à votre site Web, DOMAIN_NAME: 8000 , pour vous assurer que tout fonctionne! Mais, pour le moment, nous n'avons pas encore beaucoup configuré, ce ne sont que des paramètres de base, nous devons configurer le fonctionnement normal du serveur, connecter la statique, etc.
Si votre site ne démarre pas, alors vous devez vous plonger dans les paramètres (éventuellement les droits d'accès) et voir quel package n'a pas été installé, tout est très individuel.

Vous pouvez terminer l'exécution en appuyant sur les touches: Vérifiez le fonctionnement de Gunicorn: les touches CTRL + C du .

Ensuite, nous ne continuons que si votre projet a commencé, je vous recommande fortement de ne pas poursuivre si quelque chose ne fonctionne pas. Il vaut mieux résoudre le problème au stade initial que de démolir le serveur à la racine (j'ai démoli 3 fois, puis j'ai commencé à écrire cette instruction, en corrigeant chaque action).



gunicorn --bind 0.0.0.0:8000 MAINAPPNAME.wsgi

MAINAPPNAME est le nom de l'application principale qui contient settings.py .

Si le serveur fonctionne, continuez.

Vous pouvez terminer l'exécution en appuyant sur les touches: C TRL + le C .

DĂ©finition de settings.py


Lors du déploiement sur un serveur de production, vous devez désactiver le débogage du projet et modifier plusieurs paramètres, je l'ai fait comme suit dans settings.py de mon projet.

DEBUG = False
if DEBUG:
    ALLOWED_HOSTS = ['*']
else:
    ALLOWED_HOSTS = ['HOST IP', 'DOMAIN NAIM', 'localhost']
...
STATIC_URL = '/static/'
if DEBUG:
    STATIC_DIR = os.path.join(BASE_DIR, 'static')
    STATICFILES_DIRS = [
        STATIC_DIR,
        '/var/www/static/',
    ]
else:
    STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
    STATICFILES_FINDERS = (
        'django.contrib.staticfiles.finders.FileSystemFinder',
        'django.contrib.staticfiles.finders.AppDirectoriesFinder',
    )
MEDIA_URL = '/media/'

Dans urls.py, j'ai changé les paramètres pour la statique et les médias.

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
    urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

Je ne sais pas dans quelle mesure c'est la bonne décision, et il y a peut-être des changements plus corrects à ces fichiers. Mais dans ce cas, il me suffit de changer la valeur de DEBUG pour basculer entre développement et publication.

Exécutez la commande:

python3.8 manage.py collectstatic

Pour collecter des statiques et désactiver l'environnement virtuel:

deactivate

Configurer Gunicorn


Ouvrons pour la personnalisation

sudo nano /etc/systemd/system/gunicorn.socket

Écrivons quelques paramètres dans le fichier:

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Nous avons créé la section [Unit] pour décrire le socket, dans la section [Socket] nous avons déterminé l'emplacement du socket et dans la section [Install] nous devons installer le socket au bon moment.

Ouvrez le fichier utilitaire systemd pour configurer le service:

sudo nano /etc/systemd/system/gunicorn.service

[Unit]
Description=gunicorn daemon
Requires=gunicorn.socket
After=network.target

[Service]
User=username
Group=www-data
WorkingDirectory=/var/www/djangoprojectname
ExecStart=/var/www/djangoprojectname/env/bin/gunicorn \
          --access-logfile - \
          --workers 5 \
          --bind unix:/run/gunicorn.sock \
          myproject.wsgi:application

[Install]
WantedBy=multi-user.target

N'oubliez pas d'indiquer votre utilisateur, le nom de votre projet et votre environnement virtuel.

Comme on m'a expliqué, les travailleurs sont calculés comme le nombre de cœurs de processeur * 2 + 1 .
Maintenant, nous lançons et activons la prise Gunicorn.

sudo systemctl start gunicorn.socket
sudo systemctl enable gunicorn.socket

Et assurez-vous de tester que tout fonctionne!

sudo systemctl status gunicorn.socket

Doit afficher des informations sur le service en cours d'exécution.

Appuyez sur la touche Q pour quitter (requis dans la disposition en anglais).

file /run/gunicorn.sock

La dernière commande devrait afficher un message sur le fichier.

Si la première commande sudo systemctl status gunicorn.socket échoue , ou si la deuxième commande filer //ungunicorn.sock signale que le fichier gunicorn.sock ne se trouve pas dans le répertoire, le socket Gunicorn n'a pas pu être créé. Vous devez vérifier les journaux de socket Gunicorn avec la commande suivante:

sudo journalctl -u gunicorn.socket

Voyez quelle est l'erreur et corrigez-la.

Passons au test d'activation de socket.

sudo systemctl status gunicorn

Vous aurez probablement un dossier:

Active: inactive (dead)

Jusqu'à présent, tout se passe bien.

Établissez une connexion à la prise via curl.

curl --unix-socket /run/gunicorn.sock localhost


Peut générer une erreur de requête incorrecte (400).

Essayez au lieu de localhost de spécifier l' IP de votre serveur , si tout va bien, cela est probablement dû aux paramètres nginx que nous n'avons pas encore effectués. Continuez.

Et encore une fois, demandez la sortie d'Ă©tat:

sudo systemctl status gunicorn

Active: active (running)

Si l'enregistrement est le suivant, il y a encore beaucoup d'informations, mais pas sur les erreurs, alors tout va bien.

Sinon, nous regardons les erreurs dans le journal

sudo journalctl -u gunicorn

Et redémarrez les processus gunicorn

sudo systemctl daemon-reload
sudo systemctl restart gunicorn

Configuration de NGINX


Nous allons créer un nouveau bloc serveur pour notre site et le configurer afin que lors de l'accès à notre site dans la barre d'adresse, le serveur comprenne quoi et où l'obtenir.

sudo nano /etc/nginx/sites-available/djangoprojectname

server {
    listen 80;
    server_name server_domain_or_IP;

    location = /favicon.ico { access_log off; log_not_found off; }
    location /static/ {
        alias /var/www/djangoprojectname/static/;
    }

    location /media/ {
        alias /var/www/djangoprojectname/media/;
    }

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

Dans la section sever_name, vous pouvez spécifier plusieurs adresses séparées par des espaces.

Testez les erreurs de syntaxe:

sudo nginx -t

S'il n'y a pas d'erreur, redémarrez le serveur et donnez à notre pare-feu les droits nécessaires:

sudo systemctl restart nginx
sudo ufw allow 'Nginx Full'

Vous pouvez également supprimer l'accès au port 8000

sudo ufw delete allow 8000

À ce stade, tout devrait fonctionner, mais cela n'a pas fonctionné correctement jusqu'à ce que je configure https. Malheureusement, je ne peux pas expliquer à quoi cela est lié, mais la statique n'a pas été chargée, bien que les fichiers multimédias aient été chargés normalement.

Configuration HTTPS


Nous utiliserons Cerbot pour configurer

sudo apt-get install certbot python-certbot-nginx
sudo certbot –nginx

Et suivez les invites à l'écran. S'il y a des erreurs, éliminez-les et réessayez. Par exemple, une erreur peut se produire si vous spécifiez un nom de domaine qui n'est pas lié à ce serveur.
Pour renouveler automatiquement le certificat, entrez la commande.

sudo certbot renew --dry-run 

Nous testons maintenant le site et tout devrait fonctionner!

Si les statistiques n'apparaissent toujours pas, essayez d'ouvrir un fichier css indiquant l'adresse complète avant, si vous obtenez une erreur 403, tout va bien, mais le problème des droits d'accès doit être expérimenté, essayez de réinitialiser tous les paramètres de droits pour www-data à répertoire / var / www . Si l'erreur est 404, vous devez regarder vers les paramètres d' emplacement dans les paramètres NGINX .

Configuration de PostgreSQL


Configurez PostgreSQL et importez des données depuis SQLite. Si vous n'en avez pas besoin, ignorez cette étape ou prenez uniquement les paramètres PostgreSQL.

Créez une base de données et un utilisateur.

sudo -u postgres psql

CREATE DATABASE dbforproject;
CREATE USER projectdbuser WITH PASSWORD 'password';

Nous suivrons les recommandations du projet Django.

Nous avons défini le codage par défaut sur UTF-8, défini le schéma d'isolement des transactions par défaut sur «lecture validée», pour bloquer la lecture des transactions non confirmées. Réglez le fuseau horaire sur GMT (UTC).

ALTER ROLE projectdbuser SET client_encoding TO 'utf8';
ALTER ROLE projectdbuser SET default_transaction_isolation TO 'read committed';
ALTER ROLE projectdbuser SET timezone TO 'UTC';

Après cela, vous devez fournir à l'utilisateur que nous avons créé un accès pour administrer la nouvelle base de données:

GRANT ALL PRIVILEGES ON DATABASE dbforproject TO projectdbuser;

Une fois toutes les commandes terminées, vous pouvez fermer la boîte de dialogue PostgreSQL à l'aide de la commande:

\q

Maintenant que la configuration PostgreSQL est terminée, nous allons maintenant configurer Django pour qu'il fonctionne correctement avec PostreSQL.

Tout d'abord, copiez les anciennes données de SQLite (si nécessaire). Pour ce faire, accédez à votre projet et lancez l'environnement virtuel:

cd /var/www/djangoprojectname
source ./env/bin/activate
cd mainappname/
python3.8 manage.py dumpdata > datadump.json

Modifiez les paramètres de connexion à la base de données:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'dbforproject',
        'USER': 'projectdbuser',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '',
    }
}

Exécutez la migration pour la base de données:

python3.8 manage.py migrate --run-syncdb

Après cet obus:

python3 manage.py shell

Et Ă©crivez-y:

>>> from django.contrib.contenttypes.models import ContentType
>>> ContentType.objects.all().delete()
>>> quit()

Et chargez les données précédemment téléchargées depuis SQLite:

python3.8 manage.py loaddata datadump.json

C'est tout, tout a commencé et fonctionne pour moi, mais en cas d'erreurs, c'est très individuel, donc je recommande de ne pas ignorer les étapes du test de performance afin que vous puissiez comprendre à quel stade l'erreur s'est produite.

Lors de l'écriture, j'ai utilisé:

  1. www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-18-04-ru
  2. vexxhost.com/resources/tutorials/how-to-deploy-django-on-nginx-gunicorn-with-postgres
  3. pythonworld.ru/web/django-ubuntu1604.html

All Articles