Instalar Certbot para Apache en Ubuntu 24.04
Obtén un certificado Let's Encrypt con un solo comando. Ubuntu 24.04 incluye Certbot 2.9.0 por apt; evita snap y corrige el error por falta de ServerName.
Qué va a configurar
Un sitio de Apache en Ubuntu 24.04 que responde por HTTPS con un certificado gratuito de Let's Encrypt, de confianza para los navegadores, emitido por Certbot y renovado automáticamente mediante un temporizador de systemd que no tendrá que volver a supervisar. El comando que realiza el trabajo ocupa una sola línea. Todo lo que puede fallar falla antes de esa línea: un vhost sin ServerName, el puerto 80 bloqueado por el firewall del proveedor o el DNS que todavía apunta al servidor antiguo. Por eso, esta guía dedica la mayor parte del contenido a las condiciones previas e indica la cadena de error exacta que muestra cada fallo.
Dos notas sobre el alcance. Si su servidor web es nginx, el flujo general es el mismo, pero el plugin y las configuraciones son diferentes; use la versión de esta guía para nginx. Si el servicio que quiere proteger sólo es accesible internamente, por ejemplo un panel de administración en una dirección privada o un servidor de staging que nadie más visita, no necesita una autoridad certificadora; un certificado autofirmado requiere menos configuración y funciona sin conexión.
Requisitos previos y las tres formas en que esto falla antes de que Certbot se ejecute
- Apache ya debe servir su sitio por HTTP sin cifrar. El plugin de Apache de Certbot modifica un sitio existente; no crea uno. Si parte de un VPS vacío, configure primero la pila LAMP en Ubuntu 24.04 y vuelva después. Esta guía es su capítulo de TLS pendiente.
- Un dominio público con un registro A que apunte a la dirección de su VPS. El desafío HTTP-01 de Let's Encrypt hace que sus servidores de validación se conecten a su servidor desde Internet: no puede usar un homelab detrás de NAT sin redirección de puertos, ni nombres
.local, ni direcciones IP sin más.dig +short example.comdebe devolver la dirección de su VPS. Si cambió el DNS durante la última hora, espere a que expire el TTL del registro anterior antes de emitir el certificado. - Si existe un registro AAAA, debe ser correcto. Let's Encrypt prefiere IPv6 cuando se publica un registro AAAA. Por tanto, un registro AAAA obsoleto hace que falle la validación aunque
curlfuncione correctamente desde su portátil, probablemente mediante IPv4. Publique un registro AAAA correcto o no publique ninguno.
Los puertos 80 y 443 deben estar abiertos en ufw y en el firewall de red de su proveedor. La mayoría de los paneles de alojamiento tienen un segundo firewall que el sistema operativo no puede ver. HTTP-01 valida específicamente mediante el puerto 80; no puede ejecutar este procedimiento usando sólo 443.
sudo ufw allow "Apache Full"
sudo ufw statusCon estos requisitos cumplidos, todo el proceso dura quince minutos, diez de ellos dedicados a leer.
¿Certbot mediante Snap o apt? En 24.04, apt ya funciona correctamente
Certbot pasó a distribuirse mediante snap hace años por un buen motivo: los paquetes de las distribuciones quedaron obsoletos. Ubuntu 20.04 incluía Certbot 0.40 y nunca lo actualizó, y el proyecto se cansó de depurar errores de hacía cinco años. En 24.04 ese motivo ya no existe: el repositorio incluye Certbot 2.9.0, una versión actual, y unattended-upgrades mantiene el paquete actualizado. Mi recomendación para este sistema operativo es usar apt. No necesita el daemon snapd, el plugin de Apache se instala en la misma transacción y el temporizador de renovación se integra con systemd de la forma habitual en Debian.
sudo apt update
sudo apt install -y certbot python3-certbot-apache
certbot --versionResultado correcto: certbot 2.9.0. El paquete python3-certbot-apache es el plugin que lee y modifica la configuración de Apache. Sin él, certbot --apache falla con The requested apache plugin does not appear to be installed.
Snap sigue siendo la opción adecuada en dos casos: si quiere la versión más reciente de Certbot el mismo día de su publicación, o si necesita un plugin DNS que sólo se distribuya como snap (varios plugins de proveedores de certbot-dns-* se distribuyen así). Si elige esa opción:
sudo apt remove -y certbot python3-certbot-apache
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbotElija la opción que elija, no ejecute nunca ambas. Dos instalaciones implican dos programadores de renovación compitiendo por /etc/letsencrypt, y el certbot que encuentre su shell en PATH puede no ser el que administra sus certificados. La línea apt remove anterior no es un adorno opcional.
El vhost que edita Certbot debe existir previamente; ServerName es lo que determina todo
certbot --apache funciona buscando el host virtual del puerto 80 cuyo ServerName o ServerAlias coincide con cada dominio -d que se proporciona. Después demuestra el control del dominio mediante ese host y escribe un equivalente SSL de ese vhost. Si no hay ningún ServerName coincidente, no hay coincidencia. Además, el 000-default.conf predeterminado de Ubuntu incluye ServerName comentado. Esa única línea comentada es la causa más habitual de que falle el comando grande de esta guía.
Por tanto, antes de usar Certbot, asigne al sitio un vhost basado en nombre correctamente configurado. Cree /etc/apache2/sites-available/example.com.conf:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost>Habilítelo y confirme que Apache analiza la configuración y dirige el nombre a ese vhost:
sudo a2ensite example.com.conf
sudo apache2ctl configtest
sudo systemctl reload apache2
sudo apache2ctl -Sconfigtest debe mostrar Syntax OK. Si también muestra AH00558: apache2: Could not reliably determine the server's fully qualified domain name, se trata de una advertencia sobre el ServerName global, no sobre su vhost. Aquí no causa problemas y se silencia con echo "ServerName $(hostname -f)" | sudo tee /etc/apache2/conf-available/servername.conf && sudo a2enconf servername && sudo systemctl reload apache2.
La salida de -S es la comprobación importante. Debe aparecer una línea como port 80 namevhost example.com (/etc/apache2/sites-enabled/example.com.conf:1) con alias www.example.com debajo. Apache informa del enlace simbólico sites-enabled que leyó realmente, no del archivo que editó en sites-available. Si example.com no aparece asociado al puerto 80, Certbot tampoco lo encontrará.
Emita el certificado: certbot --apache
sudo certbot --apache -d example.com -d www.example.comLa primera ejecución solicita tres datos: una dirección de correo electrónico (se usa para su cuenta de ACME y para los avisos urgentes de la CA; Let's Encrypt ya no envía avisos de vencimiento, por lo que debe supervisar las renovaciones), la aceptación de los términos de Let's Encrypt y si desea compartir su correo electrónico con la EFF. Ya no aparece la pregunta sobre la redirección: desde Certbot 2.0, el instalador de Apache redirige HTTP a HTTPS de forma predeterminada, que es lo que necesita. Use --no-redirect si realmente necesita que HTTP sin cifrar siga sirviendo contenido.
El resultado correcto es similar a este. Debe leerlo en lugar de revisarlo por encima:
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem
This certificate expires on 2026-10-14.
Deploying certificate
Successfully deployed certificate for example.com to /etc/apache2/sites-available/example.com-le-ssl.conf
Successfully deployed certificate for www.example.com to /etc/apache2/sites-available/example.com-le-ssl.conf
Congratulations! You have successfully enabled HTTPS on https://example.com and https://www.example.comDetrás de ese mensaje, Certbot hizo cuatro cosas: habilitó el módulo ssl de Apache si aún no estaba habilitado, escribió example.com-le-ssl.conf, una copia de su vhost en *:443 con SSLEngine on y las rutas de los certificados, lo habilitó y añadió un bloque RewriteRule al vhost original del puerto 80 que redirige todo a HTTPS mediante 301. El archivo de su vhost original se modifica, no se reemplaza, y la copia SSL queda junto a él para que pueda leer cada línea que se añadió.
Dónde se encuentra realmente el certificado y por qué nunca debe copiarlo
Todo se guarda en /etc/letsencrypt/live/example.com/: fullchain.pem (el certificado y la cadena intermedia, que es lo que deben usar los servidores), privkey.pem (la clave privada, legible sólo por root), además de cert.pem y chain.pem para el software que necesita los componentes por separado. Son enlaces simbólicos a /etc/letsencrypt/archive/. Esta indirección es el mecanismo de renovación: la renovación escribe archivos nuevos en archive/ y vuelve a apuntar los enlaces simbólicos. Configure cualquier otro software para usar las rutas live/ y recibirá las renovaciones automáticamente. Si copia los archivos en otra ubicación, provocará una interrupción del servicio 90 días después.
El otro archivo que debe conocer es /etc/letsencrypt/renewal/example.com.conf. Registra cómo se emitió este certificado, authenticator = apache, installer = apache y los dominios, para que la renovación pueda repetir el proceso sin intervención, incluida la recarga posterior de Apache.
La renovación ya está programada: verifíquela, no la configure de nuevo
Los certificados de Let's Encrypt duran 90 días por diseño, y el paquete apt ya instaló el mecanismo necesario: un temporizador de systemd que ejecuta Certbot dos veces al día en horarios aleatorios y renueva cualquier certificado al que le queden menos de 30 días para caducar. No añada una tarea de cron; un segundo planificador no aporta nada y sólo aumenta el ruido en los registros y la exposición a límites de frecuencia.
systemctl list-timers certbot.timer
sudo certbot renew --dry-runEl primer comando muestra el temporizador activo, con una hora NEXT dentro de las próximas 24 horas. La programación es de dos ejecuciones diarias con un retraso aleatorio, por lo que la hora exacta es deliberadamente impredecible. En la instalación mediante snap, el temporizador es snap.certbot.renew.timer. La ejecución de prueba realiza un ensayo completo de renovación contra el entorno de staging de Let's Encrypt: usa un desafío real, no emite ningún certificado y no consume el límite de frecuencia. Un resultado correcto termina con:
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/example.com/fullchain.pem (success)Si la ejecución de prueba falla, la renovación real dentro de ~60 días fallará por el mismo motivo. Corríjalo ahora, mientras el certificado actual todavía conserva toda su vigencia. La causa habitual es una regla de firewall añadida después de emitir el certificado que volvió a cerrar el puerto 80.
Verifique con curl qué debe mostrar el candado
curl -sI http://example.com | head -n 3
curl -I https://example.com
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null | openssl x509 -noout -issuer -datesEl primero debe devolver HTTP/1.1 301 Moved Permanently con una cabecera Location: https://example.com/. Esa es la redirección que instaló Certbot. El segundo debe devolver HTTP/1.1 200 OK sin que curl muestre errores relacionados con TLS. El tercero muestra el emisor, una línea O = Let's Encrypt con un CN corto como R12 o E7, y notAfter con una fecha aproximada de 90 días. En un navegador aparece el candado. Al hacer clic en él, se muestra el mismo emisor. Si curl funciona y el navegador muestra una advertencia, casi con toda seguridad está viendo una página almacenada en caché o usando el nombre de host incorrecto, no hay un problema con el certificado.
Varios sitios: un certificado SAN o un certificado por sitio
Ambas opciones funcionan y se renuevan de la misma forma. Para sitios no relacionados en el mismo servidor, ejecute el comando de emisión una vez por sitio. Cada uno tendrá su propio directorio en live/ y su propia configuración de renovación. Un problema con un dominio nunca impedirá renovar los demás. Esta es mi opción predeterminada.
Para un sitio con varios nombres, inclúyalos en un solo certificado SAN. Un certificado puede incluir hasta 100 nombres. Ya lo hizo antes con example.com y www.example.com. Para añadir un nombre a un certificado existente más adelante, vuelva a emitirlo indicando el nombre del certificado y la lista nueva completa:
sudo certbot --apache --cert-name example.com -d example.com -d www.example.com -d blog.example.comCertbot detecta que el conjunto de dominios ha cambiado, le pide que confirme la ampliación y reemplaza el certificado en la misma ruta live/. Por tanto, no es necesario modificar nada más. Tenga en cuenta que la lista reemplaza a la anterior; no se amplía. Si omite www de ese comando, el nuevo certificado lo elimina silenciosamente.
Los comodines requieren DNS-01 y, normalmente, no necesita un certificado comodín
HTTP-01 no puede emitir *.example.com. Colocar un archivo en un servidor web demuestra el control de un nombre de host, no de todo un espacio de nombres. Los comodines requieren el desafío DNS-01: Certbot establece un registro TXT en _acme-challenge.example.com. En la práctica, esto significa usar un plugin certbot-dns-* con credenciales de API del proveedor DNS, o editar manualmente los registros TXT en cada renovación con --manual (es una opción poco práctica; no base su planificación en ella). La guía completa, desde el funcionamiento de los registros TXT hasta un plugin que renueva los certificados sin intervención, está en certificados comodín con Certbot mediante DNS-01. Recomendación práctica: si conoce cuatro subdominios, un certificado SAN que incluya los cuatro es más sencillo que un comodín y no requiere almacenar claves de API de DNS en el servidor.
Modos de fallo y mensajes que verá
Certbot no se inicia porque la configuración de Apache tiene errores.
The apache plugin is not working; there may be problems with your existing configuration.
The error was: MisconfigurationError('Error while running apache2ctl configtest.\n\nAction \'configtest\' failed.\nThe Apache error log may have more information.\n\nAH00526: Syntax error on line 12 of /etc/apache2/sites-enabled/example.com.conf')El plugin ejecuta configtest antes de modificar nada y se detiene si Apache tiene algún problema. Los \n son literales porque Certbot muestra la representación de la excepción. Ejecute sudo apache2ctl configtest manualmente: indica el archivo y la línea. Normalmente, el problema es un error tipográfico al editar a mano, un SSLCertificateFile que apunta a una ruta que ya no existe o un módulo referenciado que no está habilitado. Corrija el problema hasta que muestre Syntax OK y vuelva a ejecutar Certbot.
Ningún vhost coincide con el dominio.
Unable to find a virtual host listening on port 80 which is currently the only challenge port.Este es el fallo de ServerName que se describió antes, detectado al solicitar el certificado. Certbot buscó en todos los vhost habilitados del puerto 80 un ServerName/ServerAlias que coincidiera con su -d y no encontró ninguno. sudo apache2ctl -S muestra cómo Apache encamina realmente las peticiones. Añada la línea ServerName al vhost correcto, recargue Apache y vuelva a intentarlo. Un caso similar ocurre cuando la validación llega al vhost equivocado: la respuesta al desafío devuelve Invalid response ... 404 porque otro sitio recibió la petición. El diagnóstico y la herramienta son los mismos: apache2ctl -S.
La validación agota el tiempo de espera.
Certbot failed to authenticate some domains (authenticator: apache).
...
Detail: ...: Timeout during connect (likely firewall problem)Let's Encrypt no pudo abrir una conexión TCP al puerto 80 en la dirección que anuncia su DNS. Las causas más probables, en orden, son las siguientes: el firewall de red del proveedor, separado de ufw y configurado en el panel de hosting; un conjunto de reglas de ufw que permite sólo 443 o sólo SSH; un DNS que todavía apunta al servidor anterior; o el problema de un registro AAAA obsoleto. Sus servidores intentaron usar IPv6, pero el suyo sólo responde en IPv4. Pruebe desde fuera del VPS: curl -I http://example.com desde su portátil reproduce lo que ve el validador.
Ha agotado el límite de solicitudes al reintentar.
Error creating new order :: too many failed authorizations recently: see https://letsencrypt.org/docs/rate-limits/Let's Encrypt permite 5 validaciones fallidas por nombre de host, por cuenta y por hora. Desde la modificación de los límites de 2025, se trata de un depósito que se rellena: recupera aproximadamente un reintento cada 12 minutos. Reintentar continuamente contra un firewall con errores lo agota rápidamente. Esperar funciona, pero la solución correcta es cambiar el procedimiento: después de cualquier fallo, depure con el entorno de staging hasta que funcione.
sudo certbot certonly --apache --dry-run -d example.com -d www.example.comTenga en cuenta certonly: --dry-run sólo se acepta con los subcomandos certonly y renew, y la forma independiente certbot --apache --dry-run se niega a ejecutarse y muestra --dry-run currently only works with the 'certonly' or 'renew' subcommands. La ejecución de prueba valida contra staging, que tiene sus propios límites más amplios y no emite certificados reales, por lo que puede fallar allí durante toda la tarde. Vuelva a ejecutar el comando real sólo cuando staging funcione. Los otros límites, 50 certificados por dominio registrado por semana y 5 duplicados del mismo conjunto de nombres por semana, sólo se alcanzan si un script vuelve a emitir certificados en un bucle.
Cuando HTTPS esté activo, recuerde que el certificado protege el transporte, no el servidor: el puerto 22 sigue recibiendo intentos de contraseña durante todo el día. Combinarlo con Fail2ban en Ubuntu 24.04 es el siguiente paso lógico de treinta minutos.
FAQ
¿Debo instalar Certbot con snap o apt para Apache en Ubuntu 24.04?
Use apt. Ubuntu 24.04 incluye Certbot 2.9.0, una versión suficientemente actual para todo lo descrito en esta guía. Recibe parches de seguridad mediante unattended-upgrades y no requiere snapd. Elija snap sólo si necesita inmediatamente la versión más reciente o un plugin DNS distribuido exclusivamente como snap. Si cambia a snap, apt remove certbot python3-certbot-apache primero para que no coexistan dos programadores de renovación.
¿Por qué Certbot muestra "Unable to find a virtual host listening on port 80"?
Porque ningún vhost habilitado en el puerto 80 tiene un ServerName o ServerAlias que coincida con el dominio indicado mediante -d. El vhost predeterminado de Ubuntu incluye ServerName comentado. Ejecute sudo apache2ctl -S, busque o cree el vhost que debe gestionar ese nombre, añada ServerName example.com, recargue Apache y vuelva a ejecutar Certbot.
¿Cómo corrijo "Timeout during connect (likely firewall problem)"?
Let's Encrypt no pudo acceder al puerto 80 en la dirección publicada por su DNS. Compruebe el firewall de red del panel de su proveedor y también ufw. Confirme que dig +short example.com devuelve este VPS y elimine o corrija cualquier registro AAAA obsoleto. La validación prefiere IPv6 cuando existe. Confirme la corrección desde fuera del servidor con curl -I http://example.com y haga una prueba con sudo certbot certonly --apache --dry-run -d example.com antes de emitir el certificado real.
¿Certbot renueva los certificados automáticamente en Ubuntu 24.04?
Sí. El paquete apt instala certbot.timer, un temporizador de systemd que se ejecuta dos veces al día y renueva cualquier certificado al que le queden 30 días o menos para caducar. Después recarga Apache. snap usa snap.certbot.renew.timer para la misma tarea. Verifique con systemctl list-timers certbot.timer y haga una prueba con sudo certbot renew --dry-run. No añada su propio trabajo de cron.
¿Cómo obtengo un certificado comodín con Certbot y Apache?
Los certificados comodín requieren el desafío DNS-01. Certbot debe crear un registro TXT en _acme-challenge.example.com. Esto requiere un plugin certbot-dns-* con credenciales de API para su proveedor DNS. La alternativa --manual requiere editar manualmente los registros TXT en cada renovación. Si sólo tiene unos pocos subdominios conocidos, es más sencillo usar un certificado SAN que los enumere explícitamente. Así también evita almacenar las claves de la API DNS en el servidor.