Cómo Resolver Errores de Renovación SSL con Certbot: El Problema de los Certificados Huérfanos - Chuda
15893
wp-singular,post-template-default,single,single-post,postid-15893,single-format-standard,wp-theme-bridge,wp-child-theme-bridge-child,bridge-core-3.3,qode-page-transition-enabled,ajax_fade,page_not_loaded,,qode-child-theme-ver-1.0.0,qode-theme-ver-30.8,qode-theme-bridge,disabled_footer_top,qode_header_in_grid,wpb-js-composer js-comp-ver-8.5,vc_responsive

Cómo Resolver Errores de Renovación SSL con Certbot: El Problema de los Certificados Huérfanos

Cómo Resolver Errores de Renovación SSL con Certbot: El Problema de los Certificados Huérfanos

Como ingeniero de infraestructura, uno de los problemas más frustrantes que puedes encontrar es cuando tu script de renovación automática de certificados SSL falla inesperadamente. Hoy te voy a contar sobre un error común que me encontré recientemente y cómo resolverlo de manera definitiva.

El Problema: Timeout Durante la Renovación

Todo comenzó con este error en mi script de renovación que deje en el post de este mismo blog (“Como instalar y configurar Certbot para NGINX en Amazon Linux 2023“) :

Certbot failed to authenticate some domains (authenticator: nginx). 
The Certificate Authority reported these problems:
  Domain: dev.domain.com
  Type:   connection
  Detail: Fetching http://dev.domain.com/.well-known/acme-challenge/: 
  Timeout during connect (likely firewall problem)

Al principio pensé en las causas típicas:

  • Problemas de firewall
  • Security Groups mal configurados en AWS
  • DNS mal configurado
  • Nginx caído

Pero después de verificar todo esto, el problema persistía. ¿La causa real? Certificados huérfanos.

¿Qué son los Certificados Huérfanos?

Un certificado huérfano es un certificado SSL que existe en el sistema de Let’s Encrypt pero ya no tiene una configuración correspondiente en tu servidor web. Esto suele ocurrir cuando:

  • Eliminas un dominio de tu configuración de nginx
  • Migras servicios a otros servidores
  • Cambias la arquitectura de tu aplicación
  • Removes subdominios que ya no usas

En mi caso, tenía un certificado para dev.wms-alphas.com que ya no existía en mi configuración de nginx, pero certbot seguía intentando renovarlo automáticamente.

Diagnóstico Paso a Paso

1. Verificar Certificados Existentes

# Listar todos los certificados
sudo certbot certificates

# Ver detalles específicos
sudo certbot certificates --cert-name dev.domain.com

2. Verificar Configuración de Nginx

# Listar sitios habilitados
ls -la /etc/nginx/sites-enabled/

# Buscar configuraciones de dominio
grep -r "server_name" /etc/nginx/sites-enabled/

# Verificar dominio específico
grep -r "dev.domain.com" /etc/nginx/sites-enabled/

3. Identificar el Desajuste

Si el comando certbot certificates muestra un certificado pero grep no encuentra configuración en nginx, tienes un certificado huérfano.

La Solución: Limpieza de Certificados

Opción 1: Eliminar Certificados No Utilizados (Recomendado)

# Eliminar el certificado huérfano
sudo certbot delete --cert-name dev.domain.com

# Verificar que se eliminó correctamente
sudo certbot certificates

# Probar renovación
sudo certbot renew --dry-run

Opción 2: Crear Configuración Temporal

Si planeas usar el dominio en el futuro:

# /etc/nginx/sites-available/dev.domain.com
server {
    listen 80;
    server_name dev.domain.com;
    
    location /.well-known/acme-challenge/ {
        root /var/www/html;
        allow all;
    }
    
    location / {
        return 503; # Service unavailable
    }
}

Script de Renovación Mejorado

Aquí tienes un script optimizado que evita estos problemas en el futuro:

#!/bin/bash
# updatessl.sh - Versión mejorada con validaciones

echo "=== SSL Certificate Renewal Script ==="

# Verificar configuración de nginx
if ! sudo nginx -t; then
    echo "❌ ERROR: Invalid nginx configuration"
    exit 1
fi

# Verificar certificados vs configuración
echo "🔍 Checking for orphaned certificates..."

for cert_conf in /etc/letsencrypt/renewal/*.conf; do
    if [ -f "$cert_conf" ]; then
        cert_name=$(basename "$cert_conf" .conf)
        domains=$(grep "^domains = " "$cert_conf" | cut -d' ' -f3- | tr ',' ' ')
        
        for domain in $domains; do
            if ! grep -r "$domain" /etc/nginx/sites-enabled/ > /dev/null; then
                echo "⚠️  WARNING: Domain $domain has no nginx configuration"
                echo "   Consider running: sudo certbot delete --cert-name $cert_name"
            fi
        done
    fi
done

# Proceder con renovación
echo "🔄 Starting certificate renewal..."
sudo systemctl stop nginx

if sudo certbot renew --force-renewal; then
    echo "✅ Certificate renewal successful"
else
    echo "❌ Certificate renewal failed"
    sudo systemctl start nginx
    exit 1
fi

# Reiniciar nginx
if sudo systemctl start nginx; then
    echo "✅ Nginx restarted successfully"
    sudo systemctl status nginx --no-pager -l
else
    echo "❌ Failed to start nginx"
    sudo journalctl -xeu nginx.service --no-pager
    exit 1
fi

echo "🎉 SSL renewal completed successfully!"

Automatización con AWS

Para entornos de producción, considera automatizar esto con Infrastructure as Code:

# Lambda function para renovación automática
import boto3
import json

def lambda_handler(event, context):
    ssm = boto3.client('ssm')
    
    commands = [
        "sudo certbot certificates",
        "sudo certbot renew --quiet --no-self-upgrade",
        "sudo systemctl reload nginx"
    ]
    
    response = ssm.send_command(
        InstanceIds=[event['instance_id']],
        DocumentName='AWS-RunShellScript',
        Parameters={'commands': commands},
        TimeoutSeconds=300
    )
    
    return {
        'statusCode': 200,
        'body': json.dumps({
            'message': 'SSL renewal initiated',
            'command_id': response['Command']['CommandId']
        })
    }

Mejores Prácticas

  1. Auditoría Regular: Revisa periódicamente tus certificados vs configuración de nginx
  2. Monitoreo: Implementa alertas para fallos de renovación
  3. Documentación: Mantén un registro de qué dominios están activos
  4. Automatización: Usa Infrastructure as Code para gestionar certificados
  5. Testing: Siempre usa --dry-run antes de renovaciones forzadas

Conclusión

Los certificados huérfanos son un problema común pero fácil de resolver una vez que sabes qué buscar. La clave está en mantener sincronizada tu configuración de certificados con tu configuración de servidor web.

Este tipo de problemas son perfectos ejemplos de por qué la infraestructura debe tratarse como código: versionada, documentada y auditable.


Enlaces Útiles


Happy Hacking!