Skip to content

Instantly share code, notes, and snippets.

@CallumCarmicheal
Created March 13, 2026 10:37
Show Gist options
  • Select an option

  • Save CallumCarmicheal/f4e195da446b1c2e23de047f6adbe8d8 to your computer and use it in GitHub Desktop.

Select an option

Save CallumCarmicheal/f4e195da446b1c2e23de047f6adbe8d8 to your computer and use it in GitHub Desktop.
[WePanel] acme.sh deployment hook

This is a hook file created for use with WePanel, a replica/replacement for CPanel which is being used by names.co.uk.

Setup

  • Download the script below wepanel.sh and store it inside ~/.acme.sh/deploy or where ever you have installed acme/deploy
  • Mark the script as runnable: chmod +x wepanel.sh
  • Issue and deploy the domain
export WEPANEL_USER="ca4saen1"
export WEPANEL_PASS="supersecurePassword$"
export WEPANEL_URL="abcd1234.webapps.net:2443"

acme.sh --issue  -d domain.co.uk -d www.domain.co.uk -w /home/<username>/sites/domain.co.uk
acme.sh --deploy -d domain.co.uk -d www.domain.co.uk --deploy-hook wepanel
  • If you already have a website just run the deploy command and it will add the hook.

Environment Variables

Please note these variables are automatically saved so that they may be used in a cron job, these are saved in plain text alongside the website inside the website configuration folder. For example: ~/.acme.sh/example.com_ecc/example.com.conf

  • WEPANEL_USER - The username of the web panel login
  • WEPANEL_PASS - The password of the web panel login
  • WEPANEL_URL - The web panel url

Example:

WEPANEL_USER='ca4saen1'
WEPANEL_PASS='supersecurePassword$'
WEPANEL_URL='abcd1234.webapps.net:2443'
#!/bin/bash
# ~/.acme.sh/deploy/wepanel.sh
#
# --------------------------------------------------------------------
# Lightweight fall-back for acme.sh helper functions
# (Safe in POSIX sh, dash, bash, zsh …)
# --------------------------------------------------------------------
#command -v _info >/dev/null 2>&1 || _info() { printf '%s\n' "$@"; }
#command -v _err >/dev/null 2>&1 || _err() { printf 'ERROR: %s\n' "$@" >&2; }
#command -v _error >/dev/null 2>&1 || _error() { _err "$@"; } # acme.sh uses _err, but alias just in case
# ---------------------------------------------
# log in to wePanel API and capture auth token
# ---------------------------------------------
_wepanel_authenticate() {
host=$WEPANEL_URL
user=$WEPANEL_USER
pass=$WEPANEL_PASS
_debug AUTH_WEPANEL_USER "$WEPANEL_USER"
_debug AUTH_WEPANEL_PASS "$WEPANEL_PASS"
_debug AUTH_WEPANEL_URL "$WEPANEL_URL"
# build JSON payload safely
payload=$(jq -Rn --arg user "$user" --arg pass "$pass" \
'{code2fa:"",twofactor:false,type:"",username:$user,password:$pass}')
# hit the endpoint
resp=$(curl -sS --connect-timeout 10 --max-time 60 --fail \
-X POST "https://$host/api/v1/user/login" \
-H 'Content-Type: application/json' \
-d "$payload")
# DEBUG: Print the login response
#printf "[WePanel] response:"
#printf $resp
#printf "\n"
authUser=$(printf '%s' "$resp" | jq -r '.result.user')
authToken=$(printf '%s' "$resp" | jq -r '.result.data.token')
status=$(printf '%s' "$resp" | jq -r '.result.status')
# boolean for calling scripts
authLoggedIn=false
[ "$status" = "true" ] && authLoggedIn=true
# export for downstream steps
export authUser authToken authLoggedIn
# show the token (or use >> ~/.auth_token, etc.)
if [ "$authLoggedIn" != "true" ]; then
return 1
fi
_info "[WePanel] Autenticated: $authLoggedIn, Auth Token: $authToken"
return 0
}
_wepanel_certificate_verify() {
domain=$1
ca=$2
cert=$3
key=$4
host=$WEPANEL_URL
#_info "[WePanel.wepanel_certificate_verify] Domain: $domain"
#_info "[WePanel.wepanel_certificate_verify] Certificate: $cert"
#_info "[WePanel.wepanel_certificate_verify] Private Key: $key"
#_info "[WePanel.wepanel_certificate_verify] CA Authority: $ca"
payload=$(jq -Rn --arg domain "$domain" \
--arg ca "$ca" \
--arg cert "$cert" \
--arg key "$key" \
'{domain:$domain,ca:$ca,cert:$cert,key:$key}')
# hit the endpoint
resp=$(curl -sS --connect-timeout 10 --max-time 60 --fail \
-X POST "https://$host/api/v1/ssl/info" \
-H 'Content-Type: application/json' \
--cookie "token=$authToken" \
-d "$payload")
certStatus=$(printf '%s' "$resp" | jq -r '.result.data.status')
certSuccessMessage=$(printf '%s' "$resp" | jq -r '.result.messages')
certErrorMessage=$(printf '%s' "$resp" | jq -r '.result.data.error_status')
#_info "[WePanel.wepanel_certificate_verify] \$payload =\n$payload";
_info "[WePanel.wepanel_certificate_verify] \$resp = $resp"
_info "[WePanel.wepanel_certificate_verify] \$certStatus = $certStatus"
_info "[WePanel.wepanel_certificate_verify] \$certSuccessMessage = $certSuccessMessage"
_info "[WePanel.wepanel_certificate_verify] \$certErrorMessage = $certErrorMessage"
export certStatus certSuccessMessage certErrorMessage
if [ "$certStatus" != "true" ]; then
return 1
fi
return 0
}
_wepanel_certificate_install() {
domain=$1
ca=$2
cert=$3
key=$4
host=$WEPANEL_URL
#_info "[WePanel.wepanel_certificate_verify] Domain: $domain"
#_info "[WePanel.wepanel_certificate_verify] Certificate: $cert"
#_info "[WePanel.wepanel_certificate_verify] Private Key: $key"
#_info "[WePanel.wepanel_certificate_verify] CA Authority: $ca"
payload=$(jq -Rn --arg domain "$domain" \
--arg ca "$ca" \
--arg cert "$cert" \
--arg key "$key" \
'{domain:$domain,ca:$ca,cert:$cert,key:$key}')
# hit the endpoint
resp=$(curl -sS -sS --connect-timeout 10 --max-time 60 --fail \
-X POST "https://$host/api/v1/ssl/install" \
-H 'Content-Type: application/json' \
--cookie "token=$authToken" \
-d "$payload")
certStatus=$(printf '%s' "$resp" | jq -r '.result.data.status')
certSuccessMessage=$(printf '%s' "$resp" | jq -r '.result.messages')
certErrorMessage=$(printf '%s' "$resp" | jq -r '.result.data.error_status')
#_info "[WePanel.wepanel_certificate_install] \$payload =\n$payload";
_info "[WePanel.wepanel_certificate_install] \$resp = $resp"
_info "[WePanel.wepanel_certificate_install] \$certStatus = $certStatus"
_info "[WePanel.wepanel_certificate_install] \$certSuccessMessage = $certSuccessMessage"
_info "[WePanel.wepanel_certificate_install] \$certErrorMessage = $certErrorMessage"
export certStatus certSuccessMessage certErrorMessage
if [ "$certStatus" != "true" ]; then
return 1
fi
return 0
}
_wepanel_upload_certificate() {
domain=$1
certPath=$2
privKeyPath=$3
caPath=$4
_info '[WePanel] Loading certificate files.'
_info "[WePanel] - Loading certificate: $certPath"
cert=$(cat $certPath)
_info "[WePanel] - Loading private key: $privKeyPath"
key=$(cat $privKeyPath)
_info "[WePanel] - Loading ca: $caPath"
ca=$(cat $caPath)
# Attempt to authenticate
_wepanel_authenticate
authState="$?"
if [ "$authState" -ne 0 ]; then
_err "[WePanel] Failed to authenticate."
return 1
fi
_info '[WePanel] Authenticated, testing certificate.'
#_info "[WePanel.wepanel_upload_certificate] Domain: $domain"
#_info "[WePanel.wepanel_upload_certificate] Certificate: $cert"
#_info "[WePanel.wepanel_upload_certificate] Private Key: $key"
#_info "[WePanel.wepanel_upload_certificate] CA Authority: $ca"
_wepanel_certificate_verify "$domain" "$ca" "$cert" "$key"
certStatus="$?"
if [ "$certStatus" -ne 0 ]; then
_err "[WePanel] Certificate error - $certErrorMessage"
return 1
fi
_info "[WePanel] Installing certificate for domain $domain"
_wepanel_certificate_install "$domain" "$ca" "$cert" "$key"
installStatus="$?"
if [ "$installStatus" -ne 0 ]; then
_err "[WePanel] Certificate failed to install - $certErrorMessage"
return 1
fi
return 0
}
wepanel_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"
# pick up any already-saved values, fall back to env if present
: "${WEPANEL_USER:=$(cat "$DOMAIN_CONF" | grep '^WEPANEL_USER=' | cut -d= -f2-)}"
: "${WEPANEL_PASS:=$(cat "$DOMAIN_CONF" | grep '^WEPANEL_PASS=' | cut -d= -f2-)}"
: "${WEPANEL_URL:=$(cat "$DOMAIN_CONF" | grep '^WEPANEL_URL=' | cut -d= -f2-)}"
_debug WEPANEL_USER "$WEPANEL_USER"
_debug WEPANEL_PASS "$WEPANEL_PASS"
_debug WEPANEL_URL "$WEPANEL_URL"
# first run: persist whatever the user exported so future cron jobs have it
_savedomainconf WEPANEL_USER "$WEPANEL_USER"
_savedomainconf WEPANEL_PASS "$WEPANEL_PASS"
_savedomainconf WEPANEL_URL "$WEPANEL_URL"
_domain="${Le_Domain:-$1}" # works whether we are called by acme.sh or stand-alone
_wepanel_upload_certificate "$_cdomain" "$_ccert" "$_ckey" "$_cca"
ret="$?"
if [ "$ret" -ne 0 ]; then
_err "WebPanel upload failed – \$resultError='${resultError:-unknown}'"
return 1 # tell acme.sh the deploy failed
fi
_info "Certificate for $_domain uploaded to WebPanel"
return 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment