AutoSSL is one of cPanel’s most convenient features—automatically provisioning and renewing SSL certificates for every domain on your server. But if you’ve ever tried to get a wildcard certificate through AutoSSL, you’ve hit a wall. AutoSSL simply doesn’t support them.
This isn’t an oversight. Wildcard certificates require DNS-based validation (DNS-01 challenge), and AutoSSL relies on HTTP validation (HTTP-01 challenge) which can’t prove control over an entire subdomain namespace. For most use cases, AutoSSL’s per-domain approach works fine. But when you’re running applications that spawn dynamic subdomains—think multi-tenant SaaS platforms, development environments with feature-branch subdomains, or mail servers with per-user subdomains—you need wildcards.
Enter acme.sh: a pure shell implementation of the ACME protocol that handles DNS validation beautifully. Here’s how to make it work alongside your existing AutoSSL setup.
Understanding the Limitation
Let’s be clear about what we’re working around. AutoSSL uses either Sectigo or Let’s Encrypt as its CA (depending on your configuration), and it validates domain ownership by placing a file at /.well-known/acme-challenge/ on your web server. This works great for individual domains and explicitly defined subdomains, but wildcards are different.
To get a wildcard certificate for *.example.com, you must prove you control the DNS for example.com by creating a specific TXT record. AutoSSL has no mechanism to do this—it doesn’t integrate with DNS APIs, and for good reason. In a shared hosting environment, giving AutoSSL DNS access would be a security nightmare.
But on servers you control, acme.sh fills this gap perfectly.
Installing acme.sh
The installation is straightforward. As root:
curl https://get.acme.sh | sh -s [email protected]
source ~/.bashrc
This installs acme.sh to ~/.acme.sh/ and sets up a cron job for automatic renewals. The email address is used for Let’s Encrypt account registration and expiration notices.
For a cleaner setup on cPanel servers, I prefer installing to a dedicated location:
curl https://get.acme.sh | sh -s [email protected] home=/opt/acme.sh
After installation, verify it’s working:
/opt/acme.sh/acme.sh --version
Configuring DNS API Access
This is where the magic happens. acme.sh supports over 150 DNS providers through their APIs. You’ll need to configure API credentials for your DNS provider before issuing certificates.
Cloudflare
Cloudflare is the most common setup I see. You’ll need either a Global API Key or a scoped API Token.
For a scoped token (recommended), create one in the Cloudflare dashboard with these permissions:
- Zone → Zone → Read
- Zone → DNS → Edit
Then export your credentials:
export CF_Token="your-api-token"
export CF_Zone_ID="your-zone-id"
For the Global API Key approach:
export CF_Key="your-global-api-key"
export CF_Email="your-cloudflare-email"
cPanel/WHM DNS (localhost)
If you’re using cPanel’s DNS server and the domains are hosted on the same server, you can use the cPanel API directly:
export CPANEL_USERNAME="root"
export CPANEL_APITOKEN="your-api-token"
Create the API token in WHM under “Manage API Tokens.” This approach keeps everything local but requires the DNS to be served by cPanel.
Other Providers
For other providers, check the acme.sh wiki. Each provider has specific environment variables. Common ones include:
Route53:
export AWS_ACCESS_KEY_ID="your-key"
export AWS_SECRET_ACCESS_KEY="your-secret"
DigitalOcean:
export DO_API_KEY="your-api-key"
Linode:
export LINODE_V4_API_KEY="your-api-key"
Issuing Your First Wildcard Certificate
With DNS API credentials configured, request your wildcard:
/opt/acme.sh/acme.sh --issue \
-d example.com \
-d "*.example.com" \
--dns dns_cf \
--keylength 2048
A few important notes here:
- Include the base domain. The wildcard
*.example.comdoesn’t coverexample.comitself. If you want both, include both. - Use the correct DNS plugin. Replace
dns_cfwith your provider’s plugin name (e.g.,dns_aws,dns_linode,dns_cpanel). - Key length matters. I use 2048-bit RSA for compatibility. If your stack supports it, you can use
--keylength ec-256for ECDSA certificates.
The first issuance takes a minute or two while DNS propagates. Subsequent renewals are faster because acme.sh caches your API credentials.
Installing Certificates in cPanel
Now for the integration. You have several options depending on your needs.
Option 1: Deploy Hook for a Single Account
For a single cPanel account, use the built-in deploy hook:
/opt/acme.sh/acme.sh --deploy \
-d example.com \
-d "*.example.com" \
--deploy-hook cpanel_uapi \
--env DEPLOY_CPANEL_USER=cpuser
This uses cPanel’s UAPI to install the certificate for the specified user. The hook handles certificate, key, and CA bundle automatically.
Option 2: Manual Installation via WHM API
For more control, especially when managing multiple domains, install directly via WHM’s API:
/usr/local/cpanel/bin/whmapi1 installssl \
domain=example.com \
crt="$(cat /opt/acme.sh/example.com/fullchain.cer)" \
key="$(cat /opt/acme.sh/example.com/example.com.key)"
Option 3: Direct File Installation
You can also copy certificates directly to cPanel’s SSL storage:
DOMAIN="example.com"
CPUSER="cpuser"
cp /opt/acme.sh/$DOMAIN/$DOMAIN.cer /var/cpanel/ssl/installed/certs/
cp /opt/acme.sh/$DOMAIN/$DOMAIN.key /var/cpanel/ssl/installed/keys/
cp /opt/acme.sh/$DOMAIN/ca.cer /var/cpanel/ssl/installed/cabundles/
# Update the SSL database
/usr/local/cpanel/bin/checkallsslcerts
This approach is useful for bulk operations but requires more care.
Preventing AutoSSL Conflicts
Here’s where things get tricky. AutoSSL doesn’t know about your wildcard certificates, and it will happily try to replace them with individual domain certificates on its next run.
Method 1: Exclude Domains from AutoSSL
The cleanest solution is to exclude wildcard-covered domains from AutoSSL processing. In WHM, go to SSL/TLS → Manage AutoSSL and add domains to the exclusion list.
Programmatically:
/usr/local/cpanel/bin/whmapi1 set_autossl_metadata \
provider=cPanel \
excluded_domains='["*.example.com","example.com"]'
Method 2: Use AutoSSL Provider Priorities
If you’re running cPanel 110+, AutoSSL respects certificate “priority.” Certificates installed via the API with a longer validity period or earlier expiration check won’t be replaced if they’re still valid.
However, this isn’t foolproof. I’ve seen AutoSSL replace perfectly valid wildcards when it detects new subdomains. Explicit exclusions are more reliable.
Method 3: Post-Renewal Hook
You can also configure acme.sh to reinstall after AutoSSL runs. Add a reloadcmd to your certificate:
/opt/acme.sh/acme.sh --issue \
-d example.com \
-d "*.example.com" \
--dns dns_cf \
--reloadcmd "/usr/local/scripts/install-wildcard-ssl.sh"
Create the referenced script to handle reinstallation:
#!/bin/bash
# /usr/local/scripts/install-wildcard-ssl.sh
DOMAIN="example.com"
/usr/local/cpanel/bin/whmapi1 installssl \
domain=$DOMAIN \
crt="$(cat /opt/acme.sh/$DOMAIN/fullchain.cer)" \
key="$(cat /opt/acme.sh/$DOMAIN/$DOMAIN.key)"
# Force Apache to reload
/usr/local/cpanel/scripts/restartsrv_httpd --restart
Automating Renewals
acme.sh sets up a cron job during installation, typically running daily at a random time. It only attempts renewal when certificates are within 30 days of expiration.
Check the cron is in place:
crontab -l | grep acme
You should see something like:
26 0 * * * "/opt/acme.sh"/acme.sh --cron --home "/opt/acme.sh" > /dev/null
Test the renewal process manually:
/opt/acme.sh/acme.sh --cron --home /opt/acme.sh
If you’ve configured deploy hooks or reloadcmds, they’ll execute automatically after successful renewals.
Multi-Domain Wildcard Setup
For servers hosting multiple clients who need wildcards, create a management script:
#!/bin/bash
# /usr/local/scripts/issue-wildcard.sh
DOMAIN=$1
DNS_PLUGIN=$2
CPUSER=$3
if [ -z "$DOMAIN" ] || [ -z "$DNS_PLUGIN" ] || [ -z "$CPUSER" ]; then
echo "Usage: $0 <domain> <dns_plugin> <cpanel_user>"
exit 1
fi
# Issue certificate
/opt/acme.sh/acme.sh --issue \
-d $DOMAIN \
-d "*.$DOMAIN" \
--dns $DNS_PLUGIN \
--keylength 2048
# Deploy to cPanel
/opt/acme.sh/acme.sh --deploy \
-d $DOMAIN \
-d "*.$DOMAIN" \
--deploy-hook cpanel_uapi \
--env DEPLOY_CPANEL_USER=$CPUSER
# Exclude from AutoSSL
/usr/local/cpanel/bin/whmapi1 set_autossl_metadata_for_provider \
provider=cPanel \
excluded_domains='["*.'$DOMAIN'","'$DOMAIN'"]'
echo "Wildcard SSL installed for $DOMAIN"
Usage:
./issue-wildcard.sh example.com dns_cf cpuser
Troubleshooting Common Issues
DNS Propagation Delays
If validation fails with “NXDOMAIN” or similar DNS errors, propagation is likely the culprit. Add a delay:
/opt/acme.sh/acme.sh --issue \
-d example.com \
-d "*.example.com" \
--dns dns_cf \
--dnssleep 120
This waits 120 seconds after creating the TXT record before asking Let’s Encrypt to validate.
Rate Limits
Let’s Encrypt has rate limits: 50 certificates per registered domain per week. If you’re hitting limits during testing, use the staging environment:
/opt/acme.sh/acme.sh --issue \
-d example.com \
-d "*.example.com" \
--dns dns_cf \
--staging
Once testing is complete, issue the production certificate:
/opt/acme.sh/acme.sh --issue \
-d example.com \
-d "*.example.com" \
--dns dns_cf \
--force
CAA Records Blocking Issuance
If your domain has CAA records, ensure Let’s Encrypt is permitted:
example.com. IN CAA 0 issue "letsencrypt.org"
example.com. IN CAA 0 issuewild "letsencrypt.org"
The issuewild tag specifically authorizes wildcard issuance.
Certificate Not Showing in cPanel
After installation, if the certificate doesn’t appear in cPanel’s SSL manager, rebuild the SSL database:
/usr/local/cpanel/bin/checkallsslcerts
/scripts/rebuildhttpdconf
/scripts/restartsrv_httpd
Security Considerations
A few things to keep in mind:
API Token Scope: Use the minimum permissions necessary. For Cloudflare, a token scoped to a single zone is safer than the Global API Key.
Credential Storage: acme.sh stores your API credentials in ~/.acme.sh/account.conf (or your custom home). Ensure this file has proper permissions:
chmod 600 /opt/acme.sh/account.conf
Certificate Key Security: Wildcard certificates are high-value targets. The private key at /opt/acme.sh/example.com/example.com.key should be readable only by root:
chmod 600 /opt/acme.sh/*/
Wrapping Up
AutoSSL handles 95% of SSL needs on a cPanel server without any intervention. But for that remaining 5%—wildcard certificates for dynamic subdomains—acme.sh is the answer. It integrates cleanly, handles renewals automatically, and with proper exclusion rules, coexists peacefully with AutoSSL.
The key points to remember:
- acme.sh handles DNS validation that AutoSSL can’t do
- Always exclude wildcard domains from AutoSSL to prevent conflicts
- Use deploy hooks for automatic installation after renewal
- Test with staging certificates to avoid rate limits
Once configured, you can largely forget about it—which is exactly what good SSL automation should do.