From 371b7d49ec8ef15e2db4c530d202218027002088 Mon Sep 17 00:00:00 2001 From: aptalca Date: Thu, 10 Dec 2020 11:58:52 -0500 Subject: [PATCH] Add ZeroSSL support via CERTPROVIDER var and make donoteditthisfile.conf hidden --- README.md | 10 ++++++--- readme-vars.yml | 8 ++++--- root/etc/cont-init.d/50-config | 38 +++++++++++++++++++++++++--------- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 64b252b..0d1b849 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Find us at: [![Jenkins Build](https://img.shields.io/jenkins/build?labelColor=555555&logoColor=ffffff&style=for-the-badge&jobUrl=https%3A%2F%2Fci.linuxserver.io%2Fjob%2FDocker-Pipeline-Builders%2Fjob%2Fdocker-swag%2Fjob%2Fmaster%2F&logo=jenkins)](https://ci.linuxserver.io/job/Docker-Pipeline-Builders/job/docker-swag/job/master/) [![LSIO CI](https://img.shields.io/badge/dynamic/yaml?color=94398d&labelColor=555555&logoColor=ffffff&style=for-the-badge&label=CI&query=CI&url=https%3A%2F%2Fci-tests.linuxserver.io%2Flinuxserver%2Fswag%2Flatest%2Fci-status.yml)](https://ci-tests.linuxserver.io/linuxserver/swag/latest/index.html) -SWAG - Secure Web Application Gateway (formerly known as letsencrypt, no relation to Let's Encrypt™) sets up an Nginx webserver and reverse proxy with php support and a built-in certbot client that automates free SSL server certificate generation and renewal processes. It also contains fail2ban for intrusion prevention. +SWAG - Secure Web Application Gateway (formerly known as letsencrypt, no relation to Let's Encrypt™) sets up an Nginx webserver and reverse proxy with php support and a built-in certbot client that automates free SSL server certificate generation and renewal processes (Let's Encrypt and ZeroSSL). It also contains fail2ban for intrusion prevention. [![swag](https://github.com/linuxserver/docker-templates/raw/master/linuxserver.io/img/swag.gif)](https://linuxserver.io) @@ -81,6 +81,7 @@ services: - URL=yourdomain.url - SUBDOMAINS=www, - VALIDATION=http + - CERTPROVIDER= #optional - DNSPLUGIN=cloudflare #optional - PROPAGATION= #optional - DUCKDNSTOKEN= #optional @@ -109,6 +110,7 @@ docker run -d \ -e URL=yourdomain.url \ -e SUBDOMAINS=www, \ -e VALIDATION=http \ + -e CERTPROVIDER= `#optional` \ -e DNSPLUGIN=cloudflare `#optional` \ -e PROPAGATION= `#optional` \ -e DUCKDNSTOKEN= `#optional` \ @@ -139,10 +141,11 @@ 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 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 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 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 DNSPLUGIN=cloudflare` | Required if `VALIDATION` is set to `dns`. Options are `aliyun`, `cloudflare`, `cloudxns`, `cpanel`, `digitalocean`, `dnsimple`, `dnsmadeeasy`, `domeneshop`, `gandi`, `gehirn`, `google`, `inwx`, `linode`, `luadns`, `netcup`, `njalla`, `nsone`, `ovh`, `rfc2136`, `route53`, `sakuracloud` and `transip`. 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 | -| `-e EMAIL=` | Optional e-mail address used for cert expiration notifications. | +| `-e EMAIL=` | Optional e-mail address used for cert expiration notifications (Required for ZeroSSL). | | `-e ONLY_SUBDOMAINS=false` | If you wish to get certs only for certain subdomains, but not the main domain (main domain may be hosted on another machine and cannot be validated), set this to `true` | | `-e EXTRA_DOMAINS=` | Additional fully qualified domain names (comma separated, no spaces) ie. `extradomain.com,subdomain.anotherdomain.org,*.anotherdomain.org` | | `-e STAGING=false` | Set to `true` to retrieve certs in staging mode. Rate limits will be much higher, but the resulting cert will not pass the browser's security test. Only to be used for testing purposes. | @@ -223,7 +226,7 @@ This will *ask* Google et al not to index and list your site. Be careful with th 1. *(Easier)* Mount the container's config folder in other containers (ie. `-v /path-to-le-config:/le-ssl`) and in the other containers, use the cert location `/le-ssl/keys/letsencrypt/` 2. *(More secure)* Mount the SWAG folder `etc` that resides under `/config` in other containers (ie. `-v /path-to-le-config/etc:/le-ssl`) and in the other containers, use the cert location `/le-ssl/letsencrypt/live//` (This is more secure because the first method shares the entire SWAG config folder with other containers, including the www files, whereas the second method only shares the ssl certs) * These certs include: - 1. `cert.pem`, `chain.pem`, `fullchain.pem` and `privkey.pem`, which are generated by Let's Encrypt and used by nginx and various other apps + 1. `cert.pem`, `chain.pem`, `fullchain.pem` and `privkey.pem`, which are generated by Certbot and used by nginx and various other apps 2. `privkey.pfx`, a format supported by Microsoft and commonly used by dotnet apps such as Emby Server (no password) 3. `priv-fullchain-bundle.pem`, a pem cert that bundles the private key and the fullchain, used by apps like ZNC ### Using fail2ban @@ -323,6 +326,7 @@ Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64 ## Versions +* **10.12.20:** - Add support for getting certs from [ZeroSSL](https://zerossl.com/) via optional `CERTPROVIDER` env var. * **10.12.20:** - Add support for njalla dns validation * **09.12.20:** - Check for template/conf updates and notify in the log. Add support for gehirn and sakuracloud dns validation. * **01.11.20:** - Add support for netcup dns validation diff --git a/readme-vars.yml b/readme-vars.yml index cfcdcef..95b94e6 100755 --- a/readme-vars.yml +++ b/readme-vars.yml @@ -4,7 +4,7 @@ project_name: swag project_url: "https://linuxserver.io" project_logo: "https://github.com/linuxserver/docker-templates/raw/master/linuxserver.io/img/swag.gif" -project_blurb: "SWAG - Secure Web Application Gateway (formerly known as letsencrypt, no relation to Let's Encrypt™) sets up an Nginx webserver and reverse proxy with php support and a built-in certbot client that automates free SSL server certificate generation and renewal processes. It also contains fail2ban for intrusion prevention." +project_blurb: "SWAG - Secure Web Application Gateway (formerly known as letsencrypt, no relation to Let's Encrypt™) sets up an Nginx webserver and reverse proxy with php support and a built-in certbot client that automates free SSL server certificate generation and renewal processes (Let's Encrypt and ZeroSSL). It also contains fail2ban for intrusion prevention." project_lsio_github_repo_url: "https://github.com/linuxserver/docker-{{ project_name }}" project_blurb_optional_extras_enabled: false @@ -50,10 +50,11 @@ cap_add_param_vars: # optional container parameters opt_param_usage_include_env: true opt_param_env_vars: + - { 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: "DNSPLUGIN", env_value: "cloudflare", desc: "Required if `VALIDATION` is set to `dns`. Options are `aliyun`, `cloudflare`, `cloudxns`, `cpanel`, `digitalocean`, `dnsimple`, `dnsmadeeasy`, `domeneshop`, `gandi`, `gehirn`, `google`, `inwx`, `linode`, `luadns`, `netcup`, `njalla`, `nsone`, `ovh`, `rfc2136`, `route53`, `sakuracloud` and `transip`. 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: "DUCKDNSTOKEN", env_value: "", desc: "Required if `VALIDATION` is set to `duckdns`. Retrieve your token from https://www.duckdns.org" } - - { env_var: "EMAIL", env_value: "", desc: "Optional e-mail address used for cert expiration notifications." } + - { env_var: "EMAIL", env_value: "", desc: "Optional e-mail address used for cert expiration notifications (Required for ZeroSSL)." } - { env_var: "ONLY_SUBDOMAINS", env_value: "false", desc: "If you wish to get certs only for certain subdomains, but not the main domain (main domain may be hosted on another machine and cannot be validated), set this to `true`" } - { env_var: "EXTRA_DOMAINS", env_value: "", desc: "Additional fully qualified domain names (comma separated, no spaces) ie. `extradomain.com,subdomain.anotherdomain.org,*.anotherdomain.org`" } - { env_var: "STAGING", env_value: "false", desc: "Set to `true` to retrieve certs in staging mode. Rate limits will be much higher, but the resulting cert will not pass the browser's security test. Only to be used for testing purposes." } @@ -117,7 +118,7 @@ app_setup_block: | 1. *(Easier)* Mount the container's config folder in other containers (ie. `-v /path-to-le-config:/le-ssl`) and in the other containers, use the cert location `/le-ssl/keys/letsencrypt/` 2. *(More secure)* Mount the SWAG folder `etc` that resides under `/config` in other containers (ie. `-v /path-to-le-config/etc:/le-ssl`) and in the other containers, use the cert location `/le-ssl/letsencrypt/live//` (This is more secure because the first method shares the entire SWAG config folder with other containers, including the www files, whereas the second method only shares the ssl certs) * These certs include: - 1. `cert.pem`, `chain.pem`, `fullchain.pem` and `privkey.pem`, which are generated by Let's Encrypt and used by nginx and various other apps + 1. `cert.pem`, `chain.pem`, `fullchain.pem` and `privkey.pem`, which are generated by Certbot and used by nginx and various other apps 2. `privkey.pfx`, a format supported by Microsoft and commonly used by dotnet apps such as Emby Server (no password) 3. `priv-fullchain-bundle.pem`, a pem cert that bundles the private key and the fullchain, used by apps like ZNC ### Using fail2ban @@ -150,6 +151,7 @@ app_setup_nginx_reverse_proxy_block: "" # changelog changelogs: + - { date: "10.12.20:", desc: "Add support for getting certs from [ZeroSSL](https://zerossl.com/) via optional `CERTPROVIDER` env var." } - { date: "10.12.20:", desc: "Add support for njalla dns validation" } - { date: "09.12.20:", desc: "Check for template/conf updates and notify in the log. Add support for gehirn and sakuracloud dns validation." } - { date: "01.11.20:", desc: "Add support for netcup dns validation" } diff --git a/root/etc/cont-init.d/50-config b/root/etc/cont-init.d/50-config index 11bb247..e807168 100644 --- a/root/etc/cont-init.d/50-config +++ b/root/etc/cont-init.d/50-config @@ -10,6 +10,7 @@ SUBDOMAINS=${SUBDOMAINS}\\n\ EXTRA_DOMAINS=${EXTRA_DOMAINS}\\n\ ONLY_SUBDOMAINS=${ONLY_SUBDOMAINS}\\n\ VALIDATION=${VALIDATION}\\n\ +CERTPROVIDER=${CERTPROVIDER}\\n\ DNSPLUGIN=${DNSPLUGIN}\\n\ EMAIL=${EMAIL}\\n\ STAGING=${STAGING}\\n" @@ -20,7 +21,7 @@ if [ -n "${TEST_RUN}" ]; then fi # Sanitize variables -SANED_VARS=( DNSPLUGIN EMAIL EXTRA_DOMAINS ONLY_SUBDOMAINS STAGING SUBDOMAINS URL VALIDATION ) +SANED_VARS=( DNSPLUGIN EMAIL EXTRA_DOMAINS ONLY_SUBDOMAINS STAGING SUBDOMAINS URL VALIDATION CERTPROVIDER ) for i in "${SANED_VARS[@]}" do export echo "$i"="${!i//\"/}" @@ -98,15 +99,18 @@ fi rm /etc/crontabs/* cp /config/crontabs/* /etc/crontabs/ -# create original config file if it doesn't exist -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\"" > /config/donoteditthisfile.conf - echo "Created donoteditthisfile.conf" +# create original config file if it doesn't exist, move non-hidden legacy file to hidden +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\"" > /config/.donoteditthisfile.conf + echo "Created .donoteditthisfile.conf" fi # load original config settings # shellcheck disable=SC1091 -. /config/donoteditthisfile.conf +. /config/.donoteditthisfile.conf # set default validation to http if [ -z "$VALIDATION" ]; then @@ -114,11 +118,25 @@ if [ -z "$VALIDATION" ]; then echo "VALIDATION parameter not set; setting it to http" fi -# if staging is set to true, use the staging server -if [ "$STAGING" = "true" ]; then +# 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" + 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'])") + ACMESERVER="https://acme.zerossl.com/v2/DV90 --eab-kid ${ZEROSSL_EAB_KID} --eab-hmac-key ${ZEROSSL_EAB_HMAC_KEY}" +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" else + echo "Using Let's Encrypt as the cert provider" ACMESERVER="https://acme-v02.api.letsencrypt.org/directory" fi @@ -224,7 +242,7 @@ else fi # checking for changes in cert variables, revoking certs if necessary -if [ ! "$URL" = "$ORIGURL" ] || [ ! "$SUBDOMAINS" = "$ORIGSUBDOMAINS" ] || [ ! "$ONLY_SUBDOMAINS" = "$ORIGONLY_SUBDOMAINS" ] || [ ! "$EXTRA_DOMAINS" = "$ORIGEXTRA_DOMAINS" ] || [ ! "$VALIDATION" = "$ORIGVALIDATION" ] || [ ! "$DNSPLUGIN" = "$ORIGDNSPLUGIN" ] || [ ! "$PROPAGATION" = "$ORIGPROPAGATION" ] || [ ! "$STAGING" = "$ORIGSTAGING" ] || [ ! "$DUCKDNSTOKEN" = "$ORIGDUCKDNSTOKEN" ]; then +if [ ! "$URL" = "$ORIGURL" ] || [ ! "$SUBDOMAINS" = "$ORIGSUBDOMAINS" ] || [ ! "$ONLY_SUBDOMAINS" = "$ORIGONLY_SUBDOMAINS" ] || [ ! "$EXTRA_DOMAINS" = "$ORIGEXTRA_DOMAINS" ] || [ ! "$VALIDATION" = "$ORIGVALIDATION" ] || [ ! "$DNSPLUGIN" = "$ORIGDNSPLUGIN" ] || [ ! "$PROPAGATION" = "$ORIGPROPAGATION" ] || [ ! "$STAGING" = "$ORIGSTAGING" ] || [ ! "$DUCKDNSTOKEN" = "$ORIGDUCKDNSTOKEN" ] || [ ! "$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 [ "$ORIGONLY_SUBDOMAINS" = "true" ] && [ ! "$ORIGSUBDOMAINS" = "wildcard" ]; then ORIGDOMAIN="$(echo "$ORIGSUBDOMAINS" | tr ',' ' ' | awk '{print $1}').${ORIGURL}" @@ -237,7 +255,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\"" > /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\"" > /config/.donoteditthisfile.conf # alter extension for error message if [ "$DNSPLUGIN" = "google" ]; then