Instalación de app Django en servidor Linux
Publicado el 12 Abr 2025

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

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:
- clonar tu repositorio usando git
- crear y activar un entorno virtual usando python3-venv
- instalar las dependencias de tu proyecto (pip install -r requirements.txt)
- 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.