Instalación de app Django en servidor Linux

Instalación de app Django en servidor Linux

Esta publicación cubre el despliegue de una app Django a producción en un servidor Linux.

Para nuestros fines lo único que nos interesa de la app Django es que el proyecto se llama mysite, el archivo de configuración es mysite/mysite/settings.py y usaremos el nombre mysite para todos los archivos de configuraciones.

También asumiremos que ya estamos conectados a nuestro servidor vía SSH.

Instalando dependencias

Instalando Python

sudo apt-get updtae
sudo apt-get install
sudo apt-get install python3-venv
sudo apt-get install python3-pip

Instalando NGINX y Sqlite3

sudo apt-get install nginx
sudo apt install sqlite3

Instalando Nodejs

En caso de que necesites compilar archivos para el frontend usualmente querrás mantener estos archivos fuera del flujo de control de Git, en este caso puedes compilar tus archivos en el servidor usando Vitejs, Webpack o incluso SASS.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash
source ~/.bashrc
nvm list-remote
nvm install v22.14.0

Abriendo puertos

Por defecto, algunas VM's traen los puertos 80 y 443 cerrados. Necesitaremos abrirlos.

# Abrir puerto 80 (HTTP)
sudo iptables -I INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT

# Abrir puerto 443 (HTTPS)
sudo iptables -I INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT

# Guardar cambios
sudo netfilter-persistent save

Probando NGINX

Antes de continuar es importante saber que NGINX está funcionando correctamente, ejecuta los siguientes comandos y dirígete a la IP de tu servidor.

sudo systemctl start nginx

Deberíamos ver la siguiente pantalla

Pantalla inicial de NGINX

Querremos que NGINX inicie junto con nuestro servidor.

sudo systemctl enable nginx

Probando la app Django

Antes de rodar el próximo comando, asegúrate de:

  1. clonar tu repositorio usando git
  2. crear y activar un entorno virtual usando python3-venv
  3. instalar las dependencias de tu proyecto (pip install -r requirements.txt)
  4. Setear variables de entorno para el proyecto (por ejemplo en un archivo .env)
python3 manage.py runserver 0.0.0.0:8000

Si obtenemos un error debemos revisar los pasos arriba mencionados o incluso el código de nuestra app.

# ejecutamos las migraciones de la base de datos
python3 manage.py migrate

# colectamos los archivos estaticos
python3 manage.py collectstatic

Creando Servicio y Socket

como mencionamos al comienzo, asumiremos que el proyecto se llama mysite y que el archivo de configuración esta en mysite/mysite/settings.py. Utilizaremos el nombre mysite para todos los archivos de configuraciones restantes

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

Copia el siguiente código reemplazando <user> por tu usuario.

Estamos asumiendo que nombramos al entorno virtual como venv y que estamos usando gunicorn para servir nuestra app en producción

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

[Service]
User=<user>
Group=www-data
WorkingDirectory=/home/<user>/mysite
ExecStart=/home/<user>/venv/bin/gunicorn \
        --access-logfile - \
        --workers 3 \
        --bind unix:/run/mysite.sock \
        mysite.wsgi:application

[Install]
WantedBy=multi-user.target

Creamos el socket

[Unit]
Description=mysite socket

[Socket]
ListenStream=/run/mysite.sock

[Install]
WantedBy=sockets.target

Ejecutamos el servicio que acabamos de crear, habilitamos su inicio junto al sistema y probamos su status

sudo systemctl start mysite
sudo systemctl enable mysite
sudo systemctl status mysite

Configurando sitio en Nginx

Creamos el archivo que NGINX usara para servir nuestro sitio

sudo nano /etc/nginx/sites-available/mysite.conf
server {
        listen 80;
        listen [::]:80;
        server_name <ip_or_domain>; # mysite.com www.mysite.com;
        charset utf-8;

	location = /favicon.ico { access_log off; log_not_found off; }

	access_log /var/log/nginx/mysite/access.log;
        error_log /var/log/nginx/mysite/error.log;        
	
        location /media {
                alias /home/<user>/mysite/media;
        }
	
        location /static {
                alias /home/<user>/mysite/static;
        }

	# restricted requests
        location ~ /\.(htaccess|htpasswd|ini|log|conf|sql|git|env)$ {
                deny all;
                return 403 "Forbidden request\n";
        }

        # Send all non-media requests to the wsgi
        location / {
                include proxy_params;
                proxy_pass http://unix://run/mysite.sock;
        }
}

Creamos un link simbólico de nuestro archivo hacia la carpeta de sitios habilitados

sudo ln -s /etc/nginx/sites-available/mysite.conf /etc/nginx/sites-enabled/

Eliminamos el sitio por defecto.

sudo rm /etc/nginx/sites-enabled/default

Ahora crearemos los archivos en donde nginx escribirá logs para este sitio.

sudo mkdir /var/log/nginx/mysite
sudo touch /var/log/nginx/mysite/{access,error}.log

Probando Configuración de NGINX

para probar que la sintaxis del archivo que creamos está bien, podemos ejecutar:

sudo nginx -t

Para cargar los cambios realizados puedes reiniciar nginx.

sudo systemctl restart nginx

Cuando hagas cambios al código de tu app, recuerda siempre reiniciar el servicio para cargar los cambios en memoria.

sudo systemctl restart mysite

En este punto todo debería estar funcionando bien.

En caso de que los archivos estáticos te muestren un mensaje de 403 es porque tu carpeta de usuario no concede permisos de lectura a otros. NGINX está intentando entrar a la carpeta para leer y poder servir los archivos y el sistema de archivos lo está impidiendo. Hay varias formas de solucionar esto.

Los siguientes comandos otorgarán los permisos de lectura necesarios para que nginx entre hasta los archivos de tu proyecto. Recuerda siempre cambiar <user> por tu nombre de usuario.

sudo chmod o+x /home
sudo chmod o+x /home/<user>
sudo chmod -R o+x /home/<user>/mysite

# opcionalmente puedes cambiar la ultima linea por las siguientes tres
sudo chmod o+x /home/<user>/mysite
sudo chmod -R o+x /home/<user>/mysite/static
sudo chmod -R o+x /home/<user>/mysite/media

Bonus (Certificado SSL/TLS)

Puedes obtener un certificado gratis proporcionado por Let's Encrypt, usando certbot.

# instala certbot
sudo apt-get install python3-certbot-nginx

# solicita el certificado
sudo certbot --nginx  -d mysite.com -d www.mysite.com

En este ejemplo usamos mysite.com, pero tú puedes cambiarlo por el dominio que hayas comprado.

No olvides que para que esto funcione debes haber configurado los records en tu DNS para apuntar a la IP de tu servidor.

Una forma un poco diferente de hacer lo mismo

Me tomó un tiempo aprender a hacer el despliegue de una app en Django. A menudo pienso en este proceso, como en el trabajo de aquellos míticos mineros del oro, buscando incansablemente ese tesoro. Revisé muchos recursos antes de comenzar a sentir que había entendido como hacerlo funcionar.

Esta publicación es intencionalmente "corta" y es posible que quieras algo más extenso, quieras otro punto de vista o simplemente otro formato, me encantaría invitarte a que le des una vista al siguiente video, es diferente, pero conseguirás muchas parecidas. Finalmente, espero que más adelante mi publicación te vuelva a ser útil.

Contacto

Puedes escribirme por Whatsapp, pero si prefieres no usar ese medio tambien puedes contactarme el formulario de contacto en esta sección.

Yo prefiero el contacto por medio de Whatsapp.

Iniciar conversación