cPanel / WHM module
Installs the certificate — leaf, chain and private key — onto each listed domain of a cPanel/WHM server. It is the hosting-panel sibling of the IIS/F5 install modules, and closes the loop for cPanel-hosted sites: issue or renew in CertAutoPilot, then install directly onto the panel.
If cPanel AutoSSL manages a domain you install onto, it may later re-install its own certificate on top of this one. Exclude the domain from AutoSSL (WHM → Manage AutoSSL) when CertAutoPilot owns its certificate.
Overview
Two modes share one module:
- cpanel — the account-level cPanel UAPI (
SSL::install_sslon port 2083), authenticated ascpanel <user>:<token>. Installs onto the account's own domains. - whm — the root/reseller WHM API 1 (
installsslon port 2087), authenticated aswhm <user>:<token>. Installs onto any account's domain on the server. WHM always resolves the owning account from the domain —installsslhas no account parameter — and the deploy log shows the account it chose.
A cPanel install replaces the domain's current certificate, so one target serves many certificates and renewals just re-install. Every run installs unconditionally — a redundant re-install is harmless, and no expiry-based skip is applied (two different certificates can share an expiry second, so a skip there risked serving the wrong certificate).
Target configuration
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
host | string | yes | — | Bare cPanel/WHM hostname or IPv4 — no scheme, path, port or userinfo (any : is rejected, so an IPv6 literal cannot be used; give it a DNS name). Use the port field for a custom port. |
mode | enum | no | cpanel | cpanel (account UAPI) or whm (root/reseller). |
port | number | no | 2083 / 2087 | Overrides the mode default port. |
use_ssl | bool | no | true | Connect over https. false switches to plain http and the API token then travels unencrypted — only for a test proxy. |
ssl_verify | bool | no | true | Enforce the server TLS certificate (disable for a self-signed host). |
http_timeout | number | no | 30 | Per-request timeout in seconds (must be ≥ 1 when set; omit for the default). |
domains | string[] | no | — | The domain(s) to install onto. Optional — leave empty to make each distribution supply its own via a target override (one server target serving many certificates on different domains, with no shared default to inherit accidentally). A distribution that supplies none fails clearly at deploy. Overridable per distribution (full replacement). |
whm_user | string | no | — | Deprecated, ignored. WHM API 1 installssl takes no account parameter, so the value is stored but never sent; WHM resolves the owner from the domain. Still rejected if set while mode is cpanel. |
Credential & required privileges
The credential type is cpanel_api_token, stored as {"username":"...","api_token":"..."}.
Authentication is an API token, not the login password — create it in the panel and grant
exactly the privileges below (least privilege).
- cpanel mode — in cPanel: Security → Manage API Tokens → Create Token. A cPanel account
API token has full access to that account's API (there is no per-feature scope to choose), so the
only requirement is that the account's plan (its Feature List) includes SSL/TLS — that is
what makes
SSL::install_sslavailable. Setusernameto the cPanel account (e.g.elchi) andapi_tokento the generated token. - whm mode — in WHM: Development → Manage API Tokens → Generate Token. Restrict the token
to the single ACL
ssl(listed as SSL/TLS) — that ACL alone is sufficient to install certificates (verified: a token scoped to onlysslinstalls successfully viainstallssl); nothing else is needed. Setusernametoroot(or a reseller who holds thesslACL and owns the target account) andapi_tokento the generated token. Do not use a full-access token.
Per-distribution overrides
One cPanel target can be reused across many certificates. A distribution can override the install domain list (a full replacement of the target's domains) so a shared server target installs each certificate onto exactly the right domains. The whm_user override is deprecated like the target field: it is never sent, and it is rejected (422) when the named target is in cpanel mode.
Rollback
cPanel is a stateful module: rollback re-installs a previous retained certificate version through the normal install path, and auto-rollback fires on a failed/partial run where a target changed. Because an install simply replaces the domain's certificate, rolling forward again is a fresh install.
Health check, validate and dry run
The health check runs a cheap authenticated probe per target — the cPanel installed-hosts list (UAPI) or the WHM version call — proving the host, port and API token authenticate. The post-deploy Validate step is the same probe: reachability and authentication only, it does not read back which certificate a domain serves — configure a tls_fingerprint validation endpoint for that. In cpanel mode the dry run additionally lists the installed certificates so each planned install says what it would replace; WHM mode shows the plain plan.
Outbound network policy
Every request goes through the same guarded dialer as the webhook, Cloudflare and Vault modules: link-local addresses (169.254/16, fe80::/10), cloud-metadata endpoints and DNS-rebinding answers are refused before the connection is made and fail as CPANEL_CONNECT. Private (RFC 1918) and loopback hosts, where a cPanel server usually lives, stay reachable.
Error codes
| Code | Class | Meaning |
|---|---|---|
CPANEL_CONNECT | network (retried) | No response (DNS, TCP, TLS verification, timeout, refused by the outbound policy) or HTTP 5xx. |
CPANEL_AUTH | auth | HTTP 401/403, a body failure whose reason reads as an access/login problem, or an invalid stored credential. |
CPANEL_NOT_FOUND | validation | The server answered HTTP 404 — usually the UAPI path on the WHM port (or the reverse), or a proxy in front of the API. |
CPANEL_CONFLICT | validation | The server answered HTTP 409 — read the error text in the target detail. |
CPANEL_VALIDATION | validation | No cpanel spec or no domains; any other 3xx/4xx (a redirect is not followed); or a 2xx body that was not JSON. |
CPANEL_INSTALL | io_permanent | HTTP 2xx but the API reported failure — status ≠ 1 (cpanel) or metadata.result ≠ 1 / data.status ≠ 1 (whm) — with a non-auth reason. |
CPANEL_QUOTA | io_transient (retried) | HTTP 429. |
CREDENTIAL_MISSING | auth | The target has no default credential at deploy time. |
Notes
- The cPanel module is validated against a real cPanel/WHM server (both the cPanel account API and the WHM root API) — install, renewal, the rejected-cert error path, and multi-domain partial installs — in addition to Go unit tests.
- Installing a certificate on cPanel does not change discovery ownership — discovery links a discovered cert to a managed one by fingerprint independently.