Cliente ACME Lego
El cliente ACME Lego es un proyecto independiente, gratuito y de código abierto escrito en el lenguaje Go. Es ideal para integraciones personalizadas y scripting y cuenta con un amplio soporte de registradores de dominios y proveedores de DNS. Lego es un cliente ACME flexible que puede integrarse fácilmente en sistemas y scripts propios. Además de la validación HTTP-01, ofrece validación DNS a través de muchos proveedores de DNS (lista de proveedores de DNS compatibles) para obtener certificados SSL WildCard.
La guía usa una sintaxis verificada en la versión Lego 5.*.* y está pensada para Debian/Ubuntu con Apache 2 y el cliente ACME Lego.
Contenido del artículo
- Instalación de Lego
- Apache, webroot
- Archivos de configuración de Lego
- Emisión del certificado
- Despliegue en Apache
- Renovación automática
Conceptos básicos
- ACME – protocolo para la emisión y renovación automatizadas de certificados SSL/TLS.
- HTTP-01 – método de validación ACME que verifica la propiedad del dominio usando un archivo temporal accesible por HTTP.
- DNS-01 – método de validación mediante el registro DNS TXT
_acme-challenge. - EAB kid + hmac – datos de External Account Binding (EAB) de la autoridad de certificación. Vinculan Certbot a una cuenta o producto.
- Servicio systemd - un archivo de configuración que indica al sistema Linux cómo iniciar una aplicación y mantenerla en ejecución incluso después de reiniciar el servidor.
Si en los ejemplos aparece el dominio example.com, sustitúyelo siempre por tu propio dominio.
Instalación de Lego
apt update
apt install -y curl tar
cd /tmp
LEGO_URL=$(curl -s https://api.github.com/repos/go-acme/lego/releases/latest | sed -n 's/.*"browser_download_url": "\(.*linux_amd64.tar.gz\)".*/\1/p' | head -n1)
echo "$LEGO_URL"
curl -L -o lego.tar.gz "$LEGO_URL"
tar -xzf lego.tar.gz
install -m 0755 lego /usr/local/bin/lego
lego --version
Tras una instalación correcta, recomendamos eliminar los archivos temporales.
rm -f /tmp/lego /tmp/lego.tar.gz /tmp/LICENSE /tmp/CHANGELOG.md
| Comando / valor | Qué hace / qué sustituir |
|---|---|
apt update |
Actualiza la lista de paquetes. |
apt install -y curl tar |
Instala las herramientas para descargar y extraer Lego. |
LEGO_URL=... |
Encuentra la URL del último paquete de la versión Linux amd64. |
curl -L -o lego.tar.gz |
Descarga el archivo comprimido de Lego. |
tar -xzf lego.tar.gz |
Extrae el archivo comprimido. |
install -m 0755 lego /usr/local/bin/lego |
Instala Lego como un comando ejecutable del sistema. |
lego --version |
Verifica la versión instalada de Lego. |
Apache, webroot
Este procedimiento crea una configuración básica de VirtualHost para el dominio en el puerto 80. Establece DocumentRoot, los permisos del directorio web, crea los logs de Apache, habilita la configuración con a2ensite, verifica su corrección (apache2ctl configtest) y recarga los cambios. Por último, verifica la disponibilidad del sitio web mediante una petición HTTP curl.
Antes de ejecutar, sustituye el valor example.com en la línea DOMAIN="example.com" por tu propio dominio. La variable $DOMAIN se usa luego en los siguientes comandos para las rutas, el vhost de Apache y la página de prueba.
cd /var/www
apt update
apt install -y apache2
systemctl enable --now apache2
a2enmod rewrite headers ssl
systemctl reload apache2
# or just updates
apt update
apt install --only-upgrade apache2
systemctl reload apache2
DOMAIN="example.com"
mkdir -p /var/www/$DOMAIN/public
chown -R www-data:www-data /var/www/$DOMAIN
chmod -R 755 /var/www/$DOMAIN
echo "OK $DOMAIN" > /var/www/$DOMAIN/public/index.html
| Comando / valor | Qué hace / qué sustituir |
|---|---|
cd /var/www |
Cambia al directorio donde normalmente se guardan los archivos web. |
apt update |
Actualiza la lista de paquetes. |
apt install -y apache2 |
Instala Apache; -y confirma automáticamente la instalación. |
systemctl enable --now apache2 |
Habilita Apache al arrancar el servidor y lo inicia al mismo tiempo. |
a2enmod rewrite headers ssl |
Habilita los módulos para redirecciones, cabeceras y HTTPS. |
DOMAIN="example.com" |
Establece la variable del dominio. Sustituye example.com por tu propio dominio. |
mkdir/chown/chmod/echo |
Crea el webroot, establece los permisos para Apache y guarda una página de prueba sencilla. |
Vhost HTTP para el apex y el subdominio:
cat > /etc/apache2/sites-available/$DOMAIN.conf <<EOF
<VirtualHost *:80>
ServerName $DOMAIN
ServerAlias www.$DOMAIN
DocumentRoot /var/www/$DOMAIN/public
<Directory /var/www/$DOMAIN/public>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog \${APACHE_LOG_DIR}/${DOMAIN}_error.log
CustomLog \${APACHE_LOG_DIR}/${DOMAIN}_access.log combined
</VirtualHost>
EOF
a2ensite "$DOMAIN.conf"
apache2ctl configtest
systemctl reload apache2
curl -I "http://$DOMAIN"
curl -I "http://www.$DOMAIN"
Resultado: Tras abrir http://example.com, debería aparecer la página de prueba.
| Comando / valor | Qué hace / qué sustituir |
|---|---|
cat > ... <<EOF |
Escribe un nuevo vhost HTTP de Apache en un archivo en sites-available. |
ServerName $DOMAIN |
El dominio principal del virtual host. |
ServerAlias www.$DOMAIN |
Crea el manejo del subdominio de primer nivel. |
DocumentRoot |
El directorio desde el que Apache sirve el contenido. |
a2ensite "$DOMAIN.conf" |
Habilita el vhost. |
apache2ctl configtest |
Verifica la sintaxis de la configuración de Apache. |
curl -I http://$DOMAIN |
Verifica la respuesta HTTP del dominio. |
Archivos de configuración de Lego
El enfoque recomendado para Lego v5 es almacenar la configuración en un archivo de configuración. Así, el servicio systemd no necesita contener un comando largo con dominios y hooks.
Archivo de configuración lego.yml
El archivo .yml es un archivo de configuración de texto en formato YAML, usado para una notación clara de ajustes, parámetros y datos estructurados. Antes de guardar la configuración YAML, sustituye example.com por tu propio dominio, vas@email.cz por tu correo de contacto y los valores KID / HMAC por los datos de tu pedido de certificado ACME.
mkdir /etc/lego/$DOMAIN
nano /etc/lego/$DOMAIN/lego.yml
storage: /etc/lego/example.com
accounts:
certum-account:
server: certum
email: your@email.com # your email address for CA Certum
acceptsTermsOfService: true
eab:
kid: KID
hmacKey: HMAC
servers:
certum:
url: https://acme.certum.pl/directory
challenges:
http-chal:
http:
# Path to your website's document root.
# Lego will temporarily write a file to this directory .well-known/acme-challenge/
webroot: /var/www/example.com/public
certificates:
example-com:
account: certum-account
challenge: http-chal
domains:
- example.com
- www.example.com
renew:
days: 30
hooks:
deploy:
command: systemctl reload apache2
¡Consejo! Puedes generar un contenido YML casi completo directamente en el servidor y luego solo rellenar el e-mail, kid y hmacKey correctos. Basta con ejecutar el comando de abajo y copiar el contenido de la página index.html en el archivo lego.yml.
›› Mostrar/Ocultar el YML preparado.
cat > "/var/www/$DOMAIN/public/index.html" <<EOF
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>${DOMAIN}</title>
<style>
body { font-family: sans-serif; max-width: 900px; margin: 40px auto; }
pre { background:#f4f4f4; padding:1em; overflow:auto; }
</style>
</head>
<body>
<h1>OK – ${DOMAIN}</h1>
<p>Apache is working correctly.</p>
<h2>lego.yml</h2>
<pre><code>storage: /etc/lego/${DOMAIN}
accounts:
certum-account:
server: certum
email: YOUR_EMAIL
acceptsTermsOfService: true
eab:
kid: YOUR_KID
hmacKey: YOUR_HMAC_KEY
servers:
certum:
url: https://acme.certum.pl/directory
challenges:
http-chal:
http:
webroot: /var/www/${DOMAIN}/public
certificates:
${DOMAIN//./-}:
account: certum-account
challenge: http-chal
domains:
- ${DOMAIN}
- www.${DOMAIN}
renew:
days: 30
hooks:
deploy:
command: systemctl reload apache2
</code></pre>
</body>
</html>
EOF
El archivo lego.yml contiene el EAB HMAC, por lo que debe tener permisos restringidos. En la documentación, usa solo marcadores de posición.
chmod 600 /etc/lego/$DOMAIN/lego.yml
Comprobación de los permisos y el propietario del archivo:
stat -c "%a %U:%G %n" /etc/lego/$DOMAIN/lego.yml
| Comando / valor | Qué hace / qué sustituir |
|---|---|
storage |
Directorio para la cuenta de Lego, los certificados y los metadatos. |
accounts |
Definición de la cuenta ACME, incluidos el e-mail y los datos EAB. |
servers.certum.url |
El endpoint ACME de Certum. |
challenges.http-chal |
Validación por http. |
certificates |
Lista de certificados que Lego debe gestionar. |
domains |
El dominio apex y el dominio comodín del certificado. |
renew.days |
Cuántos días antes de la caducidad debe renovar Lego. |
hooks.deploy.command |
Comando tras una emisión o renovación correcta, aquí la recarga de Apache. |
Emisión del certificado SSL/TLS
Antes de ejecutar, comprueba echo ${DOMAIN} o establece la variable DOMAIN con el nombre de tu dominio DOMAIN="example.com". La herramienta Lego realiza la validación HTTP-01 usando un archivo almacenado temporalmente en el webroot, verifica la propiedad del dominio y luego crea un certificado SSL/TLS. El certificado, la clave privada y el certificado del emisor (intermedio) se almacenarán en el directorio /etc/lego/${DOMAIN}/certificates/.
lego --config /etc/lego/$DOMAIN/lego.yml
Durante la generación, el cliente ACME Lego imprimirá información sobre la solicitud:
root@vmiXXXXXXXX:~# echo ${DOMAIN}
example.com
root@:~# lego --config /etc/lego/$DOMAIN/lego.yml
INFO Archive account scope=accountID filepath=/etc/lego/example.com/accounts/acme.certum.pl/certum-acme/
archives=/etc/lego/example.com/archives/accounts/acme.certum.pl_certum-acme_1785270773.zip
INFO Private key saved. filepath=/etc/lego/example.com/accounts/acme.certum.pl/certum-account/certum-account.key
INFO Registering the account (EAB). email=your@email.com
WARN !!!! HEADS UP !!!!
Your account credentials have been saved in your
configuration directory at "/etc/lego/example.com/accounts".
You should make a secure backup of this folder now. This
configuration directory will also contain private keys
generated by lego and certificates obtained from the ACME
server. Making regular backups of this folder is ideal.
INFO Obtaining bundled SAN certificate. domains="example.com, www.example.com"
INFO Use solver. domain=www.example.com type=http-01
INFO Use solver. domain=example.com type=http-01
INFO http01: Trying to solve HTTP-01. domain=www.example.com
INFO The server validated our request. domain=www.example.com
INFO http01: Trying to solve HTTP-01. domain=example.com
INFO The server validated our request. domain=example.com
INFO Validations succeeded; requesting certificates. domains="example.com, www.example.com"
INFO Waiting for certificates. timeout=30s interval=500ms domains="example.com, www.example.com"
INFO Server responded with a certificate. domains="example.com, www.example.com"
INFO Writing file. filepath=/etc/lego/example.com/certificates/acmeapi-online.crt
INFO Writing file. filepath=/etc/lego/example.com/certificates/acmeapi-online.issuer.crt
INFO Writing file. filepath=/etc/lego/example.com/certificates/acmeapi-online.key
INFO Writing file. filepath=/etc/lego/example.com/certificates/acmeapi-online.pem
INFO Writing file. filepath=/etc/lego/example.com/certificates/acmeapi-online.json
Verifica los archivos del certificado SSL generado
Muestra el contenido del directorio certificates creado por el servicio Lego, incluidos el certificado, la clave privada y el certificado del emisor para el dominio seleccionado.
ls -la /etc/lego/$DOMAIN/certificates/
El directorio certificates/ contiene el .crt emitido, la .key, los certificados intermedios de la autoridad de certificación y los metadatos.
Despliegue del certificado en Apache
Este ejemplo usa la variable ${DOMAIN}, que ya deberías tener establecida desde el principio de la guía. Antes de ejecutar los comandos, puedes asegurarte de que la variable esté correctamente establecida, por ejemplo: echo ${DOMAIN}
La variable ${DOMAIN} se usa en el nombre del archivo de configuración, en los valores ServerName y ServerAlias y en la ruta al webroot.
¡Atención! - las rutas al certificado SSL y a la clave privada usan el dominio con el formato example-com. Las rutas deben coincidir con el dominio usado en la configuración de Lego.
cat > /etc/apache2/sites-available/${DOMAIN}-le-ssl.conf <<EOF
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName ${DOMAIN}
ServerAlias www.${DOMAIN}
DocumentRoot /var/www/${DOMAIN}/public
<Directory /var/www/${DOMAIN}/public>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
SSLEngine on
SSLCertificateFile /etc/lego/${DOMAIN}/certificates/${DOMAIN//./-}.crt
SSLCertificateKeyFile /etc/lego/${DOMAIN}/certificates/${DOMAIN//./-}.key
ErrorLog ${APACHE_LOG_DIR}/${DOMAIN}_ssl_error.log
CustomLog ${APACHE_LOG_DIR}/${DOMAIN}_ssl_access.log combined
</VirtualHost>
</IfModule>
EOF
a2ensite ${DOMAIN}-le-ssl.conf
apache2ctl configtest
systemctl reload apache2
curl -I https://${DOMAIN}
curl -I https://www.${DOMAIN}
Resultado: HTTPS funcionando.
| Comando / valor | Qué hace / qué sustituir |
|---|---|
cat > ...-le-ssl.conf |
Crea el vhost HTTPS de Apache. |
ServerName / ServerAlias |
Especifica el dominio apex y el subdominio. |
SSLCertificateFile |
Ruta al certificado. |
SSLCertificateKeyFile |
Ruta a la clave privada. |
a2ensite |
Habilita el vhost HTTPS. |
systemctl reload apache2 |
Recarga la nueva configuración de Apache. |
curl -I https://... |
Verifica la respuesta HTTPS. |
Renovación automática
Lego puede renovar el certificado automáticamente, pero tras la instalación no crea por sí mismo las unidades systemd para la ejecución periódica. Por lo tanto, es necesario crear dos unidades para la renovación automática:
- lego-example-com-renew.service – ejecuta la comprobación y, si es necesario, la renovación del certificado.
- lego-example-com-renew.timer – asegura que el servicio se ejecute a diario a una hora establecida.
Antes de insertarlo, sustituye example-com en el nombre del service/timer por tu propio nombre si es necesario, y sustituye example.com en la ruta de configuración por tu propio dominio.
cat > /etc/systemd/system/lego-${DOMAIN//./-}-renew.service <<EOF
[Unit]
Description=Renew ACME Certum SSL for example.com using Lego HTTP-01
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/lego --config /etc/lego/${DOMAIN}/lego.yml
EOF
cat > /etc/systemd/system/lego-${DOMAIN//./-}-renew.timer <<EOF
[Unit]
Description=Daily Lego renewal check for ${DOMAIN}
[Timer]
OnCalendar=*-*-* 03:20:00
RandomizedDelaySec=1800
Persistent=true
[Install]
WantedBy=timers.target
EOF
Tras crear las unidades, verifica su contenido:
cat /etc/systemd/system/lego-example-com-renew.service
echo "----------------"
cat /etc/systemd/system/lego-example-com-renew.timer
Recarga las nuevas unidades, habilita el timer y verifica que esté en ejecución:
systemctl daemon-reload
systemctl enable --now lego-${DOMAIN//./-}-renew.timer
systemctl list-timers | grep lego
Resultado: El timer está activo y systemd ha programado su próxima ejecución.
| Comando / valor | Qué hace / qué sustituir |
|---|---|
lego-example-com-renew.service |
Servicio systemd para una ejecución única de Lego renew/run. |
Type=oneshot |
El servicio se inicia, realiza su trabajo y finaliza. |
ExecStart |
Ejecuta Lego según lego.yml. |
lego-example-com-renew.timer |
Timer systemd que ejecuta el servicio de forma periódica. |
OnCalendar |
Hora de la comprobación diaria. |
RandomizedDelaySec |
Retardo aleatorio para que las peticiones no se inicien todas exactamente al mismo tiempo. |
Persistent=true |
Ejecuta una ejecución omitida después de que arranque el servidor. |
systemctl enable --now |
Habilita el timer y lo activa de inmediato. |
Prueba segura del servicio:
systemctl start lego-${DOMAIN//./-}-renew.service
systemctl status lego-${DOMAIN//./-}-renew.service --no-pager
journalctl -u lego-${DOMAIN//./-}-renew.service -n 100 --no-pager
Resultado: Si el certificado no está próximo a caducar, Lego puede informar de que la renovación no es necesaria. Este es el comportamiento correcto.
| Comando / valor | Qué hace / qué sustituir |
|---|---|
systemctl start ...service |
Ejecuta manualmente el servicio de renovación como prueba. |
systemctl status ... |
Muestra si el servicio finalizó correctamente |
journalctl -u ... |
Muestra los últimos logs del servicio. |
Lista de las unidades de Lego disponibles:
ls -l /etc/systemd/system/lego*
systemctl list-timers | grep lego
Resultado: Ambas variantes muestran todos los servicios y timers relacionados con el cliente ACME Lego.
¿A dónde ir a continuación?
Volver a Ayuda
¿Encontraste un error o no entiendes algo? ¡Escríbenos!
