How to Delete Addon Domains in cPanel with a Script (Maps, Confirms, and Continues on Errors)

This guide shows how to delete addon domains in cPanel with a script that first prints an addon domain → associated subdomain map, asks for confirmation, then deletes both names while continuing on errors. It uses UAPI to discover relationships and whmapi1 to perform deletions.

Why this approach

  • Discovery with UAPI: DomainInfo::domains_data exposes each addon domain and its associated subdomain (servername).
  • Deletion with WHM API 1: delete_domain removes a domain. The script explicitly deletes the addon domain and then its linked subdomain.
  • Safe flow: Print the mapping, confirm with y/n, proceed, and never abort the run on a failed deletion.

Prerequisites

  • Run as root on the cPanel server.
  • Tools installed and on PATH: uapi, whmapi1, jq.
  • The target cPanel username and a file listing addon domains to remove.

Create your domain list

Save the domains (one per line) to a file (comments allowed):

# /root/addons.txt
addon1.com
addon2.net
# lines starting with # are ignored

The bash script

The script prints the map, asks for confirmation, deletes the addon domain and its associated subdomain, and logs failures without stopping.

#!/usr/bin/env bash
set -euo pipefail

CPUSER="cpanel_username"           # target cPanel user
DOMAINS_FILE="/root/addons.txt"    # one addon domain per line

need(){ command -v "$1" >/dev/null 2>&1 || { echo "Missing: $1"; exit 1; }; }
need uapi; need whmapi1; need jq

echo "Collecting domain data for user: $CPUSER ..."
json="$(uapi --user "$CPUSER" DomainInfo domains_data format=list --output=json)"

# Build map: addon_domain -> associated subdomain (servername)
declare -A ADDON2SUB
while IFS= read -r row; do
  addon=$(jq -r '.domain' <<<"$row")
  sub=$(jq -r '.servername' <<<"$row")
  ADDON2SUB["$addon"]="$sub"
done < <(jq -c '.result.data[] | select(.type=="addon_domain")' <<<"$json")

echo
echo "Mapped addon domains and their associated subdomains:"
echo "------------------------------------------------------"
declare -a TARGETS=()
while IFS= read -r addon || [[ -n "$addon" ]]; do
  [[ -z "$addon" || "$addon" =~ ^# ]] && continue
  TARGETS+=("$addon")
  sub="${ADDON2SUB[$addon]:-<not found>}"
  printf "%-30s -> %s\n" "$addon" "$sub"
done < "$DOMAINS_FILE"
echo "------------------------------------------------------"
echo

read -rp "Proceed with deletion? (y/n): " ans
[[ "$ans" =~ ^[Yy]$ ]] || { echo "Aborted."; exit 0; }

# --- deletion helpers (continue on error) ---
declare -a FAILS=()

del_domain() {
  local user="$1" name="$2"
  # prevent set -e from killing the script on failure
  set +e
  out="$(whmapi1 delete_domain user="$user" domain="$name" 2>&1)"
  rc=$?
  set -e
  if [[ $rc -ne 0 ]]; then
    echo "ERROR deleting '$name' (rc=$rc): ${out%%$'\n'*}"
    FAILS+=("$name")
    return 1
  fi
  echo "Deleted: $name"
  return 0
}

# Perform deletions (continue on errors)
for addon in "${TARGETS[@]}"; do
  sub="${ADDON2SUB[$addon]:-}"

  echo "Deleting addon: $addon"
  if ! del_domain "$CPUSER" "$addon"; then
    # Skip subdomain if addon delete failed
    continue
  fi

  if [[ -n "$sub" ]]; then
    echo "Deleting associated subdomain: $sub"
    del_domain "$CPUSER" "$sub" || true
  else
    echo "WARNING: No associated subdomain found for $addon"
  fi
done

echo
if ((${#FAILS[@]})); then
  echo "Completed with errors on ${#FAILS[@]} item(s):"
  printf ' - %s\n' "${FAILS[@]}"
  exit 1
else
  echo "Completed without deletion errors."
fi

How to run

  1. Update CPUSER and verify DOMAINS_FILE path.
  2. Save the script, make it executable: chmod +x delete-addons.sh.
  3. Run as root: ./delete-addons.sh.
  4. Review the printed map, enter y to proceed.

Troubleshooting

  • JSON parse errors from whmapi1: If your environment injects HTTP headers that confuse whmapi1, switch the deletion calls to curl against /json-api/delete_domain and parse the JSON response with jq.
  • Permissions: Ensure you are root and that the account exists. Check /usr/local/cpanel/logs/error_log if deletions fail.
  • SSL certs: If you manage custom certs, remove or reissue certs that referenced the deleted names to avoid stale SANs.

Security and safety notes

  • Always review the map before confirming.
  • Back up vhost configs or home directories if you need to preserve content or settings related to the domains.

FAQ

Does deleting an addon domain also remove its associated subdomain?

No. The script deletes the addon domain and then explicitly deletes the associated subdomain identified via servername.

Why use UAPI for discovery and WHM API 1 for deletion?

UAPI exposes detailed domain metadata per account. WHM API 1 provides the delete_domain action required for removals.

What happens if a deletion fails?

The script continues, logs the failure, and shows a summary at the end.

Will this remove website files?

Domain removal does not automatically delete arbitrary content in the user’s home directory. Verify and clean up files as needed.

Can I dry run?

Yes. Run the script and abort at the confirmation prompt after reviewing the printed map.

Leave a Reply

Your email address will not be published. Required fields are marked *