Configuración de Debian, Nginx y Gunicorn para un proyecto Django



Buen día a todos.

Hubo una tarea para elevar el servidor Debian en Nginx para los proyectos Django 3.x. Romper un montón de información en Internet, logré hacer esto combinando recomendaciones de varios sitios diferentes. Si está interesado en leer cómo configurar su primer servidor para un proyecto Django, bienvenido.

Te contaré un poco sobre ti para que entiendas quién soy. No soy desarrollador, ni programador, ni administrador de sistemas, ni siquiera tengo educación en TI. Soy profesora de informática. Pero en el trabajo, tengo que explicar a los estudiantes algunos puntos que están muy lejos del curso escolar en informática, y uno de ellos es el desarrollo de proyectos en Django.

Ajustes básicos


Para empezar, ya tenemos un servidor con Debian 10 instalado, no debería haber problemas para instalar Debian. Tuve una instalación limpia, sin ninguna configuración adicional, así que fui a mi servidor a través de la raíz y comencé a instalar algunos de los componentes principales para mí.

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

Puede poner todo esto en una instalación, pero recibí un error, y en este orden todo salió bien.

Luego, cree un nuevo usuario y agréguelo al grupo sudo para que pueda iniciar procesos en nombre del superusuario.

adduser username 
usermod -aG sudo username

donde username es el nombre de usuario que usará en el futuro.
Instale la última versión de Python desde la fuente. Al momento de escribir, esto era 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

Explicación de acciones
cd — , change directory;
curl — URL. ;
tar — .

Después de descargar la última versión de Python y pasar al directorio de origen, ejecutamos:

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

Esto nos permitirá preparar todo lo necesario para instalar Python. Aquí, el número 2, este es el número de núcleos de procesador. Puede averiguarlo con el comando nproc .
Comenzamos la instalación.
make altinstall

Puede verificar que Python se haya instalado utilizando el comando:

python3.8 -V

Producirá una versión de Python .
Después de eso, actualizamos pip e instalamos los paquetes más utilizados para 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

Configuración de Django


Reiniciamos el sistema y pasamos al usuario que creó. Vayamos al directorio / var / www y descarguemos nuestro proyecto, que se carga en GitHub .

cd /var/www
sudo git clone LINK_TO_PROJECT

Configure los derechos para el funcionamiento normal con el directorio / 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

Puede parecer que hacemos ciertas acciones y luego las cancelamos, pero el punto es que primero eliminamos todos los permisos para todos y luego los asignamos a un usuario o grupo específico.

Vamos a nuestro proyecto, creamos un entorno virtual y lo ejecutamos:

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

Si todo está activado, habrá una línea del formulario: (env) username @ server.

Entregaremos / actualizaremos los paquetes principales que necesitamos para nuestro proyecto.

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

Ponemos Django, Gunicorn y un adaptador para PostgreSQL.

pip install django gunicorn psycopg2-binary

También puede poner los paquetes necesarios para su proyecto, yo uso summernote para el texto:

pip install django-summernote

Configuramos un cortafuegos, por lo que debemos crear una excepción en el puerto 8000 (lo usamos de manera predeterminada, si planeamos usar otro, luego especifíquelo):

sudo ufw allow 8000

El paso requerido es verificar el estado del servidor:

python3.8 manage.py runserver 0.0.0.0:8000

¡Y ve a tu sitio web, DOMAIN_NAME: 8000 , para asegurarte de que todo funcione! Pero, por el momento, aún no hemos configurado mucho, estos son solo ajustes básicos, necesitamos configurar el funcionamiento normal del servidor, conectar las estadísticas, etc.
Si su sitio no se inicia, entonces necesita profundizar en la configuración (posiblemente los derechos de acceso) y ver qué paquete no se ha instalado, todo es muy individual.

Para completar pulsando las teclas: Ctrl + C del .

Luego, seguimos adelante solo si su proyecto ha comenzado, le recomiendo que no continúe si algo no funciona. Es mejor solucionar el problema en la etapa inicial que derribar el servidor hasta la raíz (demolí 3 veces, y luego comencé a escribir estas instrucciones, arreglando cada acción).

Comprobando el trabajo de Gunicorn:

gunicorn --bind 0.0.0.0:8000 MAINAPPNAME.wsgi

MAINAPPNAME es el nombre de la aplicación principal que contiene settings.py .

Si el servidor está funcionando, continúe.

Para completar pulsando las teclas: la C TRL + el C .

Configuración settings.py


Cuando se implementa en un servidor de producción, debe deshabilitar la depuración del proyecto y cambiar varias configuraciones, hice esto de la siguiente manera en settings.py de mi proyecto.

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/'

En urls.py, cambié la configuración de las estadísticas y los medios.

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

No sé cuánto es esta la decisión correcta, y tal vez hay más cambios correctos en estos archivos. Pero en este caso, es suficiente para mí cambiar el valor de DEBUG para cambiar entre desarrollo y publicación.

Ejecute el comando:

python3.8 manage.py collectstatic

Para recopilar estadísticas y desactivar el entorno virtual:

deactivate

Configurar Gunicorn


Abramos para personalizar

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

Escribamos algunas configuraciones en el archivo:

[Unit]
Description=gunicorn socket

[Socket]
ListenStream=/run/gunicorn.sock

[Install]
WantedBy=sockets.target

Creamos la sección [Unidad] para describir el zócalo, en la sección [Zócalo] determinamos la ubicación del zócalo y en la sección [Instalar] necesitamos instalar el zócalo en el momento adecuado.

Abra el archivo de utilidad systemd para configurar el servicio:

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

No olvide indicar su usuario, el nombre de su proyecto y su entorno virtual.

Como se me explicó, los trabajadores se calculan como el número de núcleos de procesador * 2 + 1 .
Ahora lanzamos y activamos el socket Gunicorn.

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

¡Y asegúrese de probar que todo funciona!

sudo systemctl status gunicorn.socket

Debe mostrar información sobre el servicio en ejecución.

Presione la tecla Q para salir (requerido en el diseño en inglés).

file /run/gunicorn.sock

El último comando debe mostrar un mensaje sobre el archivo.

Si el primer comando sudo systemctl status gunicorn.socket falla , o si el segundo archivo /run/gunicorn.sock informa que el archivo gunicorn.sock no está en el directorio, no se pudo crear el socket Gunicorn. Debe verificar los registros de socket de Gunicorn con el siguiente comando:

sudo journalctl -u gunicorn.socket

Vea cuál es el error y corríjalo.

Pasemos a probar la activación del socket.

sudo systemctl status gunicorn

Lo más probable es que tenga un registro:

Active: inactive (dead)

Hasta ahora, todo va bien.

Establezca una conexión al zócalo a través de curl.

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


Puede arrojar un error de solicitud incorrecta (400).

Intente en lugar de localhost para especificar la IP de su servidor , si todo está bien, lo más probable es que esto se deba a la configuración de nginx que aún no hemos hecho. Simplemente seguir adelante.

Y nuevamente, solicite la salida del estado:

sudo systemctl status gunicorn

Active: active (running)

Si el registro es este + todavía hay mucha información, pero no sobre errores, entonces todo está bien.

De lo contrario, observamos errores en el registro

sudo journalctl -u gunicorn

Y reiniciar los procesos gunicorn

sudo systemctl daemon-reload
sudo systemctl restart gunicorn

Configuración NGINX


Crearemos un nuevo bloque de servidor para nuestro sitio y lo configuraremos de modo que al acceder a nuestro sitio en la barra de direcciones, el servidor entienda de qué y dónde obtenerlo.

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;
    }
}

En la sección sever_name, puede especificar varias direcciones separadas por espacios.

Prueba de errores de sintaxis:

sudo nginx -t

Si no hay errores, reinicie el servidor y otorgue a nuestro firewall los derechos necesarios:

sudo systemctl restart nginx
sudo ufw allow 'Nginx Full'

También puede eliminar el acceso al puerto 8000

sudo ufw delete allow 8000

En este punto, todo debería funcionar, pero no funcionó bien hasta que configuré https. Desafortunadamente, no puedo explicar con qué está conectado esto, pero las estadísticas no se cargaron, aunque los archivos multimedia se cargaron normalmente.

Configuración HTTPS


Usaremos Cerbot para configurar

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

Y sigue las indicaciones en la pantalla. Si hay errores, elimine y vuelva a intentar. Por ejemplo, puede producirse un error si especifica un nombre de dominio que no está relacionado con este servidor.
Para renovar automáticamente el certificado, ingrese el comando.

sudo certbot renew --dry-run 

¡Ahora estamos probando el sitio y todo debería funcionar!

Si las estadísticas aún no aparecían, intente abrir algún archivo css que indique la dirección completa antes, si obtiene un error 403, entonces todo está bien, pero el problema de derechos de acceso debe ser experimentado, intente restablecer todas las configuraciones de derechos para www-data a directorio / var / www . Si el error es 404, entonces debe mirar hacia la configuración de ubicación en la configuración de NGINX .

Configuración de PostgreSQL


Configure PostgreSQL e importe datos desde SQLite. Si no lo necesita, omita este paso o tome solo la configuración de PostgreSQL.

Crear una base de datos y usuario.

sudo -u postgres psql

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

Seguiremos las recomendaciones para el proyecto Django.

Establecemos la codificación predeterminada en UTF-8, establecemos el esquema de aislamiento de transacción predeterminado en "lectura confirmada", para bloquear la lectura de transacciones no confirmadas. Establezca la zona horaria en 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';

Después de eso, debe proporcionar acceso al usuario que creamos para administrar la nueva base de datos:

GRANT ALL PRIVILEGES ON DATABASE dbforproject TO projectdbuser;

Después de completar todos los comandos, puede cerrar el cuadro de diálogo PostgreSQL con el comando:

\q

Ahora la configuración de PostgreSQL está completa, ahora configuraremos Django para que funcione correctamente con PostreSQL.

Primero, copie los datos antiguos de SQLite (si es necesario). Para hacer esto, vaya a su proyecto e inicie el entorno virtual:

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

Cambie la configuración para conectarse a la base de datos:

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

Ejecute la migración para la base de datos:

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

Después de este caparazón:

python3 manage.py shell

Y escribe en él:

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

Y cargue los datos cargados previamente desde SQLite:

python3.8 manage.py loaddata datadump.json

Eso es todo, todo comenzó y funciona para mí, pero en caso de errores es muy individual, por lo que recomiendo no omitir los pasos con las pruebas de rendimiento para que pueda entender en qué etapa se produjo el error.

Cuando escribía, usaba:

  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