diff --git a/Dockerfile b/Dockerfile index b829a5f..0213595 100755 --- a/Dockerfile +++ b/Dockerfile @@ -121,6 +121,7 @@ RUN \ certbot-dns-linode \ certbot-dns-loopia \ certbot-dns-luadns \ + certbot-dns-mijn-host \ certbot-dns-namecheap \ certbot-dns-netcup \ certbot-dns-njalla \ diff --git a/Dockerfile.aarch64 b/Dockerfile.aarch64 index fdb4c9d..aeaf4cd 100755 --- a/Dockerfile.aarch64 +++ b/Dockerfile.aarch64 @@ -121,6 +121,7 @@ RUN \ certbot-dns-linode \ certbot-dns-loopia \ certbot-dns-luadns \ + certbot-dns-mijn-host \ certbot-dns-namecheap \ certbot-dns-netcup \ certbot-dns-njalla \ diff --git a/Jenkinsfile b/Jenkinsfile index a8021da..e31d35d 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -77,6 +77,7 @@ pipeline { script{ env.EXIT_STATUS = '' env.CI_TEST_ATTEMPTED = '' + env.PUSH_ATTEMPTED = '' env.LS_RELEASE = sh( script: '''docker run --rm quay.io/skopeo/stable:v1 inspect docker://ghcr.io/${LS_USER}/${CONTAINER_NAME}:latest 2>/dev/null | jq -r '.Labels.build_version' | awk '{print $3}' | grep '\\-ls' || : ''', returnStdout: true).trim() @@ -925,6 +926,9 @@ pipeline { environment name: 'EXIT_STATUS', value: '' } steps { + script{ + env.PUSH_ATTEMPTED = 'true' + } retry_backoff(5,5) { sh '''#! /bin/bash set -e @@ -954,11 +958,18 @@ pipeline { environment name: 'EXIT_STATUS', value: '' } steps { + script{ + env.PUSH_ATTEMPTED = 'true' + } retry_backoff(5,5) { sh '''#! /bin/bash set -e for MANIFESTIMAGE in "${IMAGE}" "${GITLABIMAGE}" "${GITHUBIMAGE}" "${QUAYIMAGE}"; do - [[ ${MANIFESTIMAGE%%/*} =~ \\. ]] && MANIFESTIMAGEPLUS="${MANIFESTIMAGE}" || MANIFESTIMAGEPLUS="docker.io/${MANIFESTIMAGE}" + if [[ "${MANIFESTIMAGE%%/*}" =~ \\. ]]; then + MANIFESTIMAGEPLUS="${MANIFESTIMAGE}" + else + MANIFESTIMAGEPLUS="docker.io/${MANIFESTIMAGE}" + fi IFS=',' read -ra CACHE <<< "$BUILDCACHE" for i in "${CACHE[@]}"; do if [[ "${MANIFESTIMAGEPLUS}" == "$(cut -d "/" -f1 <<< ${i})"* ]]; then @@ -1126,7 +1137,7 @@ EOF } script { if (env.GITHUBIMAGE =~ /lspipepr/){ - if (env.CI_TEST_ATTEMPTED == "true"){ + if (env.CI_TEST_ATTEMPTED == "true" || env.PUSH_ATTEMPTED == "true"){ sh '''#! /bin/bash # Function to retrieve JSON data from URL get_json() { @@ -1187,14 +1198,21 @@ EOF curl -X POST -H "Authorization: token $GITHUB_TOKEN" \ -H "Accept: application/vnd.github.v3+json" \ "https://api.github.com/repos/$LS_USER/$LS_REPO/issues/$PULL_REQUEST/comments" \ - -d "{\\"body\\": \\"I am a bot, here are the test results for this PR: \\n${CI_URL}\\n${SHELLCHECK_URL}\\n${table}\\"}" + -d "{\\"body\\": \\"I am a bot, here are the test results for this PR for commit ${COMMIT_SHA:0:7} : \\n${CI_URL}\\n${SHELLCHECK_URL}\\n${table}\\"}" else curl -X POST -H "Authorization: token $GITHUB_TOKEN" \ -H "Accept: application/vnd.github.v3+json" \ "https://api.github.com/repos/$LS_USER/$LS_REPO/issues/$PULL_REQUEST/comments" \ - -d "{\\"body\\": \\"I am a bot, here is the pushed image/manifest for this PR: \\n\\n\\`${GITHUBIMAGE}:${META_TAG}\\`\\"}" + -d "{\\"body\\": \\"I am a bot, here is the pushed image/manifest for this PR for commit ${COMMIT_SHA:0:7} : \\n\\n\\`${GITHUBIMAGE}:${META_TAG}\\`\\"}" fi ''' + } else { + sh '''#! /bin/bash + curl -X POST -H "Authorization: token $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + "https://api.github.com/repos/$LS_USER/$LS_REPO/issues/$PULL_REQUEST/comments" \ + -d "{\\"body\\": \\"I am a bot, the build for PR commit ${COMMIT_SHA:0:7} failed and as a result no CI test was attempted and no images were pushed.\\"}" + ''' } } } diff --git a/README.md b/README.md index a4e8e71..d039eb6 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ The architectures supported by this image are: 2. Certs that cover sub-subdomains of your main subdomain (ie. `*.yoursubdomain.duckdns.org`, set the `SUBDOMAINS` variable to `wildcard`) * `--cap-add=NET_ADMIN` is required for fail2ban to modify iptables * After setup, navigate to `https://example.com` to access the default homepage (http access through port 80 is disabled by default, you can enable it by editing the default site config at `/config/nginx/site-confs/default.conf`). -* Certs are checked nightly and if expiration is within 30 days, renewal is attempted. If your cert is about to expire in less than 30 days, check the logs under `/config/log/letsencrypt` to see why the renewals have been failing. It is recommended to input your e-mail in docker parameters so you receive expiration notices from Let's Encrypt in those circumstances. +* Certs are checked twice daily using ACME Renewal Information (ARI) to determine the optimal renewal window. If your cert is about to expire, check the logs under `/config/log/letsencrypt` to see why the renewals have been failing. ### Certbot Plugins @@ -190,6 +190,7 @@ services: - VALIDATION=http - SUBDOMAINS=www, #optional - CERTPROVIDER= #optional + - CERT_PROFILE= #optional - DNSPLUGIN=cloudflare #optional - PROPAGATION= #optional - EMAIL= #optional @@ -221,6 +222,7 @@ docker run -d \ -e VALIDATION=http \ -e SUBDOMAINS=www, `#optional` \ -e CERTPROVIDER= `#optional` \ + -e CERT_PROFILE= `#optional` \ -e DNSPLUGIN=cloudflare `#optional` \ -e PROPAGATION= `#optional` \ -e EMAIL= `#optional` \ @@ -254,7 +256,8 @@ Containers are configured using parameters passed at runtime (such as those abov | `-e VALIDATION=http` | Certbot validation method to use, options are `http` or `dns` (`dns` method also requires `DNSPLUGIN` variable set). | | `-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` 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 DNSPLUGIN=cloudflare` | 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`. | +| `-e CERT_PROFILE=` | 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/ | +| `-e DNSPLUGIN=cloudflare` | 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`, `mijn-host`, `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`. | | `-e PROPAGATION=` | Optionally override (in seconds) the default propagation time for the dns plugins. | | `-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` | @@ -433,6 +436,9 @@ Once registered you can define the dockerfile to use with `-f Dockerfile.aarch64 ## Versions +* **10.07.26:** - Add support for Let's Encrypt cert profiles. Run certbot twice daily with a random delay. +* **19.06.26:** - Add support for mijn.host dns validation. +* **01.06.26:** - Remove obsolete old cert check logic. * **23.01.26:** - Reorder init to fix proxy conf version checks. * **21.12.25:** - Add support for hetzner-cloud dns validation. * **04.11.25:** - Switch default Gandi credentials from API Key to Token, allow DNS propagation time for Azure DNS plugin. diff --git a/package_versions.txt b/package_versions.txt index caf90dc..5b34729 100755 --- a/package_versions.txt +++ b/package_versions.txt @@ -1,50 +1,51 @@ NAME VERSION TYPE Simple Launcher 1.1.0.14 binary (+5 duplicates) acl-libs 2.3.2-r1 apk -acme 5.5.0 python +acme 5.6.0 python alpine-baselayout 3.7.0-r0 apk alpine-baselayout-data 3.7.0-r0 apk alpine-keys 2.5-r0 apk -alpine-release 3.22.3-r0 apk +alpine-release 3.22.5-r0 apk +annotated-types 0.7.0 python +anyio 4.14.1 python aom-libs 3.12.1-r0 apk -apache2-utils 2.4.66-r0 apk -apk-tools 2.14.9-r3 apk +apache2-utils 2.4.68-r0 apk +apk-tools 2.14.10-r0 apk apr 1.7.5-r0 apk apr-util 1.6.3-r1 apk argon2-libs 20190702-r5 apk -attrs 26.1.0 python autocommand 2.2.2 python azure-common 1.1.28 python -azure-core 1.39.0 python +azure-core 1.41.0 python azure-identity 1.25.3 python azure-mgmt-core 1.6.0 python azure-mgmt-dns 9.0.0 python backports-tarfile 1.2.0 python bash 5.2.37-r0 apk -beautifulsoup4 4.14.3 python -boto3 1.42.91 python -botocore 1.42.91 python +beautifulsoup4 4.15.0 python +boto3 1.43.46 python +botocore 1.43.46 python brotli-libs 1.1.0-r2 apk bs4 0.0.2 python busybox 1.37.0-r20 apk busybox-binsh 1.37.0-r20 apk c-ares 1.34.6-r0 apk c-client 2007f-r15 apk -ca-certificates 20250911-r0 apk -ca-certificates-bundle 20250911-r0 apk +ca-certificates 20260611-r0 apk +ca-certificates-bundle 20260611-r0 apk catatonit 0.2.1-r0 apk -certbot 5.5.0 python +certbot 5.6.0 python certbot-dns-acmedns 0.1.0 python certbot-dns-aliyun 2.0.0 python certbot-dns-azure 1.5.0 python certbot-dns-bunny 3.0.0 python -certbot-dns-cloudflare 5.5.0 python +certbot-dns-cloudflare 5.6.0 python certbot-dns-cpanel 0.4.0 python certbot-dns-desec 1.3.2 python -certbot-dns-digitalocean 5.5.0 python +certbot-dns-digitalocean 5.6.0 python certbot-dns-directadmin 1.0.15 python -certbot-dns-dnsimple 5.5.0 python -certbot-dns-dnsmadeeasy 5.5.0 python +certbot-dns-dnsimple 5.6.0 python +certbot-dns-dnsmadeeasy 5.6.0 python certbot-dns-dnspod 0.1.0 python certbot-dns-do 0.31.0 python certbot-dns-domeneshop 0.2.9 python @@ -52,59 +53,59 @@ certbot-dns-dreamhost 1.0 python certbot-dns-duckdns 1.8.0 python certbot-dns-dynudns 0.0.6 python certbot-dns-freedns 0.2.0 python -certbot-dns-gehirn 5.5.0 python +certbot-dns-gehirn 5.6.0 python certbot-dns-glesys 2.1.0 python certbot-dns-godaddy 2.8.0 python -certbot-dns-google 5.5.0 python +certbot-dns-google 5.6.0 python certbot-dns-he 1.0.0 python -certbot-dns-hetzner 3.0.0 python +certbot-dns-hetzner 4.0.0 python certbot-dns-hetzner-cloud 1.0.5 python certbot-dns-infomaniak 0.2.4 python certbot-dns-inwx 3.0.3 python certbot-dns-ionos 2024.11.9 python -certbot-dns-linode 5.5.0 python +certbot-dns-linode 5.6.0 python certbot-dns-loopia 1.0.1 python -certbot-dns-luadns 5.5.0 python +certbot-dns-luadns 5.6.0 python +certbot-dns-mijn-host 0.0.9 python certbot-dns-namecheap 1.0.0 python certbot-dns-netcup 2.0.3 python certbot-dns-njalla 2.0.2 python -certbot-dns-nsone 5.5.0 python -certbot-dns-ovh 5.5.0 python +certbot-dns-nsone 5.6.0 python +certbot-dns-ovh 5.6.0 python certbot-dns-porkbun 0.11.0 python -certbot-dns-rfc2136 5.5.0 python -certbot-dns-route53 5.5.0 python -certbot-dns-sakuracloud 5.5.0 python +certbot-dns-rfc2136 5.6.0 python +certbot-dns-route53 5.6.0 python +certbot-dns-sakuracloud 5.6.0 python certbot-dns-standalone 1.2.1 python certbot-dns-transip 0.5.2 python certbot-dns-vultr 1.1.0 python certbot-plugin-gandi 1.5.0 python -certifi 2026.2.25 python -cffi 2.0.0 python -charset-normalizer 3.4.7 python +certifi 2024.8.30 python +cffi 1.17.0 python +charset-normalizer 3.3.2 python cli UNKNOWN binary cli-32 UNKNOWN binary cli-64 UNKNOWN binary cli-arm64 UNKNOWN binary -cloudflare 2.19.4 python -composer 2.9.7 binary -configargparse 1.7.5 python -configobj 5.0.9 python +cloudflare 5.4.0 python +composer 2.10.2 binary +configargparse 1.7 python +configobj 5.0.8 python coreutils 9.7-r1 apk coreutils-env 9.7-r1 apk coreutils-fmt 9.7-r1 apk coreutils-sha512sum 9.7-r1 apk -cryptography 46.0.7 python +cryptography 46.0.0 python curl 8.14.1-r2 apk distro 1.9.0 python -dns-lexicon 3.23.2 python -dns-lexicon-coop 3.24.2 python +dns-lexicon 3.25.2 python dnslib 0.9.26 python dnspython 2.8.0 python domeneshop 0.4.4 python fail2ban 1.1.0 python fail2ban 1.1.0-r3 apk fail2ban-pyc 1.1.0-r3 apk -filelock 3.28.0 python +filelock 3.29.7 python findutils 4.10.0-r0 apk fontconfig 2.15.0-r3 apk freetype 2.13.3-r0 apk @@ -120,12 +121,12 @@ gnupg-gpgconf 2.4.9-r0 apk gnupg-keyboxd 2.4.9-r0 apk gnupg-utils 2.4.9-r0 apk gnupg-wks-client 2.4.9-r0 apk -gnutls 3.8.12-r0 apk +gnutls 3.8.13-r0 apk google-api-core 2.30.3 python -google-api-python-client 2.194.0 python -google-auth 2.49.2 python -google-auth-httplib2 0.3.1 python -googleapis-common-protos 1.74.0 python +google-api-python-client 2.198.0 python +google-auth 2.55.2 python +google-auth-httplib2 0.4.0 python +googleapis-common-protos 1.75.0 python gpg 2.4.9-r0 apk gpg-agent 2.4.9-r0 apk gpg-wks-server 2.4.9-r0 apk @@ -135,39 +136,43 @@ gui UNKNOWN binary gui-32 UNKNOWN binary gui-64 UNKNOWN binary gui-arm64 UNKNOWN binary -hcloud 2.17.1 python -httplib2 0.31.2 python +h11 0.16.0 python +hcloud 2.22.0 python +httpcore 1.0.9 python +httplib2 0.32.0 python +httpx 0.28.1 python icu-data-en 76.1-r1 apk icu-libs 76.1-r1 apk -idna 3.11 python -importlib-metadata 8.7.1 python +idna 3.8 python +importlib-metadata 8.0.0 python +importlib-resources 6.4.0 python +inflect 7.3.1 python inotify-tools 4.23.9.0-r0 apk inotify-tools-libs 4.23.9.0-r0 apk inwx-domrobot 3.2.0 python iptables 1.8.11-r1 apk iptables-legacy 1.8.11-r1 apk isodate 0.7.2 python -jaraco-context 6.1.0 python -jaraco-functools 4.4.0 python -jaraco-text 4.0.0 python +jaraco-context 5.3.0 python +jaraco-functools 4.0.1 python +jaraco-text 3.12.1 python jinja2 3.1.6 python jmespath 1.1.0 python josepy 2.2.0 python jq 1.8.1-r0 apk -jsonlines 4.0.0 python -jsonpickle 4.1.1 python -libapk2 2.14.9-r3 apk +jsonpickle 4.1.2 python +libapk2 2.14.10-r0 apk libassuan 2.5.7-r0 apk libattr 2.5.2-r2 apk libavif 1.3.0-r0 apk libbsd 0.12.2-r0 apk libbz2 1.0.8-r6 apk -libcrypto3 3.5.6-r0 apk +libcrypto3 3.5.7-r0 apk libcurl 8.14.1-r2 apk libdav1d 1.5.1-r0 apk libedit 20250104.3.1-r1 apk -libevent 2.1.12-r8 apk -libexpat 2.7.5-r0 apk +libevent 2.1.13-r0 apk +libexpat 2.8.2-r0 apk libffi 3.4.8-r0 apk libgcc 14.2.0-r6 apk libgcrypt 1.10.3-r1 apk @@ -189,7 +194,7 @@ libncursesw 6.5_p20250503-r0 apk libnftnl 1.2.9-r0 apk libpanelw 6.5_p20250503-r0 apk libpng 1.6.57-r0 apk -libpq 17.9-r0 apk +libpq 17.10-r0 apk libproc2 4.0.4-r3 apk libpsl 0.21.5-r3 apk libsasl 2.1.28-r8 apk @@ -197,7 +202,7 @@ libseccomp 2.6.0-r0 apk libsharpyuv 1.5.0-r0 apk libsm 1.2.5-r0 apk libsodium 1.0.20-r1 apk -libssl3 3.5.6-r0 apk +libssl3 3.5.7-r0 apk libstdc++ 14.2.0-r6 apk libtasn1 4.21.0-r0 apk libunistring 1.3-r0 apk @@ -208,8 +213,8 @@ libxau 1.0.12-r0 apk libxcb 1.17.0-r0 apk libxdmcp 1.1.5-r1 apk libxext 1.3.6-r2 apk -libxml2 2.13.9-r0 apk -libxpm 3.5.17-r0 apk +libxml2 2.13.9-r1 apk +libxpm 3.5.19-r0 apk libxslt 1.1.43-r3 apk libxt 1.3.1-r0 apk libxtables 1.8.11-r1 apk @@ -218,47 +223,48 @@ libzip 1.11.4-r0 apk linux-pam 1.7.0-r4 apk logrotate 3.21.0-r1 apk loopialib 0.2.0 python -lxml 6.1.0 python +lxml 6.1.1 python lz4-libs 1.10.0-r0 apk markupsafe 3.0.3 python memcached 1.6.32-r0 apk mock 5.2.0 python -more-itertools 10.8.0 python +more-itertools 10.3.0 python mpdecimal 4.0.1-r0 apk -msal 1.36.0 python +msal 1.37.0 python msal-extensions 1.3.1 python musl 1.2.5-r12 apk musl-utils 1.2.5-r12 apk +my-test-package 1.0 python nano 8.4-r0 apk ncurses-terminfo-base 6.5_p20250503-r0 apk netcat-openbsd 1.229.1-r0 apk nettle 3.10.2-r0 apk -nghttp2-libs 1.65.0-r0 apk -nginx 1.28.3-r0 apk -nginx-mod-devel-kit 1.28.3-r0 apk -nginx-mod-http-brotli 1.28.3-r0 apk -nginx-mod-http-dav-ext 1.28.3-r0 apk -nginx-mod-http-echo 1.28.3-r0 apk -nginx-mod-http-fancyindex 1.28.3-r0 apk -nginx-mod-http-geoip2 1.28.3-r0 apk -nginx-mod-http-headers-more 1.28.3-r0 apk -nginx-mod-http-image-filter 1.28.3-r0 apk -nginx-mod-http-perl 1.28.3-r0 apk -nginx-mod-http-redis2 1.28.3-r0 apk -nginx-mod-http-set-misc 1.28.3-r0 apk -nginx-mod-http-upload-progress 1.28.3-r0 apk -nginx-mod-http-xslt-filter 1.28.3-r0 apk -nginx-mod-mail 1.28.3-r0 apk -nginx-mod-rtmp 1.28.3-r0 apk -nginx-mod-stream 1.28.3-r0 apk -nginx-mod-stream-geoip2 1.28.3-r0 apk -nginx-vim 1.28.3-r0 apk +nghttp2-libs 1.69.0-r0 apk +nginx 1.28.3-r4 apk +nginx-mod-devel-kit 1.28.3-r4 apk +nginx-mod-http-brotli 1.28.3-r4 apk +nginx-mod-http-dav-ext 1.28.3-r4 apk +nginx-mod-http-echo 1.28.3-r4 apk +nginx-mod-http-fancyindex 1.28.3-r4 apk +nginx-mod-http-geoip2 1.28.3-r4 apk +nginx-mod-http-headers-more 1.28.3-r4 apk +nginx-mod-http-image-filter 1.28.3-r4 apk +nginx-mod-http-perl 1.28.3-r4 apk +nginx-mod-http-redis2 1.28.3-r4 apk +nginx-mod-http-set-misc 1.28.3-r4 apk +nginx-mod-http-upload-progress 1.28.3-r4 apk +nginx-mod-http-xslt-filter 1.28.3-r4 apk +nginx-mod-mail 1.28.3-r4 apk +nginx-mod-rtmp 1.28.3-r4 apk +nginx-mod-stream 1.28.3-r4 apk +nginx-mod-stream-geoip2 1.28.3-r4 apk +nginx-vim 1.28.3-r4 apk npth 1.8-r0 apk oniguruma 6.9.10-r0 apk -openssl 3.5.6-r0 apk -p11-kit 0.25.5-r2 apk -packaging 26.0 python -packaging 26.1 python +openssl 3.5.7-r0 apk +p11-kit 0.26.2-r0 apk +packaging 24.1 python +packaging 26.2 python parsedatetime 2.6 python pcre2 10.46-r0 apk perl 5.40.4-r0 apk @@ -313,57 +319,67 @@ php84-xmlwriter 8.4.16-r0 apk php84-xsl 8.4.16-r0 apk php84-zip 8.4.16-r0 apk pinentry 1.3.1-r0 apk -pip 26.0.1 python +pip 26.1.2 python pkb-client 2.3.1 python -platformdirs 4.4.0 python +platformdirs 4.2.2 python popt 1.19-r4 apk procps-ng 4.0.4-r3 apk -proto-plus 1.27.2 python -protobuf 7.34.1 python +proto-plus 1.28.1 python +protobuf 7.35.1 python pyacmedns 0.4 python -pyasn1 0.6.3 python +pyasn1 0.6.4 python pyasn1-modules 0.4.2 python pyc 3.12.13-r0 apk -pycparser 3.0 python -pyjwt 2.12.1 python +pycparser 2.22 python +pydantic 2.13.4 python +pydantic-core 2.46.4 python +pyjwt 2.13.0 python pynamecheap 0.0.3 python -pyopenssl 26.0.0 python -pyotp 2.9.0 python +pyopenssl 26.2.0 python +pyotp 2.10.0 python pyparsing 3.3.2 python -pyrfc3339 2.1.0 python +pyrfc3339 1.1 python python-dateutil 2.9.0.post0 python python-digitalocean 1.17.0 python python-transip 0.6.0 python python3 3.12.13-r0 apk python3-pyc 3.12.13-r0 apk python3-pycache-pyc0 3.12.13-r0 apk +pytz 2024.1 python pyyaml 6.0.3 python readline 8.2.13-r1 apk -requests 2.33.1 python +requests 2.32.3 python requests-file 3.0.1 python requests-mock 1.12.1 python -s3transfer 0.16.0 python +requests-unixsocket 0.4.1 python +ruff 0.6.3 python +s3transfer 0.19.1 python scanelf 1.3.8-r1 apk -setuptools 82.0.1 python +setuptools 74.0.0 python shadow 4.17.3-r0 apk -six 1.17.0 python +six 1.16.0 python skalibs-libs 2.14.4.0-r0 apk -soupsieve 2.8.3 python +sniffio 1.3.1 python +soupsieve 2.8.4 python sqlite-libs 3.49.2-r1 apk ssl_client 1.37.0-r20 apk tiff 4.7.1-r0 apk tldextract 5.3.1 python -tomli 2.4.0 python -typing-extensions 4.15.0 python -tzdata 2026a-r0 apk +tomli 2.0.1 python +typeguard 4.3.0 python +typing-extensions 4.12.2 python +typing-extensions 4.16.0 python +typing-inspection 0.4.2 python +tzdata 2026b-r0 apk unixodbc 2.3.12-r0 apk uritemplate 4.2.0 python -urllib3 2.6.3 python +urllib3 2.2.2 python utmps-libs 0.1.3.1-r0 apk -wheel 0.46.3 python (+1 duplicate) +wheel 0.43.0 python +wheel 0.44.0 python whois 5.6.3-r0 apk -xz-libs 5.8.1-r0 apk -zipp 3.23.0 python +xz-libs 5.8.3-r0 apk +zipp 3.19.2 python zlib 1.3.2-r0 apk -zope-interface 8.3 python +zope-interface 8.5 python zstd-libs 1.5.7-r0 apk diff --git a/readme-vars.yml b/readme-vars.yml index 27bde09..5c3a963 100644 --- a/readme-vars.yml +++ b/readme-vars.yml @@ -32,7 +32,8 @@ 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: "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: "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`, `mijn-host`, `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)."} - {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`"} @@ -65,7 +66,7 @@ app_setup_block: | 2. Certs that cover sub-subdomains of your main subdomain (ie. `*.yoursubdomain.duckdns.org`, set the `SUBDOMAINS` variable to `wildcard`) * `--cap-add=NET_ADMIN` is required for fail2ban to modify iptables * After setup, navigate to `https://example.com` to access the default homepage (http access through port 80 is disabled by default, you can enable it by editing the default site config at `/config/nginx/site-confs/default.conf`). - * Certs are checked nightly and if expiration is within 30 days, renewal is attempted. If your cert is about to expire in less than 30 days, check the logs under `/config/log/letsencrypt` to see why the renewals have been failing. It is recommended to input your e-mail in docker parameters so you receive expiration notices from Let's Encrypt in those circumstances. + * Certs are checked twice daily using ACME Renewal Information (ARI) to determine the optimal renewal window. If your cert is about to expire, check the logs under `/config/log/letsencrypt` to see why the renewals have been failing. ### Certbot Plugins @@ -219,6 +220,9 @@ init_diagram: | "swag:latest" <- Base Images # changelog changelogs: + - {date: "10.07.26:", desc: "Add support for Let's Encrypt cert profiles. Run certbot twice daily with a random delay."} + - {date: "19.06.26:", desc: "Add support for mijn.host dns validation."} + - {date: "01.06.26:", desc: "Remove obsolete old cert check logic."} - {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/defaults/dns-conf/mijn-host.ini b/root/defaults/dns-conf/mijn-host.ini new file mode 100644 index 0000000..4c124ce --- /dev/null +++ b/root/defaults/dns-conf/mijn-host.ini @@ -0,0 +1,3 @@ +# Instructions: https://github.com/mijnhost/certbot-dns-mijn-host +# Replace with your API key from your mijn.host account. +dns_mijn_host_api_key = yourapikeygoeshere diff --git a/root/etc/crontabs/root b/root/etc/crontabs/root index c848b3f..49c2d31 100644 --- a/root/etc/crontabs/root +++ b/root/etc/crontabs/root @@ -5,4 +5,4 @@ 0 3 * * 6 run-parts /etc/periodic/weekly 0 5 1 * * run-parts /etc/periodic/monthly -8 2 * * * /app/le-renew.sh >> /config/log/letsencrypt/renewal.log 2>&1 +0 */12 * * * sleep $((60 + $RANDOM % 230)); /app/le-renew.sh >> /config/log/letsencrypt/renewal.log 2>&1 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 5e34aaa..f0cf582 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,19 +206,7 @@ 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." - 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 - else - 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-name "${ORIGDOMAIN}" --server "${REV_ACMESERVER[@]}" || true - fi - rm -rf /config/etc/letsencrypt/{accounts,archive,live,renewal} -fi +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 # if zerossl is selected or staging is set to true, use the relevant server if [[ "${CERTPROVIDER}" = "zerossl" ]] && [[ "${STAGING}" = "true" ]]; then @@ -239,6 +229,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 diff --git a/root/etc/s6-overlay/s6-rc.d/init-renew/run b/root/etc/s6-overlay/s6-rc.d/init-renew/run index b402a0b..5645a5b 100755 --- a/root/etc/s6-overlay/s6-rc.d/init-renew/run +++ b/root/etc/s6-overlay/s6-rc.d/init-renew/run @@ -3,7 +3,7 @@ # Check if the cert is expired or expires within a day, if so, renew if openssl x509 -in /config/keys/letsencrypt/fullchain.pem -noout -checkend 86400 >/dev/null; then - echo "The cert does not expire within the next day. Letting the cron script handle the renewal attempts overnight (2:08am)." + echo "The cert does not expire within the next day. Letting the cron script handle the renewal attempts." else echo "The cert is either expired or it expires within the next day. Attempting to renew. This could take up to 10 minutes." /app/le-renew.sh