diff --git a/readme-vars.yml b/readme-vars.yml index 27bde094..4713fc9f 100644 --- a/readme-vars.yml +++ b/readme-vars.yml @@ -32,6 +32,7 @@ opt_param_usage_include_env: true opt_param_env_vars: - {env_var: "SUBDOMAINS", env_value: "www,", desc: "Subdomains you'd like the cert to cover (comma separated, no spaces) ie. `www,ftp,cloud`. For a wildcard cert, set this *exactly* to `wildcard` (wildcard cert is available via `dns` validation only)"} - {env_var: "CERTPROVIDER", env_value: "", desc: "Optionally define the cert provider. Set to `zerossl` for ZeroSSL certs (requires existing [ZeroSSL account](https://app.zerossl.com/signup) and the e-mail address entered in `EMAIL` env var). Otherwise defaults to Let's Encrypt."} + - {env_var: "CERT_PROFILE", env_value: "", desc: "Optionally define a cert profile to use for cert generation. This is useful if you want to use a custom cert profile instead of the default one. Currently only supported for Let's Encrypt. See https://letsencrypt.org/docs/profiles/ "} - {env_var: "DNSPLUGIN", env_value: "cloudflare", desc: "Required if `VALIDATION` is set to `dns`. Options are `acmedns`, `aliyun`, `azure`, `bunny`, `cloudflare`, `cpanel`, `desec`, `digitalocean`, `directadmin`, `dnsimple`, `dnsmadeeasy`, `dnspod`, `do`, `domeneshop`, `dreamhost`, `duckdns`, `dynu`, `freedns`, `gandi`, `gehirn`, `glesys`, `godaddy`, `google`, `he`, `hetzner`, `hetzner-cloud`, `infomaniak`, `inwx`, `ionos`, `linode`, `loopia`, `luadns`, `namecheap`, `netcup`, `njalla`, `nsone`, `ovh`, `porkbun`, `rfc2136`, `route53`, `sakuracloud`, `standalone`, `transip`, and `vultr`. Also need to enter the credentials into the corresponding ini (or json for some plugins) file under `/config/dns-conf`."} - {env_var: "PROPAGATION", env_value: "", desc: "Optionally override (in seconds) the default propagation time for the dns plugins."} - {env_var: "EMAIL", env_value: "", desc: "Optional e-mail address used for cert expiration notifications (Required for ZeroSSL)."} @@ -219,6 +220,7 @@ init_diagram: | "swag:latest" <- Base Images # changelog changelogs: + - {date: "05.05.26:", desc: "Added support for Let's Encrypt cert profiles." } - {date: "23.01.26:", desc: "Reorder init to fix proxy conf version checks."} - {date: "21.12.25:", desc: "Add support for hetzner-cloud dns validation."} - {date: "04.11.25:", desc: "Switch default Gandi credentials from API Key to Token, allow DNS propagation time for Azure DNS plugin."} diff --git a/root/etc/s6-overlay/s6-rc.d/init-certbot-config/run b/root/etc/s6-overlay/s6-rc.d/init-certbot-config/run index 5e34aaae..dd24ba1d 100755 --- a/root/etc/s6-overlay/s6-rc.d/init-certbot-config/run +++ b/root/etc/s6-overlay/s6-rc.d/init-certbot-config/run @@ -12,12 +12,13 @@ EXTRA_DOMAINS=${EXTRA_DOMAINS}\\n\ ONLY_SUBDOMAINS=${ONLY_SUBDOMAINS}\\n\ VALIDATION=${VALIDATION}\\n\ CERTPROVIDER=${CERTPROVIDER}\\n\ +CERT_PROFILE=${CERT_PROFILE}\\n\ DNSPLUGIN=${DNSPLUGIN}\\n\ EMAIL=${EMAIL}\\n\ STAGING=${STAGING}\\n" # Sanitize variables -SANED_VARS=(DNSPLUGIN EMAIL EXTRA_DOMAINS ONLY_SUBDOMAINS STAGING SUBDOMAINS URL VALIDATION CERTPROVIDER) +SANED_VARS=(DNSPLUGIN EMAIL EXTRA_DOMAINS ONLY_SUBDOMAINS STAGING SUBDOMAINS URL VALIDATION CERTPROVIDER CERT_PROFILE) for i in "${SANED_VARS[@]}"; do export echo "${i}"="${!i//\"/}" export echo "${i}"="$(echo "${!i}" | tr '[:upper:]' '[:lower:]')" @@ -80,7 +81,7 @@ if [[ -f "/config/donoteditthisfile.conf" ]]; then mv /config/donoteditthisfile.conf /config/.donoteditthisfile.conf fi if [[ ! -f "/config/.donoteditthisfile.conf" ]]; then - echo -e "ORIGURL=\"${URL}\" ORIGSUBDOMAINS=\"${SUBDOMAINS}\" ORIGONLY_SUBDOMAINS=\"${ONLY_SUBDOMAINS}\" ORIGEXTRA_DOMAINS=\"${EXTRA_DOMAINS}\" ORIGVALIDATION=\"${VALIDATION}\" ORIGDNSPLUGIN=\"${DNSPLUGIN}\" ORIGPROPAGATION=\"${PROPAGATION}\" ORIGSTAGING=\"${STAGING}\" ORIGCERTPROVIDER=\"${CERTPROVIDER}\" ORIGEMAIL=\"${EMAIL}\"" >/config/.donoteditthisfile.conf + echo -e "ORIGURL=\"${URL}\" ORIGSUBDOMAINS=\"${SUBDOMAINS}\" ORIGONLY_SUBDOMAINS=\"${ONLY_SUBDOMAINS}\" ORIGEXTRA_DOMAINS=\"${EXTRA_DOMAINS}\" ORIGVALIDATION=\"${VALIDATION}\" ORIGDNSPLUGIN=\"${DNSPLUGIN}\" ORIGPROPAGATION=\"${PROPAGATION}\" ORIGSTAGING=\"${STAGING}\" ORIGCERTPROVIDER=\"${CERTPROVIDER}\" ORIGEMAIL=\"${EMAIL}\" ORIGCERT_PROFILE=\"${CERT_PROFILE}\"" >/config/.donoteditthisfile.conf echo "Created .donoteditthisfile.conf" fi @@ -186,7 +187,8 @@ if [[ ! "${URL}" = "${ORIGURL}" ]] || [[ ! "${DNSPLUGIN}" = "${ORIGDNSPLUGIN}" ]] || [[ ! "${PROPAGATION}" = "${ORIGPROPAGATION}" ]] || [[ ! "${STAGING}" = "${ORIGSTAGING}" ]] || - [[ ! "${CERTPROVIDER}" = "${ORIGCERTPROVIDER}" ]]; then + [[ ! "${CERTPROVIDER}" = "${ORIGCERTPROVIDER}" ]] || + [[ ! "${CERT_PROFILE}" = "${ORIGCERT_PROFILE}" ]]; then echo "Different validation parameters entered than what was used before. Revoking and deleting existing certificate, and an updated one will be created" if [[ "${ORIGCERTPROVIDER}" = "zerossl" ]]; then REV_ACMESERVER=("https://acme.zerossl.com/v2/DV90") @@ -204,11 +206,14 @@ if [[ ! "${URL}" = "${ORIGURL}" ]] || fi # saving new variables -echo -e "ORIGURL=\"${URL}\" ORIGSUBDOMAINS=\"${SUBDOMAINS}\" ORIGONLY_SUBDOMAINS=\"${ONLY_SUBDOMAINS}\" ORIGEXTRA_DOMAINS=\"${EXTRA_DOMAINS}\" ORIGVALIDATION=\"${VALIDATION}\" ORIGDNSPLUGIN=\"${DNSPLUGIN}\" ORIGPROPAGATION=\"${PROPAGATION}\" ORIGSTAGING=\"${STAGING}\" ORIGCERTPROVIDER=\"${CERTPROVIDER}\" ORIGEMAIL=\"${EMAIL}\"" >/config/.donoteditthisfile.conf - -# Check if the cert is using the old LE root cert, revoke and regen if necessary -if [[ -f "/config/keys/letsencrypt/chain.pem" ]] && { [[ "${CERTPROVIDER}" == "letsencrypt" ]] || [[ "${CERTPROVIDER}" == "" ]]; } && [[ "${STAGING}" != "true" ]] && ! openssl x509 -in /config/keys/letsencrypt/chain.pem -noout -issuer | grep -q "ISRG Root X"; then - echo "The cert seems to be using the old LE root cert, which is no longer valid. Deleting and revoking." +echo -e "ORIGURL=\"${URL}\" ORIGSUBDOMAINS=\"${SUBDOMAINS}\" ORIGONLY_SUBDOMAINS=\"${ONLY_SUBDOMAINS}\" ORIGEXTRA_DOMAINS=\"${EXTRA_DOMAINS}\" ORIGVALIDATION=\"${VALIDATION}\" ORIGDNSPLUGIN=\"${DNSPLUGIN}\" ORIGPROPAGATION=\"${PROPAGATION}\" ORIGSTAGING=\"${STAGING}\" ORIGCERTPROVIDER=\"${CERTPROVIDER}\" ORIGEMAIL=\"${EMAIL}\" ORIGCERT_PROFILE=\"${CERT_PROFILE}\"" >/config/.donoteditthisfile.conf + +# Check if the cert is chained through the expired DST Root CA X3, revoke and regen if necessary +if [[ -f "/config/keys/letsencrypt/chain.pem" ]] && \ + { [[ "${CERTPROVIDER}" == "letsencrypt" ]] || [[ "${CERTPROVIDER}" == "" ]]; } && \ + [[ "${STAGING}" != "true" ]] && \ + openssl x509 -in /config/keys/letsencrypt/chain.pem -noout -issuer | grep -q "DST Root CA X3"; then + echo "The cert is chained through the expired DST Root CA X3. Deleting and revoking to force re-issuance." REV_ACMESERVER=("https://acme-v02.api.letsencrypt.org/directory") if [[ -f /config/etc/letsencrypt/live/"${ORIGDOMAIN}"/fullchain.pem ]]; then certbot revoke --config-dir /config/etc/letsencrypt --logs-dir /config/log/letsencrypt --work-dir /tmp/letsencrypt --config /config/etc/letsencrypt/cli.ini --non-interactive --cert-path /config/etc/letsencrypt/live/"${ORIGDOMAIN}"/fullchain.pem --server "${REV_ACMESERVER[@]}" || true @@ -239,6 +244,21 @@ fi set_ini_value "server" "${ACMESERVER}" /config/etc/letsencrypt/cli.ini +# set certificate profile (e.g. "shortlived" for 6-day certs, "classic" for 90-day) +# Profiles are a Let's Encrypt ACME feature; ZeroSSL ignores it. +if [[ -n "${CERT_PROFILE}" ]]; then + if [[ "${CERTPROVIDER}" = "zerossl" ]]; then + echo "ZeroSSL does not support ACME profiles, ignoring CERT_PROFILE variable" + sed -i "/^preferred-profile\b/d" /config/etc/letsencrypt/cli.ini + else + echo "Requesting certificate with profile: ${CERT_PROFILE}" + set_ini_value "preferred-profile" "${CERT_PROFILE}" /config/etc/letsencrypt/cli.ini + fi +else + # remove if previously set so going back to default works + sed -i "/^preferred-profile\b/d" /config/etc/letsencrypt/cli.ini +fi + # figuring out domain only vs domain & subdomains vs subdomains only DOMAINS_ARRAY=() if [[ -z "${SUBDOMAINS}" ]] || [[ "${ONLY_SUBDOMAINS}" != true ]]; then