Ciao ragazzi
Ho dovuto utilizzare il metodo DNS per autenticare la proprietà del mio certificato SSL con Let’s Encrypt.
Ho preso una copia del file web.letsencrypt.ssl.template.yml esistente, che si trova in /var/discourse/templates/, e l’ho modificato per utilizzare il metodo di integrazione automatica dell’API DNS. Di seguito è riportato il mio modello di esempio, sarei felice se ci fossero suggerimenti su come migliorarlo.
Ho chiamato questo file 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 "LETSENCRYPT_ACCOUNT_EMAIL ENV variable is required and has not been set."; exit 1; fi
- /bin/bash -c "if [[ ! \"$LETSENCRYPT_ACCOUNT_EMAIL\" =~ ([^@]+)@([^\\.]+) ]]; then echo \"LETSENCRYPT_ACCOUNT_EMAIL is not a valid email address\"; 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")"]]
}
########################################################
# RSA cert
########################################################
issue_cert "4096"
if ! cert_exists ""; then
# Try to issue the cert again if something goes wrong
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"
########################################################
# ECDSA cert
########################################################
issue_cert "ec-256"
if ! cert_exists "_ecc"; then
# Try to issue the cert again if something goes wrong
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"
- 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';
Ci sono alcune variabili d’ambiente aggiuntive che devi aggiungere ad app.yml e possibilmente modificare se non utilizzi Cloudflare come provider DNS. Tutte le impostazioni API dei diversi provider sono qui
Questo è ciò che ho aggiunto al mio app.yml nella sezione templates
templates:
- "templates/postgres.template.yml"
- "templates/redis.template.yml"
- "templates/web.template.yml"
## Uncomment the next line to enable the IPv6 listener
#- "templates/web.ipv6.template.yml"
- "templates/web.ratelimited.template.yml"
## Uncomment these two lines if you wish to add Lets Encrypt (https)
- "templates/web.ssl.template.yml"
- "templates/web.letsencrypt.ssl.dns.template.yml"
#- "templates/web.letsencrypt.ssl.template.yml"
E più in basso nella sezione env.
## If you added the Lets Encrypt template, uncomment below to get a free SSL certificate
LETSENCRYPT_ACCOUNT_EMAIL: me@mydomain.com
LETSENCRYPT_CF_TOKEN: "YOUR_TOKEN"
LETSENCRYPT_CF_ACCOUNT_ID: "YOUR_ACCOUNT_ID"
LETSENCRYPT_CF_ZONE_ID: "YOUR_ZONE_ID"
LETSENCRYPT_DNS_PROVIDER: "YOUR_DNS_PROVIDER" ## i.e. dns_cf
Dopo aver aggiornato quei file, ho semplicemente eseguito il comando per ricostruire l’app docker
cd /var/discourse
./launcher rebuild app
Una volta ricostruito, dovresti avere la tua app in esecuzione su https:// e dovrebbe esserci un cron job che controlla quotidianamente se il tuo certificato necessita di aggiornamenti. Se necessita di aggiornamenti, otterrà un nuovo certificato e lo installerà automaticamente.
Spero che questo aiuti qualcuno.