From 5a730bf00d705c7914dc630ecc5149b3bd9ad87e Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Thu, 20 Feb 2025 21:42:11 +0100 Subject: [PATCH 01/41] implemented checking deploy file --- deploy/multideploy.sh | 114 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 deploy/multideploy.sh diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh new file mode 100644 index 00000000..ba57afa1 --- /dev/null +++ b/deploy/multideploy.sh @@ -0,0 +1,114 @@ +#!/usr/bin/env sh + +# MULTIDEPLOY_CONFIG="default" + +######## Public functions ##################### + +MULTIDEPLOY_VERSION="1.0" +MULTIDEPLOY_FILENAME="multideploy.yaml" + +# domain keyfile certfile cafile fullchain pfx +multideploy_deploy() { + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + _cpfx="$6" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + _debug _cpfx "$_cpfx" + + DOMAIN_DIR=$_cdomain + if echo "$DOMAIN_PATH" | grep -q "$ECC_SUFFIX"; then + DOMAIN_DIR="$DOMAIN_DIR"_ecc + fi + _debug2 "DOMAIN_DIR" "$DOMAIN_DIR" + + _preprocess_deployfile "$DOMAIN_DIR/$MULTIDEPLOY_FILENAME" + + MULTIDEPLOY_CONFIG="${MULTIDEPLOY_CONFIG:-$(_getdeployconf MULTIDEPLOY_CONFIG)}" + if [ -z "$MULTIDEPLOY_CONFIG" ]; then + MULTIDEPLOY_CONFIG="default" + _info "MULTIDEPLOY_CONFIG is not set, so I will use 'default'." + else + _savedeployconf "MULTIDEPLOY_CONFIG" "$MULTIDEPLOY_CONFIG" + _debug2 "MULTIDEPLOY_CONFIG" "$MULTIDEPLOY_CONFIG" + fi + + # TODO: Deploy to services +} + +#################### Private functions below ##################### + +# deploy_filepath +_preprocess_deployfile() { + deploy_file="$1" + + # Check if yq is installed + if ! command -v yq >/dev/null 2>&1; then + _err "yq is not installed! Please install yq and try again." + return 1 + fi + + # Check if deploy file exists and create a default template if not + if [ -f "$deploy_file" ]; then + _debug3 "Deploy file found." + _check_deployfile "$deploy_file" "$MULTIDEPLOY_CONFIG" + else + # TODO: Replace URL with wiki link + _err "Deploy file not found. Go to https://CHANGE_URL_TO_WIKI to see how to create one." + return 1 + fi +} + +# deploy_filepath deploy_config +_check_deployfile() { + deploy_file="$1" + deploy_config="$3" + + # Check version + deploy_file_version=$(yq '.version' "$deploy_file") + if [ "$MULTIDEPLOY_VERSION" != "$deploy_file_version" ]; then + _err "As of $PROJECT_NAME $VER, the deploy file needs version $MULTIDEPLOY_VERSION! Your current deploy file is of version $deploy_file_version." + return 1 + fi + + # Check if config exists + if ! yq e ".configs[] | select(.name == \"$deploy_config\")" "$deploy_file" >/dev/null; then + _err "Config '$deploy_config' not found." + return 1 + fi + + # Extract all services from config + services=$(yq e ".configs[] | select(.name == \"$deploy_config\").services[]" "$deploy_file") + + if [ -z "$services" ]; then + _err "Config '$deploy_config' does not have any services to deploy to." + return 1 + fi + + # Check if extracted services exist in services list + for service in $services; do + if ! yq e ".services[] | select(.name == \"$service\")" "$deploy_file" >/dev/null; then + _err "Service '$service' not found." + return 1 + fi + + # Check if service has hook + if ! yq e ".services[] | select(.name == \"$service\").hook" "$deploy_file" >/dev/null; then + _err "Service '$service' does not have a hook." + return 1 + fi + + # Check if service has environment + if ! yq e ".services[] | select(.name == \"$service\").environment" "$deploy_file" >/dev/null; then + _err "Service '$service' does not an environment." + return 1 + fi + done +} From 3c184486c3b0749bfa6d1812071d3f099a155815 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Thu, 20 Feb 2025 21:56:28 +0100 Subject: [PATCH 02/41] fixed indents --- deploy/multideploy.sh | 174 +++++++++++++++++++++--------------------- 1 file changed, 87 insertions(+), 87 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index ba57afa1..08e0aba6 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -9,106 +9,106 @@ MULTIDEPLOY_FILENAME="multideploy.yaml" # domain keyfile certfile cafile fullchain pfx multideploy_deploy() { - _cdomain="$1" - _ckey="$2" - _ccert="$3" - _cca="$4" - _cfullchain="$5" - _cpfx="$6" - - _debug _cdomain "$_cdomain" - _debug _ckey "$_ckey" - _debug _ccert "$_ccert" - _debug _cca "$_cca" - _debug _cfullchain "$_cfullchain" - _debug _cpfx "$_cpfx" - - DOMAIN_DIR=$_cdomain - if echo "$DOMAIN_PATH" | grep -q "$ECC_SUFFIX"; then - DOMAIN_DIR="$DOMAIN_DIR"_ecc - fi - _debug2 "DOMAIN_DIR" "$DOMAIN_DIR" - - _preprocess_deployfile "$DOMAIN_DIR/$MULTIDEPLOY_FILENAME" - - MULTIDEPLOY_CONFIG="${MULTIDEPLOY_CONFIG:-$(_getdeployconf MULTIDEPLOY_CONFIG)}" - if [ -z "$MULTIDEPLOY_CONFIG" ]; then - MULTIDEPLOY_CONFIG="default" - _info "MULTIDEPLOY_CONFIG is not set, so I will use 'default'." - else - _savedeployconf "MULTIDEPLOY_CONFIG" "$MULTIDEPLOY_CONFIG" - _debug2 "MULTIDEPLOY_CONFIG" "$MULTIDEPLOY_CONFIG" - fi - - # TODO: Deploy to services + _cdomain="$1" + _ckey="$2" + _ccert="$3" + _cca="$4" + _cfullchain="$5" + _cpfx="$6" + + _debug _cdomain "$_cdomain" + _debug _ckey "$_ckey" + _debug _ccert "$_ccert" + _debug _cca "$_cca" + _debug _cfullchain "$_cfullchain" + _debug _cpfx "$_cpfx" + + DOMAIN_DIR=$_cdomain + if echo "$DOMAIN_PATH" | grep -q "$ECC_SUFFIX"; then + DOMAIN_DIR="$DOMAIN_DIR"_ecc + fi + _debug2 "DOMAIN_DIR" "$DOMAIN_DIR" + + _preprocess_deployfile "$DOMAIN_DIR/$MULTIDEPLOY_FILENAME" + + MULTIDEPLOY_CONFIG="${MULTIDEPLOY_CONFIG:-$(_getdeployconf MULTIDEPLOY_CONFIG)}" + if [ -z "$MULTIDEPLOY_CONFIG" ]; then + MULTIDEPLOY_CONFIG="default" + _info "MULTIDEPLOY_CONFIG is not set, so I will use 'default'." + else + _savedeployconf "MULTIDEPLOY_CONFIG" "$MULTIDEPLOY_CONFIG" + _debug2 "MULTIDEPLOY_CONFIG" "$MULTIDEPLOY_CONFIG" + fi + + # TODO: Deploy to services } #################### Private functions below ##################### # deploy_filepath _preprocess_deployfile() { - deploy_file="$1" - - # Check if yq is installed - if ! command -v yq >/dev/null 2>&1; then - _err "yq is not installed! Please install yq and try again." - return 1 - fi - - # Check if deploy file exists and create a default template if not - if [ -f "$deploy_file" ]; then - _debug3 "Deploy file found." - _check_deployfile "$deploy_file" "$MULTIDEPLOY_CONFIG" - else - # TODO: Replace URL with wiki link - _err "Deploy file not found. Go to https://CHANGE_URL_TO_WIKI to see how to create one." - return 1 - fi + deploy_file="$1" + + # Check if yq is installed + if ! command -v yq >/dev/null 2>&1; then + _err "yq is not installed! Please install yq and try again." + return 1 + fi + + # Check if deploy file exists and create a default template if not + if [ -f "$deploy_file" ]; then + _debug3 "Deploy file found." + _check_deployfile "$deploy_file" "$MULTIDEPLOY_CONFIG" + else + # TODO: Replace URL with wiki link + _err "Deploy file not found. Go to https://CHANGE_URL_TO_WIKI to see how to create one." + return 1 + fi } # deploy_filepath deploy_config _check_deployfile() { - deploy_file="$1" - deploy_config="$3" - - # Check version - deploy_file_version=$(yq '.version' "$deploy_file") - if [ "$MULTIDEPLOY_VERSION" != "$deploy_file_version" ]; then - _err "As of $PROJECT_NAME $VER, the deploy file needs version $MULTIDEPLOY_VERSION! Your current deploy file is of version $deploy_file_version." - return 1 + deploy_file="$1" + deploy_config="$3" + + # Check version + deploy_file_version=$(yq '.version' "$deploy_file") + if [ "$MULTIDEPLOY_VERSION" != "$deploy_file_version" ]; then + _err "As of $PROJECT_NAME $VER, the deploy file needs version $MULTIDEPLOY_VERSION! Your current deploy file is of version $deploy_file_version." + return 1 + fi + + # Check if config exists + if ! yq e ".configs[] | select(.name == \"$deploy_config\")" "$deploy_file" >/dev/null; then + _err "Config '$deploy_config' not found." + return 1 + fi + + # Extract all services from config + services=$(yq e ".configs[] | select(.name == \"$deploy_config\").services[]" "$deploy_file") + + if [ -z "$services" ]; then + _err "Config '$deploy_config' does not have any services to deploy to." + return 1 + fi + + # Check if extracted services exist in services list + for service in $services; do + if ! yq e ".services[] | select(.name == \"$service\")" "$deploy_file" >/dev/null; then + _err "Service '$service' not found." + return 1 fi - # Check if config exists - if ! yq e ".configs[] | select(.name == \"$deploy_config\")" "$deploy_file" >/dev/null; then - _err "Config '$deploy_config' not found." - return 1 + # Check if service has hook + if ! yq e ".services[] | select(.name == \"$service\").hook" "$deploy_file" >/dev/null; then + _err "Service '$service' does not have a hook." + return 1 fi - # Extract all services from config - services=$(yq e ".configs[] | select(.name == \"$deploy_config\").services[]" "$deploy_file") - - if [ -z "$services" ]; then - _err "Config '$deploy_config' does not have any services to deploy to." - return 1 + # Check if service has environment + if ! yq e ".services[] | select(.name == \"$service\").environment" "$deploy_file" >/dev/null; then + _err "Service '$service' does not an environment." + return 1 fi - - # Check if extracted services exist in services list - for service in $services; do - if ! yq e ".services[] | select(.name == \"$service\")" "$deploy_file" >/dev/null; then - _err "Service '$service' not found." - return 1 - fi - - # Check if service has hook - if ! yq e ".services[] | select(.name == \"$service\").hook" "$deploy_file" >/dev/null; then - _err "Service '$service' does not have a hook." - return 1 - fi - - # Check if service has environment - if ! yq e ".services[] | select(.name == \"$service\").environment" "$deploy_file" >/dev/null; then - _err "Service '$service' does not an environment." - return 1 - fi - done + done } From b2eb1d2bbc8fed4f940afa1fb20a4e0beb33bf3a Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Thu, 20 Feb 2025 23:02:56 +0100 Subject: [PATCH 03/41] refactored getting services --- deploy/multideploy.sh | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 08e0aba6..2a83a19f 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -85,7 +85,7 @@ _check_deployfile() { fi # Extract all services from config - services=$(yq e ".configs[] | select(.name == \"$deploy_config\").services[]" "$deploy_file") + services=$(_get_services_list "$deploy_file" "$deploy_config") if [ -z "$services" ]; then _err "Config '$deploy_config' does not have any services to deploy to." @@ -112,3 +112,29 @@ _check_deployfile() { fi done } + +# deploy_filepath deploy_config +_get_services_list() { + deploy_file="$1" + deploy_config="$2" + + services=$(yq e ".configs[] | select(.name == \"$deploy_config\").services[]" "$deploy_file") + echo "$services" +} + +# deploy_filepath service_names +_get_full_services_list() { + deploy_file="$1" + shift + service_names="$*" + + full_services="" + for service in $service_names; do + full_service=$(yq e ".services[] | select(.name == \"$service\")" "$deploy_file") + full_services="$full_services +$full_service" + done + + echo "$full_services" +} + From 0ed5e21232ddcf821f47a1bd223fd05511494775 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Fri, 21 Feb 2025 10:49:08 +0100 Subject: [PATCH 04/41] fixed formatting and private var names --- deploy/multideploy.sh | 68 +++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 2a83a19f..245c95a6 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -29,7 +29,7 @@ multideploy_deploy() { fi _debug2 "DOMAIN_DIR" "$DOMAIN_DIR" - _preprocess_deployfile "$DOMAIN_DIR/$MULTIDEPLOY_FILENAME" + _preprocess_deployfile "$DOMAIN_DIR/$MULTIDEPLOY_FILENAME" || return 1 MULTIDEPLOY_CONFIG="${MULTIDEPLOY_CONFIG:-$(_getdeployconf MULTIDEPLOY_CONFIG)}" if [ -z "$MULTIDEPLOY_CONFIG" ]; then @@ -47,7 +47,7 @@ multideploy_deploy() { # deploy_filepath _preprocess_deployfile() { - deploy_file="$1" + _deploy_file="$1" # Check if yq is installed if ! command -v yq >/dev/null 2>&1; then @@ -56,9 +56,9 @@ _preprocess_deployfile() { fi # Check if deploy file exists and create a default template if not - if [ -f "$deploy_file" ]; then + if [ -f "$_deploy_file" ]; then _debug3 "Deploy file found." - _check_deployfile "$deploy_file" "$MULTIDEPLOY_CONFIG" + _check_deployfile "$_deploy_file" "$MULTIDEPLOY_CONFIG" else # TODO: Replace URL with wiki link _err "Deploy file not found. Go to https://CHANGE_URL_TO_WIKI to see how to create one." @@ -66,48 +66,48 @@ _preprocess_deployfile() { fi } -# deploy_filepath deploy_config +# deploy_filepath _deploy_config _check_deployfile() { - deploy_file="$1" - deploy_config="$3" + _deploy_file="$1" + _deploy_config="$3" # Check version - deploy_file_version=$(yq '.version' "$deploy_file") - if [ "$MULTIDEPLOY_VERSION" != "$deploy_file_version" ]; then - _err "As of $PROJECT_NAME $VER, the deploy file needs version $MULTIDEPLOY_VERSION! Your current deploy file is of version $deploy_file_version." + _deploy_file_version=$(yq '.version' "$_deploy_file") + if [ "$MULTIDEPLOY_VERSION" != "$_deploy_file_version" ]; then + _err "As of $PROJECT_NAME $VER, the deploy file needs version $MULTIDEPLOY_VERSION! Your current deploy file is of version $_deploy_file_version." return 1 fi # Check if config exists - if ! yq e ".configs[] | select(.name == \"$deploy_config\")" "$deploy_file" >/dev/null; then - _err "Config '$deploy_config' not found." + if ! yq e ".configs[] | select(.name == \"$_deploy_config\")" "$_deploy_file" >/dev/null; then + _err "Config '$_deploy_config' not found." return 1 fi # Extract all services from config - services=$(_get_services_list "$deploy_file" "$deploy_config") + _services=$(_get_services_list "$_deploy_file" "$_deploy_config") - if [ -z "$services" ]; then - _err "Config '$deploy_config' does not have any services to deploy to." + if [ -z "$_services" ]; then + _err "Config '$_deploy_config' does not have any services to deploy to." return 1 fi # Check if extracted services exist in services list - for service in $services; do - if ! yq e ".services[] | select(.name == \"$service\")" "$deploy_file" >/dev/null; then - _err "Service '$service' not found." + for _service in $_services; do + if ! yq e ".services[] | select(.name == \"$_service\")" "$_deploy_file" >/dev/null; then + _err "Service '$_service' not found." return 1 fi # Check if service has hook - if ! yq e ".services[] | select(.name == \"$service\").hook" "$deploy_file" >/dev/null; then - _err "Service '$service' does not have a hook." + if ! yq e ".services[] | select(.name == \"$_service\").hook" "$_deploy_file" >/dev/null; then + _err "Service '$_service' does not have a hook." return 1 fi # Check if service has environment - if ! yq e ".services[] | select(.name == \"$service\").environment" "$deploy_file" >/dev/null; then - _err "Service '$service' does not an environment." + if ! yq e ".services[] | select(.name == \"$_service\").environment" "$_deploy_file" >/dev/null; then + _err "Service '$_service' does not an environment." return 1 fi done @@ -115,26 +115,26 @@ _check_deployfile() { # deploy_filepath deploy_config _get_services_list() { - deploy_file="$1" - deploy_config="$2" + _deploy_file="$1" + _deploy_config="$2" - services=$(yq e ".configs[] | select(.name == \"$deploy_config\").services[]" "$deploy_file") - echo "$services" + _services=$(yq e ".configs[] | select(.name == \"$_deploy_config\").services[]" "$_deploy_file") + echo "$_services" } # deploy_filepath service_names _get_full_services_list() { - deploy_file="$1" + _deploy_file="$1" shift - service_names="$*" + _service_names="$*" - full_services="" - for service in $service_names; do - full_service=$(yq e ".services[] | select(.name == \"$service\")" "$deploy_file") - full_services="$full_services -$full_service" + _full_services="" + for _service in $_service_names; do + _full_service=$(yq e ".services[] | select(.name == \"$_service\")" "$_deploy_file") + _full_services="$_full_services +$_full_service" done - echo "$full_services" + echo "$_full_services" } From 67d58a12e76944389fab15632e078c3c10717b79 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Fri, 21 Feb 2025 10:50:11 +0100 Subject: [PATCH 05/41] implemented handling envs --- deploy/multideploy.sh | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 245c95a6..d1642538 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -138,3 +138,25 @@ $_full_service" echo "$_full_services" } +# env_list +_export_envs() { + _env_list="$1" + + for _env in $_env_list; do + _key=$(echo "$_env" | cut -d '=' -f1) + _value=$(echo "$_env" | cut -d '=' -f2-) + _savedomainconf "$_key" "$_value" + _secure_debug3 "Saved $_key" "$_value" + done +} + +_clear_envs() { + _env_list="$1" + + for _env in $_env_list; do + _key=$(echo "$_env" | cut -d '=' -f1) + _debug3 "Deleting key" "$_key" + _cleardomainconf "SAVED_$_key" + unset "$_key" + done +} From 23e1a53ec8d7b33e44fe81d5cf19534f1a5de296 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Fri, 21 Feb 2025 10:50:35 +0100 Subject: [PATCH 06/41] implemented deploying to services --- deploy/multideploy.sh | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index d1642538..caca02e2 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -40,7 +40,16 @@ multideploy_deploy() { _debug2 "MULTIDEPLOY_CONFIG" "$MULTIDEPLOY_CONFIG" fi - # TODO: Deploy to services + # Deploy to services + _services=$(_get_services_list "$DOMAIN_DIR/$MULTIDEPLOY_FILENAME" "$MULTIDEPLOY_CONFIG") + _full_services=$(_get_full_services_list "$DOMAIN_DIR/$MULTIDEPLOY_FILENAME" "$_services") + _deploy_services "$DOMAIN_DIR/$MULTIDEPLOY_FILENAME" "$_full_services" + + # Save deployhook for renewals + _debug2 "Setting Le_DeployHook" + _savedomainconf "Le_DeployHook" "multideploy" + + return 0 } #################### Private functions below ##################### @@ -160,3 +169,34 @@ _clear_envs() { unset "$_key" done } + +# deploy_filepath services_array +_deploy_services() { + _deploy_file="$1" + shift + _services="$*" + + for _service in $_services; do + _hook=$(yq e ".services[] | select(.name == \"$_service\").hook" "$_deploy_file") + _envs=$(yq e ".services[] | select(.name == \"$_service\").environment[]" "$_deploy_file") + _export_envs "$_envs" + _deploy_service "$_service" "$_hook" + _clear_envs "$_envs" + done +} + +_deploy_service() { + _name="$1" + _hook="$2" + + _debug2 "SERVICE" "$_name" + _debug2 "HOOK" "$_hook" + + _info "$(__green "Deploying") to '$_name' using '$_hook'" + if echo "$DOMAIN_PATH" | grep -q "$ECC_SUFFIX"; then + _debug2 "User wants to use ECC." + deploy "$_cdomain" "$_hook" "isEcc" + else + deploy "$_cdomain" "$_hook" + fi +} From 34eb2a655a8da40827478931ce984ad3f265356f Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Fri, 21 Feb 2025 10:50:50 +0100 Subject: [PATCH 07/41] added yq to dockerfile --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 88edc4a2..4852cde4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,6 +13,7 @@ RUN apk --no-cache add -f \ tar \ libidn \ jq \ + yq \ cronie ENV LE_WORKING_DIR=/acmebin From fb0926dc81ccbdcbfc833f07de307f029e4289bc Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Fri, 21 Feb 2025 15:51:02 +0100 Subject: [PATCH 08/41] implemented checking for different kinds of deploy file --- deploy/multideploy.sh | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index caca02e2..9df2c423 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -5,7 +5,8 @@ ######## Public functions ##################### MULTIDEPLOY_VERSION="1.0" -MULTIDEPLOY_FILENAME="multideploy.yaml" +MULTIDEPLOY_FILENAME="multideploy.yml" +MULTIDEPLOY_FILENAME2="multideploy.yaml" # domain keyfile certfile cafile fullchain pfx multideploy_deploy() { @@ -56,18 +57,30 @@ multideploy_deploy() { # deploy_filepath _preprocess_deployfile() { - _deploy_file="$1" - # Check if yq is installed if ! command -v yq >/dev/null 2>&1; then _err "yq is not installed! Please install yq and try again." return 1 fi + _debug3 "yq is installed." + + # Check if deploy file exists + for file in "$@"; do + _debug3 "Checking file" "$DOMAIN_PATH/$file" + if [ -f "$DOMAIN_PATH/$file" ]; then + _debug3 "File found" + if [ -n "$found_file" ]; then + _err "Multiple deploy files found. Please keep only one deploy file." + return 1 + fi + found_file="$file" + else + _debug3 "File not found" + fi + done - # Check if deploy file exists and create a default template if not - if [ -f "$_deploy_file" ]; then - _debug3 "Deploy file found." - _check_deployfile "$_deploy_file" "$MULTIDEPLOY_CONFIG" + if [ -n "$found_file" ]; then + _check_deployfile "$DOMAIN_PATH/$found_file" "$MULTIDEPLOY_CONFIG" else # TODO: Replace URL with wiki link _err "Deploy file not found. Go to https://CHANGE_URL_TO_WIKI to see how to create one." From db1dc4de0deb66b75bf83a4b1d6a274b7b5e6f09 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Fri, 21 Feb 2025 15:52:02 +0100 Subject: [PATCH 09/41] added debug messages --- deploy/multideploy.sh | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 9df2c423..3c243c04 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -30,8 +30,6 @@ multideploy_deploy() { fi _debug2 "DOMAIN_DIR" "$DOMAIN_DIR" - _preprocess_deployfile "$DOMAIN_DIR/$MULTIDEPLOY_FILENAME" || return 1 - MULTIDEPLOY_CONFIG="${MULTIDEPLOY_CONFIG:-$(_getdeployconf MULTIDEPLOY_CONFIG)}" if [ -z "$MULTIDEPLOY_CONFIG" ]; then MULTIDEPLOY_CONFIG="default" @@ -91,7 +89,10 @@ _preprocess_deployfile() { # deploy_filepath _deploy_config _check_deployfile() { _deploy_file="$1" - _deploy_config="$3" + _deploy_config="$2" + + _debug2 "Deploy file" "$_deploy_file" + _debug2 "Deploy config" "$_deploy_config" # Check version _deploy_file_version=$(yq '.version' "$_deploy_file") @@ -99,23 +100,29 @@ _check_deployfile() { _err "As of $PROJECT_NAME $VER, the deploy file needs version $MULTIDEPLOY_VERSION! Your current deploy file is of version $_deploy_file_version." return 1 fi + _debug2 "Deploy file version is compatible: $_deploy_file_version" # Check if config exists if ! yq e ".configs[] | select(.name == \"$_deploy_config\")" "$_deploy_file" >/dev/null; then _err "Config '$_deploy_config' not found." return 1 fi + _debug2 "Config found: $_deploy_config" # Extract all services from config _services=$(_get_services_list "$_deploy_file" "$_deploy_config") + _debug2 "Services" "$_services" if [ -z "$_services" ]; then _err "Config '$_deploy_config' does not have any services to deploy to." return 1 fi + _debug2 "Config has services." # Check if extracted services exist in services list for _service in $_services; do + _debug2 "Checking service" "$_service" + # Check if service exists if ! yq e ".services[] | select(.name == \"$_service\")" "$_deploy_file" >/dev/null; then _err "Service '$_service' not found." return 1 @@ -140,6 +147,10 @@ _get_services_list() { _deploy_file="$1" _deploy_config="$2" + _debug2 "Getting services list" + _debug3 "Deploy file" "$_deploy_file" + _debug3 "Deploy config" "$_deploy_config" + _services=$(yq e ".configs[] | select(.name == \"$_deploy_config\").services[]" "$_deploy_file") echo "$_services" } @@ -150,6 +161,9 @@ _get_full_services_list() { shift _service_names="$*" + _debug3 "Deploy file" "$_deploy_file" + _debug3 "Service names" "$_service_names" + _full_services="" for _service in $_service_names; do _full_service=$(yq e ".services[] | select(.name == \"$_service\")" "$_deploy_file") @@ -164,6 +178,8 @@ $_full_service" _export_envs() { _env_list="$1" + _secure_debug3 "Exporting envs" "$_env_list" + for _env in $_env_list; do _key=$(echo "$_env" | cut -d '=' -f1) _value=$(echo "$_env" | cut -d '=' -f2-) @@ -175,6 +191,8 @@ _export_envs() { _clear_envs() { _env_list="$1" + _secure_debug3 "Clearing envs" "$_env_list" + for _env in $_env_list; do _key=$(echo "$_env" | cut -d '=' -f1) _debug3 "Deleting key" "$_key" @@ -189,6 +207,9 @@ _deploy_services() { shift _services="$*" + _debug3 "Deploy file" "$_deploy_file" + _debug3 "Services" "$_services" + for _service in $_services; do _hook=$(yq e ".services[] | select(.name == \"$_service\").hook" "$_deploy_file") _envs=$(yq e ".services[] | select(.name == \"$_service\").environment[]" "$_deploy_file") From 768de270bf6943047f3f52d38b0af28c423dd765 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Fri, 21 Feb 2025 18:23:13 +0100 Subject: [PATCH 10/41] improved preprocessing and fixed bug with wrong param of services --- deploy/multideploy.sh | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 3c243c04..7b4e1400 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -39,10 +39,13 @@ multideploy_deploy() { _debug2 "MULTIDEPLOY_CONFIG" "$MULTIDEPLOY_CONFIG" fi + OLDIFS=$IFS + file=$(_preprocess_deployfile "$MULTIDEPLOY_FILENAME" "$MULTIDEPLOY_FILENAME2") || return 1 + _debug3 "File" "$file" + # Deploy to services - _services=$(_get_services_list "$DOMAIN_DIR/$MULTIDEPLOY_FILENAME" "$MULTIDEPLOY_CONFIG") - _full_services=$(_get_full_services_list "$DOMAIN_DIR/$MULTIDEPLOY_FILENAME" "$_services") - _deploy_services "$DOMAIN_DIR/$MULTIDEPLOY_FILENAME" "$_full_services" + _services=$(_get_services_list "$file" "$MULTIDEPLOY_CONFIG") + _deploy_services "$file" "$_services" # Save deployhook for renewals _debug2 "Setting Le_DeployHook" @@ -84,6 +87,8 @@ _preprocess_deployfile() { _err "Deploy file not found. Go to https://CHANGE_URL_TO_WIKI to see how to create one." return 1 fi + + echo "$DOMAIN_PATH/$found_file" } # deploy_filepath _deploy_config @@ -155,25 +160,6 @@ _get_services_list() { echo "$_services" } -# deploy_filepath service_names -_get_full_services_list() { - _deploy_file="$1" - shift - _service_names="$*" - - _debug3 "Deploy file" "$_deploy_file" - _debug3 "Service names" "$_service_names" - - _full_services="" - for _service in $_service_names; do - _full_service=$(yq e ".services[] | select(.name == \"$_service\")" "$_deploy_file") - _full_services="$_full_services -$_full_service" - done - - echo "$_full_services" -} - # env_list _export_envs() { _env_list="$1" @@ -211,6 +197,7 @@ _deploy_services() { _debug3 "Services" "$_services" for _service in $_services; do + _debug2 "Service" "$_service" _hook=$(yq e ".services[] | select(.name == \"$_service\").hook" "$_deploy_file") _envs=$(yq e ".services[] | select(.name == \"$_service\").environment[]" "$_deploy_file") _export_envs "$_envs" From ba7c368ee535c198187320a740d5da816126c51b Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Fri, 21 Feb 2025 18:23:29 +0100 Subject: [PATCH 11/41] fixed IFS problems --- deploy/multideploy.sh | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 7b4e1400..9e2fb1d2 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -66,6 +66,7 @@ _preprocess_deployfile() { _debug3 "yq is installed." # Check if deploy file exists + IFS=$(printf '\n') for file in "$@"; do _debug3 "Checking file" "$DOMAIN_PATH/$file" if [ -f "$DOMAIN_PATH/$file" ]; then @@ -79,6 +80,7 @@ _preprocess_deployfile() { _debug3 "File not found" fi done + IFS=$OLDIFS if [ -n "$found_file" ]; then _check_deployfile "$DOMAIN_PATH/$found_file" "$MULTIDEPLOY_CONFIG" @@ -124,6 +126,7 @@ _check_deployfile() { fi _debug2 "Config has services." + IFS=$(printf '\n') # Check if extracted services exist in services list for _service in $_services; do _debug2 "Checking service" "$_service" @@ -145,6 +148,7 @@ _check_deployfile() { return 1 fi done + IFS=$OLDIFS } # deploy_filepath deploy_config @@ -166,25 +170,27 @@ _export_envs() { _secure_debug3 "Exporting envs" "$_env_list" - for _env in $_env_list; do - _key=$(echo "$_env" | cut -d '=' -f1) - _value=$(echo "$_env" | cut -d '=' -f2-) + IFS=$(printf '\n') + echo "$_env_list" | yq e -r 'to_entries | .[] | .key + "=" + .value' | while IFS='=' read -r _key _value; do _savedomainconf "$_key" "$_value" _secure_debug3 "Saved $_key" "$_value" done + IFS=$OLDIFS } _clear_envs() { _env_list="$1" _secure_debug3 "Clearing envs" "$_env_list" + env_pairs=$(echo "$_env_list" | yq e -r 'to_entries | .[] | .key + "=" + .value') - for _env in $_env_list; do - _key=$(echo "$_env" | cut -d '=' -f1) + IFS=$(printf '\n') + echo "$env_pairs" | while IFS='=' read -r _key _value; do _debug3 "Deleting key" "$_key" _cleardomainconf "SAVED_$_key" unset "$_key" done + IFS="$OLDIFS" } # deploy_filepath services_array @@ -196,14 +202,17 @@ _deploy_services() { _debug3 "Deploy file" "$_deploy_file" _debug3 "Services" "$_services" + IFS=$(printf '\n') for _service in $_services; do _debug2 "Service" "$_service" _hook=$(yq e ".services[] | select(.name == \"$_service\").hook" "$_deploy_file") _envs=$(yq e ".services[] | select(.name == \"$_service\").environment[]" "$_deploy_file") + _export_envs "$_envs" _deploy_service "$_service" "$_hook" _clear_envs "$_envs" done + IFS=$OLDIFS } _deploy_service() { From 2cc5e66517908eed21bbc03ba5066919dd27365e Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Fri, 21 Feb 2025 18:31:24 +0100 Subject: [PATCH 12/41] added docs --- deploy/multideploy.sh | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 9e2fb1d2..129bb38f 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -151,7 +151,13 @@ _check_deployfile() { IFS=$OLDIFS } -# deploy_filepath deploy_config +# Description: +# This function retrieves a list of services from the deploy configuration file. +# Arguments: +# $1 - The path to the deploy configuration file. +# $2 - The name of the deploy configuration to use. +# Usage: +# _get_services_list "" "" _get_services_list() { _deploy_file="$1" _deploy_config="$2" @@ -164,7 +170,12 @@ _get_services_list() { echo "$_services" } -# env_list +# Description: This function takes a list of environment variables in YAML format, +# parses them, and exports each key-value pair as environment variables. +# Arguments: +# $1 - A string containing the list of environment variables in YAML format. +# Usage: +# _export_envs "$env_list" _export_envs() { _env_list="$1" @@ -178,6 +189,13 @@ _export_envs() { IFS=$OLDIFS } +# Description: +# This function takes a YAML formatted string of environment variables, parses it, +# and clears each environment variable. It logs the process of clearing each variable. +# Arguments: +# $1 - A YAML formatted string containing environment variable key-value pairs. +# Usage: +# _clear_envs "" _clear_envs() { _env_list="$1" @@ -188,7 +206,7 @@ _clear_envs() { echo "$env_pairs" | while IFS='=' read -r _key _value; do _debug3 "Deleting key" "$_key" _cleardomainconf "SAVED_$_key" - unset "$_key" + unset -v "$_key" done IFS="$OLDIFS" } From 74ed0354a3f135884b37c5b5adf3557a22afb2d2 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Fri, 21 Feb 2025 18:44:46 +0100 Subject: [PATCH 13/41] added docs and enhanced log messages --- deploy/multideploy.sh | 57 +++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 129bb38f..81754f1c 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -2,13 +2,21 @@ # MULTIDEPLOY_CONFIG="default" -######## Public functions ##################### - MULTIDEPLOY_VERSION="1.0" MULTIDEPLOY_FILENAME="multideploy.yml" MULTIDEPLOY_FILENAME2="multideploy.yaml" -# domain keyfile certfile cafile fullchain pfx +# Description: This function handles the deployment of certificates to multiple services. +# It processes the provided certificate files and deploys them according to the +# configuration specified in the MULTIDEPLOY_CONFIG. +# +# Parameters: +# _cdomain - The domain name for which the certificate is issued. +# _ckey - The private key file for the certificate. +# _ccert - The certificate file. +# _cca - The CA (Certificate Authority) file. +# _cfullchain - The full chain certificate file. +# _cpfx - The PFX (Personal Information Exchange) file. multideploy_deploy() { _cdomain="$1" _ckey="$2" @@ -40,7 +48,10 @@ multideploy_deploy() { fi OLDIFS=$IFS - file=$(_preprocess_deployfile "$MULTIDEPLOY_FILENAME" "$MULTIDEPLOY_FILENAME2") || return 1 + if ! file=$(_preprocess_deployfile "$MULTIDEPLOY_FILENAME" "$MULTIDEPLOY_FILENAME2"); then + _err "Failed to preprocess deploy file." + return 1 + fi _debug3 "File" "$file" # Deploy to services @@ -54,9 +65,13 @@ multideploy_deploy() { return 0 } -#################### Private functions below ##################### - -# deploy_filepath +# Description: +# This function preprocesses the deploy file by checking if 'yq' is installed, +# verifying the existence of the deploy file, and ensuring only one deploy file is present. +# Arguments: +# $@ - Posible deploy file names. +# Usage: +# _preprocess_deployfile "" "" _preprocess_deployfile() { # Check if yq is installed if ! command -v yq >/dev/null 2>&1; then @@ -93,7 +108,13 @@ _preprocess_deployfile() { echo "$DOMAIN_PATH/$found_file" } -# deploy_filepath _deploy_config +# Description: +# This function checks the deploy file for version compatibility and the existence of the specified configuration and services. +# Arguments: +# $1 - The path to the deploy configuration file. +# $2 - The name of the deploy configuration to use. +# Usage: +# _check_deployfile "" "" _check_deployfile() { _deploy_file="$1" _deploy_config="$2" @@ -144,7 +165,7 @@ _check_deployfile() { # Check if service has environment if ! yq e ".services[] | select(.name == \"$_service\").environment" "$_deploy_file" >/dev/null; then - _err "Service '$_service' does not an environment." + _err "Service '$_service' does not have an environment." return 1 fi done @@ -211,7 +232,13 @@ _clear_envs() { IFS="$OLDIFS" } -# deploy_filepath services_array +# Description: +# This function deploys services listed in the deploy configuration file. +# Arguments: +# $1 - The path to the deploy configuration file. +# $2 - The list of services to deploy. +# Usage: +# _deploy_services "" "" _deploy_services() { _deploy_file="$1" shift @@ -220,8 +247,7 @@ _deploy_services() { _debug3 "Deploy file" "$_deploy_file" _debug3 "Services" "$_services" - IFS=$(printf '\n') - for _service in $_services; do + printf '%s\n' "$_services" | while IFS= read -r _service; do _debug2 "Service" "$_service" _hook=$(yq e ".services[] | select(.name == \"$_service\").hook" "$_deploy_file") _envs=$(yq e ".services[] | select(.name == \"$_service\").environment[]" "$_deploy_file") @@ -230,9 +256,14 @@ _deploy_services() { _deploy_service "$_service" "$_hook" _clear_envs "$_envs" done - IFS=$OLDIFS } +# Description: Deploys a service using the specified hook. +# Arguments: +# $1 - The name of the service to deploy. +# $2 - The hook to use for deployment. +# Usage: +# _deploy_service _deploy_service() { _name="$1" _hook="$2" From 88d4637ee31e4d27a6e9978d8bfb1b52e55ef8d7 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Fri, 21 Feb 2025 19:02:55 +0100 Subject: [PATCH 14/41] added header doc --- deploy/multideploy.sh | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 81754f1c..bea4622b 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -1,6 +1,25 @@ #!/usr/bin/env sh -# MULTIDEPLOY_CONFIG="default" +################################################################################ +# ACME.sh 3rd party deploy plugin for multiple (same) services +################################################################################ +# Authors: tomo2403 (creator), https://github.com/tomo2403 +# Updated: 2024-07-03 +# Issues: https://github.com/acmesh-official/acme.sh/issues/XXXXX +################################################################################ +# Usage (shown values are the examples): +# 1. Set optional environment variables +# - export MULTIDEPLOY_CONFIG="default" - "default" will be automatically used if not set" +# +# 2. Run command: +# acme.sh --deploy --deploy-hook multideploy -d example.com +################################################################################ +# Dependencies: +# - yq +################################################################################ +# Return value: +# 0 means success, otherwise error. +################################################################################ MULTIDEPLOY_VERSION="1.0" MULTIDEPLOY_FILENAME="multideploy.yml" From c16e059535b873a46f6ee2a47f8810843f0b2292 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Fri, 21 Feb 2025 19:15:42 +0100 Subject: [PATCH 15/41] allowed using varaibles in deploy file --- deploy/multideploy.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index bea4622b..58df0482 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -223,6 +223,7 @@ _export_envs() { IFS=$(printf '\n') echo "$_env_list" | yq e -r 'to_entries | .[] | .key + "=" + .value' | while IFS='=' read -r _key _value; do + _value=$(eval echo "$_value") _savedomainconf "$_key" "$_value" _secure_debug3 "Saved $_key" "$_value" done From 88cde7be6db1901932f9458f624b0362f348edd4 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Fri, 21 Feb 2025 19:26:56 +0100 Subject: [PATCH 16/41] fixed missing wiki link --- deploy/multideploy.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 58df0482..9e3f4e17 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -119,8 +119,7 @@ _preprocess_deployfile() { if [ -n "$found_file" ]; then _check_deployfile "$DOMAIN_PATH/$found_file" "$MULTIDEPLOY_CONFIG" else - # TODO: Replace URL with wiki link - _err "Deploy file not found. Go to https://CHANGE_URL_TO_WIKI to see how to create one." + _err "Deploy file not found. Go to https://github.com/acmesh-official/acme.sh/wiki/deployhooks#36-deploying-to-multiple-services-with-the-same-hooks to see how to create one." return 1 fi From c1e17c366fd367cc68a3b89d9eca2abd161cbbde Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Sat, 1 Mar 2025 13:26:53 +0100 Subject: [PATCH 17/41] Update links in multideploy.sh --- deploy/multideploy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 9e3f4e17..b002f068 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -4,8 +4,8 @@ # ACME.sh 3rd party deploy plugin for multiple (same) services ################################################################################ # Authors: tomo2403 (creator), https://github.com/tomo2403 -# Updated: 2024-07-03 -# Issues: https://github.com/acmesh-official/acme.sh/issues/XXXXX +# Updated: 2025-03-01 +# Issues: https://github.com/acmesh-official/acme.sh/issues and mention @tomo2403 ################################################################################ # Usage (shown values are the examples): # 1. Set optional environment variables From 95c75460513f8faa5cdfbee869cc70d0354c9bce Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Thu, 27 Mar 2025 19:11:31 +0100 Subject: [PATCH 18/41] removed configs and implemented specification of deploy file name --- deploy/multideploy.sh | 67 +++++++++++-------------------------------- 1 file changed, 17 insertions(+), 50 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index b002f068..24177e66 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -9,7 +9,7 @@ ################################################################################ # Usage (shown values are the examples): # 1. Set optional environment variables -# - export MULTIDEPLOY_CONFIG="default" - "default" will be automatically used if not set" +# - export MULTIDEPLOY_FILENAME="multideploy.yaml" - "multideploy.yml" will be automatically used if not set" # # 2. Run command: # acme.sh --deploy --deploy-hook multideploy -d example.com @@ -22,12 +22,10 @@ ################################################################################ MULTIDEPLOY_VERSION="1.0" -MULTIDEPLOY_FILENAME="multideploy.yml" -MULTIDEPLOY_FILENAME2="multideploy.yaml" # Description: This function handles the deployment of certificates to multiple services. # It processes the provided certificate files and deploys them according to the -# configuration specified in the MULTIDEPLOY_CONFIG. +# configuration specified in the multideploy file. # # Parameters: # _cdomain - The domain name for which the certificate is issued. @@ -57,25 +55,24 @@ multideploy_deploy() { fi _debug2 "DOMAIN_DIR" "$DOMAIN_DIR" - MULTIDEPLOY_CONFIG="${MULTIDEPLOY_CONFIG:-$(_getdeployconf MULTIDEPLOY_CONFIG)}" - if [ -z "$MULTIDEPLOY_CONFIG" ]; then - MULTIDEPLOY_CONFIG="default" - _info "MULTIDEPLOY_CONFIG is not set, so I will use 'default'." + MULTIDEPLOY_FILENAME="${MULTIDEPLOY_FILENAME:-$(_getdeployconf MULTIDEPLOY_FILENAME)}" + if [ -z "$MULTIDEPLOY_FILENAME" ]; then + MULTIDEPLOY_FILENAME="multideploy.yml" + _info "MULTIDEPLOY_FILENAME is not set, so I will use 'multideploy.yml'." else - _savedeployconf "MULTIDEPLOY_CONFIG" "$MULTIDEPLOY_CONFIG" - _debug2 "MULTIDEPLOY_CONFIG" "$MULTIDEPLOY_CONFIG" + _savedeployconf "MULTIDEPLOY_FILENAME" "$MULTIDEPLOY_FILENAME" + _debug2 "MULTIDEPLOY_FILENAME" "$MULTIDEPLOY_FILENAME" fi OLDIFS=$IFS - if ! file=$(_preprocess_deployfile "$MULTIDEPLOY_FILENAME" "$MULTIDEPLOY_FILENAME2"); then + if ! file=$(_preprocess_deployfile "$MULTIDEPLOY_FILENAME"); then _err "Failed to preprocess deploy file." return 1 fi _debug3 "File" "$file" # Deploy to services - _services=$(_get_services_list "$file" "$MULTIDEPLOY_CONFIG") - _deploy_services "$file" "$_services" + _deploy_services "$file" # Save deployhook for renewals _debug2 "Setting Le_DeployHook" @@ -90,7 +87,7 @@ multideploy_deploy() { # Arguments: # $@ - Posible deploy file names. # Usage: -# _preprocess_deployfile "" "" +# _preprocess_deployfile "" "?" _preprocess_deployfile() { # Check if yq is installed if ! command -v yq >/dev/null 2>&1; then @@ -117,7 +114,7 @@ _preprocess_deployfile() { IFS=$OLDIFS if [ -n "$found_file" ]; then - _check_deployfile "$DOMAIN_PATH/$found_file" "$MULTIDEPLOY_CONFIG" + _check_deployfile "$DOMAIN_PATH/$found_file" else _err "Deploy file not found. Go to https://github.com/acmesh-official/acme.sh/wiki/deployhooks#36-deploying-to-multiple-services-with-the-same-hooks to see how to create one." return 1 @@ -132,13 +129,10 @@ _preprocess_deployfile() { # $1 - The path to the deploy configuration file. # $2 - The name of the deploy configuration to use. # Usage: -# _check_deployfile "" "" +# _check_deployfile "" _check_deployfile() { _deploy_file="$1" - _deploy_config="$2" - _debug2 "Deploy file" "$_deploy_file" - _debug2 "Deploy config" "$_deploy_config" # Check version _deploy_file_version=$(yq '.version' "$_deploy_file") @@ -148,19 +142,12 @@ _check_deployfile() { fi _debug2 "Deploy file version is compatible: $_deploy_file_version" - # Check if config exists - if ! yq e ".configs[] | select(.name == \"$_deploy_config\")" "$_deploy_file" >/dev/null; then - _err "Config '$_deploy_config' not found." - return 1 - fi - _debug2 "Config found: $_deploy_config" - # Extract all services from config - _services=$(_get_services_list "$_deploy_file" "$_deploy_config") + _services=$(yq e '.services[].name' "$_deploy_file") _debug2 "Services" "$_services" if [ -z "$_services" ]; then - _err "Config '$_deploy_config' does not have any services to deploy to." + _err "Config does not have any services to deploy to." return 1 fi _debug2 "Config has services." @@ -190,25 +177,6 @@ _check_deployfile() { IFS=$OLDIFS } -# Description: -# This function retrieves a list of services from the deploy configuration file. -# Arguments: -# $1 - The path to the deploy configuration file. -# $2 - The name of the deploy configuration to use. -# Usage: -# _get_services_list "" "" -_get_services_list() { - _deploy_file="$1" - _deploy_config="$2" - - _debug2 "Getting services list" - _debug3 "Deploy file" "$_deploy_file" - _debug3 "Deploy config" "$_deploy_config" - - _services=$(yq e ".configs[] | select(.name == \"$_deploy_config\").services[]" "$_deploy_file") - echo "$_services" -} - # Description: This function takes a list of environment variables in YAML format, # parses them, and exports each key-value pair as environment variables. # Arguments: @@ -260,10 +228,9 @@ _clear_envs() { # _deploy_services "" "" _deploy_services() { _deploy_file="$1" - shift - _services="$*" - _debug3 "Deploy file" "$_deploy_file" + + _services=$(yq e '.services[].name' "$_deploy_file") _debug3 "Services" "$_services" printf '%s\n' "$_services" | while IFS= read -r _service; do From 17e0bbcbb67c32fff1cb620d08a0c1b277565332 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Thu, 27 Mar 2025 19:16:07 +0100 Subject: [PATCH 19/41] fixed formatting --- deploy/multideploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 24177e66..c297878c 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -229,7 +229,7 @@ _clear_envs() { _deploy_services() { _deploy_file="$1" _debug3 "Deploy file" "$_deploy_file" - + _services=$(yq e '.services[].name' "$_deploy_file") _debug3 "Services" "$_services" From 88e4d64c1a242342a60f7aa1bddd4ba842c5b500 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Thu, 10 Apr 2025 10:24:32 +0200 Subject: [PATCH 20/41] fixed IFS problems for some hooks --- deploy/multideploy.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index c297878c..b728ee77 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -233,7 +233,9 @@ _deploy_services() { _services=$(yq e '.services[].name' "$_deploy_file") _debug3 "Services" "$_services" - printf '%s\n' "$_services" | while IFS= read -r _service; do + _service_list=$(printf '%s\n' "$_services") + + for _service in $(printf '%s\n' "$_service_list"); do _debug2 "Service" "$_service" _hook=$(yq e ".services[] | select(.name == \"$_service\").hook" "$_deploy_file") _envs=$(yq e ".services[] | select(.name == \"$_service\").environment[]" "$_deploy_file") From c1c49d5a01e929d326b8a7f4a8fb2d3780f6e8ec Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Sun, 13 Apr 2025 16:38:28 +0200 Subject: [PATCH 21/41] simplified deploy method --- deploy/multideploy.sh | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index b728ee77..93809e6e 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -260,10 +260,5 @@ _deploy_service() { _debug2 "HOOK" "$_hook" _info "$(__green "Deploying") to '$_name' using '$_hook'" - if echo "$DOMAIN_PATH" | grep -q "$ECC_SUFFIX"; then - _debug2 "User wants to use ECC." - deploy "$_cdomain" "$_hook" "isEcc" - else - deploy "$_cdomain" "$_hook" - fi + _deploy "$_cdomain" "$_hook" } From a55d40be972e7ebd4f64599211b0e861ed2f83e9 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Tue, 27 May 2025 22:07:22 +0200 Subject: [PATCH 22/41] fixed bug with envs due to the use of a wrong function --- deploy/multideploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 93809e6e..c77d1fdf 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -191,7 +191,7 @@ _export_envs() { IFS=$(printf '\n') echo "$_env_list" | yq e -r 'to_entries | .[] | .key + "=" + .value' | while IFS='=' read -r _key _value; do _value=$(eval echo "$_value") - _savedomainconf "$_key" "$_value" + _savedeployconf "$_key" "$_value" _secure_debug3 "Saved $_key" "$_value" done IFS=$OLDIFS From e5b47f6402567d75db58edcb5b4b67194de58202 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Wed, 28 May 2025 20:02:07 +0200 Subject: [PATCH 23/41] implemented exiting with 1 if at least one deployment fails --- deploy/multideploy.sh | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index c77d1fdf..5b323303 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -72,13 +72,17 @@ multideploy_deploy() { _debug3 "File" "$file" # Deploy to services - _deploy_services "$file" + if _deploy_services "$file"; then + _deploymentOk=0 + else + _deploymentOk=1 + fi # Save deployhook for renewals _debug2 "Setting Le_DeployHook" _savedomainconf "Le_DeployHook" "multideploy" - return 0 + return "$_deploymentOk" } # Description: @@ -235,15 +239,26 @@ _deploy_services() { _service_list=$(printf '%s\n' "$_services") + _errors="" for _service in $(printf '%s\n' "$_service_list"); do _debug2 "Service" "$_service" _hook=$(yq e ".services[] | select(.name == \"$_service\").hook" "$_deploy_file") _envs=$(yq e ".services[] | select(.name == \"$_service\").environment[]" "$_deploy_file") _export_envs "$_envs" - _deploy_service "$_service" "$_hook" + if ! _deploy_service "$_service" "$_hook"; then + _errors="$_service, $_errors" + fi _clear_envs "$_envs" done + + if [ -n "$_errors" ]; then + _err "Deployment failed for services: $_errors" + return 1 + else + _debug "All services deployed successfully." + return 0 + fi } # Description: Deploys a service using the specified hook. @@ -261,4 +276,5 @@ _deploy_service() { _info "$(__green "Deploying") to '$_name' using '$_hook'" _deploy "$_cdomain" "$_hook" + return $? } From 093f36b4d670a03b571ea68f28b4d180ad6f6261 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Wed, 28 May 2025 20:19:18 +0200 Subject: [PATCH 24/41] implemented exiting with the number of failed deployments --- deploy/multideploy.sh | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 5b323303..fd04043a 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -72,17 +72,14 @@ multideploy_deploy() { _debug3 "File" "$file" # Deploy to services - if _deploy_services "$file"; then - _deploymentOk=0 - else - _deploymentOk=1 - fi + _deploy_services "$file" + _exitCode="$?" # Save deployhook for renewals _debug2 "Setting Le_DeployHook" _savedomainconf "Le_DeployHook" "multideploy" - return "$_deploymentOk" + return "$_exitCode" } # Description: @@ -239,7 +236,8 @@ _deploy_services() { _service_list=$(printf '%s\n' "$_services") - _errors="" + _failedServices="" + _failedCount=0 for _service in $(printf '%s\n' "$_service_list"); do _debug2 "Service" "$_service" _hook=$(yq e ".services[] | select(.name == \"$_service\").hook" "$_deploy_file") @@ -247,18 +245,21 @@ _deploy_services() { _export_envs "$_envs" if ! _deploy_service "$_service" "$_hook"; then - _errors="$_service, $_errors" + _failedServices="$_service, $_failedServices" + _failedCount=$((_failedCount + 1)) fi _clear_envs "$_envs" done - if [ -n "$_errors" ]; then - _err "Deployment failed for services: $_errors" - return 1 + _debug3 "Failed services" "$_failedServices" + _debug2 "Failed count" "$_failedCount" + if [ -n "$_failedServices" ]; then + _info "$(__red "Deployment failed") for services: $_failedServices" else _debug "All services deployed successfully." - return 0 fi + + return "$_failedCount" } # Description: Deploys a service using the specified hook. From 7b16526e7f0f217a4d0e02505d32f4260e884c40 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Sat, 31 May 2025 19:21:10 +0200 Subject: [PATCH 25/41] removed dead code --- deploy/multideploy.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index fd04043a..85a8dfd4 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -49,12 +49,6 @@ multideploy_deploy() { _debug _cfullchain "$_cfullchain" _debug _cpfx "$_cpfx" - DOMAIN_DIR=$_cdomain - if echo "$DOMAIN_PATH" | grep -q "$ECC_SUFFIX"; then - DOMAIN_DIR="$DOMAIN_DIR"_ecc - fi - _debug2 "DOMAIN_DIR" "$DOMAIN_DIR" - MULTIDEPLOY_FILENAME="${MULTIDEPLOY_FILENAME:-$(_getdeployconf MULTIDEPLOY_FILENAME)}" if [ -z "$MULTIDEPLOY_FILENAME" ]; then MULTIDEPLOY_FILENAME="multideploy.yml" From 37c25aa107e0c05e2ddc4131cc0d9efc0dad5971 Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Sat, 31 May 2025 20:19:49 +0200 Subject: [PATCH 26/41] removed unneeded return value --- deploy/multideploy.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 85a8dfd4..88a2c6cc 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -271,5 +271,4 @@ _deploy_service() { _info "$(__green "Deploying") to '$_name' using '$_hook'" _deploy "$_cdomain" "$_hook" - return $? } From d375012c5db3d688daba40425430778ac0106aaf Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Tue, 1 Jul 2025 16:02:50 +0200 Subject: [PATCH 27/41] fixed yml file env list --- deploy/multideploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 88a2c6cc..9ab16d0d 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -235,7 +235,7 @@ _deploy_services() { for _service in $(printf '%s\n' "$_service_list"); do _debug2 "Service" "$_service" _hook=$(yq e ".services[] | select(.name == \"$_service\").hook" "$_deploy_file") - _envs=$(yq e ".services[] | select(.name == \"$_service\").environment[]" "$_deploy_file") + _envs=$(yq e ".services[] | select(.name == \"$_service\").environment" "$_deploy_file") _export_envs "$_envs" if ! _deploy_service "$_service" "$_hook"; then From f850e8d0e466514262ecb6ee6d051da228dad115 Mon Sep 17 00:00:00 2001 From: Jacobo de Vera Date: Sun, 31 Aug 2025 13:45:34 +0100 Subject: [PATCH 28/41] Support spaces in service names - Prefer using a pipe to `while read` - But use a temp file when the loop needs to modify variables that need to be used outside the loop, as the pipe creates a subshell and modifications do not survive after the loop exits. --- deploy/multideploy.sh | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 9ab16d0d..f5d6f587 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -147,9 +147,8 @@ _check_deployfile() { fi _debug2 "Config has services." - IFS=$(printf '\n') # Check if extracted services exist in services list - for _service in $_services; do + echo "$_services" | while read -r _service; do _debug2 "Checking service" "$_service" # Check if service exists if ! yq e ".services[] | select(.name == \"$_service\")" "$_deploy_file" >/dev/null; then @@ -169,7 +168,6 @@ _check_deployfile() { return 1 fi done - IFS=$OLDIFS } # Description: This function takes a list of environment variables in YAML format, @@ -225,14 +223,15 @@ _deploy_services() { _deploy_file="$1" _debug3 "Deploy file" "$_deploy_file" - _services=$(yq e '.services[].name' "$_deploy_file") - _debug3 "Services" "$_services" + _tempfile=$(mktemp) + trap "rm -f $_tempfile" EXIT - _service_list=$(printf '%s\n' "$_services") + yq e '.services[].name' "$_deploy_file" > $_tempfile + _debug3 "Services" "$(cat $_tempfile)" _failedServices="" _failedCount=0 - for _service in $(printf '%s\n' "$_service_list"); do + while read -r _service; do _debug2 "Service" "$_service" _hook=$(yq e ".services[] | select(.name == \"$_service\").hook" "$_deploy_file") _envs=$(yq e ".services[] | select(.name == \"$_service\").environment" "$_deploy_file") @@ -243,7 +242,7 @@ _deploy_services() { _failedCount=$((_failedCount + 1)) fi _clear_envs "$_envs" - done + done < "$_tempfile" _debug3 "Failed services" "$_failedServices" _debug2 "Failed count" "$_failedCount" From 986a6138ebda928297a859f12ab72f2b040d7e27 Mon Sep 17 00:00:00 2001 From: Jacobo de Vera Date: Sun, 31 Aug 2025 19:19:44 +0100 Subject: [PATCH 29/41] Fix config file checks The config file checks were returning okay even when there were errors. The yq tool returns "null" when it cannot find what's queried, but exists with a 0 rc still. --- deploy/multideploy.sh | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index f5d6f587..5ed62ec3 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -127,7 +127,7 @@ _preprocess_deployfile() { # _check_deployfile "" _check_deployfile() { _deploy_file="$1" - _debug2 "Deploy file" "$_deploy_file" + _debug2 "check: Deploy file" "$_deploy_file" # Check version _deploy_file_version=$(yq '.version' "$_deploy_file") @@ -135,38 +135,44 @@ _check_deployfile() { _err "As of $PROJECT_NAME $VER, the deploy file needs version $MULTIDEPLOY_VERSION! Your current deploy file is of version $_deploy_file_version." return 1 fi - _debug2 "Deploy file version is compatible: $_deploy_file_version" + _debug2 "check: Deploy file version is compatible: $_deploy_file_version" # Extract all services from config _services=$(yq e '.services[].name' "$_deploy_file") - _debug2 "Services" "$_services" if [ -z "$_services" ]; then _err "Config does not have any services to deploy to." return 1 fi - _debug2 "Config has services." + _debug2 "check: Config has services." + echo "$_services" | while read -r _service; do + _debug3 " - $_service" + done # Check if extracted services exist in services list echo "$_services" | while read -r _service; do - _debug2 "Checking service" "$_service" + _debug2 "check: Checking service: $_service" # Check if service exists - if ! yq e ".services[] | select(.name == \"$_service\")" "$_deploy_file" >/dev/null; then + _service_config=$(yq e ".services[] | select(.name == \"$_service\")" "$_deploy_file") + if [ -z "$_service_config" ] || [ "$_service_config" = "null" ]; then _err "Service '$_service' not found." return 1 fi + _secure_debug3 "check: Service '$_service' configuration" "$_service_config" - # Check if service has hook - if ! yq e ".services[] | select(.name == \"$_service\").hook" "$_deploy_file" >/dev/null; then + _service_hook=$(echo "$_service_config" | yq e ".hook" -) + if [ -z "$_service_hook" ] || [ "$_service_hook" = "null" ]; then _err "Service '$_service' does not have a hook." return 1 fi + _debug3 "check: Service '$_service' hook" "$_service_hook" - # Check if service has environment - if ! yq e ".services[] | select(.name == \"$_service\").environment" "$_deploy_file" >/dev/null; then + _service_environment=$(echo "$_service_config" | yq e ".environment" -) + if [ -z "$_service_environment" ] || [ "$_service_environment" = "null" ]; then _err "Service '$_service' does not have an environment." return 1 fi + _secure_debug3 "check: Service '$_service' environment" "$_service_environment" done } From 1d8788767f0173423a03201ece84562268beccb9 Mon Sep 17 00:00:00 2001 From: Jacobo de Vera Date: Sun, 31 Aug 2025 19:20:38 +0100 Subject: [PATCH 30/41] Make failure to check file stop the deployment Before this, checker issues were only logged. This stops the deployment if any configuration is incorrect. --- deploy/multideploy.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 5ed62ec3..18b6d7ce 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -108,12 +108,15 @@ _preprocess_deployfile() { done IFS=$OLDIFS - if [ -n "$found_file" ]; then - _check_deployfile "$DOMAIN_PATH/$found_file" - else + if [ -z "$found_file" ]; + then _err "Deploy file not found. Go to https://github.com/acmesh-official/acme.sh/wiki/deployhooks#36-deploying-to-multiple-services-with-the-same-hooks to see how to create one." return 1 fi + if ! _check_deployfile "$DOMAIN_PATH/$found_file"; then + _err "Deploy file is not valid: $DOMAIN_PATH/$found_file" + return 1 + fi echo "$DOMAIN_PATH/$found_file" } From 1eee4dee9cfd165587f8a95104b5f4251c440416 Mon Sep 17 00:00:00 2001 From: Jacobo de Vera Date: Sun, 31 Aug 2025 19:22:21 +0100 Subject: [PATCH 31/41] Update dependency name from yq to yq-go --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 4852cde4..36b2adac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ RUN apk --no-cache add -f \ tar \ libidn \ jq \ - yq \ + yq-go \ cronie ENV LE_WORKING_DIR=/acmebin From a961e03a597537f09ce9475bd9609ddb858d3773 Mon Sep 17 00:00:00 2001 From: Jacobo de Vera Date: Sun, 31 Aug 2025 19:32:52 +0100 Subject: [PATCH 32/41] Explain the use of eval --- deploy/multideploy.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 18b6d7ce..8c6f4267 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -192,6 +192,7 @@ _export_envs() { IFS=$(printf '\n') echo "$_env_list" | yq e -r 'to_entries | .[] | .key + "=" + .value' | while IFS='=' read -r _key _value; do + # Using eval to expand nested variables in the configuration file _value=$(eval echo "$_value") _savedeployconf "$_key" "$_value" _secure_debug3 "Saved $_key" "$_value" From 69dd2cf78b71d1e616011428b5500a15f463f9d3 Mon Sep 17 00:00:00 2001 From: Jacobo de Vera Date: Sun, 31 Aug 2025 19:36:07 +0100 Subject: [PATCH 33/41] Explain _clear_envs rationale --- deploy/multideploy.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 8c6f4267..8a2fbd37 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -203,6 +203,14 @@ _export_envs() { # Description: # This function takes a YAML formatted string of environment variables, parses it, # and clears each environment variable. It logs the process of clearing each variable. +# +# Note: Environment variables for a hook may be optional and differ between +# services using the same hook. +# If one service sets optional environment variables and another does not, the +# variables may persist and affect subsequent deployments. +# Clearing these variables after each service ensures that only the +# environment variables explicitly specified for each service in the deploy +# file are used. # Arguments: # $1 - A YAML formatted string containing environment variable key-value pairs. # Usage: From 8a788651745b39ba15d8b6a078180822f91cd1da Mon Sep 17 00:00:00 2001 From: Jacobo de Vera Date: Sun, 31 Aug 2025 19:41:12 +0100 Subject: [PATCH 34/41] Quote paths to prevent word splitting --- deploy/multideploy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 8a2fbd37..2db9a758 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -244,8 +244,8 @@ _deploy_services() { _tempfile=$(mktemp) trap "rm -f $_tempfile" EXIT - yq e '.services[].name' "$_deploy_file" > $_tempfile - _debug3 "Services" "$(cat $_tempfile)" + yq e '.services[].name' "$_deploy_file" > "$_tempfile" + _debug3 "Services" "$(cat "$_tempfile")" _failedServices="" _failedCount=0 From 4f0a4850a68ed0b7882f463fe755516fee4b1ecc Mon Sep 17 00:00:00 2001 From: Jacobo de Vera Date: Sun, 31 Aug 2025 19:43:49 +0100 Subject: [PATCH 35/41] Remove unnecessary resetting of IFS --- deploy/multideploy.sh | 7 ------- 1 file changed, 7 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 2db9a758..eec7b8ac 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -58,7 +58,6 @@ multideploy_deploy() { _debug2 "MULTIDEPLOY_FILENAME" "$MULTIDEPLOY_FILENAME" fi - OLDIFS=$IFS if ! file=$(_preprocess_deployfile "$MULTIDEPLOY_FILENAME"); then _err "Failed to preprocess deploy file." return 1 @@ -92,7 +91,6 @@ _preprocess_deployfile() { _debug3 "yq is installed." # Check if deploy file exists - IFS=$(printf '\n') for file in "$@"; do _debug3 "Checking file" "$DOMAIN_PATH/$file" if [ -f "$DOMAIN_PATH/$file" ]; then @@ -106,7 +104,6 @@ _preprocess_deployfile() { _debug3 "File not found" fi done - IFS=$OLDIFS if [ -z "$found_file" ]; then @@ -190,14 +187,12 @@ _export_envs() { _secure_debug3 "Exporting envs" "$_env_list" - IFS=$(printf '\n') echo "$_env_list" | yq e -r 'to_entries | .[] | .key + "=" + .value' | while IFS='=' read -r _key _value; do # Using eval to expand nested variables in the configuration file _value=$(eval echo "$_value") _savedeployconf "$_key" "$_value" _secure_debug3 "Saved $_key" "$_value" done - IFS=$OLDIFS } # Description: @@ -221,13 +216,11 @@ _clear_envs() { _secure_debug3 "Clearing envs" "$_env_list" env_pairs=$(echo "$_env_list" | yq e -r 'to_entries | .[] | .key + "=" + .value') - IFS=$(printf '\n') echo "$env_pairs" | while IFS='=' read -r _key _value; do _debug3 "Deleting key" "$_key" _cleardomainconf "SAVED_$_key" unset -v "$_key" done - IFS="$OLDIFS" } # Description: From 6b66e734a92d1d6a5b2bfedeb81ded69f04d02ec Mon Sep 17 00:00:00 2001 From: Jacobo de Vera Date: Sun, 31 Aug 2025 20:02:56 +0100 Subject: [PATCH 36/41] Remove explicit save of the deployhook acme.sh takes care of that --- deploy/multideploy.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index eec7b8ac..e1b8bf87 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -68,10 +68,6 @@ multideploy_deploy() { _deploy_services "$file" _exitCode="$?" - # Save deployhook for renewals - _debug2 "Setting Le_DeployHook" - _savedomainconf "Le_DeployHook" "multideploy" - return "$_exitCode" } From b8b1f1e9b40765dbe917f510e205a5f81f70b0f9 Mon Sep 17 00:00:00 2001 From: Jacobo de Vera Date: Mon, 1 Sep 2025 00:04:42 +0100 Subject: [PATCH 37/41] Remove config logging when checking Because it causes a mysterious crash and it's honestly not worth it. --- deploy/multideploy.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index e1b8bf87..2d2a7a37 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -154,21 +154,18 @@ _check_deployfile() { _err "Service '$_service' not found." return 1 fi - _secure_debug3 "check: Service '$_service' configuration" "$_service_config" _service_hook=$(echo "$_service_config" | yq e ".hook" -) if [ -z "$_service_hook" ] || [ "$_service_hook" = "null" ]; then _err "Service '$_service' does not have a hook." return 1 fi - _debug3 "check: Service '$_service' hook" "$_service_hook" _service_environment=$(echo "$_service_config" | yq e ".environment" -) if [ -z "$_service_environment" ] || [ "$_service_environment" = "null" ]; then _err "Service '$_service' does not have an environment." return 1 fi - _secure_debug3 "check: Service '$_service' environment" "$_service_environment" done } From ab7835ec58a74d002dfc2eba593000789edda9b3 Mon Sep 17 00:00:00 2001 From: Jacobo de Vera Date: Mon, 1 Sep 2025 00:06:07 +0100 Subject: [PATCH 38/41] Fix eval bug by quoting Before this, the eval call would try to run some commands (if they were compound commands) in the yaml file on the machine running acme.sh Eval might not be worth it for the little benefit it brings. --- deploy/multideploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 2d2a7a37..460e06d5 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -182,7 +182,7 @@ _export_envs() { echo "$_env_list" | yq e -r 'to_entries | .[] | .key + "=" + .value' | while IFS='=' read -r _key _value; do # Using eval to expand nested variables in the configuration file - _value=$(eval echo "$_value") + _value=$(eval 'echo "'"$_value"'"') _savedeployconf "$_key" "$_value" _secure_debug3 "Saved $_key" "$_value" done From 96f38655b4bc8a7147eec36742c5ac3e10779384 Mon Sep 17 00:00:00 2001 From: Jacobo de Vera Date: Mon, 1 Sep 2025 00:07:44 +0100 Subject: [PATCH 39/41] Use file descriptor 3 for main deployment loop Before this, some deployment scripts would interact with STDIN and that would cause this loop to skip some elements. By using descriptor 3 we avoid clashing with the very common stdin and stdout. --- deploy/multideploy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 460e06d5..590cfba7 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -235,7 +235,7 @@ _deploy_services() { _failedServices="" _failedCount=0 - while read -r _service; do + while read -r _service <&3; do _debug2 "Service" "$_service" _hook=$(yq e ".services[] | select(.name == \"$_service\").hook" "$_deploy_file") _envs=$(yq e ".services[] | select(.name == \"$_service\").environment" "$_deploy_file") @@ -246,7 +246,7 @@ _deploy_services() { _failedCount=$((_failedCount + 1)) fi _clear_envs "$_envs" - done < "$_tempfile" + done 3< "$_tempfile" _debug3 "Failed services" "$_failedServices" _debug2 "Failed count" "$_failedCount" From 61b59831c491e1f038c64bd31f863fc8fd8e280b Mon Sep 17 00:00:00 2001 From: tomo <49612544+tomo2403@users.noreply.github.com> Date: Sat, 6 Sep 2025 12:31:56 +0200 Subject: [PATCH 40/41] minor code style adjustments in multideploy script --- deploy/multideploy.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 590cfba7..9e8b7164 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -101,8 +101,7 @@ _preprocess_deployfile() { fi done - if [ -z "$found_file" ]; - then + if [ -z "$found_file" ]; then _err "Deploy file not found. Go to https://github.com/acmesh-official/acme.sh/wiki/deployhooks#36-deploying-to-multiple-services-with-the-same-hooks to see how to create one." return 1 fi @@ -228,9 +227,9 @@ _deploy_services() { _debug3 "Deploy file" "$_deploy_file" _tempfile=$(mktemp) - trap "rm -f $_tempfile" EXIT + trap 'rm -f $_tempfile' EXIT - yq e '.services[].name' "$_deploy_file" > "$_tempfile" + yq e '.services[].name' "$_deploy_file" >"$_tempfile" _debug3 "Services" "$(cat "$_tempfile")" _failedServices="" @@ -246,7 +245,7 @@ _deploy_services() { _failedCount=$((_failedCount + 1)) fi _clear_envs "$_envs" - done 3< "$_tempfile" + done 3<"$_tempfile" _debug3 "Failed services" "$_failedServices" _debug2 "Failed count" "$_failedCount" From 11cae37405e2f82b6356fd662551be625a16cb6f Mon Sep 17 00:00:00 2001 From: invario <67800603+invario@users.noreply.github.com> Date: Sat, 20 Dec 2025 11:04:04 -0500 Subject: [PATCH 41/41] make compatible with both yq versions kislyuk yq (used by Debian packages) does not accept `yq e` and also returns strings with double quotes. mikefarah's yq-go (used by Alpine) accepts `yq e` and `yq`. replace `yq e` with `yq` and also use `-r` switch to remove double quoting to ensure uniform return values from both yq versions. Signed-off-by: invario <67800603+invario@users.noreply.github.com> --- deploy/multideploy.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/deploy/multideploy.sh b/deploy/multideploy.sh index 9e8b7164..ef920f64 100644 --- a/deploy/multideploy.sh +++ b/deploy/multideploy.sh @@ -125,7 +125,7 @@ _check_deployfile() { _debug2 "check: Deploy file" "$_deploy_file" # Check version - _deploy_file_version=$(yq '.version' "$_deploy_file") + _deploy_file_version=$(yq -r '.version' "$_deploy_file") if [ "$MULTIDEPLOY_VERSION" != "$_deploy_file_version" ]; then _err "As of $PROJECT_NAME $VER, the deploy file needs version $MULTIDEPLOY_VERSION! Your current deploy file is of version $_deploy_file_version." return 1 @@ -133,7 +133,7 @@ _check_deployfile() { _debug2 "check: Deploy file version is compatible: $_deploy_file_version" # Extract all services from config - _services=$(yq e '.services[].name' "$_deploy_file") + _services=$(yq -r '.services[].name' "$_deploy_file") if [ -z "$_services" ]; then _err "Config does not have any services to deploy to." @@ -148,19 +148,19 @@ _check_deployfile() { echo "$_services" | while read -r _service; do _debug2 "check: Checking service: $_service" # Check if service exists - _service_config=$(yq e ".services[] | select(.name == \"$_service\")" "$_deploy_file") + _service_config=$(yq -r ".services[] | select(.name == \"$_service\")" "$_deploy_file") if [ -z "$_service_config" ] || [ "$_service_config" = "null" ]; then _err "Service '$_service' not found." return 1 fi - _service_hook=$(echo "$_service_config" | yq e ".hook" -) + _service_hook=$(echo "$_service_config" | yq -r ".hook" -) if [ -z "$_service_hook" ] || [ "$_service_hook" = "null" ]; then _err "Service '$_service' does not have a hook." return 1 fi - _service_environment=$(echo "$_service_config" | yq e ".environment" -) + _service_environment=$(echo "$_service_config" | yq -r ".environment" -) if [ -z "$_service_environment" ] || [ "$_service_environment" = "null" ]; then _err "Service '$_service' does not have an environment." return 1 @@ -179,7 +179,7 @@ _export_envs() { _secure_debug3 "Exporting envs" "$_env_list" - echo "$_env_list" | yq e -r 'to_entries | .[] | .key + "=" + .value' | while IFS='=' read -r _key _value; do + echo "$_env_list" | yq -r 'to_entries | .[] | .key + "=" + .value' | while IFS='=' read -r _key _value; do # Using eval to expand nested variables in the configuration file _value=$(eval 'echo "'"$_value"'"') _savedeployconf "$_key" "$_value" @@ -206,7 +206,7 @@ _clear_envs() { _env_list="$1" _secure_debug3 "Clearing envs" "$_env_list" - env_pairs=$(echo "$_env_list" | yq e -r 'to_entries | .[] | .key + "=" + .value') + env_pairs=$(echo "$_env_list" | yq -r 'to_entries | .[] | .key + "=" + .value') echo "$env_pairs" | while IFS='=' read -r _key _value; do _debug3 "Deleting key" "$_key" @@ -229,15 +229,15 @@ _deploy_services() { _tempfile=$(mktemp) trap 'rm -f $_tempfile' EXIT - yq e '.services[].name' "$_deploy_file" >"$_tempfile" + yq -r '.services[].name' "$_deploy_file" >"$_tempfile" _debug3 "Services" "$(cat "$_tempfile")" _failedServices="" _failedCount=0 while read -r _service <&3; do _debug2 "Service" "$_service" - _hook=$(yq e ".services[] | select(.name == \"$_service\").hook" "$_deploy_file") - _envs=$(yq e ".services[] | select(.name == \"$_service\").environment" "$_deploy_file") + _hook=$(yq -r ".services[] | select(.name == \"$_service\").hook" "$_deploy_file") + _envs=$(yq -r ".services[] | select(.name == \"$_service\").environment" "$_deploy_file") _export_envs "$_envs" if ! _deploy_service "$_service" "$_hook"; then