Runbook: SSL/TLS Certificates
Overview
Section titled “Overview”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
Dominios Protegidos
Section titled “Dominios Protegidos”| Dominio | Servicio | Certificado |
|---|---|---|
app.nostromo.cl | Sevastopol Frontend | Let’s Encrypt |
api.nostromo.cl | Orchestrator API | Let’s Encrypt |
*.nostromo.cl | Wildcard (opcional) | Let’s Encrypt |
Verificar Estado de Certificados
Section titled “Verificar Estado de Certificados”Verificar desde línea de comandos
Section titled “Verificar desde línea de comandos”# Ver fecha de expiraciónsudo certbot certificates
# Output esperado:# Certificate Name: app.nostromo.cl# Domains: app.nostromo.cl# Expiry Date: 2026-04-18 (VALID: 89 days)Verificar con OpenSSL
Section titled “Verificar con OpenSSL”# Verificar certificado remotoecho | 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 GMTVerificar desde navegador
Section titled “Verificar desde navegador”- Ir a
https://app.nostromo.cl - Click en candado → “Certificate”
- Verificar fecha de “Valid to”
Renovación Automática
Section titled “Renovación Automática”Let’s Encrypt renueva automáticamente vía cron. Verificar que esté configurado:
# Verificar cron de certbotsudo cat /etc/cron.d/certbot
# Contenido esperado:# 0 */12 * * * root test -x /usr/bin/certbot && perl -e 'sleep int(rand(43200))' && certbot -q renewTest de renovación
Section titled “Test de renovación”sudo certbot renew --dry-runExpected output:
Congratulations, all renewals succeeded.Renovación Manual
Section titled “Renovación Manual”Si la renovación automática falla o necesitas renovar inmediatamente:
-
Conectar al servidor
Terminal window -
Detener Nginx temporalmente (standalone mode)
Terminal window sudo systemctl stop nginx -
Renovar certificados
Terminal window sudo certbot renewO para un dominio específico:
Terminal window sudo certbot certonly --standalone -d app.nostromo.cl -
Reiniciar Nginx
Terminal window sudo systemctl start nginx -
Verificar certificado
Terminal window sudo certbot certificatescurl -I https://app.nostromo.cl
Obtener Nuevo Certificado
Section titled “Obtener Nuevo Certificado”Para un dominio nuevo:
-
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 -
Obtener certificado
Terminal window sudo certbot --nginx -d new-domain.nostromo.cl -
Verificar configuración Nginx
Certbot modifica automáticamente la config. Verificar:
Terminal window sudo nginx -tsudo cat /etc/nginx/sites-enabled/new-domain.conf -
Recargar Nginx
Terminal window sudo systemctl reload nginx
Troubleshooting
Section titled “Troubleshooting”Error: “Challenge failed”
Section titled “Error: “Challenge failed””Causa: DNS no apunta al servidor o firewall bloquea puerto 80.
# Verificar DNSdig +short app.nostromo.cl
# Verificar puerto 80 abiertosudo ufw status | grep 80sudo ufw allow 80/tcpError: “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:
sudo certbot --staging -d test.nostromo.clError: “Certificate not found”
Section titled “Error: “Certificate not found””# Ver todos los certificadossudo ls -la /etc/letsencrypt/live/
# Verificar que Nginx usa el path correctogrep ssl_certificate /etc/nginx/sites-enabled/app.nostromo.cl.confNginx no inicia después de renovación
Section titled “Nginx no inicia después de renovación”# Verificar sintaxissudo nginx -t
# Ver error específicosudo journalctl -u nginx --since "5 minutes ago"
# Común: permisos incorrectossudo chmod 755 /etc/letsencrypt/live/sudo chmod 755 /etc/letsencrypt/archive/Configuración Nginx SSL
Section titled “Configuración Nginx SSL”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}Alertas de Expiración
Section titled “Alertas de Expiración”Script de monitoreo
Section titled “Script de monitoreo”#!/bin/bashDOMAIN="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"fiCron para alertas
Section titled “Cron para alertas”# Verificar diariamente a las 9am0 9 * * * /opt/scripts/check_ssl_expiry.shBackup de Certificados
Section titled “Backup de Certificados”# Backup de todos los certificadossudo tar -czvf /opt/backups/letsencrypt-$(date +%Y%m%d).tar.gz /etc/letsencrypt/
# Restaurarsudo tar -xzvf /opt/backups/letsencrypt-20260118.tar.gz -C /Pre-Expiry Checklist
Section titled “Pre-Expiry Checklist”- 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
Related Documentation
Section titled “Related Documentation”Changelog
Section titled “Changelog”| Fecha | Version | Cambios |
|---|---|---|
| 2026-01-18 | 1.0 | Runbook inicial creado |