Skip to content
GitHub

Runbook: SSL/TLS Certificates

Propósito: Gestión y renovación de certificados SSL/TLS para los dominios del ecosistema Nostromo.

Frecuencia: Automática cada 60-90 días (Let’s Encrypt)

Tiempo estimado: 5-10 minutos (manual)

Criticidad: 🔴 ALTA - Certificados expirados causan errores HTTPS


DominioServicioCertificado
app.nostromo.clSevastopol FrontendLet’s Encrypt
api.nostromo.clOrchestrator APILet’s Encrypt
*.nostromo.clWildcard (opcional)Let’s Encrypt

Terminal window
# Ver fecha de expiración
sudo certbot certificates
# Output esperado:
# Certificate Name: app.nostromo.cl
# Domains: app.nostromo.cl
# Expiry Date: 2026-04-18 (VALID: 89 days)
Terminal window
# Verificar certificado remoto
echo | openssl s_client -servername app.nostromo.cl -connect app.nostromo.cl:443 2>/dev/null | openssl x509 -noout -dates
# Output:
# notBefore=Jan 18 00:00:00 2026 GMT
# notAfter=Apr 18 23:59:59 2026 GMT
  1. Ir a https://app.nostromo.cl
  2. Click en candado → “Certificate”
  3. Verificar fecha de “Valid to”

Let’s Encrypt renueva automáticamente vía cron. Verificar que esté configurado:

Terminal window
# Verificar cron de certbot
sudo cat /etc/cron.d/certbot
# Contenido esperado:
# 0 */12 * * * root test -x /usr/bin/certbot && perl -e 'sleep int(rand(43200))' && certbot -q renew
Terminal window
sudo certbot renew --dry-run

Expected output:

Congratulations, all renewals succeeded.

Si la renovación automática falla o necesitas renovar inmediatamente:

  1. Conectar al servidor

    Terminal window
  2. Detener Nginx temporalmente (standalone mode)

    Terminal window
    sudo systemctl stop nginx
  3. Renovar certificados

    Terminal window
    sudo certbot renew

    O para un dominio específico:

    Terminal window
    sudo certbot certonly --standalone -d app.nostromo.cl
  4. Reiniciar Nginx

    Terminal window
    sudo systemctl start nginx
  5. Verificar certificado

    Terminal window
    sudo certbot certificates
    curl -I https://app.nostromo.cl

Para un dominio nuevo:

  1. Configurar DNS

    Asegurar que el dominio apunta a la IP del servidor.

    Terminal window
    dig +short new-domain.nostromo.cl
    # Debe retornar la IP del servidor
  2. Obtener certificado

    Terminal window
    sudo certbot --nginx -d new-domain.nostromo.cl
  3. Verificar configuración Nginx

    Certbot modifica automáticamente la config. Verificar:

    Terminal window
    sudo nginx -t
    sudo cat /etc/nginx/sites-enabled/new-domain.conf
  4. Recargar Nginx

    Terminal window
    sudo systemctl reload nginx

Causa: DNS no apunta al servidor o firewall bloquea puerto 80.

Terminal window
# Verificar DNS
dig +short app.nostromo.cl
# Verificar puerto 80 abierto
sudo ufw status | grep 80
sudo ufw allow 80/tcp

Error: “Too many certificates already issued”

Section titled “Error: “Too many certificates already issued””

Causa: Rate limit de Let’s Encrypt (5 certs/semana/dominio).

Solución: Esperar 7 días o usar staging para tests:

Terminal window
sudo certbot --staging -d test.nostromo.cl

Terminal window
# Ver todos los certificados
sudo ls -la /etc/letsencrypt/live/
# Verificar que Nginx usa el path correcto
grep ssl_certificate /etc/nginx/sites-enabled/app.nostromo.cl.conf

Terminal window
# Verificar sintaxis
sudo nginx -t
# Ver error específico
sudo journalctl -u nginx --since "5 minutes ago"
# Común: permisos incorrectos
sudo chmod 755 /etc/letsencrypt/live/
sudo chmod 755 /etc/letsencrypt/archive/

Best practices (/etc/nginx/snippets/ssl-params.conf):

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_ecdh_curve secp384r1;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
add_header Strict-Transport-Security "max-age=63072000" always;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

Incluir en cada server block:

server {
listen 443 ssl http2;
server_name app.nostromo.cl;
ssl_certificate /etc/letsencrypt/live/app.nostromo.cl/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.nostromo.cl/privkey.pem;
include snippets/ssl-params.conf;
# ... resto de config
}

/opt/scripts/check_ssl_expiry.sh
#!/bin/bash
DOMAIN="app.nostromo.cl"
DAYS_WARNING=14
EXPIRY=$(echo | openssl s_client -servername $DOMAIN -connect $DOMAIN:443 2>/dev/null | \
openssl x509 -noout -enddate | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( ($EXPIRY_EPOCH - $NOW_EPOCH) / 86400 ))
if [ $DAYS_LEFT -lt $DAYS_WARNING ]; then
echo "WARNING: SSL certificate for $DOMAIN expires in $DAYS_LEFT days!"
# Enviar alerta
mail -s "SSL Certificate Warning: $DOMAIN" [email protected] <<< "Certificate expires in $DAYS_LEFT days"
fi
Terminal window
# Verificar diariamente a las 9am
0 9 * * * /opt/scripts/check_ssl_expiry.sh

Terminal window
# Backup de todos los certificados
sudo tar -czvf /opt/backups/letsencrypt-$(date +%Y%m%d).tar.gz /etc/letsencrypt/
# Restaurar
sudo tar -xzvf /opt/backups/letsencrypt-20260118.tar.gz -C /

  • Verificar renovación automática: certbot renew --dry-run
  • Verificar cron de certbot existe
  • Verificar que DNS sigue apuntando correctamente
  • Verificar que puerto 80 está abierto (para challenge)
  • Verificar script de alertas configurado


FechaVersionCambios
2026-01-181.0Runbook inicial creado