SSLmentor

Certificados TLS/SSL de calidad para sitios web y proyectos en Internet.

Lego

Lego

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.

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.

›› Mostrar/Ocultar sección

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.

Volver a Ayuda
¿Encontraste un error o no entiendes algo? ¡Escríbenos!

CA Sectigo
CA RapidSSL
CA Thawte
CA GeoTrust
CA DigiCert
CA Certum