Arquitectura de producción
En producción, Django se ejecuta con la siguiente arquitectura:
Internet → Nginx → Gunicorn (workers) → Django
↓
Archivos estáticos (servidos por Nginx directamente)

Nginx actúa como:
- Proxy inverso que reenvía las peticiones a Gunicorn.
- Servidor de archivos estáticos (mucho más eficiente que Django).
- Terminación SSL/TLS.
Gunicorn es el servidor WSGI que ejecuta el código Django con múltiples workers para manejar peticiones concurrentes.
Instalar y configurar Gunicorn
pip install gunicorn
# Ejecutar Gunicorn manualmente para probar
gunicorn mi_proyecto.wsgi:application \
--bind 0.0.0.0:8000 \
--workers 3 \
--worker-class sync \
--timeout 30 \
--log-level info
La fórmula para el número de workers es (2 × núcleos_CPU) + 1.
Archivo de configuración de Gunicorn
# gunicorn.conf.py
import multiprocessing
bind = 'unix:/run/gunicorn/gunicorn.sock' # Socket Unix (más rápido que TCP)
workers = multiprocessing.cpu_count() * 2 + 1
worker_class = 'sync'
timeout = 30
keepalive = 2
max_requests = 1000
max_requests_jitter = 50
preload_app = True
accesslog = '/var/log/gunicorn/access.log'
errorlog = '/var/log/gunicorn/error.log'
loglevel = 'info'
Servicio systemd para Gunicorn
# /etc/systemd/system/gunicorn.service
[Unit]
Description=Gunicorn daemon para Django
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/srv/mi-app
RuntimeDirectory=gunicorn
ExecStart=/srv/mi-app/venv/bin/gunicorn \
--config /srv/mi-app/gunicorn.conf.py \
mi_proyecto.wsgi:application
ExecReload=/bin/kill -s HUP $MAINPID
Restart=always
RestartSec=3
Environment="DJANGO_SETTINGS_MODULE=mi_proyecto.settings.produccion"
EnvironmentFile=/srv/mi-app/.env
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable gunicorn
sudo systemctl start gunicorn
sudo systemctl status gunicorn
Configuración de Nginx
# /etc/nginx/sites-available/mi-app
upstream django_app {
server unix:/run/gunicorn/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name mi-dominio.com www.mi-dominio.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name mi-dominio.com www.mi-dominio.com;
ssl_certificate /etc/letsencrypt/live/mi-dominio.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mi-dominio.com/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
client_max_body_size 20M; # Tamaño máximo de subida de archivos
# Archivos estáticos (servidos directamente por Nginx)
location /static/ {
alias /srv/mi-app/staticfiles/;
expires 30d;
add_header Cache-Control "public, no-transform";
}
# Archivos media
location /media/ {
alias /srv/mi-app/media/;
expires 7d;
}
# Django (Gunicorn)
location / {
proxy_pass http://django_app;
proxy_set_header Host $http_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;
proxy_redirect off;
proxy_connect_timeout 30s;
proxy_read_timeout 30s;
}
}
sudo ln -s /etc/nginx/sites-available/mi-app /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
HTTPS con Let's Encrypt
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d mi-dominio.com -d www.mi-dominio.com
# La renovación automática se configura con cron
sudo certbot renew --dry-run
Checklist de despliegue
# 1. Recopilar archivos estáticos
python manage.py collectstatic --noinput
# 2. Aplicar migraciones
python manage.py migrate
# 3. Crear superusuario (primera vez)
python manage.py createsuperuser
# 4. Comprimir assets (si usas WhiteNoise)
python manage.py compress
# 5. Reiniciar Gunicorn
sudo systemctl restart gunicorn
# 6. Verificar logs
sudo journalctl -u gunicorn -n 50 --no-pager
sudo tail -f /var/log/nginx/error.log
Alan Sastre
Ingeniero de Software y formador, CEO en CertiDevs
Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Django es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.
Más tutoriales de Django
Explora más contenido relacionado con Django y continúa aprendiendo con nuestros tutoriales gratuitos.
Aprendizajes de esta lección
Configurar Gunicorn como servidor WSGI para Django en producción. Instalar y configurar Nginx como proxy inverso delante de Gunicorn. Configurar los archivos estáticos y media para ser servidos por Nginx. Crear un servicio systemd para que Gunicorn se inicie automáticamente. Configurar HTTPS con certificados SSL de Let's Encrypt.