Common Issues

Expired SSL Certificate: Renewal and Resolution

Your site shows 'Certificate not valid' or 'Connection is not private'? Guide to renewing Let's Encrypt certificates and preventing with automatic renewal.

An expired SSL certificate shows visitors a security warning and blocks access to the site. The most common problem is that Certbot's automatic renewal has stopped working.


Quick diagnosis

# Check certificate expiration for a domain
echo | openssl s_client -connect tuodominio.com:443 -servername tuodominio.com 2>/dev/null \
  | openssl x509 -noout -dates

# Example output:
# notBefore=Jan  1 00:00:00 2025 GMT
# notAfter=Apr  1 00:00:00 2025 GMT   ← this is the expiration

# Or check local certificates
certbot certificates

Manual immediate renewal

# Renew all certificates expiring soon (within 30 days)
certbot renew

# Force renewal even if not expiring
certbot renew --force-renewal

# Renew only a specific domain
certbot certonly --force-renewal -d tuodominio.com -d www.tuodominio.com

# After renewal, reload nginx/apache
systemctl reload nginx
# or
systemctl reload apache2

Let's Encrypt Rate limit

Let's Encrypt limits to 5 identical certificates per week. Don't abuse --force-renewal. Use it only when necessary.


Why automatic renewal stopped working

1. Cron / systemd timer is disabled

# Check if Certbot timer is active
systemctl status certbot.timer

# If inactive, enable it
systemctl enable --now certbot.timer

# Verify cron is present (alternative method)
cat /etc/cron.d/certbot

2. Port 80 is blocked

Certbot uses HTTP-01 challenge on port 80. If firewall blocks it or proxy doesn't forward it, renewal fails.

# Verify port 80 responds
curl -I http://tuodominio.com

# Check firewall
ufw status | grep 80
# or
iptables -L INPUT -n | grep 80

3. Webroot changed

# Display certbot configuration
cat /etc/letsencrypt/renewal/tuodominio.com.conf

# The webroot must point to nginx/apache site root
# Correct example: webroot_path = /var/www/html

4. Nginx/Apache not configured for challenge

Add this block to nginx if missing:

server {
    listen 80;
    server_name tuodominio.com www.tuodominio.com;

    location /.well-known/acme-challenge/ {
        root /var/www/html;
    }

    # Rest of HTTP traffic → HTTPS
    location / {
        return 301 https://$host$request_uri;
    }
}

Renewal with DNS challenge (if port 80 not accessible)

Useful when server is behind NAT or port 80 is blocked by ISP:

# Certbot with manual DNS challenge
certbot certonly --manual --preferred-challenges dns -d tuodominio.com

# Certbot will ask you to add a TXT record to DNS:
# _acme-challenge.tuodominio.com → "generated_value"
# Add the record, wait for propagation (60-120s), then press Enter

Verify and test renewed certificate

# Verify new expiration
certbot certificates

# Complete SSL test (grade A+)
# Visit: https://www.ssllabs.com/ssltest/

# Quick local test
openssl s_client -connect tuodominio.com:443 -servername tuodominio.com 2>/dev/null \
  | openssl x509 -noout -dates -issuer

Prevention: reliable automatic renewal

# Verify timer is active
systemctl status certbot.timer

# Run a dry-run to verify it works
certbot renew --dry-run

# Correct output:
# Congratulations, all simulated renewals succeeded

Method 2: Cron with notification

crontab -e
# Check every day at 3:30, renew if needed
# and reload nginx after renewal
30 3 * * * certbot renew --quiet --post-hook "systemctl reload nginx" 2>&1 | mail -s "Certbot renew" admin@tuodominio.com

Method 3: Certbot post-renewal hook for nginx

# Create hook file
cat > /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh << 'EOF'
#!/bin/bash
systemctl reload nginx
EOF
chmod +x /etc/letsencrypt/renewal-hooks/post/reload-nginx.sh

Certbot automatically runs scripts in /etc/letsencrypt/renewal-hooks/post/ after every successful renewal.


Let's Encrypt certificate not available (special case)

If server can't reach internet for validation, use a temporary self-signed certificate:

# Generate self-signed certificate (valid 365 days)
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout /etc/ssl/private/selfsigned.key \
  -out /etc/ssl/certs/selfsigned.crt \
  -subj "/C=IT/ST=Italy/O=DeluxHost/CN=tuodominio.com"

Expiration monitoring

Consider adding the domain to an SSL monitoring service like UptimeRobot or Uptime Kuma with alerts a few days before expiration: it alerts you if automatic renewal fails silently.

On this page