Django es un poderoso marco web que puede ayudarlo a poner en marcha su aplicación o sitio web de Python. Django incluye un servidor de desarrollo simplificado para probar su código localmente, pero para cualquier cosa que esté ligeramente relacionada con la producción, se requiere un servidor web más seguro y potente (Nginx - Apache).
En esta guía, demostraremos cómo instalar y configurar algunos componentes en Ubuntu 18.04 para admitir y servir aplicaciones Django. Configuraremos una base de datos PostgreSQL en lugar de usar la base de datos SQLite predeterminada. Configuraremos el servidor de aplicaciones Gunicorn para interactuar con nuestras aplicaciones. Luego configuraremos Nginx para revertir el proxy a Gunicorn, lo que nos dará acceso a sus funciones de seguridad y rendimiento para servir nuestras aplicaciones.
Crear usuario no root con privilegios sudo configurados
- Iniciar sesión como root
- Creando un nuevo usuario
# adduser bobby
- Concesión de privilegios administrativos
Para agregar estos privilegios a nuestro nuevo usuario, debemos agregar el nuevo usuario al grupo sudo. De forma predeterminada, en Ubuntu 18.04, los usuarios que pertenecen al grupo sudo pueden usar el comando sudo.# usermod -aG sudo bobby
Instalar los paquetes desde los repositorios de Ubuntu
Para comenzar el proceso, descargaremos e instalaremos todos los elementos que necesitamos de los repositorios de Ubuntu. Usaremos el pip del administrador de paquetes de Python para instalar componentes adicionales un poco más tarde.
Necesitamos actualizar el índice de paquetes apt local y luego descargar e instalar los paquetes. Los paquetes que instalamos dependen de la versión de Python que usará su proyecto.
Instalando Django con Python 3, escriba:
$ sudo apt-get update
$ sudo apt-get install python3-pip python3-dev libpq-dev postgresql postgresql-contrib nginx
Esto instalará pip, los archivos de desarrollo de Python necesarios para compilar Gunicorn más adelante, el sistema de base de datos Postgres y las bibliotecas necesarias para interactuar con él, y el servidor web Nginx.
Crear la base de datos y el usuario de PostgreSQL
Vamos a saltar directamente y crear una base de datos y un usuario de base de datos para nuestra aplicación Django. De manera predeterminada, Postgres usa un esquema de autenticación llamado autenticación de pares para conexiones locales. Básicamente, esto significa que si el nombre de usuario del sistema operativo del usuario coincide con un nombre de usuario de Postgres válido, ese usuario puede iniciar sesión sin más autenticación.
Durante la instalación de Postgres, se creó un usuario del sistema operativo llamado postgres para corresponder al usuario administrativo de postgres PostgreSQL. Necesitamos usar este usuario para realizar tareas administrativas. Podemos usar sudo y pasar el nombre de usuario con la opción -u.
Inicie sesión en una sesión interactiva de Postgres escribiendo:
$ sudo -u postgres psql
Se le dará un aviso de PostgreSQL donde podemos configurar nuestros requisitos.
Primero, crea una base de datos para tu proyecto
Postgres=# CREATE DATABASE newproject;
A continuación, cree un usuario de base de datos para nuestro proyecto. Asegúrese de seleccionar una contraseña segura
Postgres=# CREATE USER newprojectuser WITH PASSWORD 'password';
Luego, modificaremos algunos de los parámetros de conexión para el usuario que acabamos de crear. Esto acelerará las operaciones de la base de datos para que no sea necesario consultar y establecer los valores correctos cada vez que se establece una conexión.
Estamos configurando la codificación predeterminada en UTF-8, que espera Django. También estamos configurando el esquema de aislamiento de transacciones predeterminado para leer confirmadas, lo que bloquea las lecturas de transacciones no confirmadas. Por último, estamos configurando la zona horaria. De forma predeterminada, nuestros proyectos de Django se configurarán para usar UTC. Todas estas son recomendaciones del propio proyecto Django.
Postgres=# ALTER ROLE newprojectuser SET client_encoding TO 'utf8';
Postgres=# ALTER ROLE newprojectuser SET default_transaction_isolation TO 'read committed';
Postgres=# ALTER ROLE newprojectuser SET timezone TO 'UTC';
Ahora, podemos dar acceso a nuestro nuevo usuario para administrar nuestra nueva base de datos
Postgres=# GRANT ALL PRIVILEGES ON DATABASE newproject TO newprojectuser;
Cuando haya terminado, salga del indicador de PostgreSQL escribiendo:
Postgres=# \q
Cree un entorno virtual de Python 3 para su proyecto
Ahora que tenemos nuestra base de datos, podemos comenzar a preparar el resto de los requisitos de nuestro proyecto. Instalaremos nuestros requisitos de Python 3 dentro de un entorno virtual para facilitar la administración.
Para hacer esto, primero necesitamos acceder al comando virtualenv. Podemos instalar esto con pip3.
Actualice pip3 e instale el paquete escribiendo:
$ sudo -H pip3 install --upgrade pip
$ sudo -H pip3 install virtualenv
Con virtualenv instalado, podemos comenzar a formar nuestro proyecto. Cree y muévase a un directorio donde podamos guardar nuestros archivos de proyecto:
$ mkdir ~/djangoproject
$ cd ~/djangoproject
Dentro del directorio del proyecto, cree un entorno virtual de Python escribiendo:
$ virtualenv djangoprojectenv
Esto creará un directorio llamado djangoprojectenv
dentro de tu djangoproject
directorio. En el interior, instalará una versión local de Python y una versión local de pip. Podemos usar esto para instalar y configurar un entorno de Python aislado para nuestro proyecto.
Antes de instalar los requisitos de Python de nuestro proyecto, debemos activar el entorno virtual. Puede hacerlo escribiendo:
$ source djangoproject/bin/activate
Su mensaje debería cambiar para indicar que ahora está operando dentro de un entorno virtual de Python. Se verá así:(djangoprojectenv)user@host:~/djangoproject$
.
Con su entorno virtual activo, instale Django, Gunicorn y el adaptador psycopg2 PostgreSQL con la instancia local de pip:
(djangoprojectenv)$ pip install django gunicorn psycopg2-binary
Ahora debería tener todo el software necesario para iniciar un proyecto Django.
Crear y configurar un nuevo proyecto Django
Con nuestros componentes de Python instalados, podemos crear los archivos de proyecto reales de Django.
Como ya tenemos un directorio de proyectos, le diremos a Django que instale los archivos aquí. Creará un directorio de segundo nivel con el código real, lo cual es normal, y colocará un script de administración en este directorio. La clave de esto es que estamos definiendo el directorio explícitamente en lugar de permitir que Django tome decisiones relativas a nuestro directorio actual:
(djangoprojectenv)$ django-admin.py startproject djangoproject ~/djangoproject
En este punto, el directorio de su proyecto (~/djangoproject
en nuestro caso) debe tener el siguiente contenido:
~/djangoproject/manage.py
:Un script de gestión de proyectos de Django.~/djangoproject/myproject/
:El paquete del proyecto Django. Esto debería contener el__init__.py
,settings.py
,urls.py
ywsgi.py
archivos.~/djangoproject/djangoprojectenv/
:El directorio del entorno virtual que creamos anteriormente.
Lo primero que debemos hacer con nuestros archivos de proyecto recién creados es ajustar la configuración. Abra el archivo de configuración en su editor de texto:
(djangoprojectenv)$ nano ~/djangoproject/djangoproject/settings.py
Comience por ubicar la directiva ALLOWED_HOSTS. Esto define una lista de las direcciones del servidor o los nombres de dominio que se pueden usar para conectarse a la instancia de Django. Cualquier solicitud entrante con un encabezado de host que no esté en esta lista generará una excepción. Django requiere que configures esto para evitar una cierta clase de vulnerabilidad de seguridad.
Entre corchetes, enumere las direcciones IP o los nombres de dominio asociados con su servidor Django. Cada elemento debe enumerarse entre comillas con las entradas separadas por una coma. Si desea solicitudes para un dominio completo y cualquier subdominio, anteponga un punto al comienzo de la entrada. En el fragmento a continuación, hay algunos ejemplos comentados que se usan para demostrarlo.
~/djangoproject/djangoproject/settings.py
. . .
# The simplest case: just add the domain name(s) and IP addresses of your Django server
# ALLOWED_HOSTS = [ 'example.com', '203.0.113.5']
# To respond to 'example.com' and any subdomains, start the domain with a dot
# ALLOWED_HOSTS = ['.example.com', '103.25.111.5']
ALLOWED_HOSTS = ['your_server_domain_or_IP', 'second_domain_or_IP', . . .]
A continuación, busque la sección que configura el acceso a la base de datos. Comenzará con BASES DE DATOS. La configuración en el archivo es para una base de datos SQLite. Ya creamos una base de datos PostgreSQL para nuestro proyecto, por lo que debemos ajustar la configuración.
Cambie la configuración con la información de su base de datos PostgreSQL. Le decimos a Django que use el psycopg2adaptor que instalamos con pip. Necesitamos dar el nombre de la base de datos, el nombre de usuario de la base de datos, la contraseña del usuario de la base de datos y luego especificar que la base de datos se encuentra en la computadora local. Puede dejar la configuración de PUERTO como una cadena vacía:
~/djangoproject/djangoproject/settings.py
. . .
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'newproject',
'USER': 'newprojectuser',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '',
}
}
. . .
A continuación, baje hasta la parte inferior del archivo y agregue una configuración que indique dónde deben colocarse los archivos estáticos. Esto es necesario para que Nginx pueda gestionar las solicitudes de estos elementos. La siguiente línea le dice a Django que los coloque en un directorio llamado estático en el directorio base del proyecto:
~/djangoproject/djangoproject/settings.py
. . .
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
Guarde y cierre escribiendo Ctrl + x
el archivo cuando haya terminado.
Ahora, podemos migrar el esquema de base de datos inicial a nuestra base de datos PostgreSQL usando el script de administración:
(djangoprojectenv)$ ~/djangoproject/manage.py makemigrations
(djangoprojectenv)$ ~/djangoproject/manage.py migrate
Cree un usuario administrativo para el proyecto escribiendo:
(djangoprojectenv)$ ~/djangoproject/manage.py createsuperuser
Deberá seleccionar un nombre de usuario, proporcionar una dirección de correo electrónico y elegir y confirmar una contraseña.
Podemos recopilar todo el contenido estático en la ubicación del directorio que configuramos escribiendo:
(djangoprojectenv)$ ~/djangoproject/manage.py collectstatic
Tendrás que confirmar la operación. Los archivos estáticos se colocarán en un directorio llamado estático dentro del directorio de su proyecto.
Si siguió la guía de configuración inicial del servidor, debería tener un firewall UFW que proteja su servidor. Para probar el servidor de desarrollo, tendremos que permitir el acceso al puerto que usaremos.
Cree una excepción para el puerto 8000 escribiendo:
(djangoprojectenv)$ sudo ufw allow 8000
Finalmente, puede probar su proyecto iniciando el servidor de desarrollo de Django con este comando:
(djangoprojectenv)$ ~/djangoproject/manage.py runserver 0.0.0.0:8000
En su navegador web, visite el nombre de dominio o la dirección IP de su servidor seguido de :8000:
http://server_domain_or_IP:8000
Debería ver la página de índice de Django predeterminada para Django 2.0.7:
Si escribe http://server_domain_or_IP:8000/admin en la barra de direcciones, se le solicitará el nombre de usuario y la contraseña administrativos que creó con el comando createsuperuser:
Después de la autenticación, puede acceder a la interfaz de administración de Django predeterminada:
Cuando haya terminado de explorar, presione CTRL-C
en la ventana de la terminal para cerrar el servidor de desarrollo.
Prueba de la capacidad de Gunicorn para servir al proyecto
Lo último que queremos hacer antes de abandonar nuestro entorno virtual es probar Gunicorn para asegurarnos de que puede servir la aplicación. Podemos hacer esto ingresando a nuestro directorio de proyectos y usando gunicorn para cargar el módulo WSGI del proyecto:
(djangoprojectenv)$ cd ~/djangoproject
(djangoprojectenv)$ gunicorn --bind 0.0.0.0:8000 djangoproject.wsgi
Esto iniciará Gunicorn en la misma interfaz en la que se estaba ejecutando el servidor de desarrollo de Django. Puede regresar y probar la aplicación nuevamente.
Pasamos un módulo a Gunicorn especificando la ruta del directorio relativo al archivo wsgi.py de Django, que es el punto de entrada a nuestra aplicación, utilizando la sintaxis del módulo de Python. Dentro de este archivo, se define una función llamada aplicación, que se utiliza para comunicarse con la aplicación.
Cuando haya terminado de probar, presione CTRL-C en la ventana de la terminal para detener a Gunicorn.
Ahora hemos terminado de configurar nuestra aplicación Django. Podemos salir de nuestro entorno virtual escribiendo:
(myprojectenv)$ deactivate
Se eliminará el indicador de entorno virtual en su aviso.
Crear un archivo de servicio de gunicorn systemd
Hemos probado que Gunicorn puede interactuar con nuestra aplicación Django, pero deberíamos implementar una forma más robusta de iniciar y detener el servidor de aplicaciones. Para lograr esto, crearemos un archivo de servicio systemd.
Cree y abra un archivo de servicio systemd para Gunicorn con privilegios sudo en su editor de texto:
$ sudo nano /etc/systemd/system/gunicorn.service
Comienza con el [Unit]
sección, que se utiliza para especificar metadatos y dependencias. Pondremos una descripción de nuestro servicio aquí y le indicaremos al sistema de inicio que solo inicie esto después de que se haya alcanzado el objetivo de la red.
A continuación, abriremos el [Service]
sección. Especificaremos el usuario y el grupo que queremos procesar para ejecutar. Daremos a nuestra cuenta de usuario habitual la propiedad del proceso, ya que posee todos los archivos relevantes. Daremos propiedad de grupo a www-data
grupo para que Nginx pueda comunicarse fácilmente con Gunicorn.
Luego trazaremos el directorio de trabajo y especificaremos el comando que se usará para iniciar el servicio. En este caso, tendremos que especificar la ruta completa al ejecutable de Gunicorn, que está instalado dentro de nuestro entorno virtual. Lo vincularemos a un socket Unix dentro del directorio del proyecto ya que Nginx está instalado en la misma computadora. Esto es más seguro y rápido que usar un puerto de red. También podemos especificar cualquier ajuste opcional de Gunicorn aquí. Por ejemplo, especificamos 3 procesos de trabajo en este caso.
Finalmente, agregaremos un [Install]
sección. Esto le dirá a systemd a qué vincular este servicio si lo habilitamos para que se inicie en el arranque. Queremos que este servicio se inicie cuando el sistema multiusuario regular esté en funcionamiento:
/etc/systemd/system/gunicorn.service
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=bobby
Group=www-data
WorkingDirectory=/home/bobby/djangoproject
ExecStart=/home/bobby/djangoproject/djangoproject/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/bobby/djangoproject/djangoproject.sock djangoproject.wsgi:application
[Install]
WantedBy=multi-user.target
Con eso, nuestro archivo de servicio systemd está completo. Guárdelo y ciérrelo ahora.
debemos agregar al usuario bobby al grupo www-data:
$ sudo usermod –a –G www-data bobby
Ahora podemos iniciar el servicio de Gunicorn que creamos y habilitarlo para que se inicie en el arranque:
$ sudo systemctl start gunicorn
$ sudo systemctl enable gunicorn
Podemos confirmar que la operación se realizó correctamente comprobando el archivo de socket.
Verifique el estado del proceso para saber si se pudo iniciar:
$ sudo systemctl status gunicorn
A continuación, compruebe la existencia de djangoproject.sock
archivo dentro del directorio de su proyecto:
$ ls /home/bobby/djangoproject
Output
manage.py djangoproject djangoprojectenv djangoproject.sock static
Si el comando systemctl status indicó que ocurrió un error o si no encuentra el djangoproject.sock
archivo en el directorio, es una indicación de que Gunicorn no pudo iniciarse correctamente. Verifique los registros de proceso de Gunicorn escribiendo:
$ sudo journalctl -u gunicorn
Eche un vistazo a los mensajes en los registros para averiguar dónde tuvo problemas Gunicorn. Hay muchas razones por las que puede haber tenido problemas, pero a menudo, si Gunicorn no pudo crear el archivo de socket, es por una de estas razones:
- Los archivos del proyecto son propiedad del usuario root en lugar de un usuario sudo
- El
WorkingDirectory
ruta dentro de/etc/systemd/system/gunicorn.service
el archivo no apunta al directorio del proyecto - Las opciones de configuración dadas al proceso gunicorn en el
ExecStart
directiva no son correctas. Compruebe los siguientes elementos:- La ruta al binario gunicorn apunta a la ubicación real del binario dentro del entorno virtual
- El
--bind
directiva define un archivo para crear dentro de un directorio al que puede acceder Gunicorn - El
djangoproject.wsgi:application
es una ruta precisa al WSGI invocable. Esto significa que cuando esté en WorkingDirectory, debería poder llegar a la aplicación nombrada invocable buscando endjangoproject.wsgi
módulo (que se traduce en un archivo llamado./djangoproject/wsgi.py
)
Si realiza cambios en el archivo /etc/systemd/system/gunicorn.service, vuelva a cargar el demonio para volver a leer la definición del servicio y reinicie el proceso de Gunicorn escribiendo:
$ sudo systemctl daemon-reload
$ sudo systemctl restart gunicorn
Asegúrese de solucionar cualquiera de los problemas anteriores antes de continuar.
Configurar Nginx para pase de proxy a Gunicorn
Ahora que Gunicorn está configurado, necesitamos configurar Nginx para pasar el tráfico al proceso. Comience por crear y abrir un nuevo bloque de servidor en el directorio de sitios disponibles de Nginx:
$ sudo nano /etc/nginx/sites-available/djangoproject
En el interior, abra un nuevo bloque de servidor. Comenzaremos especificando que este bloque debe escuchar en el puerto normal 80 y que debe responder al nombre de dominio o dirección IP de nuestro servidor.
A continuación, le diremos a Nginx que ignore cualquier problema para encontrar un favicon. También le diremos dónde encontrar los activos estáticos que recopilamos en nuestro ~/djangoproject/static
directorio. Todos estos archivos tienen un prefijo URI estándar de "/static"
, para que podamos crear un bloque de ubicación que coincida con esas solicitudes.
Finalmente, crearemos un bloque de ubicación / {} para que coincida con todas las demás solicitudes. Dentro de esta ubicación, incluiremos los proxy_params
estándar archivo incluido con la instalación de Nginx y luego pasaremos el tráfico al socket que creó nuestro proceso Gunicorn:
/etc/nginx/sites-available/djangoproject
server {
listen 80;
server_name server_domain_or_IP;
location = /favicon.ico { access_log off; log_not_found off; }
location /static/ {
root /home/bobby/djangoproject;
}
location / {
include proxy_params;
proxy_pass http://unix:/home/bobby/djangoproject/djangoproject.sock;
}
}
Guarde y cierre el archivo cuando haya terminado. Ahora, podemos habilitar el archivo vinculándolo a sites-enabled
directorio:
$ sudo ln -s /etc/nginx/sites-available/djangoproject /etc/nginx/sites-enabled
Pruebe su configuración de Nginx en busca de errores de sintaxis escribiendo:
$ sudo nginx -t
Si no se informan errores, continúe y reinicie Nginx escribiendo:
$ sudo systemctl restart nginx
Finalmente, debemos abrir nuestro firewall al tráfico normal en el puerto 80. Dado que ya no necesitamos acceso al servidor de desarrollo, también podemos eliminar la regla para abrir el puerto 8000:
$ sudo ufw delete allow 8000
$ sudo ufw allow 'Nginx Full'
Ahora debería poder ir al dominio o dirección IP de su servidor para ver su aplicación.
Leer también
- Cómo configurar el cortafuegos UFW en Ubuntu 18.04
- Cómo instalar LAMP Stack en Ubuntu 18.04
Nota:Después de configurar Nginx, el próximo paso debe ser asegurar el tráfico al servidor usando SSL/TLS. Esto es importante porque sin él, toda la información, incluidas las contraseñas, se envía a través de la red en texto sin formato.