Configurar Nginx con certbot para múltiples subdominios en un VPS Debian
Guía paso a paso para montar Nginx como reverse proxy con HTTPS automático en múltiples subdominios usando certbot en Debian 12.
Por qué Nginx + certbot
Si tienes un VPS con Debian 12 y necesitas servir varias aplicaciones web (Astro, Node, Python) bajo distintos subdominios, Nginx como reverse proxy con certbot para SSL es la combinación más fiable y ligera. Sin Docker, sin paneles de control.
Requisitos previos
- VPS con Debian 12 (Bookworm) recién instalado
- Acceso root o usuario con sudo
- DNS ya configurado apuntando al VPS (registros A para cada subdominio)
Instalación
sudo apt update && sudo apt upgrade -y
sudo apt install nginx certbot python3-certbot-nginx -y
Comprobamos versiones:
nginx -v # 1.22.x en Debian 12
certbot --version
Configuración base de Nginx
Primero, desactivamos el site por defecto:
sudo rm /etc/nginx/sites-enabled/default
Creamos la estructura de directorios para nuestros sites:
sudo mkdir -p /etc/nginx/sites-available /etc/nginx/sites-enabled
Site principal (app.example.com)
Creamos /etc/nginx/sites-available/app:
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:4321;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
}
Lo activamos:
sudo ln -s /etc/nginx/sites-available/app /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
Certbot: SSL para todos los subdominios
En lugar de ejecutar certbot uno por uno, le pasamos todos los subdominios de golpe:
sudo certbot --nginx -d app.example.com -d api.example.com -d admin.example.com
Certbot modificará automáticamente los archivos de configuración para añadir SSL y las redirecciones HTTP→HTTPS.
Renovación automática
Certbot instala un timer de systemd automáticamente. Verificamos:
sudo systemctl status certbot.timer
sudo certbot renew --dry-run
Problemas comunes y soluciones
Error “Could not bind to 0.0.0.0:80”
Si otro servicio ocupa el puerto 80 durante la verificación:
sudo systemctl stop nginx
sudo certbot certonly --standalone -d app.example.com
sudo systemctl start nginx
Rate limiting de Let’s Encrypt
Si has hecho muchas pruebas, usa --staging para tests:
sudo certbot --staging --nginx -d app.example.com
Script de despliegue para nuevos subdominios
He creado este helper en /usr/local/bin/add-site:
#!/bin/bash
DOMAIN=$1
PORT=$2
CONF="/etc/nginx/sites-available/$DOMAIN"
cat > "$CONF" <<EOF
server {
listen 80;
server_name $DOMAIN;
location / {
proxy_pass http://127.0.0.1:$PORT;
proxy_http_version 1.1;
proxy_set_header Upgrade \$http_upgrade;
proxy_set_header Connection "upgrade";
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;
}
}
EOF
ln -s "$CONF" /etc/nginx/sites-enabled/
nginx -t && systemctl reload nginx
certbot --nginx -d "$DOMAIN" --non-interactive --agree-tos --email admin@example.com
Uso: sudo add-site nuevo.example.com 3000
Así añadir un subdominio nuevo con SSL lleva 30 segundos en lugar de 5 minutos.