discourse_docker/templates/web.letsencrypt.ssl.template.yml
2025-01-14 16:44:52 +00:00

133 lines
4.7 KiB
YAML

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.6 --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/nginx/letsencrypt.conf"
contents: |
user www-data;
worker_processes auto;
daemon on;
events {
worker_connections 768;
# multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
access_log /var/log/nginx/access.letsencrypt.log;
error_log /var/log/nginx/error.letsencrypt.log;
server {
listen 80;
listen [::]:80;
location ~ /.well-known {
root /var/www/discourse/public;
allow all;
}
}
}
- file:
path: /etc/runit/1.d/letsencrypt
chmod: "+x"
contents: |
#!/bin/bash
/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf
issue_cert() {
LE_WORKING_DIR="${LETSENCRYPT_DIR}" $$ENV_LETSENCRYPT_DIR/acme.sh --issue $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"
fi
/usr/sbin/nginx -c /etc/nginx/letsencrypt.conf -s stop
- 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';