Wildcard SSL Workarounds for AutoSSL Using acme.sh

5/5 - (1 vote)

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:

  1. Include the base domain. The wildcard *.example.com doesn’t cover example.com itself. If you want both, include both.
  2. Use the correct DNS plugin. Replace dns_cf with your provider’s plugin name (e.g., dns_aws, dns_linode, dns_cpanel).
  3. Key length matters. I use 2048-bit RSA for compatibility. If your stack supports it, you can use --keylength ec-256 for 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:

  1. acme.sh handles DNS validation that AutoSSL can’t do
  2. Always exclude wildcard domains from AutoSSL to prevent conflicts
  3. Use deploy hooks for automatic installation after renewal
  4. 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.

Leave a Comment

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

Scroll to Top