Hola chicos
Necesitaba usar el método DNS para autenticar la propiedad de mi certificado SSL con Let’s Encrypt.
Tomé una copia del archivo web.letsencrypt.ssl.template.yml existente que se encuentra en /var/discourse/templates/ y lo modifiqué para usar el método de Integración Automática de API DNS. A continuación, presento mi plantilla de ejemplo, agradecería cualquier sugerencia sobre cómo mejorarla.
Llamé a este archivo web.letsencrypt.ssl.dns.template.yml
env:
LETSENCRYPT_DIR: "/shared/letsencrypt"
DISCOURSE_FORCE_HTTPS: true
hooks:
after_ssl:
- exec:
cmd:
- if [ -z "$LETSENCRYPT_ACCOUNT_EMAIL" ]; then echo "La variable de entorno LETSENCRYPT_ACCOUNT_EMAIL es requerida y no ha sido establecida."; exit 1; fi
- /bin/bash -c "if [[ ! \"$LETSENCRYPT_ACCOUNT_EMAIL\" =~ ([^@]+)@([^\\.]+) ]]; then echo \"LETSENCRYPT_ACCOUNT_EMAIL no es una dirección de correo electrónico válida\"; exit 1; fi"
- exec:
cmd:
- cd /root && git clone --branch 3.0.7 --depth 1 https://github.com/acmesh-official/acme.sh.git && cd /root/acme.sh
- touch /var/spool/cron/crontabs/root
- install -d -m 0755 -g root -o root $LETSENCRYPT_DIR
- cd /root/acme.sh && LE_WORKING_DIR="${LETSENCRYPT_DIR}" ./acme.sh --install --log "${LETSENCRYPT_DIR}/acme.sh.log"
- cd /root/acme.sh && LE_WORKING_DIR="${LETSENCRYPT_DIR}" ./acme.sh --upgrade --auto-upgrade
- cd /root/acme.sh && LE_WORKING_DIR="${LETSENCRYPT_DIR}" ./acme.sh --set-default-ca --server letsencrypt
- file:
path: /etc/runit/1.d/letsencrypt
chmod: "+x"
contents: |
#!/bin/bash
issue_cert() {
export CF_Token="$ENV_LETSENCRYPT_CF_TOKEN"
export CF_Account_ID="$ENV_LETSENCRYPT_CF_ACCOUNT_ID"
export CF_Zone_ID="$ENV_LETSENCRYPT_CF_ZONE_ID"
LE_WORKING_DIR="${LETSENCRYPT_DIR}" $ENV_LETSENCRYPT_DIR/acme.sh --issue --dns $ENV_LETSENCRYPT_DNS_PROVIDER $2 -d $ENV_DISCOURSE_HOSTNAME --keylength $1 -w /var/www/discourse/public
}
cert_exists() {
[[ "$(cd ${ENV_LETSENCRYPT_DIR}/${ENV_DISCOURSE_HOSTNAME}$1 && openssl verify -CAfile <(openssl x509 -in ca.cer) fullchain.cer | grep "OK")"]]
}
########################################################
# Certificado RSA
########################################################
issue_cert "4096"
if ! cert_exists ""; then
# Intenta emitir el certificado de nuevo si algo sale mal
issue_cert "4096" "--force"
fi
LE_WORKING_DIR="${LETSENCRYPT_DIR}" $ENV_LETSENCRYPT_DIR/acme.sh \
--installcert \
-d $ENV_DISCOURSE_HOSTNAME \
--fullchainpath /shared/ssl/$ENV_DISCOURSE_HOSTNAME.cer \
--keypath /shared/ssl/$ENV_DISCOURSE_HOSTNAME.key \
--reloadcmd "sv reload nginx"
########################################################
# Certificado ECDSA
########################################################
issue_cert "ec-256"
if ! cert_exists "_ecc"; then
# Intenta emitir el certificado de nuevo si algo sale mal
issue_cert "ec-256" "--force"
fi
LE_WORKING_DIR="${LETSENCRYPT_DIR}" $ENV_LETSENCRYPT_DIR/acme.sh \
--installcert --ecc \
-d $ENV_DISCOURSE_HOSTNAME \
--fullchainpath /shared/ssl/$ENV_DISCOURSE_HOSTNAME_ecc.cer \
--keypath /shared/ssl/$ENV_DISCOURSE_HOSTNAME_ecc.key \
--reloadcmd "sv reload nginx"
if cert_exists "" || cert_exists "_ecc"; then
grep -q 'force_https' "/var/www/discourse/config/discourse.conf" || echo "force_https = 'true'" >> "/var/www/discourse/config/discourse.conf"
fi
- replace:
filename: "/etc/nginx/conf.d/discourse.conf"
from: /ssl_certificate.+/
to: |
ssl_certificate /shared/ssl/$ENV_DISCOURSE_HOSTNAME.cer;
ssl_certificate /shared/ssl/$ENV_DISCOURSE_HOSTNAME_ecc.cer;
- replace:
filename: /shared/letsencrypt/account.conf
from: /#?ACCOUNT_EMAIL=.+/
to: |
ACCOUNT_EMAIL=$ENV_LETSENCRYPT_ACCOUNT_EMAIL
- replace:
filename: "/etc/nginx/conf.d/discourse.conf"
from: /ssl_certificate_key.+/
to: |
ssl_certificate_key /shared/ssl/$ENV_DISCOURSE_HOSTNAME.key;
ssl_certificate_key /shared/ssl/$ENV_DISCOURSE_HOSTNAME_ecc.key;
- replace:
filename: "/etc/nginx/conf.d/discourse.conf"
from: /add_header.+/
to: |
add_header Strict-Transport-Security 'max-age=63072000';
Hay algunas variables de entorno adicionales que necesita agregar a app.yml y posiblemente modificar si no está utilizando Cloudflare como su proveedor de DNS. Todas las configuraciones de API de los diferentes proveedores están aquí
Esto es lo que agregué a mi app.yml en la sección templates
templates:
- "templates/postgres.template.yml"
- "templates/redis.template.yml"
- "templates/web.template.yml"
## Descomenta la siguiente línea para habilitar el oyente IPv6
#- "templates/web.ipv6.template.yml"
- "templates/web.ratelimited.template.yml"
## Descomenta estas dos líneas si deseas agregar Let's Encrypt (https)
- "templates/web.ssl.template.yml"
- "templates/web.letsencrypt.ssl.dns.template.yml"
#- "templates/web.letsencrypt.ssl.template.yml"
Y más abajo, en la sección env.
## Si agregaste la plantilla de Let's Encrypt, descomenta a continuación para obtener un certificado SSL gratuito
LETSENCRYPT_ACCOUNT_EMAIL: me@mydomain.com
LETSENCRYPT_CF_TOKEN: "TU_TOKEN"
LETSENCRYPT_CF_ACCOUNT_ID: "TU_ACCOUNT_ID"
LETSENCRYPT_CF_ZONE_ID: "TU_ZONE_ID"
LETSENCRYPT_DNS_PROVIDER: "TU_PROVEEDOR_DNS" ## por ejemplo, dns_cf
Después de actualizar esos archivos, simplemente ejecuté el comando para reconstruir la aplicación docker
cd /var/discourse
./launcher rebuild app
Una vez reconstruido, deberías tener tu aplicación ejecutándose en https:// y debería haber un trabajo cron que verifique diariamente si tu certificado necesita ser actualizado. Si necesita ser actualizado, obtendrá un nuevo certificado y lo instalará automáticamente.
Espero que esto ayude a alguien.