From 54eba51b35b7ec48f5e4eecfad3139e6a6ed34f4 Mon Sep 17 00:00:00 2001 From: b1n23 <97284148+b1n23@users.noreply.github.com> Date: Wed, 20 Mar 2024 19:14:00 +0800 Subject: [PATCH 01/49] Add deployhook for Netlify --- deploy/netlify.sh | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 deploy/netlify.sh diff --git a/deploy/netlify.sh b/deploy/netlify.sh new file mode 100644 index 00000000..3b854018 --- /dev/null +++ b/deploy/netlify.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env sh + +# Script to deploy certificate to Netlify +# https://docs.netlify.com/api/get-started/#authentication +# https://open-api.netlify.com/#tag/sniCertificate + +# This deployment required following variables +# export Netlify_ACCESS_TOKEN="Your Netlify Access Token" +# export Netlify_SITE_ID="Your Netlify Site ID" + +# returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +netlify_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + if [ -z "$Netlify_ACCESS_TOKEN" ]; then + _err "Netlify_ACCESS_TOKEN is not defined." + return 1 + else + _savedomainconf Netlify_ACCESS_TOKEN "$Netlify_ACCESS_TOKEN" + fi + if [ -z "$Netlify_SITE_ID" ]; then + _err "Netlify_SITE_ID is not defined." + return 1 + else + _savedomainconf Netlify_SITE_ID "$Netlify_SITE_ID" + fi + + _info "Deploying certificate to Netlify..." + + ## upload certificate + string_ccert=$(sed 's/$/\\n/' "$_ccert" | tr -d '\n') + string_cca=$(sed 's/$/\\n/' "$_cca" | tr -d '\n') + string_key=$(sed 's/$/\\n/' "$_ckey" | tr -d '\n') + _request_body="{\"certificate\":\"$string_ccert\",\"key\":\"$string_key\",\"ca_certificates\":\"$string_cca\"}" + _debug _request_body "$_request_body" + _debug Netlify_ACCESS_TOKEN "$Netlify_ACCESS_TOKEN" + export _H1="Authorization: Bearer $Netlify_ACCESS_TOKEN" + _response=$(_post "$_request_body" "https://api.netlify.com/api/v1/sites/$Netlify_SITE_ID/ssl" "" "POST" "application/json") + + if _contains "$_response" "\"error\""; then + _err "Error in deploying $_cdomain certificate to Netlify." + _err "$_response" + return 1 + fi + _debug response "$_response" + _info "Domain $_cdomain certificate successfully deployed to Netlify." + return 0 +} \ No newline at end of file From c508984f564fc99235e5d99142f0af6972430d0c Mon Sep 17 00:00:00 2001 From: b1n23 <97284148+b1n23@users.noreply.github.com> Date: Wed, 20 Mar 2024 18:16:53 +0800 Subject: [PATCH 02/49] Add deployhook for Edgio --- deploy/edgio.sh | 80 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 deploy/edgio.sh diff --git a/deploy/edgio.sh b/deploy/edgio.sh new file mode 100644 index 00000000..604b00e8 --- /dev/null +++ b/deploy/edgio.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env sh + +# Here is a script to deploy cert to edgio using its API +# https://docs.edg.io/guides/v7/develop/rest_api/authentication +# https://docs.edg.io/rest_api/#tag/tls-certs/operation/postConfigV01TlsCerts + +# This deployment required following variables +# export EDGIO_CLIENT_ID="Your Edgio Client ID" +# export EDGIO_CLIENT_SECRET="Your Edgio Client Secret" +# export EDGIO_ENVIRONMENT_ID="Your Edgio Environment ID" + +#returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +edgio_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + if [ -z "$EDGIO_CLIENT_ID" ]; then + _err "EDGIO_CLIENT_ID is not defined." + return 1 + else + _savedomainconf EDGIO_CLIENT_ID "$EDGIO_CLIENT_ID" + fi + + if [ -z "$EDGIO_CLIENT_SECRET" ]; then + _err "EDGIO_CLIENT_SECRET is not defined." + return 1 + else + _savedomainconf EDGIO_CLIENT_SECRET "$EDGIO_CLIENT_SECRET" + fi + + if [ -z "$EDGIO_ENVIRONMENT_ID" ]; then + _err "EDGIO_ENVIRONMENT_ID is not defined." + return 1 + else + _savedomainconf EDGIO_ENVIRONMENT_ID "$EDGIO_ENVIRONMENT_ID" + fi + + _info "Getting access token" + _data="client_id=$EDGIO_CLIENT_ID&client_secret=$EDGIO_CLIENT_SECRET&grant_type=client_credentials&scope=app.config" + _debug Get_access_token_data "$_data" + _response=$(_post "$_data" "https://id.edgio.app/connect/token" "" "POST" "application/x-www-form-urlencoded" ) + _debug Get_access_token_response "$_response" + _access_token=$(echo "$_response" | _json_decode | _egrep_o '"access_token":"[^"]*' | cut -d : -f 2 | tr -d '"') + _debug _access_token "$_access_token" + if [ -z "$_access_token" ]; then + _err "Error in getting access token" + return 1 + fi + + _info "Uploading certificate" + string_ccert=$(sed 's/$/\\n/' "$_ccert" | tr -d '\n') + string_cca=$(sed 's/$/\\n/' "$_cca" | tr -d '\n') + string_key=$(sed 's/$/\\n/' "$_ckey" | tr -d '\n') + _data="{\"environment_id\":\"$EDGIO_ENVIRONMENT_ID\",\"primary_cert\":\"$string_ccert\",\"intermediate_cert\":\"$string_cca\",\"private_key\":\"$string_key\"}" + _debug Upload_certificate_data "$_data" + _H1="Authorization: Bearer $_access_token" + _response=$(_post "$_data" "https://edgioapis.com/config/v0.1/tls-certs" "" "POST" "application/json") + + if _contains "$_response" "message"; then + _err "Error in deploying $_cdomain certificate to Edgio." + _err "$_response" + return 1 + fi + _debug Upload_certificate_response "$_response" + _info "Domain $_cdomain certificate successfully deployed to Edgio." + return 0 +} \ No newline at end of file From d1a1d1da8f550bf80a8339a7c15735619e581a2b Mon Sep 17 00:00:00 2001 From: b1n23 <97284148+b1n23@users.noreply.github.com> Date: Wed, 20 Mar 2024 18:16:44 +0800 Subject: [PATCH 03/49] Add deployhook for CacheFly --- deploy/cachefly.sh | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 deploy/cachefly.sh diff --git a/deploy/cachefly.sh b/deploy/cachefly.sh new file mode 100644 index 00000000..0e436d26 --- /dev/null +++ b/deploy/cachefly.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env sh + +# Script to deploy certificate to CacheFly +# https://api.cachefly.com/api/2.5/docs#tag/Certificates/paths/~1certificates/post + +# This deployment required following variables +# export CACHEFLY_TOKEN="Your CacheFly API Token" + +# returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +CACHEFLY_API_BASE="https://api.cachefly.com/api/2.5" + +cachefly_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + if [ -z "$CACHEFLY_TOKEN" ]; then + _err "CACHEFLY_TOKEN is not defined." + return 1 + else + _savedomainconf CACHEFLY_TOKEN "$CACHEFLY_TOKEN" + fi + + _info "Deploying certificate to CacheFly..." + + ## upload certificate + string_fullchain=$(sed 's/$/\\n/' "$_cfullchain" | tr -d '\n') + string_key=$(sed 's/$/\\n/' "$_ckey" | tr -d '\n') + + _request_body="{\"certificate\":\"$string_fullchain\",\"certificateKey\":\"$string_key\"}" + _debug _request_body "$_request_body" + _debug CACHEFLY_TOKEN "$CACHEFLY_TOKEN" + export _H1="Authorization: Bearer $CACHEFLY_TOKEN" + _response=$(_post "$_request_body" "$CACHEFLY_API_BASE/certificates" "" "POST" "application/json") + + if _contains "$_response" "message"; then + _err "Error in deploying $_cdomain certificate to CacheFly." + _err "$_response" + return 1 + fi + _debug response "$_response" + _info "Domain $_cdomain certificate successfully deployed to CacheFly." + return 0 +} \ No newline at end of file From 696182cfa4ceff50cd7c5b05a15cc591c55173bd Mon Sep 17 00:00:00 2001 From: b1n23 <97284148+b1n23@users.noreply.github.com> Date: Wed, 20 Mar 2024 23:05:43 +0800 Subject: [PATCH 04/49] deployhook Edgio: Support multiple Environment ID --- deploy/edgio.sh | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/deploy/edgio.sh b/deploy/edgio.sh index 604b00e8..aadaa98a 100644 --- a/deploy/edgio.sh +++ b/deploy/edgio.sh @@ -9,7 +9,10 @@ # export EDGIO_CLIENT_SECRET="Your Edgio Client Secret" # export EDGIO_ENVIRONMENT_ID="Your Edgio Environment ID" -#returns 0 means success, otherwise error. +# If have more than one Environment ID +# export EDGIO_ENVIRONMENT_ID="ENVIRONMENT_ID_1 ENVIRONMENT_ID_2" + +# returns 0 means success, otherwise error. ######## Public functions ##################### @@ -64,17 +67,20 @@ edgio_deploy() { string_ccert=$(sed 's/$/\\n/' "$_ccert" | tr -d '\n') string_cca=$(sed 's/$/\\n/' "$_cca" | tr -d '\n') string_key=$(sed 's/$/\\n/' "$_ckey" | tr -d '\n') - _data="{\"environment_id\":\"$EDGIO_ENVIRONMENT_ID\",\"primary_cert\":\"$string_ccert\",\"intermediate_cert\":\"$string_cca\",\"private_key\":\"$string_key\"}" - _debug Upload_certificate_data "$_data" - _H1="Authorization: Bearer $_access_token" - _response=$(_post "$_data" "https://edgioapis.com/config/v0.1/tls-certs" "" "POST" "application/json") - if _contains "$_response" "message"; then - _err "Error in deploying $_cdomain certificate to Edgio." - _err "$_response" - return 1 - fi - _debug Upload_certificate_response "$_response" - _info "Domain $_cdomain certificate successfully deployed to Edgio." + for ENVIRONMENT_ID in $EDGIO_ENVIRONMENT_ID; do + _data="{\"environment_id\":\"$ENVIRONMENT_ID\",\"primary_cert\":\"$string_ccert\",\"intermediate_cert\":\"$string_cca\",\"private_key\":\"$string_key\"}" + _debug Upload_certificate_data "$_data" + _H1="Authorization: Bearer $_access_token" + _response=$(_post "$_data" "https://edgioapis.com/config/v0.1/tls-certs" "" "POST" "application/json") + if _contains "$_response" "message"; then + _err "Error in deploying $_cdomain certificate to Edgio ENVIRONMENT_ID $ENVIRONMENT_ID." + _err "$_response" + return 1 + fi + _debug Upload_certificate_response "$_response" + _info "Domain $_cdomain certificate successfully deployed to Edgio ENVIRONMENT_ID $ENVIRONMENT_ID." + done + return 0 } \ No newline at end of file From 3b46060caa7a94e04926099ba32118efd07cc116 Mon Sep 17 00:00:00 2001 From: b1n23 <97284148+b1n23@users.noreply.github.com> Date: Wed, 20 Mar 2024 23:06:09 +0800 Subject: [PATCH 05/49] deployhook Netlify: Support multiple Site ID --- deploy/netlify.sh | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/deploy/netlify.sh b/deploy/netlify.sh index 3b854018..2ff9bcb6 100644 --- a/deploy/netlify.sh +++ b/deploy/netlify.sh @@ -8,6 +8,9 @@ # export Netlify_ACCESS_TOKEN="Your Netlify Access Token" # export Netlify_SITE_ID="Your Netlify Site ID" +# If have more than one SITE ID +# export Netlify_SITE_ID="SITE_ID_1 SITE_ID_2" + # returns 0 means success, otherwise error. ######## Public functions ##################### @@ -45,18 +48,22 @@ netlify_deploy() { string_ccert=$(sed 's/$/\\n/' "$_ccert" | tr -d '\n') string_cca=$(sed 's/$/\\n/' "$_cca" | tr -d '\n') string_key=$(sed 's/$/\\n/' "$_ckey" | tr -d '\n') - _request_body="{\"certificate\":\"$string_ccert\",\"key\":\"$string_key\",\"ca_certificates\":\"$string_cca\"}" - _debug _request_body "$_request_body" - _debug Netlify_ACCESS_TOKEN "$Netlify_ACCESS_TOKEN" - export _H1="Authorization: Bearer $Netlify_ACCESS_TOKEN" - _response=$(_post "$_request_body" "https://api.netlify.com/api/v1/sites/$Netlify_SITE_ID/ssl" "" "POST" "application/json") - if _contains "$_response" "\"error\""; then - _err "Error in deploying $_cdomain certificate to Netlify." - _err "$_response" - return 1 - fi - _debug response "$_response" - _info "Domain $_cdomain certificate successfully deployed to Netlify." + for SITE_ID in $Netlify_SITE_ID; do + _request_body="{\"certificate\":\"$string_ccert\",\"key\":\"$string_key\",\"ca_certificates\":\"$string_cca\"}" + _debug _request_body "$_request_body" + _debug Netlify_ACCESS_TOKEN "$Netlify_ACCESS_TOKEN" + export _H1="Authorization: Bearer $Netlify_ACCESS_TOKEN" + _response=$(_post "$_request_body" "https://api.netlify.com/api/v1/sites/$SITE_ID/ssl" "" "POST" "application/json") + + if _contains "$_response" "\"error\""; then + _err "Error in deploying $_cdomain certificate to Netlify SITE_ID $SITE_ID." + _err "$_response" + return 1 + fi + _debug response "$_response" + _info "Domain $_cdomain certificate successfully deployed to Netlify SITE_ID $SITE_ID." + done + return 0 } \ No newline at end of file From e7284df1df2eb586ec89bf69e19086779d63ff02 Mon Sep 17 00:00:00 2001 From: b1n23 <97284148+b1n23@users.noreply.github.com> Date: Thu, 21 Mar 2024 21:44:33 +0800 Subject: [PATCH 06/49] Add deployhook for DirectAdmin --- deploy/directadmin.sh | 80 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 deploy/directadmin.sh diff --git a/deploy/directadmin.sh b/deploy/directadmin.sh new file mode 100644 index 00000000..23d46df9 --- /dev/null +++ b/deploy/directadmin.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env sh + +# Script to deploy certificate to DirectAdmin +# https://docs.directadmin.com/directadmin/customizing-workflow/api-all-about.html#creating-a-login-key +# https://docs.directadmin.com/changelog/version-1.24.4.html#cmd-api-catch-all-pop-passwords-frontpage-protected-dirs-ssl-certs + +# This deployment required following variables +# export DirectAdmin_ENDPOINT="example.com:2222" +# export DirectAdmin_USERNAME="Your DirectAdmin Username" +# export DirectAdmin_KEY="Your DirectAdmin Login Key or Password" +# export DirectAdmin_MAIN_DOMAIN="Your DirectAdmin Main Domain, NOT Subdomain" + +# returns 0 means success, otherwise error. + +######## Public functions ##################### + +#domain keyfile certfile cafile fullchain +directadmin_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + if [ -z "$DirectAdmin_ENDPOINT" ]; then + _err "DirectAdmin_ENDPOINT is not defined." + return 1 + else + _savedomainconf DirectAdmin_ENDPOINT "$DirectAdmin_ENDPOINT" + fi + if [ -z "$DirectAdmin_USERNAME" ]; then + _err "DirectAdmin_USERNAME is not defined." + return 1 + else + _savedomainconf DirectAdmin_USERNAME "$DirectAdmin_USERNAME" + fi + if [ -z "$DirectAdmin_KEY" ]; then + _err "DirectAdmin_KEY is not defined." + return 1 + else + _savedomainconf DirectAdmin_KEY "$DirectAdmin_KEY" + fi + if [ -z "$DirectAdmin_MAIN_DOMAIN" ]; then + _err "DirectAdmin_MAIN_DOMAIN is not defined." + return 1 + else + _savedomainconf DirectAdmin_MAIN_DOMAIN "$DirectAdmin_MAIN_DOMAIN" + fi + + _info "Deploying certificate to DirectAdmin..." + + # upload certificate + string_cfullchain=$(sed 's/$/\\n/' "$_cfullchain" | tr -d '\n') + string_key=$(sed 's/$/\\n/' "$_ckey" | tr -d '\n') + + _request_body="{\"domain\":\"$DirectAdmin_MAIN_DOMAIN\",\"action\":\"save\",\"type\":\"paste\",\"certificate\":\"$string_key\n$string_cfullchain\n\"}" + _debug _request_body "$_request_body" + _debug DirectAdmin_ENDPOINT "$DirectAdmin_ENDPOINT" + _debug DirectAdmin_USERNAME "$DirectAdmin_USERNAME" + _debug DirectAdmin_KEY "$DirectAdmin_KEY" + _debug DirectAdmin_MAIN_DOMAIN "$DirectAdmin_MAIN_DOMAIN" + _response=$(_post "$_request_body" "https://$DirectAdmin_USERNAME:$DirectAdmin_KEY@$DirectAdmin_ENDPOINT/CMD_API_SSL" "" "POST" "application/json") + + if _contains "$_response" "error=1"; then + _err "Error in deploying $_cdomain certificate to DirectAdmin Domain $DirectAdmin_MAIN_DOMAIN." + _err "$_response" + return 1 + fi + + _info "$_response" + _info "Domain $_cdomain certificate successfully deployed to DirectAdmin Domain $DirectAdmin_MAIN_DOMAIN." + + return 0 +} \ No newline at end of file From 295af0168753caf491a86745f0c8ef6b6bc207be Mon Sep 17 00:00:00 2001 From: b1n23 <97284148+b1n23@users.noreply.github.com> Date: Thu, 28 Mar 2024 23:07:14 +0800 Subject: [PATCH 07/49] Add deployhook for KeyHelp --- deploy/keyhelp.sh | 111 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 deploy/keyhelp.sh diff --git a/deploy/keyhelp.sh b/deploy/keyhelp.sh new file mode 100644 index 00000000..b792f021 --- /dev/null +++ b/deploy/keyhelp.sh @@ -0,0 +1,111 @@ +#!/usr/bin/env sh + +# Script to deploy certificate to KeyHelp +# This deployment required following variables +# export DEPLOY_KEYHELP_BASEURL="https://keyhelp.example.com" +# export DEPLOY_KEYHELP_USERNAME="Your KeyHelp Username" +# export DEPLOY_KEYHELP_PASSWORD="Your KeyHelp Password" +# export DEPLOY_KEYHELP_DOMAIN_ID="Depoly certificate to this Domain ID" + +# Open the 'Edit domain' page, and you will see id=xxx at the end of the URL. This is the Domain ID. +# https://DEPLOY_KEYHELP_BASEURL/index.php?page=domains&action=edit&id=xxx + +# If have more than one domain name +# export DEPLOY_KEYHELP_DOMAIN_ID="111 222 333" + +keyhelp_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + + if [ -z "$DEPLOY_KEYHELP_BASEURL" ]; then + _err "DEPLOY_KEYHELP_BASEURL is not defined." + return 1 + else + _savedomainconf DEPLOY_KEYHELP_BASEURL "$DEPLOY_KEYHELP_BASEURL" + fi + + if [ -z "$DEPLOY_KEYHELP_USERNAME" ]; then + _err "DEPLOY_KEYHELP_USERNAME is not defined." + return 1 + else + _savedomainconf DEPLOY_KEYHELP_USERNAME "$DEPLOY_KEYHELP_USERNAME" + fi + + if [ -z "$DEPLOY_KEYHELP_PASSWORD" ]; then + _err "DEPLOY_KEYHELP_PASSWORD is not defined." + return 1 + else + _savedomainconf DEPLOY_KEYHELP_PASSWORD "$DEPLOY_KEYHELP_PASSWORD" + fi + + if [ -z "$DEPLOY_KEYHELP_DOMAIN_ID" ]; then + _err "DEPLOY_KEYHELP_DOMAIN_ID is not defined." + return 1 + else + _savedomainconf DEPLOY_KEYHELP_DOMAIN_ID "$DEPLOY_KEYHELP_DOMAIN_ID" + fi + + _info "Logging in to keyhelp panel" + username_encoded="$(printf "%s" "${DEPLOY_KEYHELP_USERNAME}" | _url_encode)" + password_encoded="$(printf "%s" "${DEPLOY_KEYHELP_PASSWORD}" | _url_encode)" + _H1="Content-Type: application/x-www-form-urlencoded" + _response=$(_get "$DEPLOY_KEYHELP_BASEURL/index.php?submit=1&username=$username_encoded&password=$password_encoded" "TRUE") + _cookie="$(grep -i '^set-cookie:' "$HTTP_HEADER" | _head_n 1 | cut -d " " -f 2)" + + # If cookies is not empty then logon successful + if [ -z "$_cookie" ]; then + _err "Fail to get cookie." + return 1 + fi + _debug "cookie" "$_cookie" + + _info "Uploading certificate" + _date=$(date +"%Y%m%d") + encoded_key="$(_url_encode <"$_ckey")" + encoded_ccert="$(_url_encode <"$_ccert")" + encoded_cca="$(_url_encode <"$_cca")" + certificate_name="$_cdomain-$_date" + + _request_body="submit=1&certificate_name=$certificate_name&add_type=upload&text_private_key=$encoded_key&text_certificate=$encoded_ccert&text_ca_certificate=$encoded_cca" + _H1="Cookie: $_cookie" + _response=$(_post "$_request_body" "$DEPLOY_KEYHELP_BASEURL/index.php?page=ssl_certificates&action=add" "" "POST") + _message=$(echo "$_response" | grep -A 2 'message-body' | sed -n '/
/,/<\/div>/{//!p;}' | sed 's/<[^>]*>//g' | sed 's/^ *//;s/ *$//') + _info "_message" "$_message" + if [ -z "$_message" ]; then + _err "Fail to upload certificate." + return 1 + fi + + for DOMAIN_ID in $DEPLOY_KEYHELP_DOMAIN_ID; do + _info "Apply certificate to domain id $DOMAIN_ID" + _response=$(_get "$DEPLOY_KEYHELP_BASEURL/index.php?page=domains&action=edit&id=$DOMAIN_ID") + cert_value=$(echo "$_response" | grep "$certificate_name" | sed -n 's/.*value="\([^"]*\).*/\1/p') + target_type=$(echo "$_response" | grep 'target_type' | grep 'checked' | sed -n 's/.*value="\([^"]*\).*/\1/p') + _debug "cert_value" "$cert_value" + if [ -z "$cert_value" ]; then + _err "Fail to get certificate id." + return 1 + fi + + _request_body="submit=1&id=$DOMAIN_ID&target_type=$target_type&certificate_type=custom&certificate_id=$cert_value" + _response=$(_post "$_request_body" "$DEPLOY_KEYHELP_BASEURL/index.php?page=domains&action=edit" "" "POST") + _message=$(echo "$_response" | grep -A 2 'message-body' | sed -n '/
/,/<\/div>/{//!p;}' | sed 's/<[^>]*>//g' | sed 's/^ *//;s/ *$//') + _info "_message" "$_message" + if [ -z "$_message" ]; then + _err "Fail to apply certificate." + return 1 + fi + done + + _info "Domain $_cdomain certificate successfully deployed to KeyHelp Domain ID $DEPLOY_KEYHELP_DOMAIN_ID." + return 0 +} \ No newline at end of file From c466f063c82ed23e695612d946ac9dcf98f71a1c Mon Sep 17 00:00:00 2001 From: b1n23 <97284148+b1n23@users.noreply.github.com> Date: Mon, 1 Apr 2024 21:59:12 +0800 Subject: [PATCH 08/49] add newline at end of file --- deploy/cachefly.sh | 2 +- deploy/directadmin.sh | 2 +- deploy/edgio.sh | 2 +- deploy/keyhelp.sh | 2 +- deploy/netlify.sh | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/deploy/cachefly.sh b/deploy/cachefly.sh index 0e436d26..325b2230 100644 --- a/deploy/cachefly.sh +++ b/deploy/cachefly.sh @@ -53,4 +53,4 @@ cachefly_deploy() { _debug response "$_response" _info "Domain $_cdomain certificate successfully deployed to CacheFly." return 0 -} \ No newline at end of file +} diff --git a/deploy/directadmin.sh b/deploy/directadmin.sh index 23d46df9..84818f93 100644 --- a/deploy/directadmin.sh +++ b/deploy/directadmin.sh @@ -77,4 +77,4 @@ directadmin_deploy() { _info "Domain $_cdomain certificate successfully deployed to DirectAdmin Domain $DirectAdmin_MAIN_DOMAIN." return 0 -} \ No newline at end of file +} diff --git a/deploy/edgio.sh b/deploy/edgio.sh index aadaa98a..1b0569cb 100644 --- a/deploy/edgio.sh +++ b/deploy/edgio.sh @@ -83,4 +83,4 @@ edgio_deploy() { done return 0 -} \ No newline at end of file +} diff --git a/deploy/keyhelp.sh b/deploy/keyhelp.sh index b792f021..58f13152 100644 --- a/deploy/keyhelp.sh +++ b/deploy/keyhelp.sh @@ -108,4 +108,4 @@ keyhelp_deploy() { _info "Domain $_cdomain certificate successfully deployed to KeyHelp Domain ID $DEPLOY_KEYHELP_DOMAIN_ID." return 0 -} \ No newline at end of file +} diff --git a/deploy/netlify.sh b/deploy/netlify.sh index 2ff9bcb6..fb254a32 100644 --- a/deploy/netlify.sh +++ b/deploy/netlify.sh @@ -66,4 +66,4 @@ netlify_deploy() { done return 0 -} \ No newline at end of file +} From bfba44fbadc142a0f8dd87e107953e17970a4a90 Mon Sep 17 00:00:00 2001 From: b1n23 <97284148+b1n23@users.noreply.github.com> Date: Sun, 7 Apr 2024 12:36:19 +0000 Subject: [PATCH 09/49] format adjustment --- deploy/cachefly.sh | 2 +- deploy/edgio.sh | 6 +++--- deploy/keyhelp.sh | 8 ++++---- deploy/netlify.sh | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/deploy/cachefly.sh b/deploy/cachefly.sh index 325b2230..7841b20b 100644 --- a/deploy/cachefly.sh +++ b/deploy/cachefly.sh @@ -44,7 +44,7 @@ cachefly_deploy() { _debug CACHEFLY_TOKEN "$CACHEFLY_TOKEN" export _H1="Authorization: Bearer $CACHEFLY_TOKEN" _response=$(_post "$_request_body" "$CACHEFLY_API_BASE/certificates" "" "POST" "application/json") - + if _contains "$_response" "message"; then _err "Error in deploying $_cdomain certificate to CacheFly." _err "$_response" diff --git a/deploy/edgio.sh b/deploy/edgio.sh index 1b0569cb..1acd0c8f 100644 --- a/deploy/edgio.sh +++ b/deploy/edgio.sh @@ -23,7 +23,7 @@ edgio_deploy() { _ccert="$3" _cca="$4" _cfullchain="$5" - + _debug _cdomain "$_cdomain" _debug _ckey "$_ckey" _debug _ccert "$_ccert" @@ -50,11 +50,11 @@ edgio_deploy() { else _savedomainconf EDGIO_ENVIRONMENT_ID "$EDGIO_ENVIRONMENT_ID" fi - + _info "Getting access token" _data="client_id=$EDGIO_CLIENT_ID&client_secret=$EDGIO_CLIENT_SECRET&grant_type=client_credentials&scope=app.config" _debug Get_access_token_data "$_data" - _response=$(_post "$_data" "https://id.edgio.app/connect/token" "" "POST" "application/x-www-form-urlencoded" ) + _response=$(_post "$_data" "https://id.edgio.app/connect/token" "" "POST" "application/x-www-form-urlencoded") _debug Get_access_token_response "$_response" _access_token=$(echo "$_response" | _json_decode | _egrep_o '"access_token":"[^"]*' | cut -d : -f 2 | tr -d '"') _debug _access_token "$_access_token" diff --git a/deploy/keyhelp.sh b/deploy/keyhelp.sh index 58f13152..839b874c 100644 --- a/deploy/keyhelp.sh +++ b/deploy/keyhelp.sh @@ -92,8 +92,8 @@ keyhelp_deploy() { target_type=$(echo "$_response" | grep 'target_type' | grep 'checked' | sed -n 's/.*value="\([^"]*\).*/\1/p') _debug "cert_value" "$cert_value" if [ -z "$cert_value" ]; then - _err "Fail to get certificate id." - return 1 + _err "Fail to get certificate id." + return 1 fi _request_body="submit=1&id=$DOMAIN_ID&target_type=$target_type&certificate_type=custom&certificate_id=$cert_value" @@ -101,8 +101,8 @@ keyhelp_deploy() { _message=$(echo "$_response" | grep -A 2 'message-body' | sed -n '/
/,/<\/div>/{//!p;}' | sed 's/<[^>]*>//g' | sed 's/^ *//;s/ *$//') _info "_message" "$_message" if [ -z "$_message" ]; then - _err "Fail to apply certificate." - return 1 + _err "Fail to apply certificate." + return 1 fi done diff --git a/deploy/netlify.sh b/deploy/netlify.sh index fb254a32..8d25f74c 100644 --- a/deploy/netlify.sh +++ b/deploy/netlify.sh @@ -48,14 +48,14 @@ netlify_deploy() { string_ccert=$(sed 's/$/\\n/' "$_ccert" | tr -d '\n') string_cca=$(sed 's/$/\\n/' "$_cca" | tr -d '\n') string_key=$(sed 's/$/\\n/' "$_ckey" | tr -d '\n') - + for SITE_ID in $Netlify_SITE_ID; do _request_body="{\"certificate\":\"$string_ccert\",\"key\":\"$string_key\",\"ca_certificates\":\"$string_cca\"}" _debug _request_body "$_request_body" _debug Netlify_ACCESS_TOKEN "$Netlify_ACCESS_TOKEN" export _H1="Authorization: Bearer $Netlify_ACCESS_TOKEN" _response=$(_post "$_request_body" "https://api.netlify.com/api/v1/sites/$SITE_ID/ssl" "" "POST" "application/json") - + if _contains "$_response" "\"error\""; then _err "Error in deploying $_cdomain certificate to Netlify SITE_ID $SITE_ID." _err "$_response" From 1116b73a08aae1b58c8edb6fbb016d82ac3364c1 Mon Sep 17 00:00:00 2001 From: b1n23 <97284148+b1n23@users.noreply.github.com> Date: Mon, 3 Jun 2024 16:47:43 +0800 Subject: [PATCH 10/49] deployhook KeyHelp: Support enabling the Enforce HTTPS option --- deploy/keyhelp.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/deploy/keyhelp.sh b/deploy/keyhelp.sh index 839b874c..0750e415 100644 --- a/deploy/keyhelp.sh +++ b/deploy/keyhelp.sh @@ -5,6 +5,7 @@ # export DEPLOY_KEYHELP_BASEURL="https://keyhelp.example.com" # export DEPLOY_KEYHELP_USERNAME="Your KeyHelp Username" # export DEPLOY_KEYHELP_PASSWORD="Your KeyHelp Password" +# export DEPLOY_KEYHELP_ENFORCE_HTTPS="1" # 0 or 1, input 1 to enable Enforce HTTP to HTTPS redirection. # export DEPLOY_KEYHELP_DOMAIN_ID="Depoly certificate to this Domain ID" # Open the 'Edit domain' page, and you will see id=xxx at the end of the URL. This is the Domain ID. @@ -54,6 +55,11 @@ keyhelp_deploy() { _savedomainconf DEPLOY_KEYHELP_DOMAIN_ID "$DEPLOY_KEYHELP_DOMAIN_ID" fi + # Optional DEPLOY_KEYHELP_ENFORCE_HTTPS + _getdeployconf DEPLOY_KEYHELP_ENFORCE_HTTPS + # set default values for DEPLOY_KEYHELP_ENFORCE_HTTPS + [ -n "${DEPLOY_KEYHELP_ENFORCE_HTTPS}" ] || DEPLOY_KEYHELP_ENFORCE_HTTPS="1" + _info "Logging in to keyhelp panel" username_encoded="$(printf "%s" "${DEPLOY_KEYHELP_USERNAME}" | _url_encode)" password_encoded="$(printf "%s" "${DEPLOY_KEYHELP_PASSWORD}" | _url_encode)" @@ -96,7 +102,7 @@ keyhelp_deploy() { return 1 fi - _request_body="submit=1&id=$DOMAIN_ID&target_type=$target_type&certificate_type=custom&certificate_id=$cert_value" + _request_body="submit=1&id=$DOMAIN_ID&target_type=$target_type&certificate_type=custom&certificate_id=$cert_value&enforce_https=$DEPLOY_KEYHELP_ENFORCE_HTTPS" _response=$(_post "$_request_body" "$DEPLOY_KEYHELP_BASEURL/index.php?page=domains&action=edit" "" "POST") _message=$(echo "$_response" | grep -A 2 'message-body' | sed -n '/
/,/<\/div>/{//!p;}' | sed 's/<[^>]*>//g' | sed 's/^ *//;s/ *$//') _info "_message" "$_message" From 3f40380c69d75bbf09bdb9e4cdb1c007fe437655 Mon Sep 17 00:00:00 2001 From: b1n23 <97284148+b1n23@users.noreply.github.com> Date: Mon, 3 Jun 2024 16:57:51 +0800 Subject: [PATCH 11/49] deployhook Directadmin: Support for selecting the scheme of DirectAdmin , HTTP or HTTPS --- deploy/directadmin.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/deploy/directadmin.sh b/deploy/directadmin.sh index 84818f93..3f60a088 100644 --- a/deploy/directadmin.sh +++ b/deploy/directadmin.sh @@ -5,6 +5,7 @@ # https://docs.directadmin.com/changelog/version-1.24.4.html#cmd-api-catch-all-pop-passwords-frontpage-protected-dirs-ssl-certs # This deployment required following variables +# export DirectAdmin_SCHEME="https" # Optional, https or http, defaults to https # export DirectAdmin_ENDPOINT="example.com:2222" # export DirectAdmin_USERNAME="Your DirectAdmin Username" # export DirectAdmin_KEY="Your DirectAdmin Login Key or Password" @@ -53,6 +54,11 @@ directadmin_deploy() { _savedomainconf DirectAdmin_MAIN_DOMAIN "$DirectAdmin_MAIN_DOMAIN" fi + # Optional SCHEME + _getdeployconf DirectAdmin_SCHEME + # set default values for DirectAdmin_SCHEME + [ -n "${DirectAdmin_SCHEME}" ] || DirectAdmin_SCHEME="https" + _info "Deploying certificate to DirectAdmin..." # upload certificate @@ -65,7 +71,7 @@ directadmin_deploy() { _debug DirectAdmin_USERNAME "$DirectAdmin_USERNAME" _debug DirectAdmin_KEY "$DirectAdmin_KEY" _debug DirectAdmin_MAIN_DOMAIN "$DirectAdmin_MAIN_DOMAIN" - _response=$(_post "$_request_body" "https://$DirectAdmin_USERNAME:$DirectAdmin_KEY@$DirectAdmin_ENDPOINT/CMD_API_SSL" "" "POST" "application/json") + _response=$(_post "$_request_body" "$DirectAdmin_SCHEME://$DirectAdmin_USERNAME:$DirectAdmin_KEY@$DirectAdmin_ENDPOINT/CMD_API_SSL" "" "POST" "application/json") if _contains "$_response" "error=1"; then _err "Error in deploying $_cdomain certificate to DirectAdmin Domain $DirectAdmin_MAIN_DOMAIN." From 2f5ea120cb18d56d9d21da07034cb679457b3c94 Mon Sep 17 00:00:00 2001 From: b1n23 <97284148+b1n23@users.noreply.github.com> Date: Tue, 16 Jul 2024 00:25:53 +0800 Subject: [PATCH 12/49] deployhook KeyHelp: fix bug --- deploy/keyhelp.sh | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/deploy/keyhelp.sh b/deploy/keyhelp.sh index 0750e415..97f9c21c 100644 --- a/deploy/keyhelp.sh +++ b/deploy/keyhelp.sh @@ -5,7 +5,6 @@ # export DEPLOY_KEYHELP_BASEURL="https://keyhelp.example.com" # export DEPLOY_KEYHELP_USERNAME="Your KeyHelp Username" # export DEPLOY_KEYHELP_PASSWORD="Your KeyHelp Password" -# export DEPLOY_KEYHELP_ENFORCE_HTTPS="1" # 0 or 1, input 1 to enable Enforce HTTP to HTTPS redirection. # export DEPLOY_KEYHELP_DOMAIN_ID="Depoly certificate to this Domain ID" # Open the 'Edit domain' page, and you will see id=xxx at the end of the URL. This is the Domain ID. @@ -96,13 +95,28 @@ keyhelp_deploy() { _response=$(_get "$DEPLOY_KEYHELP_BASEURL/index.php?page=domains&action=edit&id=$DOMAIN_ID") cert_value=$(echo "$_response" | grep "$certificate_name" | sed -n 's/.*value="\([^"]*\).*/\1/p') target_type=$(echo "$_response" | grep 'target_type' | grep 'checked' | sed -n 's/.*value="\([^"]*\).*/\1/p') + if [ "$target_type" = "directory" ]; then + path=$(echo "$_response" | awk '/name="path"/{getline; print}' | sed -n 's/.*value="\([^"]*\).*/\1/p') + fi + echo "$_response" | grep "is_prefer_https" | grep "checked" >/dev/null + if [ $? -eq 0 ]; then + is_prefer_https=1 + else + is_prefer_https=0 + fi + echo "$_response" | grep "hsts_enabled" | grep "checked" >/dev/null + if [ $? -eq 0 ]; then + hsts_enabled=1 + else + hsts_enabled=0 + fi _debug "cert_value" "$cert_value" if [ -z "$cert_value" ]; then _err "Fail to get certificate id." return 1 fi - _request_body="submit=1&id=$DOMAIN_ID&target_type=$target_type&certificate_type=custom&certificate_id=$cert_value&enforce_https=$DEPLOY_KEYHELP_ENFORCE_HTTPS" + _request_body="submit=1&id=$DOMAIN_ID&target_type=$target_type&path=$path&is_prefer_https=$is_prefer_https&hsts_enabled=$hsts_enabled&certificate_type=custom&certificate_id=$cert_value&enforce_https=$DEPLOY_KEYHELP_ENFORCE_HTTPS" _response=$(_post "$_request_body" "$DEPLOY_KEYHELP_BASEURL/index.php?page=domains&action=edit" "" "POST") _message=$(echo "$_response" | grep -A 2 'message-body' | sed -n '/
/,/<\/div>/{//!p;}' | sed 's/<[^>]*>//g' | sed 's/^ *//;s/ *$//') _info "_message" "$_message" From 3b0f624302294c3d817e5c3218a263905dff9f67 Mon Sep 17 00:00:00 2001 From: Jens Spanier Date: Thu, 10 Jul 2025 10:55:05 +0200 Subject: [PATCH 13/49] Support certificate profile selection --- acme.sh | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index d70e323b..46c1124c 100755 --- a/acme.sh +++ b/acme.sh @@ -4416,6 +4416,7 @@ issue() { _preferred_chain="${15}" _valid_from="${16}" _valid_to="${17}" + _certificate_profile="${18}" if [ -z "$_ACME_IS_RENEW" ]; then _initpath "$_main_domain" "$_key_length" @@ -4491,6 +4492,11 @@ issue() { else _cleardomainconf "Le_Preferred_Chain" fi + if [ "$_certificate_profile" ]; then + _savedomainconf "Le_Certificate_Profile" "$_certificate_profile" + else + _cleardomainconf "Le_Certificate_Profile" + fi Le_API="$ACME_DIRECTORY" _savedomainconf "Le_API" "$Le_API" @@ -4622,6 +4628,9 @@ issue() { if [ "$_notAfter" ]; then _newOrderObj="$_newOrderObj,\"notAfter\": \"$_notAfter\"" fi + if [ "$_certificate_profile" ]; then + _newOrderObj="$_newOrderObj,\"profile\": \"$_certificate_profile\"" + fi _debug "STEP 1, Ordering a Certificate" if ! _send_signed_request "$ACME_NEW_ORDER" "$_newOrderObj}"; then _err "Error creating new order." @@ -5503,6 +5512,7 @@ renew() { Le_PostHook="$(_readdomainconf Le_PostHook)" Le_RenewHook="$(_readdomainconf Le_RenewHook)" Le_Preferred_Chain="$(_readdomainconf Le_Preferred_Chain)" + Le_Certificate_Profile="$(_readdomainconf Le_Certificate_Profile)" # When renewing from an old version, the empty Le_Keylength means 2048. # Note, do not use DEFAULT_DOMAIN_KEY_LENGTH as that value may change over # time but an empty value implies 2048 specifically. @@ -5517,7 +5527,7 @@ renew() { _cleardomainconf Le_OCSP_Staple fi fi - issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" "$Le_PreHook" "$Le_PostHook" "$Le_RenewHook" "$Le_LocalAddress" "$Le_ChallengeAlias" "$Le_Preferred_Chain" "$Le_Valid_From" "$Le_Valid_To" + issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" "$Le_PreHook" "$Le_PostHook" "$Le_RenewHook" "$Le_LocalAddress" "$Le_ChallengeAlias" "$Le_Preferred_Chain" "$Le_Valid_From" "$Le_Valid_To" "$Le_Certificate_Profile" res="$?" if [ "$res" != "0" ]; then return "$res" @@ -6989,6 +6999,8 @@ Parameters: If no match, the default offered chain will be used. (default: empty) See: $_PREFERRED_CHAIN_WIKI + --certificate-profile If the CA offers profiles, select the desired profile + --valid-to Request the NotAfter field of the cert. See: $_VALIDITY_WIKI --valid-from Request the NotBefore field of the cert. @@ -7364,6 +7376,7 @@ _process() { _preferred_chain="" _valid_from="" _valid_to="" + _certificate_profile="" while [ ${#} -gt 0 ]; do case "${1}" in @@ -7682,6 +7695,10 @@ _process() { _valid_to="$2" shift ;; + --certificate-profile) + _certificate_profile="$2" + shift + ;; --httpport) _httpport="$2" Le_HTTPPort="$_httpport" @@ -7957,7 +7974,7 @@ _process() { uninstall) uninstall "$_nocron" ;; upgrade) upgrade ;; issue) - issue "$_webroot" "$_domain" "$_altdomains" "$_keylength" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain" "$_valid_from" "$_valid_to" + issue "$_webroot" "$_domain" "$_altdomains" "$_keylength" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain" "$_valid_from" "$_valid_to" "$_certificate_profile" ;; deploy) deploy "$_domain" "$_deploy_hook" "$_ecc" From 06c1911a2830c7ccb7d08cf3ec210921bfbb5038 Mon Sep 17 00:00:00 2001 From: PrivacyFreak <220089342+privacyfr3ak@users.noreply.github.com> Date: Mon, 14 Jul 2025 18:48:32 +0000 Subject: [PATCH 14/49] fix keystore ownership read for unifi.sh --- deploy/unifi.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/unifi.sh b/deploy/unifi.sh index 1f274236..2af46b4a 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -143,8 +143,8 @@ unifi_deploy() { # correct file ownership according to the directory, the keystore is placed in _unifi_keystore_dir=$(dirname "${_unifi_keystore}") - _unifi_keystore_dir_owner=$(find "${_unifi_keystore_dir}" -maxdepth 0 -printf '%u\n') - _unifi_keystore_owner=$(find "${_unifi_keystore}" -maxdepth 0 -printf '%u\n') + _unifi_keystore_dir_owner=$(ls -ld "${_unifi_keystore_dir}" | awk '{print $3}') + _unifi_keystore_owner=$(ls -l "${_unifi_keystore}" | awk '{print $3}') if ! [ "${_unifi_keystore_owner}" = "${_unifi_keystore_dir_owner}" ]; then _debug "Changing keystore owner to ${_unifi_keystore_dir_owner}" chown "$_unifi_keystore_dir_owner" "${_unifi_keystore}" >/dev/null 2>&1 # fail quietly if we're not running as root From d7c428fc8d6bb123b890ec669b606eaf620b9c25 Mon Sep 17 00:00:00 2001 From: Richard Glidden Date: Mon, 30 Jun 2025 14:14:26 -0400 Subject: [PATCH 15/49] feat: Add ability to deploy to remote TrueNAS instances --- deploy/truenas_ws.sh | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh index bdc1b846..74a46530 100644 --- a/deploy/truenas_ws.sh +++ b/deploy/truenas_ws.sh @@ -39,13 +39,13 @@ _ws_call() { _debug "_ws_call arg2" "$2" _debug "_ws_call arg3" "$3" if [ $# -eq 3 ]; then - _ws_response=$(midclt -K "$DEPLOY_TRUENAS_APIKEY" call "$1" "$2" "$3") + _ws_response=$(midclt --uri $_ws_uri -K "$DEPLOY_TRUENAS_APIKEY" call "$1" "$2" "$3") fi if [ $# -eq 2 ]; then - _ws_response=$(midclt -K "$DEPLOY_TRUENAS_APIKEY" call "$1" "$2") + _ws_response=$(midclt --uri $_ws_uri -K "$DEPLOY_TRUENAS_APIKEY" call "$1" "$2") fi if [ $# -eq 1 ]; then - _ws_response=$(midclt -K "$DEPLOY_TRUENAS_APIKEY" call "$1") + _ws_response=$(midclt --uri $_ws_uri -K "$DEPLOY_TRUENAS_APIKEY" call "$1") fi _debug "_ws_response" "$_ws_response" printf "%s" "$_ws_response" @@ -60,7 +60,7 @@ _ws_upload_cert() { import sys from truenas_api_client import Client -with Client() as c: +with Client(uri="$_ws_uri") as c: ### Login with API key print("I:Trying to upload new certificate...") @@ -175,6 +175,16 @@ truenas_ws_deploy() { _debug _file_ca "$_file_ca" _debug _file_fullchain "$_file_fullchain" + ########## Default values for hostname and protocol + [ -n "${DEPLOY_TRUENAS_HOSTNAME}" ] || DEPLOY_TRUENAS_HOSTNAME="localhost" + [ -n "${DEPLOY_TRUENAS_PROTOCOL}" ] || DEPLOY_TRUENAS_PROTOCOL="ws" + + _debug2 DEPLOY_TRUENAS_HOSTNAME "$DEPLOY_TRUENAS_HOSTNAME" + _debug2 DEPLOY_TRUENAS_PROTOCOL "$DEPLOY_TRUENAS_PROTOCOL" + + _ws_uri="$DEPLOY_TRUENAS_PROTOCOL://$DEPLOY_TRUENAS_HOSTNAME/websocket" + _debug _ws_uri "$_ws_uri" + ########## Environment check _info "Checking environment variables..." @@ -304,7 +314,7 @@ truenas_ws_deploy() { _info "Restarting WebUI..." _ws_response=$(_ws_call "system.general.ui_restart") _info "Waiting for UI restart..." - sleep 6 + sleep 15 ########## Certificates From 6d40ac86449cdb80b52c6ffb647eac560174c84c Mon Sep 17 00:00:00 2001 From: Richard Glidden Date: Mon, 30 Jun 2025 14:51:36 -0400 Subject: [PATCH 16/49] chore: Fix shellcheck errors --- deploy/truenas_ws.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh index 74a46530..ea6fc7e6 100644 --- a/deploy/truenas_ws.sh +++ b/deploy/truenas_ws.sh @@ -39,13 +39,13 @@ _ws_call() { _debug "_ws_call arg2" "$2" _debug "_ws_call arg3" "$3" if [ $# -eq 3 ]; then - _ws_response=$(midclt --uri $_ws_uri -K "$DEPLOY_TRUENAS_APIKEY" call "$1" "$2" "$3") + _ws_response=$(midclt --uri "$_ws_uri" -K "$DEPLOY_TRUENAS_APIKEY" call "$1" "$2" "$3") fi if [ $# -eq 2 ]; then - _ws_response=$(midclt --uri $_ws_uri -K "$DEPLOY_TRUENAS_APIKEY" call "$1" "$2") + _ws_response=$(midclt --uri "$_ws_uri" -K "$DEPLOY_TRUENAS_APIKEY" call "$1" "$2") fi if [ $# -eq 1 ]; then - _ws_response=$(midclt --uri $_ws_uri -K "$DEPLOY_TRUENAS_APIKEY" call "$1") + _ws_response=$(midclt --uri "$_ws_uri" -K "$DEPLOY_TRUENAS_APIKEY" call "$1") fi _debug "_ws_response" "$_ws_response" printf "%s" "$_ws_response" From 8608e9cd3a49c1a9f948e19ea3a62fac62a24aef Mon Sep 17 00:00:00 2001 From: Richard Glidden Date: Fri, 12 Sep 2025 22:22:30 -0400 Subject: [PATCH 17/49] Save and read variables --- deploy/truenas_ws.sh | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh index ea6fc7e6..a204d352 100644 --- a/deploy/truenas_ws.sh +++ b/deploy/truenas_ws.sh @@ -175,25 +175,31 @@ truenas_ws_deploy() { _debug _file_ca "$_file_ca" _debug _file_fullchain "$_file_fullchain" - ########## Default values for hostname and protocol - [ -n "${DEPLOY_TRUENAS_HOSTNAME}" ] || DEPLOY_TRUENAS_HOSTNAME="localhost" - [ -n "${DEPLOY_TRUENAS_PROTOCOL}" ] || DEPLOY_TRUENAS_PROTOCOL="ws" - - _debug2 DEPLOY_TRUENAS_HOSTNAME "$DEPLOY_TRUENAS_HOSTNAME" - _debug2 DEPLOY_TRUENAS_PROTOCOL "$DEPLOY_TRUENAS_PROTOCOL" - - _ws_uri="$DEPLOY_TRUENAS_PROTOCOL://$DEPLOY_TRUENAS_HOSTNAME/websocket" - _debug _ws_uri "$_ws_uri" - ########## Environment check _info "Checking environment variables..." _getdeployconf DEPLOY_TRUENAS_APIKEY + _getdeployconf DEPLOY_TRUENAS_HOSTNAME + _getdeployconf DEPLOY_TRUENAS_PROTOCOL # Check API Key if [ -z "$DEPLOY_TRUENAS_APIKEY" ]; then _err "TrueNAS API key not found, please set the DEPLOY_TRUENAS_APIKEY environment variable." return 1 fi + # Check Hostname, default to localhost if not set + if [ -z "$DEPLOY_TRUENAS_HOSTNAME" ]; then + _info "TrueNAS hostname not set. Using 'localhost'." + DEPLOY_TRUENAS_HOSTNAME="localhost" + fi + # Check protocol, default to ws if not set + if [ -z "$DEPLOY_TRUENAS_PROTOCOL" ]; then + _info "TrueNAS protocol not set. Using 'ws'." + DEPLOY_TRUENAS_PROTOCOL="ws" + fi + _ws_uri="$DEPLOY_TRUENAS_PROTOCOL://$DEPLOY_TRUENAS_HOSTNAME/websocket" + _debug2 DEPLOY_TRUENAS_HOSTNAME "$DEPLOY_TRUENAS_HOSTNAME" + _debug2 DEPLOY_TRUENAS_PROTOCOL "$DEPLOY_TRUENAS_PROTOCOL" + _debug _ws_uri "$_ws_uri" _secure_debug2 DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY" _info "Environment variables: OK" @@ -215,6 +221,8 @@ truenas_ws_deploy() { return 2 fi _savedeployconf DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY" + _savedeployconf DEPLOY_TRUENAS_HOSTNAME "$DEPLOY_TRUENAS_HOSTNAME" + _savedeployconf DEPLOY_TRUENAS_PROTOCOL "$DEPLOY_TRUENAS_PROTOCOL" _info "TrueNAS health: OK" ########## System info From a1ea2a5aa6a63c1c99daffc66c1463e3a2ac88ab Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 14 Sep 2025 10:35:21 +0200 Subject: [PATCH 18/49] fix tr https://github.com/acmesh-official/acme.sh/issues/6511#issuecomment-3282521860 --- acme.sh | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 3316b25f..02986a33 100755 --- a/acme.sh +++ b/acme.sh @@ -436,14 +436,28 @@ _secure_debug3() { fi } +__USE_TR_TAG="" +if [ "$(echo "abc" | LANG=C tr a-z A-Z 2>/dev/null)" != "ABC" ] ; then + __USE_TR_TAG="1" +fi +export __USE_TR_TAG + _upper_case() { + if [ "$__USE_TR_TAG" ]; then + LANG=C tr '[:lower:]' '[:upper:]' + else # shellcheck disable=SC2018,SC2019 - tr '[a-z]' '[A-Z]' + LANG=C tr '[a-z]' '[A-Z]' + fi } _lower_case() { - # shellcheck disable=SC2018,SC2019 - tr '[A-Z]' '[a-z]' + if [ "$__USE_TR_TAG" ]; then + LANG=C tr '[:upper:]' '[:lower:]' + else + # shellcheck disable=SC2018,SC2019 + LANG=C tr '[A-Z]' '[a-z]' + fi } _startswith() { From d76f4b27b0f2eae8b75d41459eff6e51094045ca Mon Sep 17 00:00:00 2001 From: benyamin-codez <115509179+benyamin-codez@users.noreply.github.com> Date: Sun, 7 Sep 2025 23:54:45 +1000 Subject: [PATCH 19/49] dnsapi/dns_opnsense.sh: Refresh for OPNsense v25.7 series Updates the dns_opnsense.sh Bourne shell script for OPNSense v25.7 series: 1. Fixes historical error in rm_record() [used incorrect response variable] 2. Improves debug messaging in rm_record() 3. Fixes _get_root() for change in OPNsense API * Response is now split into pseudo-rows * We now iterate through pseudo-rows for matching domainname field 4. Fixes _existingchallenge() for change in OPNsense API * Fixes unreliable regex for uuid * Adds domain regex and %domain field 5. Fixes historical error in _existingchallenge() [incorrect variable syntax] Resolves #6467 Signed-off-by: benyamin-codez <115509179+benyamin-codez@users.noreply.github.com> --- dnsapi/dns_opnsense.sh | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/dnsapi/dns_opnsense.sh b/dnsapi/dns_opnsense.sh index d1e9c0ac..a11cfae5 100755 --- a/dnsapi/dns_opnsense.sh +++ b/dnsapi/dns_opnsense.sh @@ -110,15 +110,16 @@ rm_record() { if _existingchallenge "$_domain" "$_host" "$new_challenge"; then # Delete if _opns_rest "POST" "/record/delRecord/${_uuid}" "\{\}"; then - if echo "$_return_str" | _egrep_o "\"result\":\"deleted\"" >/dev/null; then - _opns_rest "POST" "/service/reconfigure" "{}" + if echo "$response" | _egrep_o "\"result\":\"deleted\"" >/dev/null; then _debug "Record deleted" + _opns_rest "POST" "/service/reconfigure" "{}" + _debug "Service reconfigured" else _err "Error deleting record $_host from domain $fulldomain" return 1 fi else - _err "Error deleting record $_host from domain $fulldomain" + _err "Error requesting deletion of record $_host from domain $fulldomain" return 1 fi else @@ -150,14 +151,17 @@ _get_root() { return 1 fi _debug h "$h" - id=$(echo "$_domain_response" | _egrep_o "\"uuid\":\"[a-z0-9\-]*\",\"enabled\":\"1\",\"type\":\"primary\",\"domainname\":\"${h}\"" | cut -d ':' -f 2 | cut -d '"' -f 2) - if [ -n "$id" ]; then - _debug id "$id" - _host=$(printf "%s" "$domain" | cut -d . -f 1-"$p") - _domain="${h}" - _domainid="${id}" - return 0 - fi + lines=$(echo "$_domain_response" | sed 's/{/\n/g') + for line in $lines; do + id=$(echo "$line" | _egrep_o "\"uuid\":\"[a-z0-9\-]*\",\"enabled\":\"1\",\"type\":\"primary\",.*\"domainname\":\"${h}\"" | cut -d ':' -f 2 | cut -d '"' -f 2) + if [ -n "$id" ]; then + _debug id "$id" + _host=$(printf "%s" "$domain" | cut -d . -f 1-"$p") + _domain="${h}" + _domainid="${id}" + return 0 + fi + done p=$i i=$(_math "$i" + 1) done @@ -206,13 +210,13 @@ _existingchallenge() { return 1 fi _uuid="" - _uuid=$(echo "$_record_response" | _egrep_o "\"uuid\":\"[^\"]*\",\"enabled\":\"[01]\",\"domain\":\"$1\",\"name\":\"$2\",\"type\":\"TXT\",\"value\":\"$3\"" | cut -d ':' -f 2 | cut -d '"' -f 2) + _uuid=$(echo "$_record_response" | _egrep_o "\"uuid\":\"[a-z0-9\-]*\",\"enabled\":\"[01]\",\"domain\":\"[a-z0-9\-]*\",\"%domain\":\"$1\",\"name\":\"$2\",\"type\":\"TXT\",\"value\":\"$3\"" | cut -d ':' -f 2 | cut -d '"' -f 2) if [ -n "$_uuid" ]; then _debug uuid "$_uuid" return 0 fi - _debug "${2}.$1{1} record not found" + _debug "${2}.${1} record not found" return 1 } From df350e6660df5b61e353a5daed7d7a1ee1f5ba4a Mon Sep 17 00:00:00 2001 From: neil Date: Mon, 15 Sep 2025 19:34:54 +0200 Subject: [PATCH 20/49] fix format --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 02986a33..9105a0a4 100755 --- a/acme.sh +++ b/acme.sh @@ -437,7 +437,7 @@ _secure_debug3() { } __USE_TR_TAG="" -if [ "$(echo "abc" | LANG=C tr a-z A-Z 2>/dev/null)" != "ABC" ] ; then +if [ "$(echo "abc" | LANG=C tr a-z A-Z 2>/dev/null)" != "ABC" ]; then __USE_TR_TAG="1" fi export __USE_TR_TAG @@ -446,7 +446,7 @@ _upper_case() { if [ "$__USE_TR_TAG" ]; then LANG=C tr '[:lower:]' '[:upper:]' else - # shellcheck disable=SC2018,SC2019 + # shellcheck disable=SC2018,SC2019 LANG=C tr '[a-z]' '[A-Z]' fi } From 44c7473ef97bcae83e829a4a7e6b2ddcfc0d8369 Mon Sep 17 00:00:00 2001 From: Min Wang Date: Tue, 16 Sep 2025 15:09:12 +0800 Subject: [PATCH 21/49] fix bug for #6510 --- notify/telegram.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notify/telegram.sh b/notify/telegram.sh index c0621ae7..7da05729 100644 --- a/notify/telegram.sh +++ b/notify/telegram.sh @@ -34,8 +34,8 @@ telegram_send() { fi _saveaccountconf_mutable TELEGRAM_BOT_URLBASE "$TELEGRAM_BOT_URLBASE" - _subject="$(printf "%s" "$_subject" | sed 's/\\/\\\\\\\\/g' | sed 's/\]/\\\\\]/g' | sed 's/\([_*[()~`>#+\-=|{}.!]\)/\\\\\1/g')" - _content="$(printf "%s" "$_content" | sed 's/\\/\\\\\\\\/g' | sed 's/\]/\\\\\]/g' | sed 's/\([_*[()~`>#+\-=|{}.!]\)/\\\\\1/g')" + _subject="$(printf "%s" "$_subject" | sed 's/\\/\\\\\\\\/g' | sed 's/\]/\\\\\]/g' | sed 's/\([-_*[()~`>#+\-=|{}.!]\)/\\\\\1/g')" + _content="$(printf "%s" "$_content" | sed 's/\\/\\\\\\\\/g' | sed 's/\]/\\\\\]/g' | sed 's/\([-_*[()~`>#+\-=|{}.!]\)/\\\\\1/g')" _content="$(printf "*%s*\n%s" "$_subject" "$_content" | _json_encode)" _data="{\"text\": \"$_content\", " _data="$_data\"chat_id\": \"$TELEGRAM_BOT_CHATID\", " From 1b00ced7adf0c9ffe39c2f5e883395f7abefc2cc Mon Sep 17 00:00:00 2001 From: Jens Spanier Date: Tue, 16 Sep 2025 09:20:31 +0200 Subject: [PATCH 22/49] Add `--profile` as option for selecting certificate profile --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index ead7602b..7a8e4e9b 100755 --- a/acme.sh +++ b/acme.sh @@ -7702,7 +7702,7 @@ _process() { _valid_to="$2" shift ;; - --certificate-profile) + --certificate-profile | --profile) _certificate_profile="$2" shift ;; From 070cd0f4dfe983d093e1661aab8b73678cf5b259 Mon Sep 17 00:00:00 2001 From: Richard Glidden Date: Tue, 16 Sep 2025 22:19:16 -0400 Subject: [PATCH 23/49] Use _sleep instead of sleep --- deploy/truenas_ws.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh index a204d352..d334853e 100644 --- a/deploy/truenas_ws.sh +++ b/deploy/truenas_ws.sh @@ -121,7 +121,7 @@ _ws_check_jobid() { # n/a _ws_get_job_result() { while true; do - sleep 2 + _sleep 2 _ws_response=$(_ws_call "core.get_jobs" "[[\"id\", \"=\", $1]]") if [ "$(printf "%s" "$_ws_response" | jq -r '.[]."state"')" != "RUNNING" ]; then _ws_result="$(printf "%s" "$_ws_response" | jq '.[]."result"')" @@ -322,7 +322,7 @@ truenas_ws_deploy() { _info "Restarting WebUI..." _ws_response=$(_ws_call "system.general.ui_restart") _info "Waiting for UI restart..." - sleep 15 + _sleep 15 ########## Certificates From c3ec827fdd87ae7a595f7c84aa7395a52321f6df Mon Sep 17 00:00:00 2001 From: neil Date: Fri, 19 Sep 2025 20:54:09 +0200 Subject: [PATCH 24/49] remove buypass --- acme.sh | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/acme.sh b/acme.sh index 9105a0a4..4d849845 100755 --- a/acme.sh +++ b/acme.sh @@ -23,9 +23,6 @@ _SUB_FOLDERS="$_SUB_FOLDER_DNSAPI $_SUB_FOLDER_DEPLOY $_SUB_FOLDER_NOTIFY" CA_LETSENCRYPT_V2="https://acme-v02.api.letsencrypt.org/directory" CA_LETSENCRYPT_V2_TEST="https://acme-staging-v02.api.letsencrypt.org/directory" -CA_BUYPASS="https://api.buypass.com/acme/directory" -CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory" - CA_ZEROSSL="https://acme.zerossl.com/v2/DV90" _ZERO_EAB_ENDPOINT="https://api.zerossl.com/acme/eab-credentials-email" @@ -42,14 +39,12 @@ CA_NAMES=" ZeroSSL.com,zerossl LetsEncrypt.org,letsencrypt LetsEncrypt.org_test,letsencrypt_test,letsencrypttest -BuyPass.com,buypass -BuyPass.com_test,buypass_test,buypasstest SSL.com,sslcom Google.com,google Google.com_test,googletest,google_test " -CA_SERVERS="$CA_ZEROSSL,$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_BUYPASS,$CA_BUYPASS_TEST,$CA_SSLCOM_RSA,$CA_GOOGLE,$CA_GOOGLE_TEST" +CA_SERVERS="$CA_ZEROSSL,$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_SSLCOM_RSA,$CA_GOOGLE,$CA_GOOGLE_TEST" DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)" @@ -5478,10 +5473,6 @@ renew() { _info "Switching back to $CA_LETSENCRYPT_V2" Le_API="$CA_LETSENCRYPT_V2" ;; - "$CA_BUYPASS_TEST") - _info "Switching back to $CA_BUYPASS" - Le_API="$CA_BUYPASS" - ;; "$CA_GOOGLE_TEST") _info "Switching back to $CA_GOOGLE" Le_API="$CA_GOOGLE" From 471e0c05f9b69dd2ae2ce7c7968b7f497334c18d Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 20 Sep 2025 10:38:43 +0200 Subject: [PATCH 25/49] remove mageia --- .github/workflows/Linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/Linux.yml b/.github/workflows/Linux.yml index c74e9d3e..f3352a41 100644 --- a/.github/workflows/Linux.yml +++ b/.github/workflows/Linux.yml @@ -26,7 +26,7 @@ jobs: Linux: strategy: matrix: - os: ["ubuntu:latest", "debian:latest", "almalinux:latest", "fedora:latest", "opensuse/leap:latest", "alpine:latest", "oraclelinux:8", "kalilinux/kali", "archlinux:latest", "mageia", "gentoo/stage3"] + os: ["ubuntu:latest", "debian:latest", "almalinux:latest", "fedora:latest", "opensuse/leap:latest", "alpine:latest", "oraclelinux:8", "kalilinux/kali", "archlinux:latest", "gentoo/stage3"] runs-on: ubuntu-latest env: TEST_LOCAL: 1 From f22b490a10bf07317096511e59d7791fc13b4fb7 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 21 Sep 2025 18:04:59 +0200 Subject: [PATCH 26/49] remove buypass --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 9a5c106b..a8cb5403 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,6 @@ https://github.com/acmesh-official/acmetest - [ZeroSSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/ZeroSSL.com-CA)(default) - Letsencrypt.org CA -- [BuyPass.com CA](https://github.com/acmesh-official/acme.sh/wiki/BuyPass.com-CA) - [SSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/SSL.com-CA) - [Google.com Public CA](https://github.com/acmesh-official/acme.sh/wiki/Google-Public-CA) - [Pebble strict Mode](https://github.com/letsencrypt/pebble) From 5954f0dde54488d68bdd4c92ea2f0ab8ea1ee869 Mon Sep 17 00:00:00 2001 From: Jens Spanier Date: Mon, 22 Sep 2025 12:11:50 +0200 Subject: [PATCH 27/49] Change to `--cert-profile` --- acme.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index 7a8e4e9b..d157c2a4 100755 --- a/acme.sh +++ b/acme.sh @@ -7702,7 +7702,7 @@ _process() { _valid_to="$2" shift ;; - --certificate-profile | --profile) + --certificate-profile | --cert-profile) _certificate_profile="$2" shift ;; From 604e6873ba43609dc686f869e5c42a7d31547030 Mon Sep 17 00:00:00 2001 From: Jens Spanier Date: Mon, 22 Sep 2025 12:12:17 +0200 Subject: [PATCH 28/49] Add short name + wiki link to help --- acme.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index d157c2a4..ef3c592d 100755 --- a/acme.sh +++ b/acme.sh @@ -180,6 +180,8 @@ _VALIDITY_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Validity" _DNSCHECK_WIKI="https://github.com/acmesh-official/acme.sh/wiki/dnscheck" +_PROFILESELECTION_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Profile-selection" + _DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead." _DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR" @@ -7006,7 +7008,8 @@ Parameters: If no match, the default offered chain will be used. (default: empty) See: $_PREFERRED_CHAIN_WIKI - --certificate-profile If the CA offers profiles, select the desired profile + --cert-profile, --certificate-profile If the CA offers profiles, select the desired profile + See: $_PROFILESELECTION_WIKI --valid-to Request the NotAfter field of the cert. See: $_VALIDITY_WIKI From 11995b958ab560b2e8e60c816ba79200163047e9 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 27 Sep 2025 22:57:42 +0200 Subject: [PATCH 29/49] add actalis.com CA --- acme.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/acme.sh b/acme.sh index e895bbdc..23b03039 100755 --- a/acme.sh +++ b/acme.sh @@ -32,6 +32,8 @@ CA_SSLCOM_ECC="https://acme.ssl.com/sslcom-dv-ecc" CA_GOOGLE="https://dv.acme-v02.api.pki.goog/directory" CA_GOOGLE_TEST="https://dv.acme-v02.test-api.pki.goog/directory" +CA_ACTALIS="https://acme-api.actalis.com/acme/directory" + DEFAULT_CA=$CA_ZEROSSL DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST @@ -42,9 +44,10 @@ LetsEncrypt.org_test,letsencrypt_test,letsencrypttest SSL.com,sslcom Google.com,google Google.com_test,googletest,google_test +Actalis.com,actalis.com,actalis " -CA_SERVERS="$CA_ZEROSSL,$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_SSLCOM_RSA,$CA_GOOGLE,$CA_GOOGLE_TEST" +CA_SERVERS="$CA_ZEROSSL,$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_SSLCOM_RSA,$CA_GOOGLE,$CA_GOOGLE_TEST,$CA_ACTALIS" DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)" From e5214ea2e58c9a7fd5fb95f651a5cfc1193787f4 Mon Sep 17 00:00:00 2001 From: neil Date: Sat, 27 Sep 2025 23:12:05 +0200 Subject: [PATCH 30/49] add Actalis.com CA --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a8cb5403..f7038f59 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ https://github.com/acmesh-official/acmetest - Letsencrypt.org CA - [SSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/SSL.com-CA) - [Google.com Public CA](https://github.com/acmesh-official/acme.sh/wiki/Google-Public-CA) +- [Actalis.com CA](https://github.com/acmesh-official/acme.sh/wiki/Actalis.com-CA) - [Pebble strict Mode](https://github.com/letsencrypt/pebble) - Any other [RFC8555](https://tools.ietf.org/html/rfc8555)-compliant CA From b244c76dd5f316c55812c9ebd41012625e58e5a0 Mon Sep 17 00:00:00 2001 From: Steven Zhu Date: Sat, 27 Sep 2025 17:29:12 -0400 Subject: [PATCH 31/49] Add --list-profiles command to show CA profiles This commit introduces a new command, `--list-profiles`, to allow users to discover the certificate profiles supported by a Certificate Authority. The command queries the `meta.profiles` object within the ACME directory JSON for the selected server and formats the output for readability. If a CA does not publish profiles in its directory, the command reports that none were found. Usage: acme.sh --list-profiles [--server letsencrypt] --- acme.sh | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/acme.sh b/acme.sh index 23b03039..24ebc5d4 100755 --- a/acme.sh +++ b/acme.sh @@ -5838,6 +5838,49 @@ list() { } +list_profiles() { + _initpath + _initAPI + + _l_server_url="$ACME_DIRECTORY" + _l_server_name="$(_getCAShortName "$_l_server_url")" + _info "Fetching profiles from $_l_server_name ($_l_server_url)..." + + # _initAPI fetches the directory, so we just need to parse its response. + response=$(_get "$_l_server_url" "" 10) + if [ "$?" != "0" ]; then + _err "Failed to connect to CA directory: $_l_server_url" + return 1 + fi + + # Isolate the profiles object using the script's regex tool + profiles_json=$(echo "$response" | _egrep_o '"profiles" *: *\{[^\}]*\}') + + if [ -z "$profiles_json" ]; then + _info "The CA '$_l_server_name' does not publish certificate profiles via its directory endpoint." + return 0 + fi + + # Strip the outer layer to get the key-value pairs + profiles_kv=$(echo "$profiles_json" | sed 's/"profiles" *: *{//' | sed 's/}$//' | tr ',' '\n') + + printf "\n%-15s %s\n" "name" "info" + printf -- "--------------------------------------------------------------------\n" + + _old_IFS="$IFS" + IFS=' +' + for pair in $profiles_kv; do + # Trim quotes and whitespace + _name=$(echo "$pair" | cut -d: -f1 | tr -d '" \t') + _info_url=$(echo "$pair" | cut -d: -f2- | sed 's/^ *//' | tr -d '"') + printf "%-15s %s\n" "$_name" "$_info_url" + done + IFS="$_old_IFS" + + return 0 +} + _deploy() { _d="$1" _hooks="$2" @@ -7498,6 +7541,9 @@ _process() { --set-default-chain) _CMD="setdefaultchain" ;; + --list-profiles) + _CMD="list_profiles" + ;; -d | --domain) _dvalue="$2" @@ -8063,6 +8109,9 @@ _process() { setdefaultchain) setdefaultchain "$_preferred_chain" ;; + list_profiles) + list_profiles + ;; *) if [ "$_CMD" ]; then _err "Invalid command: $_CMD" From 80748b9fe0a3e9af6f8db7b97fb9bea69e8d7206 Mon Sep 17 00:00:00 2001 From: Steven Zhu Date: Sat, 27 Sep 2025 17:37:37 -0400 Subject: [PATCH 32/49] Quick Patch --- acme.sh | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/acme.sh b/acme.sh index 24ebc5d4..308db1aa 100755 --- a/acme.sh +++ b/acme.sh @@ -5846,15 +5846,14 @@ list_profiles() { _l_server_name="$(_getCAShortName "$_l_server_url")" _info "Fetching profiles from $_l_server_name ($_l_server_url)..." - # _initAPI fetches the directory, so we just need to parse its response. response=$(_get "$_l_server_url" "" 10) if [ "$?" != "0" ]; then _err "Failed to connect to CA directory: $_l_server_url" return 1 fi - # Isolate the profiles object using the script's regex tool - profiles_json=$(echo "$response" | _egrep_o '"profiles" *: *\{[^\}]*\}') + normalized_response=$(echo "$response" | _normalizeJson) + profiles_json=$(echo "$normalized_response" | _egrep_o '"profiles" *: *\{[^\}]*\}') if [ -z "$profiles_json" ]; then _info "The CA '$_l_server_name' does not publish certificate profiles via its directory endpoint." From 0f5093c0b7555c149ae2d7ab01d548dfd7844b2c Mon Sep 17 00:00:00 2001 From: Steven Zhu Date: Sat, 27 Sep 2025 17:52:44 -0400 Subject: [PATCH 33/49] Remove space --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index 308db1aa..e5a0885f 100755 --- a/acme.sh +++ b/acme.sh @@ -7542,7 +7542,7 @@ _process() { ;; --list-profiles) _CMD="list_profiles" - ;; + ;; -d | --domain) _dvalue="$2" @@ -8110,7 +8110,7 @@ _process() { ;; list_profiles) list_profiles - ;; + ;; *) if [ "$_CMD" ]; then _err "Invalid command: $_CMD" From d439933b52a0f251afaaa780acecff85d6eb3c29 Mon Sep 17 00:00:00 2001 From: Steven Zhu Date: Sun, 28 Sep 2025 19:20:08 -0400 Subject: [PATCH 34/49] add Profile column to --list output This commit adds a new "Profile" column to the output of the `--list` command. The column displays the value of the `Le_Certificate_Profile` variable stored in each domain's respective configuration file. If a profile is not set for a certificate, the column is left empty. This enhances the utility of the list command by providing more at-a-glance information about each certificate's configuration, which is particularly useful for CAs that support different certificate profiles. --- acme.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/acme.sh b/acme.sh index e5a0885f..7caec290 100755 --- a/acme.sh +++ b/acme.sh @@ -5804,7 +5804,7 @@ list() { _sep="|" if [ "$_raw" ]; then if [ -z "$_domain" ]; then - printf "%s\n" "Main_Domain${_sep}KeyLength${_sep}SAN_Domains${_sep}CA${_sep}Created${_sep}Renew" + printf "%s\n" "Main_Domain${_sep}KeyLength${_sep}SAN_Domains${_sep}Profile${_sep}CA${_sep}Created${_sep}Renew" fi for di in "${CERT_HOME}"/*.*/; do d=$(basename "$di") @@ -5819,7 +5819,7 @@ list() { . "$DOMAIN_CONF" _ca="$(_getCAShortName "$Le_API")" if [ -z "$_domain" ]; then - printf "%s\n" "$Le_Domain${_sep}\"$Le_Keylength\"${_sep}$Le_Alt${_sep}$_ca${_sep}$Le_CertCreateTimeStr${_sep}$Le_NextRenewTimeStr" + printf "%s\n" "$Le_Domain${_sep}\"$Le_Keylength\"${_sep}$Le_Alt${_sep}$Le_Certificate_Profile${_sep}$_ca${_sep}$Le_CertCreateTimeStr${_sep}$Le_NextRenewTimeStr" else if [ "$_domain" = "$d" ]; then cat "$DOMAIN_CONF" From 17da49bb782b797209531cb00cfcc8c3ee0370a8 Mon Sep 17 00:00:00 2001 From: Jens Spanier Date: Thu, 9 Oct 2025 13:16:28 +0200 Subject: [PATCH 35/49] add keyhelp deploy hook --- deploy/keyhelp.sh | 86 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 deploy/keyhelp.sh diff --git a/deploy/keyhelp.sh b/deploy/keyhelp.sh new file mode 100644 index 00000000..224a7ea8 --- /dev/null +++ b/deploy/keyhelp.sh @@ -0,0 +1,86 @@ +#!/usr/bin/env sh + +keyhelp_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + + # Read config from saved values or env + _getdeployconf DEPLOY_KEYHELP_HOST + _getdeployconf DEPLOY_KEYHELP_API_KEY + + _debug DEPLOY_KEYHELP_HOST "$DEPLOY_KEYHELP_HOST" + _secure_debug DEPLOY_KEYHELP_API_KEY "$DEPLOY_KEYHELP_API_KEY" + + if [ -z "$DEPLOY_KEYHELP_HOST" ]; then + _err "KeyHelp host not found, please define DEPLOY_KEYHELP_HOST." + return 1 + fi + if [ -z "$DEPLOY_KEYHELP_API_KEY" ]; then + _err "KeyHelp api key not found, please define DEPLOY_KEYHELP_API_KEY." + return 1 + fi + + # Save current values + _savedeployconf DEPLOY_KEYHELP_HOST "$DEPLOY_KEYHELP_HOST" + _savedeployconf DEPLOY_KEYHELP_API_KEY "$DEPLOY_KEYHELP_API_KEY" + + _request_key="$(tr '\n' ':' <"$_ckey" | sed 's/:/\\n/g')" + _request_cert="$(tr '\n' ':' <"$_ccert" | sed 's/:/\\n/g')" + _request_ca="$(tr '\n' ':' <"$_cca" | sed 's/:/\\n/g')" + + _request_body="{ + \"name\": \"$_cdomain\", + \"components\": { + \"private_key\": \"$_request_key\", + \"certificate\": \"$_request_cert\", + \"ca_certificate\": \"$_request_ca\" + } + }" + + _hosts="$(echo "$DEPLOY_KEYHELP_HOST" | tr "," " ")" + _keys="$(echo "$DEPLOY_KEYHELP_API_KEY" | tr "," " ")" + _i=1 + + for _host in $_hosts; do + _key="$(_getfield "$_keys" "$_i" " ")" + _i="$(_math $_i + 1)" + + export _H1="X-API-Key: $_key" + + _put_url="$_host/api/v2/certificates/name/$_cdomain" + if _post "$_request_body" "$_put_url" "" "PUT" "application/json" >/dev/null; then + _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")" + else + _err "Cannot make PUT request to $_put_url" + return 1 + fi + + if [ "$_code" = "404" ]; then + _info "$_cdomain not found, creating new entry at $_host" + + _post_url="$_host/api/v2/certificates" + if _post "$_request_body" "$_post_url" "" "POST" "application/json" >/dev/null; then + _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")" + else + _err "Cannot make POST request to $_post_url" + return 1 + fi + fi + + if _startswith "$_code" "2"; then + _info "$_cdomain set at $_host" + else + _err "HTTP status code is $_code" + return 1 + fi + done + + return 0 +} From f7cc72be354c9cf90fc16e270fa0f7bb01ea1825 Mon Sep 17 00:00:00 2001 From: Jens Spanier Date: Thu, 9 Oct 2025 13:28:04 +0200 Subject: [PATCH 36/49] add missing double quotes --- deploy/keyhelp.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/keyhelp.sh b/deploy/keyhelp.sh index 224a7ea8..944ca5aa 100644 --- a/deploy/keyhelp.sh +++ b/deploy/keyhelp.sh @@ -50,7 +50,7 @@ keyhelp_deploy() { for _host in $_hosts; do _key="$(_getfield "$_keys" "$_i" " ")" - _i="$(_math $_i + 1)" + _i="$(_math "$_i" + 1)" export _H1="X-API-Key: $_key" From 25c564bae1efb7d01388b63752976957aa5dfb6b Mon Sep 17 00:00:00 2001 From: Vmichelin Date: Tue, 14 Oct 2025 10:10:19 +0200 Subject: [PATCH 37/49] fix #6555 : ovh dns api enable to remove record --- dnsapi/dns_ovh.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_ovh.sh b/dnsapi/dns_ovh.sh index 24ad0904..9f2cd23f 100755 --- a/dnsapi/dns_ovh.sh +++ b/dnsapi/dns_ovh.sh @@ -201,7 +201,7 @@ dns_ovh_rm() { if ! _ovh_rest GET "domain/zone/$_domain/record/$rid"; then return 1 fi - if _contains "$response" "\"target\":\"$txtvalue\""; then + if _contains "$response" "$txtvalue"; then _debug "Found txt id:$rid" if ! _ovh_rest DELETE "domain/zone/$_domain/record/$rid"; then return 1 From a2c2b7ffee184d3e8f4c4ccf63685ffdb68232c0 Mon Sep 17 00:00:00 2001 From: DuolaD Date: Sat, 18 Oct 2025 11:41:26 +0800 Subject: [PATCH 38/49] Fixed the issue where Telegram bots would not push notifications. --- notify/telegram.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/notify/telegram.sh b/notify/telegram.sh index 7da05729..4ed50a65 100644 --- a/notify/telegram.sh +++ b/notify/telegram.sh @@ -34,8 +34,8 @@ telegram_send() { fi _saveaccountconf_mutable TELEGRAM_BOT_URLBASE "$TELEGRAM_BOT_URLBASE" - _subject="$(printf "%s" "$_subject" | sed 's/\\/\\\\\\\\/g' | sed 's/\]/\\\\\]/g' | sed 's/\([-_*[()~`>#+\-=|{}.!]\)/\\\\\1/g')" - _content="$(printf "%s" "$_content" | sed 's/\\/\\\\\\\\/g' | sed 's/\]/\\\\\]/g' | sed 's/\([-_*[()~`>#+\-=|{}.!]\)/\\\\\1/g')" + _subject="$(printf "%s" "$_subject" | sed -E 's/([][()~`>#+=|{}.!*_\\-])/\\\\\1/g')" + _content="$(printf "%s" "$_content" | sed -E 's/([][()~`>#+=|{}.!*_\\-])/\\\\\1/g')" _content="$(printf "*%s*\n%s" "$_subject" "$_content" | _json_encode)" _data="{\"text\": \"$_content\", " _data="$_data\"chat_id\": \"$TELEGRAM_BOT_CHATID\", " From 3cdce86339d8ace8ba62c4ed756138bad669457d Mon Sep 17 00:00:00 2001 From: Jens Spanier Date: Tue, 21 Oct 2025 11:34:46 +0200 Subject: [PATCH 39/49] rename to keyhelp_api --- deploy/{keyhelp.sh => keyhelp_api.sh} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename deploy/{keyhelp.sh => keyhelp_api.sh} (99%) diff --git a/deploy/keyhelp.sh b/deploy/keyhelp_api.sh similarity index 99% rename from deploy/keyhelp.sh rename to deploy/keyhelp_api.sh index 944ca5aa..75e9d951 100644 --- a/deploy/keyhelp.sh +++ b/deploy/keyhelp_api.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -keyhelp_deploy() { +keyhelp_api_deploy() { _cdomain="$1" _ckey="$2" _ccert="$3" From 7c5b9a5b922e5bed34f64fda6b58b257820955b9 Mon Sep 17 00:00:00 2001 From: Dennis Schmidt Date: Thu, 30 Oct 2025 09:17:13 +0000 Subject: [PATCH 40/49] Add priority, tags and title to ntfy notification Make the ntfy.sh notifications easier to distinguish at a first glance. --- notify/ntfy.sh | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/notify/ntfy.sh b/notify/ntfy.sh index 21e39559..ecb65879 100644 --- a/notify/ntfy.sh +++ b/notify/ntfy.sh @@ -14,6 +14,13 @@ ntfy_send() { _debug "_content" "$_content" _debug "_statusCode" "$_statusCode" + _priority_default="default" + _priority_error="high" + + _tag_success="white_check_mark" + _tag_error="warning" + _tag_info="information_source" + NTFY_URL="${NTFY_URL:-$(_readaccountconf_mutable NTFY_URL)}" if [ "$NTFY_URL" ]; then _saveaccountconf_mutable NTFY_URL "$NTFY_URL" @@ -30,7 +37,26 @@ ntfy_send() { export _H1="Authorization: Bearer $NTFY_TOKEN" fi - _data="${_subject}. $_content" + case "$_statusCode" in + 0) + _priority="$_priority_default" + _tag="$_tag_success" + ;; + 1) + _priority="$_priority_error" + _tag="$_tag_error" + ;; + 2) + _priority="$_priority_default" + _tag="$_tag_info" + ;; + esac + + export _H2="Priority: $_priority" + export _H3="Tags: $_tag" + export _H4="Title: $PROJECT_NAME: $_subject" + + _data="$_content" response="$(_post "$_data" "$NTFY_URL/$NTFY_TOPIC" "" "POST" "")" if [ "$?" = "0" ] && _contains "$response" "expires"; then From 3d21ac4525b2b60bd5efd1b9d23e9822a8be0ded Mon Sep 17 00:00:00 2001 From: Dennis Schmidt Date: Fri, 31 Oct 2025 08:40:34 +0000 Subject: [PATCH 41/49] CS Make shfmt happy --- notify/ntfy.sh | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/notify/ntfy.sh b/notify/ntfy.sh index ecb65879..3a788a84 100644 --- a/notify/ntfy.sh +++ b/notify/ntfy.sh @@ -38,18 +38,18 @@ ntfy_send() { fi case "$_statusCode" in - 0) - _priority="$_priority_default" - _tag="$_tag_success" - ;; - 1) - _priority="$_priority_error" - _tag="$_tag_error" - ;; - 2) - _priority="$_priority_default" - _tag="$_tag_info" - ;; + 0) + _priority="$_priority_default" + _tag="$_tag_success" + ;; + 1) + _priority="$_priority_error" + _tag="$_tag_error" + ;; + 2) + _priority="$_priority_default" + _tag="$_tag_info" + ;; esac export _H2="Priority: $_priority" From 693b1f7a74a52ed3a1499f64b9ebfe2bfc70f0ad Mon Sep 17 00:00:00 2001 From: Richard Glidden Date: Sun, 2 Nov 2025 22:50:55 -0500 Subject: [PATCH 42/49] Fix TrueNAS deploy fails on TrueNAS 25.10 --- deploy/truenas_ws.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/truenas_ws.sh b/deploy/truenas_ws.sh index d334853e..df34f927 100644 --- a/deploy/truenas_ws.sh +++ b/deploy/truenas_ws.sh @@ -71,7 +71,7 @@ with Client(uri="$_ws_uri") as c: fullchain = file.read() with open('$2', 'r') as file: privatekey = file.read() - ret = c.call("certificate.create", {"name": "$3", "create_type": "CERTIFICATE_CREATE_IMPORTED", "certificate": fullchain, "privatekey": privatekey, "passphrase": ""}, job=True) + ret = c.call("certificate.create", {"name": "$3", "create_type": "CERTIFICATE_CREATE_IMPORTED", "certificate": fullchain, "privatekey": privatekey}, job=True) print("R:" + str(ret["id"])) sys.exit(0) else: From b7c8601540d1296e5409387f171c1898620b8c38 Mon Sep 17 00:00:00 2001 From: Peter Lindegaard Hansen Date: Mon, 3 Nov 2025 16:18:15 +0100 Subject: [PATCH 43/49] Update dns_curanet.sh --- dnsapi/dns_curanet.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_curanet.sh b/dnsapi/dns_curanet.sh index f57afa1f..42bc28f2 100644 --- a/dnsapi/dns_curanet.sh +++ b/dnsapi/dns_curanet.sh @@ -154,7 +154,7 @@ _get_root() { export _H3="Authorization: Bearer $CURANET_ACCESS_TOKEN" response="$(_get "$CURANET_REST_URL/$h/Records" "" "")" - if [ ! "$(echo "$response" | _egrep_o "Entity not found")" ]; then + if [ ! "$(echo "$response" | _egrep_o "Entity not found|Bad Request")" ]; then _domain=$h return 0 fi From d187b982eb922c4ba09ec8085655a760794f7edf Mon Sep 17 00:00:00 2001 From: Peter Lindegaard Hansen Date: Mon, 3 Nov 2025 18:14:27 +0100 Subject: [PATCH 44/49] Update dns_curanet.sh --- dnsapi/dns_curanet.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dnsapi/dns_curanet.sh b/dnsapi/dns_curanet.sh index 42bc28f2..0ef03fea 100644 --- a/dnsapi/dns_curanet.sh +++ b/dnsapi/dns_curanet.sh @@ -15,7 +15,7 @@ CURANET_REST_URL="https://api.curanet.dk/dns/v1/Domains" CURANET_AUTH_URL="https://apiauth.dk.team.blue/auth/realms/Curanet/protocol/openid-connect/token" CURANET_ACCESS_TOKEN="" -######## Public functions ##################### +######## Public functions #################### #Usage: dns_curanet_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" dns_curanet_add() { From 0fa53d62cbfcea7ae5626f3d90bd66e4bef2c731 Mon Sep 17 00:00:00 2001 From: seagleNet Date: Tue, 4 Nov 2025 09:35:47 +0100 Subject: [PATCH 45/49] feat: Add notify plugin for opsgenie --- notify/opsgenie.sh | 130 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 notify/opsgenie.sh diff --git a/notify/opsgenie.sh b/notify/opsgenie.sh new file mode 100644 index 00000000..d352a18c --- /dev/null +++ b/notify/opsgenie.sh @@ -0,0 +1,130 @@ +#!/usr/bin/env sh + +#Support OpsGenie API integration + +#OPSGENIE_API_KEY="" Required, opsgenie api key +#OPSGENIE_REGION="" Optional, opsgenie region, can be EU or US (default: US) +#OPSGENIE_PRIORITY_SUCCESS="" Optional, opsgenie priority for success (default: P5) +#OPSGENIE_PRIORITY_ERROR="" Optional, opsgenie priority for error (default: P2) +#OPSGENIE_PRIORITY_SKIP="" Optional, opsgenie priority for renew skipped (default: P5) + +_OPSGENIE_AVAIL_REGION="US,EU" +_OPSGENIE_AVAIL_PRIORITIES="P1,P2,P3,P4,P5" + +opsgenie_send() { + _subject="$1" + _content="$2" + _status_code="$3" #0: success, 1: error, 2($RENEW_SKIP): skipped + + OPSGENIE_API_KEY="${OPSGENIE_API_KEY:-$(_readaccountconf_mutable OPSGENIE_API_KEY)}" + if [ -z "$OPSGENIE_API_KEY" ]; then + OPSGENIE_API_KEY="" + _err "You didn't specify an OpsGenie API key OPSGENIE_API_KEY yet." + return 1 + fi + _saveaccountconf_mutable OPSGENIE_API_KEY "$OPSGENIE_API_KEY" + export _H1="Authorization: GenieKey $OPSGENIE_API_KEY" + + OPSGENIE_REGION="${OPSGENIE_REGION:-$(_readaccountconf_mutable OPSGENIE_REGION)}" + if [ -z "$OPSGENIE_REGION" ]; then + OPSGENIE_REGION="US" + _info "The OPSGENIE_REGION is not set, so use the default US as regeion." + elif ! _hasfield "$_OPSGENIE_AVAIL_REGION" "$OPSGENIE_REGION"; then + _err "The OPSGENIE_REGION \"$OPSGENIE_REGION\" is not available, should be one of $_OPSGENIE_AVAIL_REGION" + OPSGENIE_REGION="" + return 1 + else + _saveaccountconf_mutable OPSGENIE_REGION "$OPSGENIE_REGION" + fi + + OPSGENIE_PRIORITY_SUCCESS="${OPSGENIE_PRIORITY_SUCCESS:-$(_readaccountconf_mutable OPSGENIE_PRIORITY_SUCCESS)}" + if [ -z "$OPSGENIE_PRIORITY_SUCCESS" ]; then + OPSGENIE_PRIORITY_SUCCESS="P5" + _info "The OPSGENIE_PRIORITY_SUCCESS is not set, so use the default P5 as priority." + elif ! _hasfield "$_OPSGENIE_AVAIL_PRIORITIES" "$OPSGENIE_PRIORITY_SUCCESS"; then + _err "The OPSGENIE_PRIORITY_SUCCESS \"$OPSGENIE_PRIORITY_SUCCESS\" is not available, should be one of $_OPSGENIE_AVAIL_PRIORITIES" + OPSGENIE_PRIORITY_SUCCESS="" + return 1 + else + _saveaccountconf_mutable OPSGENIE_PRIORITY_SUCCESS "$OPSGENIE_PRIORITY_SUCCESS" + fi + + OPSGENIE_PRIORITY_ERROR="${OPSGENIE_PRIORITY_ERROR:-$(_readaccountconf_mutable OPSGENIE_PRIORITY_ERROR)}" + if [ -z "$OPSGENIE_PRIORITY_ERROR" ]; then + OPSGENIE_PRIORITY_ERROR="P2" + _info "The OPSGENIE_PRIORITY_ERROR is not set, so use the default P2 as priority." + elif ! _hasfield "$_OPSGENIE_AVAIL_PRIORITIES" "$OPSGENIE_PRIORITY_ERROR"; then + _err "The OPSGENIE_PRIORITY_ERROR \"$OPSGENIE_PRIORITY_ERROR\" is not available, should be one of $_OPSGENIE_AVAIL_PRIORITIES" + OPSGENIE_PRIORITY_ERROR="" + return 1 + else + _saveaccountconf_mutable OPSGENIE_PRIORITY_ERROR "$OPSGENIE_PRIORITY_ERROR" + fi + + OPSGENIE_PRIORITY_SKIP="${OPSGENIE_PRIORITY_SKIP:-$(_readaccountconf_mutable OPSGENIE_PRIORITY_SKIP)}" + if [ -z "$OPSGENIE_PRIORITY_SKIP" ]; then + OPSGENIE_PRIORITY_SKIP="P5" + _info "The OPSGENIE_PRIORITY_SKIP is not set, so use the default P5 as priority." + elif ! _hasfield "$_OPSGENIE_AVAIL_PRIORITIES" "$OPSGENIE_PRIORITY_SKIP"; then + _err "The OPSGENIE_PRIORITY_SKIP \"$OPSGENIE_PRIORITY_SKIP\" is not available, should be one of $_OPSGENIE_AVAIL_PRIORITIES" + OPSGENIE_PRIORITY_SKIP="" + return 1 + else + _saveaccountconf_mutable OPSGENIE_PRIORITY_SKIP "$OPSGENIE_PRIORITY_SKIP" + fi + + case "$OPSGENIE_REGION" in + "US") + _opsgenie_url="https://api.opsgenie.com/v2/alerts" + ;; + "EU") + _opsgenie_url="https://api.eu.opsgenie.com/v2/alerts" + ;; + *) + _err "opsgenie region error." + return 1 + ;; + esac + + case $_status_code in + 0) + _priority=$OPSGENIE_PRIORITY_SUCCESS + ;; + 1) + _priority=$OPSGENIE_PRIORITY_ERROR + ;; + 2) + _priority=$OPSGENIE_PRIORITY_SKIP + ;; + *) + _priority=$OPSGENIE_PRIORITY_ERROR + ;; + esac + + _subject_json=$(echo "$_subject" | _json_encode) + _content_json=$(echo "$_content" | _json_encode) + _subject_underscore=$(echo "$_subject" | sed 's/ /_/g') + _alias_json=$(echo "acme.sh-$(hostname)-$_subject_underscore-$(date +%Y%m%d)" | base64 --wrap=0 | _json_encode) + + _data="{ + \"message\": \"$_subject_json\", + \"alias\": \"$_alias_json\", + \"description\": \"$_content_json\", + \"tags\": [ + \"acme.sh\", + \"host:$(hostname)\" + ], + \"entity\": \"$(hostname -f)\", + \"priority\": \"$_priority\" +}" + + if response=$(_post "$_data" "$_opsgenie_url" "" "" "application/json"); then + if ! _contains "$response" error; then + _info "opsgenie send success." + return 0 + fi + fi + _err "opsgenie send error." + _err "$response" + return 1 +} From c5f41479a909f1a7cad58b74dcaedc880c7fc495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20V=C3=A1mos?= Date: Fri, 7 Nov 2025 16:16:30 +0100 Subject: [PATCH 46/49] Bump Alpine version from 3.21 to 3.22 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7523f0af..d8f8b265 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.21 +FROM alpine:3.22 RUN apk --no-cache add -f \ openssl \ From 59a286b0b76b088915455ead9e9015037d5fd579 Mon Sep 17 00:00:00 2001 From: privacyfr3ak <220089342+privacyfr3ak@users.noreply.github.com> Date: Sat, 8 Nov 2025 16:59:10 -0500 Subject: [PATCH 47/49] disable shellcheck --- deploy/unifi.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deploy/unifi.sh b/deploy/unifi.sh index 2af46b4a..1d13e04f 100644 --- a/deploy/unifi.sh +++ b/deploy/unifi.sh @@ -143,7 +143,9 @@ unifi_deploy() { # correct file ownership according to the directory, the keystore is placed in _unifi_keystore_dir=$(dirname "${_unifi_keystore}") + # shellcheck disable=SC2012 _unifi_keystore_dir_owner=$(ls -ld "${_unifi_keystore_dir}" | awk '{print $3}') + # shellcheck disable=SC2012 _unifi_keystore_owner=$(ls -l "${_unifi_keystore}" | awk '{print $3}') if ! [ "${_unifi_keystore_owner}" = "${_unifi_keystore_dir_owner}" ]; then _debug "Changing keystore owner to ${_unifi_keystore_dir_owner}" From 839d611f642ee5e739ecb6006e0347d2067d2ccf Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 9 Nov 2025 18:50:09 +0100 Subject: [PATCH 48/49] use ghcr.io/letsencrypt/pebble:latest --- .github/workflows/PebbleStrict.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/PebbleStrict.yml b/.github/workflows/PebbleStrict.yml index b0326332..af6aab4f 100644 --- a/.github/workflows/PebbleStrict.yml +++ b/.github/workflows/PebbleStrict.yml @@ -65,7 +65,7 @@ jobs: run: | docker run --rm -itd --name=pebble \ -e PEBBLE_VA_ALWAYS_VALID=1 \ - -p 14000:14000 -p 15000:15000 letsencrypt/pebble:latest pebble -config /test/config/pebble-config.json -strict + -p 14000:14000 -p 15000:15000 ghcr.io/letsencrypt/pebble:latest pebble -config /test/config/pebble-config.json -strict - name: Clone acmetest run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Run acmetest From 9a994e7f36532169da970dcada70b537bfdb6128 Mon Sep 17 00:00:00 2001 From: neil Date: Sun, 9 Nov 2025 19:03:30 +0100 Subject: [PATCH 49/49] fix --- .github/workflows/PebbleStrict.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/PebbleStrict.yml b/.github/workflows/PebbleStrict.yml index af6aab4f..729874ce 100644 --- a/.github/workflows/PebbleStrict.yml +++ b/.github/workflows/PebbleStrict.yml @@ -65,7 +65,7 @@ jobs: run: | docker run --rm -itd --name=pebble \ -e PEBBLE_VA_ALWAYS_VALID=1 \ - -p 14000:14000 -p 15000:15000 ghcr.io/letsencrypt/pebble:latest pebble -config /test/config/pebble-config.json -strict + -p 14000:14000 -p 15000:15000 ghcr.io/letsencrypt/pebble:latest -config /test/config/pebble-config.json -strict - name: Clone acmetest run: cd .. && git clone --depth=1 https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ - name: Run acmetest