Compare commits

..

18 Commits

Author SHA1 Message Date
LinuxServer-CI
9f75c7a713 Bot Updating Package Versions 2023-07-27 14:24:01 +00:00
Eric Nemchik
262c1013aa Merge pull request #339 from linuxserver/certbot-revamp-config-file
Use config file with certbot
2023-07-27 09:20:30 -05:00
Eric Nemchik
54e4cfa047 Merge branch 'master' into certbot-revamp-config-file 2023-07-27 08:05:58 -05:00
LinuxServer-CI
97ba6a7de9 Bot Updating Package Versions 2023-07-22 03:17:29 +00:00
Eric Nemchik
ee6153c817 Merge branch 'master' into certbot-revamp-config-file 2023-07-10 18:45:22 -05:00
Eric Nemchik
d7a8d6cc6a Merge branch 'master' into certbot-revamp-config-file 2023-05-31 11:33:45 -05:00
Eric Nemchik
9d695718f0 Merge branch 'master' into certbot-revamp-config-file 2023-05-11 13:45:38 -05:00
Eric Nemchik
908571dea8 Merge branch 'master' into certbot-revamp-config-file 2023-05-07 09:17:28 -05:00
Eric Nemchik
d7e2455e7a Merge remote-tracking branch 'origin/master' into certbot-revamp-config-file 2023-04-23 08:02:46 -05:00
Eric Nemchik
ebd233860e Merge remote-tracking branch 'origin/master' into certbot-revamp-config-file 2023-03-10 15:10:35 +00:00
Eric Nemchik
5fb909d7dc Use existing EAB values for revoke
Attempt to revoke by name if cert path does not exist
2023-02-18 21:20:45 -06:00
Eric Nemchik
fd6d8764a2 Fix spelling 2023-02-18 19:40:43 -06:00
Eric Nemchik
ab7c85e4de Don't match whole line in cli.ini search for agree-tos 2023-02-18 19:35:33 -06:00
Eric Nemchik
d60847483d ensure config files exist and has at least one value set
set_ini_value does not work on empty files
2023-02-18 19:08:28 -06:00
Eric Nemchik
53bb2e284f Add descriptive comments to set_ini_value 2023-02-18 18:42:59 -06:00
Eric Nemchik
43e50ffb03 Rewrite domain handling
Use jq instead of python for ZeroSSL vars
2023-02-18 18:28:03 -06:00
Eric Nemchik
18019fb216 Adjust REV_ACMESERVER handling 2023-02-18 17:26:34 -06:00
Eric Nemchik
d57dffef82 Use config file with certbot 2023-02-18 10:05:06 -06:00
2 changed files with 97 additions and 72 deletions

View File

@@ -1,7 +1,7 @@
NAME VERSION TYPE
ConfigArgParse 1.5.5 python
PyJWT 2.7.0 python
PyYAML 6.0 python
ConfigArgParse 1.7 python
PyJWT 2.8.0 python
PyYAML 6.0.1 python
acme 2.6.0 python
alpine-baselayout 3.4.3-r1 apk
alpine-baselayout-data 3.4.3-r1 apk
@@ -21,8 +21,8 @@ azure-mgmt-core 1.4.0 python
azure-mgmt-dns 8.1.0 python
bash 5.2.15-r5 apk
beautifulsoup4 4.12.2 python
boto3 1.28.3 python
botocore 1.31.3 python
boto3 1.28.12 python
botocore 1.31.12 python
brotli-libs 1.0.9-r14 apk
bs4 0.0.1 python
busybox 1.36.1 binary
@@ -49,7 +49,7 @@ certbot-dns-domeneshop 0.2.9 python
certbot-dns-duckdns 1.3 python
certbot-dns-dynu 0.0.4 python
certbot-dns-gehirn 2.6.0 python
certbot-dns-godaddy 0.2.2 python
certbot-dns-godaddy 2.6.0 python
certbot-dns-google 2.6.0 python
certbot-dns-google-domains 0.1.11 python
certbot-dns-he 1.0.0 python
@@ -72,7 +72,7 @@ certbot-dns-standalone 1.1 python
certbot-dns-transip 0.5.2 python
certbot-dns-vultr 1.1.0 python
certbot-plugin-gandi 1.4.3 python
certifi 2023.5.7 python
certifi 2023.7.22 python
cffi 1.15.1 python
charset-normalizer 3.2.0 python
cloudflare 2.11.6 python
@@ -80,11 +80,11 @@ configobj 5.0.8 python
coreutils 9.3-r1 apk
cryptography 41.0.2 python
curl 8.1.2-r0 apk
dataclasses-json 0.5.9 python
dataclasses-json 0.5.13 python
distro 1.8.0 python
dns-lexicon 3.11.7 python
dnslib 0.9.23 python
dnspython 2.3.0 python
dnspython 2.4.1 python
domeneshop 0.4.3 python
fail2ban 1.0.2 python
fail2ban 1.0.2-r2 apk
@@ -105,7 +105,7 @@ gnupg-utils 2.4.3-r0 apk
gnupg-wks-client 2.4.3-r0 apk
gnutls 3.8.0-r2 apk
google-api-core 2.11.1 python
google-api-python-client 2.93.0 python
google-api-python-client 2.95.0 python
google-auth 2.22.0 python
google-auth-httplib2 0.1.0 python
googleapis-common-protos 1.59.1 python
@@ -134,7 +134,7 @@ libavif 0.11.1-r2 apk
libbsd 0.11.7-r1 apk
libbz2 1.0.8-r5 apk
libc-utils 0.7.2-r5 apk
libcrypto3 3.1.1-r2 apk
libcrypto3 3.1.1-r3 apk
libcurl 8.1.2-r0 apk
libdav1d 1.2.1-r0 apk
libedit 20221030.3.1-r1 apk
@@ -166,7 +166,7 @@ libsasl 2.1.28-r4 apk
libseccomp 2.5.4-r2 apk
libsm 1.2.4-r1 apk
libsodium 1.0.18-r3 apk
libssl3 3.1.1-r2 apk
libssl3 3.1.1-r3 apk
libstdc++ 12.2.1_git20220924-r10 apk
libtasn1 4.19.0-r1 apk
libunistring 1.1-r1 apk
@@ -187,13 +187,12 @@ logrotate 3.21.0-r1 apk
loopialib 0.2.0 python
lxml 4.9.3 python
lz4-libs 1.9.4-r4 apk
marshmallow 3.19.0 python
marshmallow-enum 1.5.1 python
marshmallow 3.20.1 python
memcached 1.6.21 binary
memcached 1.6.21-r0 apk
mock 5.1.0 python
mpdecimal 2.5.1-r2 apk
msal 1.22.0 python
msal 1.23.0 python
msal-extensions 1.0.0 python
musl 1.2.4-r0 apk
musl-utils 1.2.4-r0 apk
@@ -224,7 +223,7 @@ nginx-mod-stream-geoip2 1.24.0-r6 apk
nginx-vim 1.24.0-r6 apk
npth 1.6-r4 apk
oniguruma 6.9.8-r1 apk
openssl 3.1.1-r2 apk
openssl 3.1.1-r3 apk
p11-kit 0.24.1-r2 apk
packaging 23.1 python
parsedatetime 2.6 python
@@ -285,7 +284,7 @@ php82-xmlwriter 8.2.8-r0 apk
php82-xsl 8.2.8-r0 apk
php82-zip 8.2.8-r0 apk
pinentry 1.2.1-r1 apk
pip 23.1.2 python
pip 23.2.1 python
pkb-client 1.2 python
popt 1.19-r2 apk
portalocker 2.7.0 python
@@ -331,7 +330,7 @@ unixodbc 2.3.11-r2 apk
uritemplate 4.1.1 python
urllib3 1.26.16 python
utmps-libs 0.1.2.1-r1 apk
wheel 0.40.0 python
wheel 0.41.0 python
whois 5.5.17-r0 apk
xz-libs 5.4.3-r0 apk
zipp 3.16.2 python

View File

@@ -29,6 +29,23 @@ if [[ "${VALIDATION}" = "dns" ]] && [[ ! "${DNSPLUGIN}" =~ ^(acmedns|aliyun|azur
sleep infinity
fi
# set_ini_value logic:
# - if the name is not found in the file, append the name=value to the end of the file
# - if the name is found in the file, replace the value
# - if the name is found in the file but commented out, uncomment the line and replace the value
# call set_ini_value with parameters: $1=name $2=value $3=file
function set_ini_value() {
name=${1//\//\\/}
value=${2//\//\\/}
sed -i \
-e '/^#\?\(\s*'"${name}"'\s*=\s*\).*/{s//\1'"${value}"'/;:a;n;ba;q}' \
-e '$a'"${name}"'='"${value}" "${3}"
}
# ensure config files exist and has at least one value set (set_ini_value does not work on empty files)
touch /config/etc/letsencrypt/cli.ini
grep -qF 'agree-tos' /config/etc/letsencrypt/cli.ini || echo 'agree-tos=true' >>/config/etc/letsencrypt/cli.ini
# copy dns default configs
cp -n /defaults/dns-conf/* /config/dns-conf/ 2> >(grep -v 'cp: not replacing')
lsiown -R abc:abc /config/dns-conf
@@ -157,21 +174,25 @@ if [[ ! "${URL}" = "${ORIGURL}" ]] ||
[[ ! "${CERTPROVIDER}" = "${ORIGCERTPROVIDER}" ]]; 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" ]] && [[ -n "${ORIGEMAIL}" ]]; then
REV_EAB_CREDS=$(curl -s https://api.zerossl.com/acme/eab-credentials-email --data "email=${ORIGEMAIL}")
REV_ZEROSSL_EAB_KID=$(echo "${REV_EAB_CREDS}" | python3 -c "import sys, json; print(json.load(sys.stdin)['eab_kid'])")
REV_ZEROSSL_EAB_HMAC_KEY=$(echo "${REV_EAB_CREDS}" | python3 -c "import sys, json; print(json.load(sys.stdin)['eab_hmac_key'])")
REV_ACMESERVER=("https://acme.zerossl.com/v2/DV90")
REV_ZEROSSL_EAB_KID=$(awk -F "=" '/eab-kid/ {print $2}' "/config/etc/letsencrypt/renewal/${ORIGDOMAIN}.conf" | tr -d ' ')
REV_ZEROSSL_EAB_HMAC_KEY=$(awk -F "=" '/eab-hmac-key/ {print $2}' "/config/etc/letsencrypt/renewal/${ORIGDOMAIN}.conf" | tr -d ' ')
if [[ -z "${REV_ZEROSSL_EAB_KID}" ]] || [[ -z "${REV_ZEROSSL_EAB_HMAC_KEY}" ]]; then
echo "Unable to retrieve EAB credentials from ZeroSSL. Check the outgoing connections to api.zerossl.com and dns. Sleeping."
sleep infinity
REV_ZEROSSL_EAB_KID=$(awk -F "=" '/eab-kid/ {print $2}' /config/etc/letsencrypt/cli.ini | tr -d ' ')
REV_ZEROSSL_EAB_HMAC_KEY=$(awk -F "=" '/eab-hmac-key/ {print $2}' /config/etc/letsencrypt/cli.ini | tr -d ' ')
fi
if [[ -n "${REV_ZEROSSL_EAB_KID}" ]] && [[ -n "${REV_ZEROSSL_EAB_HMAC_KEY}" ]]; then
REV_ACMESERVER+=("--eab-kid" "${REV_ZEROSSL_EAB_KID}" "--eab-hmac-key" "${REV_ZEROSSL_EAB_HMAC_KEY}")
fi
REV_ACMESERVER="https://acme.zerossl.com/v2/DV90 --eab-kid ${REV_ZEROSSL_EAB_KID} --eab-hmac-key ${REV_ZEROSSL_EAB_HMAC_KEY}"
elif [[ "${ORIGSTAGING}" = "true" ]]; then
REV_ACMESERVER="https://acme-staging-v02.api.letsencrypt.org/directory"
REV_ACMESERVER=("https://acme-staging-v02.api.letsencrypt.org/directory")
else
REV_ACMESERVER="https://acme-v02.api.letsencrypt.org/directory"
REV_ACMESERVER=("https://acme-v02.api.letsencrypt.org/directory")
fi
if [[ -f /config/etc/letsencrypt/live/"${ORIGDOMAIN}"/fullchain.pem ]]; then
certbot revoke --non-interactive --cert-path /config/etc/letsencrypt/live/"${ORIGDOMAIN}"/fullchain.pem --server ${REV_ACMESERVER} || true
certbot revoke --non-interactive --cert-path /config/etc/letsencrypt/live/"${ORIGDOMAIN}"/fullchain.pem --server "${REV_ACMESERVER[@]}" || true
else
certbot revoke --non-interactive --cert-name "${ORIGDOMAIN}" --server "${REV_ACMESERVER[@]}" || true
fi
rm -rf /config/etc/letsencrypt/{accounts,archive,live,renewal}
fi
@@ -182,9 +203,11 @@ echo -e "ORIGURL=\"${URL}\" ORIGSUBDOMAINS=\"${SUBDOMAINS}\" ORIGONLY_SUBDOMAINS
# 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."
REV_ACMESERVER="https://acme-v02.api.letsencrypt.org/directory"
REV_ACMESERVER=("https://acme-v02.api.letsencrypt.org/directory")
if [[ -f /config/etc/letsencrypt/live/"${ORIGDOMAIN}"/fullchain.pem ]]; then
certbot revoke --non-interactive --cert-path /config/etc/letsencrypt/live/"${ORIGDOMAIN}"/fullchain.pem --server ${REV_ACMESERVER} || true
certbot revoke --non-interactive --cert-path /config/etc/letsencrypt/live/"${ORIGDOMAIN}"/fullchain.pem --server "${REV_ACMESERVER[@]}" || true
else
certbot revoke --non-interactive --cert-name "${ORIGDOMAIN}" --server "${REV_ACMESERVER[@]}" || true
fi
rm -rf /config/etc/letsencrypt/{accounts,archive,live,renewal}
fi
@@ -208,52 +231,51 @@ else
ACMESERVER="https://acme-v02.api.letsencrypt.org/directory"
fi
# figuring out url only vs url & subdomains vs subdomains only
set_ini_value "server" "${ACMESERVER}" /config/etc/letsencrypt/cli.ini
# figuring out domain only vs domain & subdomains vs subdomains only
DOMAINS_ARRAY=()
if [[ -z "${SUBDOMAINS}" ]] || [[ "${ONLY_SUBDOMAINS}" != true ]]; then
DOMAINS_ARRAY+=("${URL}")
fi
if [[ -n "${SUBDOMAINS}" ]]; then
echo "SUBDOMAINS entered, processing"
SUBDOMAINS_ARRAY=()
if [[ "${SUBDOMAINS}" = "wildcard" ]]; then
if [[ "${ONLY_SUBDOMAINS}" = true ]]; then
export URL_REAL="-d *.${URL}"
echo "Wildcard cert for only the subdomains of ${URL} will be requested"
else
export URL_REAL="-d *.${URL} -d ${URL}"
echo "Wildcard cert for ${URL} will be requested"
fi
SUBDOMAINS_ARRAY+=("*.${URL}")
echo "Wildcard cert for ${URL} will be requested"
else
echo "SUBDOMAINS entered, processing"
for job in $(echo "${SUBDOMAINS}" | tr "," " "); do
export SUBDOMAINS_REAL="${SUBDOMAINS_REAL} -d ${job}.${URL}"
SUBDOMAINS_ARRAY+=("${job}.${URL}")
done
if [[ "${ONLY_SUBDOMAINS}" = true ]]; then
URL_REAL="${SUBDOMAINS_REAL}"
echo "Only subdomains, no URL in cert"
else
URL_REAL="-d ${URL}${SUBDOMAINS_REAL}"
fi
echo "Sub-domains processed are: ${SUBDOMAINS_REAL}"
echo "Sub-domains processed are: $(echo "${SUBDOMAINS_ARRAY[*]}" | tr " " ",")"
fi
else
echo "No subdomains defined"
URL_REAL="-d ${URL}"
DOMAINS_ARRAY+=("${SUBDOMAINS_ARRAY[@]}")
fi
# add extra domains
if [[ -n "${EXTRA_DOMAINS}" ]]; then
echo "EXTRA_DOMAINS entered, processing"
EXTRA_DOMAINS_ARRAY=()
for job in $(echo "${EXTRA_DOMAINS}" | tr "," " "); do
export EXTRA_DOMAINS_REAL="${EXTRA_DOMAINS_REAL} -d ${job}"
EXTRA_DOMAINS_ARRAY+=("${job}")
done
echo "Extra domains processed are: ${EXTRA_DOMAINS_REAL}"
URL_REAL="${URL_REAL} ${EXTRA_DOMAINS_REAL}"
echo "Extra domains processed are: $(echo "${EXTRA_DOMAINS_ARRAY[*]}" | tr " " ",")"
DOMAINS_ARRAY+=("${EXTRA_DOMAINS_ARRAY[@]}")
fi
# setting domains in cli.ini
set_ini_value "domains" "$(echo "${DOMAINS_ARRAY[*]}" | tr " " ",")" /config/etc/letsencrypt/cli.ini
# figuring out whether to use e-mail and which
if [[ ${EMAIL} == *@* ]]; then
echo "E-mail address entered: ${EMAIL}"
EMAILPARAM="-m ${EMAIL} --no-eff-email"
set_ini_value "email" "${EMAIL}" /config/etc/letsencrypt/cli.ini
set_ini_value "no-eff-email" "true" /config/etc/letsencrypt/cli.ini
set_ini_value "register-unsafely-without-email" "false" /config/etc/letsencrypt/cli.ini
else
echo "No e-mail address entered or address invalid"
EMAILPARAM="--register-unsafely-without-email"
set_ini_value "register-unsafely-without-email" "true" /config/etc/letsencrypt/cli.ini
fi
# alter extension for error message
@@ -265,37 +287,41 @@ fi
# setting the validation method to use
if [[ "${VALIDATION}" = "dns" ]]; then
AUTHENTICATORPARAM="--authenticator dns-${DNSPLUGIN}"
DNSCREDENTIALSPARAM="--dns-${DNSPLUGIN}-credentials ${DNSCREDENTIALFILE}"
if [[ -n "${PROPAGATION}" ]]; then PROPAGATIONPARAM="--dns-${DNSPLUGIN}-propagation-seconds ${PROPAGATION}"; fi
set_ini_value "preferred-challenges" "dns" /config/etc/letsencrypt/cli.ini
set_ini_value "authenticator" "dns-${DNSPLUGIN}" /config/etc/letsencrypt/cli.ini
set_ini_value "dns-${DNSPLUGIN}-credentials" "${DNSCREDENTIALFILE}" /config/etc/letsencrypt/cli.ini
if [[ -n "${PROPAGATION}" ]]; then set_ini_value "dns-${DNSPLUGIN}-propagation-seconds" "${PROPAGATION}" /config/etc/letsencrypt/cli.ini; fi
# plugins that don't support setting credentials file
if [[ "${DNSPLUGIN}" =~ ^(route53|standalone)$ ]]; then
DNSCREDENTIALSPARAM=""
sed "/^dns-${DNSPLUGIN}-credentials /d" /config/etc/letsencrypt/cli.ini
fi
# plugins that don't support setting propagation
if [[ "${DNSPLUGIN}" =~ ^(azure|gandi|route53|standalone)$ ]]; then
if [[ -n "${PROPAGATION}" ]]; then echo "${DNSPLUGIN} dns plugin does not support setting propagation time"; fi
PROPAGATIONPARAM=""
sed "/^dns-${DNSPLUGIN}-propagation-seconds /d" /config/etc/letsencrypt/cli.ini
fi
# plugins that use old parameter naming convention
if [[ "${DNSPLUGIN}" =~ ^(cpanel)$ ]]; then
AUTHENTICATORPARAM="--authenticator ${DNSPLUGIN}"
DNSCREDENTIALSPARAM="--${DNSPLUGIN}-credentials ${DNSCREDENTIALFILE}"
if [[ -n "${PROPAGATION}" ]]; then PROPAGATIONPARAM="--${DNSPLUGIN}-propagation-seconds ${PROPAGATION}"; fi
if [[ "${DNSPLUGIN}" =~ ^(cpanel|directadmin)$ ]]; then
sed "/^dns-${DNSPLUGIN}-credentials /d" /config/etc/letsencrypt/cli.ini
sed "/^dns-${DNSPLUGIN}-propagation-seconds /d" /config/etc/letsencrypt/cli.ini
set_ini_value "authenticator" "${DNSPLUGIN}" /config/etc/letsencrypt/cli.ini
set_ini_value "${DNSPLUGIN}-credentials" "${DNSCREDENTIALFILE}" /config/etc/letsencrypt/cli.ini
if [[ -n "${PROPAGATION}" ]]; then set_ini_value "${DNSPLUGIN}-propagation-seconds" "${PROPAGATION}" /config/etc/letsencrypt/cli.ini; fi
fi
# don't restore txt records when using DuckDNS plugin
if [[ "${DNSPLUGIN}" =~ ^(duckdns)$ ]]; then
AUTHENTICATORPARAM="${AUTHENTICATORPARAM} --dns-${DNSPLUGIN}-no-txt-restore"
set_ini_value "dns-${DNSPLUGIN}-no-txt-restore" "true" /config/etc/letsencrypt/cli.ini
fi
PREFCHAL="${AUTHENTICATORPARAM} ${DNSCREDENTIALSPARAM} ${PROPAGATIONPARAM}"
echo "${VALIDATION} validation via ${DNSPLUGIN} plugin is selected"
elif [[ "${VALIDATION}" = "tls-sni" ]]; then
PREFCHAL="--standalone --preferred-challenges http"
set_ini_value "preferred-challenges" "http" /config/etc/letsencrypt/cli.ini
set_ini_value "authenticator" "standalone" /config/etc/letsencrypt/cli.ini
echo "*****tls-sni validation has been deprecated, attempting http validation instead"
else
PREFCHAL="--standalone --preferred-challenges http"
set_ini_value "preferred-challenges" "http" /config/etc/letsencrypt/cli.ini
set_ini_value "authenticator" "standalone" /config/etc/letsencrypt/cli.ini
echo "http validation is selected"
fi
@@ -304,17 +330,17 @@ if [[ ! -f "/config/keys/letsencrypt/fullchain.pem" ]]; then
if [[ "${CERTPROVIDER}" = "zerossl" ]] && [[ -n "${EMAIL}" ]]; then
echo "Retrieving EAB from ZeroSSL"
EAB_CREDS=$(curl -s https://api.zerossl.com/acme/eab-credentials-email --data "email=${EMAIL}")
ZEROSSL_EAB_KID=$(echo "${EAB_CREDS}" | python3 -c "import sys, json; print(json.load(sys.stdin)['eab_kid'])")
ZEROSSL_EAB_HMAC_KEY=$(echo "${EAB_CREDS}" | python3 -c "import sys, json; print(json.load(sys.stdin)['eab_hmac_key'])")
ZEROSSL_EAB_KID=$(echo "${EAB_CREDS}" | jq .eab_kid)
ZEROSSL_EAB_HMAC_KEY=$(echo "${EAB_CREDS}" | jq .eab_hmac_key)
if [[ -z "${ZEROSSL_EAB_KID}" ]] || [[ -z "${ZEROSSL_EAB_HMAC_KEY}" ]]; then
echo "Unable to retrieve EAB credentials from ZeroSSL. Check the outgoing connections to api.zerossl.com and dns. Sleeping."
sleep infinity
fi
ZEROSSL_EAB="--eab-kid ${ZEROSSL_EAB_KID} --eab-hmac-key ${ZEROSSL_EAB_HMAC_KEY}"
set_ini_value "eab-kid" "${ZEROSSL_EAB_KID}" /config/etc/letsencrypt/cli.ini
set_ini_value "eab-hmac-key" "${ZEROSSL_EAB_HMAC_KEY}" /config/etc/letsencrypt/cli.ini
fi
echo "Generating new certificate"
# shellcheck disable=SC2086
certbot certonly --non-interactive --renew-by-default --server ${ACMESERVER} ${ZEROSSL_EAB} ${PREFCHAL} --rsa-key-size 4096 ${EMAILPARAM} --agree-tos ${URL_REAL}
certbot certonly --non-interactive --renew-by-default
if [[ ! -d /config/keys/letsencrypt ]]; then
if [[ "${VALIDATION}" = "dns" ]]; then
echo "ERROR: Cert does not exist! Please see the validation error above. Make sure you entered correct credentials into the ${DNSCREDENTIALFILE} file."