Skip to content

Commit

Permalink
Allow custom ACME server (Draft fix of linuxserver#186)
Browse files Browse the repository at this point in the history
  • Loading branch information
tashian committed Jan 11, 2022
1 parent 08d0680 commit fd8e877
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 21 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,8 @@ services:
- VALIDATION=http
- SUBDOMAINS=www, #optional
- CERTPROVIDER= #optional
- ACMESERVER= #optional
- ACMECABUNDLE= #optional
- DNSPLUGIN=cloudflare #optional
- PROPAGATION= #optional
- DUCKDNSTOKEN= #optional
Expand Down Expand Up @@ -183,6 +185,8 @@ docker run -d \
-e VALIDATION=http \
-e SUBDOMAINS=www, `#optional` \
-e CERTPROVIDER= `#optional` \
-e ACMESERVER= `#optional` \
-e ACMECABUNDLE= `#optional` \
-e DNSPLUGIN=cloudflare `#optional` \
-e PROPAGATION= `#optional` \
-e DUCKDNSTOKEN= `#optional` \
Expand Down Expand Up @@ -211,7 +215,9 @@ Container images are configured using parameters passed at runtime (such as thos
| `-e URL=yourdomain.url` | Top url you have control over (`customdomain.com` if you own it, or `customsubdomain.ddnsprovider.com` if dynamic dns). |
| `-e VALIDATION=http` | Certbot validation method to use, options are `http`, `dns` or `duckdns` (`dns` method also requires `DNSPLUGIN` variable set) (`duckdns` method requires `DUCKDNSTOKEN` variable set, and the `SUBDOMAINS` variable must be either empty or set to `wildcard`). |
| `-e SUBDOMAINS=www,` | 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` and `duckdns` validation only) |
| `-e CERTPROVIDER=` | 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. |
| `-e CERTPROVIDER=` | 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). Set to `custom` to use a custom ACME server. Defaults to Let's Encrypt unless `ACMESERVER` is set. |
| `-e ACMESERVER=` | The URL of a custom ACME server to use. |
| `-e ACMECABUNDLE=` | A base64-encoded PEM file containing a CA bundle to trust, for use with an internal ACME CA. Required for a custom ACME CA. |
| `-e DNSPLUGIN=cloudflare` | Required if `VALIDATION` is set to `dns`. Options are `aliyun`, `cloudflare`, `cloudxns`, `cpanel`, `desec`, `digitalocean`, `directadmin`, `dnsimple`, `dnsmadeeasy`, `dnspod`, `domeneshop`, `gandi`, `gehirn`, `google`, `he`, `hetzner`, `infomaniak`, `inwx`, `ionos`, `linode`, `luadns`, `netcup`, `njalla`, `nsone`, `ovh`, `rfc2136`, `route53`, `sakuracloud`, `transip` and `vultr`. Also need to enter the credentials into the corresponding ini (or json for some plugins) file under `/config/dns-conf`. |
| `-e PROPAGATION=` | Optionally override (in seconds) the default propagation time for the dns plugins. |
| `-e DUCKDNSTOKEN=` | Required if `VALIDATION` is set to `duckdns`. Retrieve your token from https://www.duckdns.org |
Expand Down
5 changes: 5 additions & 0 deletions root/app/le-renew.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ echo
echo "<------------------------------------------------->"
echo "cronjob running on "$(date)
echo "Running certbot renew"

if [ -f "/config/cabundle.pem" ]; then
export REQUESTS_CA_BUNDLE="/config/cabundle.pem"
fi

if [ "$ORIGVALIDATION" = "dns" ] || [ "$ORIGVALIDATION" = "duckdns" ]; then
certbot -n renew \
--post-hook "if ps aux | grep [n]ginx: > /dev/null; then s6-svc -h /var/run/s6/services/nginx; fi; \
Expand Down
54 changes: 34 additions & 20 deletions root/etc/cont-init.d/50-config
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ EXTRA_DOMAINS=${EXTRA_DOMAINS}\\n\
ONLY_SUBDOMAINS=${ONLY_SUBDOMAINS}\\n\
VALIDATION=${VALIDATION}\\n\
CERTPROVIDER=${CERTPROVIDER}\\n\
ACMESERVER=${ACMESERVER}\\n\
ACMECABUNDLE=${ACMECABUNDLE}\\n\
DNSPLUGIN=${DNSPLUGIN}\\n\
EMAIL=${EMAIL}\\n\
STAGING=${STAGING}\\n"
Expand All @@ -21,7 +23,7 @@ if [ -n "${TEST_RUN}" ]; then
fi

# 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 ACMESERVER ACMECABUNDLE )
for i in "${SANED_VARS[@]}"
do
export echo "$i"="${!i//\"/}"
Expand Down Expand Up @@ -133,7 +135,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\" ORIGDUCKDNSTOKEN=\"$DUCKDNSTOKEN\" 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\" ORIGDUCKDNSTOKEN=\"$DUCKDNSTOKEN\" ORIGCERTPROVIDER=\"$CERTPROVIDER\" ORIGACMESERVER=\"$ACMESERVER\" ORIGACMECABUNDLE=\"$ACMECABUNDLE\" ORIGEMAIL=\"$EMAIL\"" > /config/.donoteditthisfile.conf
echo "Created .donoteditthisfile.conf"
fi

Expand All @@ -147,23 +149,35 @@ if [ -z "$VALIDATION" ]; then
echo "VALIDATION parameter not set; setting it to http"
fi

# if zerossl is selected or staging is set to true, use the relevant server
if [ "$CERTPROVIDER" = "zerossl" ] && [ "$STAGING" = "true" ]; then
echo "ZeroSSL does not support staging mode, ignoring STAGING variable"
fi
if [ "$CERTPROVIDER" = "zerossl" ] && [ -n "$EMAIL" ]; then
echo "ZeroSSL is selected as the cert provider, registering cert with $EMAIL"
ACMESERVER="https://acme.zerossl.com/v2/DV90"
elif [ "$CERTPROVIDER" = "zerossl" ] && [ -z "$EMAIL" ]; then
echo "ZeroSSL is selected as the cert provider, but the e-mail address has not been entered. Please visit https://zerossl.com, register a new account and set the account e-mail address in the EMAIL environment variable"
sleep infinity
elif [ "$STAGING" = "true" ]; then
echo "NOTICE: Staging is active"
echo "Using Let's Encrypt as the cert provider"
ACMESERVER="https://acme-staging-v02.api.letsencrypt.org/directory"
# Choose the relevant CA server
if [ -n "$ACMESERVER" ]; then
if [ -z "$EMAIL" ]; then
echo 'A custom $ACMESERVER URL requires an account $EMAIL to be supplied'
sleep infinity
fi
echo "Using $ACMESERVER as the cert provider; registering cert with $EMAIL"
elif [ "$CERTPROVIDER" = "zerossl" ]; then
ACMESERVER="https://acme.zerossl.com/v2/DV90"
if [ "$STAGING" = "true" ]; then
echo "ZeroSSL cert provider does not support staging mode, ignoring STAGING variable"
fi
if [ -z "$EMAIL" ]; then
echo "ZeroSSL is selected as the cert provider, but the e-mail address has not been entered. Please visit https://zerossl.com, register a new account and set the account e-mail address in the EMAIL environment variable"
sleep infinity
fi
echo "Using ZeroSSL as the cert provider; registering cert with $EMAIL"
else
echo "Using Let's Encrypt as the cert provider"
ACMESERVER="https://acme-v02.api.letsencrypt.org/directory"
if [ "$STAGING" = "true" ]; then
echo "NOTICE: Staging is active"
ACMESERVER="https://acme-staging-v02.api.letsencrypt.org/directory"
else
ACMESERVER="https://acme-v02.api.letsencrypt.org/directory"
fi
echo "Using Let's Encrypt as the cert provider"
fi

if [ -n "$ACMECABUNDLE" ]; then
echo "$ACMECABUNDLE" | base64 -d - > /config/cabundle.pem
fi

# figuring out url only vs url & subdomains vs subdomains only
Expand Down Expand Up @@ -301,7 +315,7 @@ if [ ! "$URL" = "$ORIGURL" ] || [ ! "$SUBDOMAINS" = "$ORIGSUBDOMAINS" ] || [ ! "
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\" ORIGDUCKDNSTOKEN=\"$DUCKDNSTOKEN\" 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\" ORIGDUCKDNSTOKEN=\"$DUCKDNSTOKEN\" ORIGCERTPROVIDER=\"$CERTPROVIDER\" ORIGACMESERVER=\"$ACMESERVER\" ORIGACMECABUNDLE=\"$ACMECABUNDLE\" ORIGEMAIL=\"$EMAIL\"" > /config/.donoteditthisfile.conf

# alter extension for error message
if [ "$DNSPLUGIN" = "google" ]; then
Expand All @@ -311,7 +325,7 @@ else
fi

# 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
if [ -f "/config/keys/letsencrypt/chain.pem" ] && ([ "${CERTPROVIDER}" = "letsencrypt" ] || ([ "${CERTPROVIDER}" = "" ] && [ -z "$ACMECABUNDLE" ])) && [ "${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"
certbot revoke --non-interactive --cert-path /config/etc/letsencrypt/live/"$ORIGDOMAIN"/fullchain.pem --server $REV_ACMESERVER
Expand Down

0 comments on commit fd8e877

Please sign in to comment.