Resumen

En resumen: se trata de servir el django usando WSGI mediante un servidor Gunicorn corrido a través de supervisor (un gestor de tareas). El Nginx usará un proxy reverso para servir a su vez dicho contenido.

NGinx

Primero crearemos un archivo de configuración, de manera similar a cómo haríamos en Apache. Si hemos instalado nginx usando apt o similares la estructura será la misma a la de un apache y habrá que crear el archivo en sites-available y enlazarlo desde sites-enabled. Si no (porque estemos en un servidor centOS por ejemplo), esta estructura no existirá y tendremos dos opciones. Hacer lo mismo sustituyendo a sites-enabled por conf.d; o añadir una línea de importación a nginx.conf y crear a mano dicha estructura; o, por último, añadir directamente a conf.d el archivo en cuestión.

La configuración

https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/

Este sería un ejemplo de archivo a añadir

server {
    listen      80;          # ipv4
    listen      [::]:80;     # ipv6
    server_name example.org; 
    charset     utf-8;

    location = /favicon.ico { # para evitar 404 en el favicon
        access_log off;
        log_not_found off;
    }

    location /media  {
        alias /var/www/example.org/public_html/assets/media;
    }

    location /static {
        alias /var/www/example.org/public_html/assets/static;
    }

    location / {
         proxy_pass http://unix:/var/www/example.org/public_html/example.sock;
         proxy_set_header Host $host;
         proxy_set_header X-Real-IP $remote_addr;
         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Es muy similar a la configuración de un virtualhost de apache (aquí "block de nginx"). Es bastante autoexplicativo. La parte importante va en la configuración del proxy reverso:

proxy_pass http://unix:/var/www/example.org/public_html/example.sock;

Lo que hacemos es conectar todas las peticiones mediante un proxy reverso a un socket unix especificado mediante unix:<ruta-al-socket>. La creación de este socket correrá a cargo de Gunicorn.

Gunicorn

Gunicorn (Green Unicorn) es un servidor HTTP WSGI capaz de servir aplicaciones escritas en Python. Primero deberemos instalarlo. Lo haremos en el entorno virtual del django:

. env/bin/activate
pip install gunicorn

Para servir directamente el django entraríamos en la carpeta raíz y haríamos un:

../env/bin/gunicorn --bind 127.0.0.1:8000 example.wsgi:application

Vemos que:

  • Corremos el gunicorn instalado en el entorno virtual (importante: para usar el entorno virtual y no el python y los paquetes instalados globalmente)
  • Hacemos un bind (a un puerto o a un socket)
  • Especificamos el archivo principal wsgi (en este caso example.wsgi, considerando un proyecto de nombre 'example' --> usa dot notation, el archivo realmente se llama wsgi.py y estaría en la carpeta 'example').

Esto sería análogo a correr el django usando manage.py.

Supervisor

http://supervisord.org/

Es un demonio que funciona como sistema de control de procesos. Es el sistema que usaremos para controlar gunicorn. Para instalarlo haremos simplemente un:

pip install supervisor 

La configuración es muy sencilla y se hace a través de una directiva 'program' que define un comando que se ejecuta cada vez que corra el proceso 'supervisor'. Este directiva se puede incluir directamente en el archivo /etc/supervisord.conf o bien dentro de un archivo .conf en /etc/supervisord.d/:

[program:example]
command=/var/www/example.org/env/bin/gunicorn --bind unix:/var/www/example.org/example.sock example.wsgi:application
directory=/var/www/example.org/public_html
username=root
autostart=true
autorestart=true
stdout_logfile=/var/www/example.org/mapa.log
stderr_logfile=/var/www/example.org/mapa.err.log

Especificamos el directorio donde el proceso correrá, el comando (el gunicorn instalado en el entorno virtual del django), así como el usuario que lo correrá (tiene que tener permisos de lectura/escritura), los logs (las carpetas que los contengan han de existir si no queremos que falle el proceso), así como el comportamiento cuando supervisor arranca o cae (lanzarse automáticamente o no).

Por último activamos el servicio para que corra cuando el sistema arranque o reinicie:

sudo systemctl enable supervisord