# acme.sh wildcard certificate with Alibaba Cloud DNS or DNSPod

> Issue a Let's Encrypt wildcard certificate with acme.sh via the Alibaba Cloud DNS, DNSPod or DNSPod.com API, install it on Nginx, auto-renew.

Source: https://ssl.sh/guides/acme-sh-dnspod-aliyun-dns/
Last updated: 2026-11-10

acme.sh issues a Let's Encrypt wildcard certificate for `example.com` and `*.example.com` by writing DNS-01 TXT records through the Alibaba Cloud DNS or DNSPod API, so no inbound port has to be open. It then installs the certificate for Nginx and renews and reloads it on its own.

The steps apply to acme.sh 3.1.4 and later on any Linux server, including BT Panel hosts, NAS boxes and internal machines.

## Which hook to use

Pick the hook by where the domain's DNS is hosted, not by where the server runs.

- **Alibaba Cloud DNS** (China site or international account): `dns_ali`. The hook calls the `alidns.aliyuncs.com` API; acme.sh's wiki does not separate the two account types, so make your first run with `--staging`.
- **DNSPod through Tencent Cloud**: `dns_tencent` with Tencent Cloud API keys. This is the recommended option because CAM can limit the keys to DNSPod.
- **DNSPod.cn with an old DNSPod token**: `dns_dp`, kept for existing setups.
- **DNSPod.com, the international DNSPod service**: `dns_dpi`.

## Prerequisites

The only external requirement is API access to the domain's DNS.

- The domain's DNS hosted at Alibaba Cloud DNS, Tencent Cloud DNSPod (dnspod.cn) or DNSPod.com, with the domain's NS records pointing there.
- A Linux server with outbound internet access, and root or a user that can reload the web server.
- Alibaba Cloud: in **RAM**, create a RAM user with OpenAPI access, attach the `AliyunDNSFullAccess` policy (full access to Alibaba Cloud DNS and nothing else), and create an AccessKey.
- Tencent Cloud: in **Cloud Access Management (CAM)**, create a sub-user with DNSPod permissions only, and create a SecretId/SecretKey pair.
- DNSPod.com: the API ID and token from your DNSPod.com account.
- Never use the root account's keys.
- If the certificate is for a website hosted in the Chinese mainland: DNS-01 issuance itself needs no ICP filing, but serving the site from the mainland still does, and providers there block or take down websites on unfiled domains.

## Step 1: Install acme.sh

Install acme.sh with the official script, then switch its default CA to Let's Encrypt. On most servers:

```bash
curl https://get.acme.sh | sh -s email=admin@example.com
```

On servers in mainland China where GitHub downloads are slow, the acme.sh wiki documents installing from its Gitee mirror:

```bash
git clone https://gitee.com/neilpang/acme.sh.git
cd acme.sh
./acme.sh --install -m admin@example.com
```

Log in again or run `source ~/.bashrc`, then switch the default CA from ZeroSSL (the default since acme.sh v3.0) to Let's Encrypt:

```bash
acme.sh --set-default-ca --server letsencrypt
```

## Step 2: Export the DNS API keys

acme.sh reads the API keys from environment variables whose names depend on the provider. Alibaba Cloud DNS:

```bash
export Ali_Key="your-access-key-id"
export Ali_Secret="your-access-key-secret"
```

Tencent Cloud DNSPod:

```bash
export Tencent_SecretId="your-secret-id"
export Tencent_SecretKey="your-secret-key"
```

DNSPod.com (international):

```bash
export DPI_Id="your-api-id"
export DPI_Key="your-api-token"
```

After the first successful issuance acme.sh saves the keys in `~/.acme.sh/account.conf` and reuses them for renewals.

## Step 3: Issue the wildcard certificate

Run `--issue` with the hook for your DNS provider and both names, the apex and the wildcard:

```bash
acme.sh --issue --dns dns_ali -d example.com -d '*.example.com'       # Alibaba Cloud DNS
acme.sh --issue --dns dns_tencent -d example.com -d '*.example.com'   # Tencent Cloud DNSPod
acme.sh --issue --dns dns_dpi -d example.com -d '*.example.com'       # DNSPod.com
```

acme.sh adds the `_acme-challenge` TXT records, waits, completes validation and deletes the records. If validation fails because the records have not reached every authoritative server yet, add `--dnssleep 120` to wait longer. For a first test, add `--staging` so failed attempts do not count against Let's Encrypt's production limits. To get Let's Encrypt's 45-day `tlsserver` certificates, add `--cert-profile tlsserver`; see [Let's Encrypt certificate profiles](https://ssl.sh/guides/lets-encrypt-certificate-profiles/).

## Step 4: Install the certificate and set the reload command

`--install-cert` copies the certificate to a stable path and stores the reload command that acme.sh runs after every renewal:

```bash
mkdir -p /etc/nginx/ssl
acme.sh --install-cert -d example.com --ecc \
  --key-file       /etc/nginx/ssl/example.com.key \
  --fullchain-file /etc/nginx/ssl/example.com.fullchain.pem \
  --reloadcmd      "systemctl reload nginx"
```

Point Nginx at the two files:

```nginx
ssl_certificate     /etc/nginx/ssl/example.com.fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
```

On BT Panel, point `--key-file` and `--fullchain-file` at the site's certificate directory, set `--reloadcmd` to the panel's Nginx reload command (for example `/etc/init.d/nginx reload`, depending on the installation), and turn off the panel's own renewal for that site; see [BT Panel SSL](https://ssl.sh/guides/bt-panel-ssl/).

## Verify

The apex and any subdomain should present the same certificate, with `example.com` and `*.example.com` in its SAN list. Check them with the [SSL checker](https://ssl.sh/tools/ssl-checker/), or from any terminal:

```bash
curl ssl.sh/example.com
curl ssl.sh/www.example.com
```

Locally:

```bash
acme.sh --list
openssl x509 -in /etc/nginx/ssl/example.com.fullchain.pem -noout -ext subjectAltName -enddate
```

## Automatic renewal

The installer adds a cron job that runs `acme.sh --cron`. Since release 3.1.4 it runs every 6 hours and renews within the window published through ACME Renewal Information (ARI, RFC 9773); set `NO_ARI=1` to disable that. Since 3.1.5 an explicit `--days` or `--valid-to` takes precedence over the ARI window. After each renewal acme.sh repeats the install step and runs `--reloadcmd`. To check or trigger it:

```bash
crontab -l | grep acme.sh
acme.sh --cron --home ~/.acme.sh
acme.sh --upgrade --auto-upgrade
```

Let's Encrypt's default certificates change to 64 days on February 10, 2027 and 45 days on February 16, 2028; because acme.sh follows ARI, no configuration change is needed. Renewal fails if the RAM or CAM keys are disabled or deleted, and Let's Encrypt no longer sends expiry emails, so add the domain to [ssl.sh monitoring](https://ssl.sh/monitor/) (in development).

## Troubleshooting

- **InvalidAccessKeyId / Forbidden.RAM** (Alibaba Cloud): wrong AccessKey, or the RAM user lacks DNS permissions; check the attached policy.
- **AuthFailure / UnauthorizedOperation** (Tencent Cloud): wrong SecretId/SecretKey, or the sub-user lacks DNSPod permissions.
- **Verify error: no TXT record found**: the record has not reached all authoritative servers (use `--dnssleep 120`), or the domain's NS records point to a different provider than the hook you used. See [acme.sh verify error](https://ssl.sh/errors/acme-sh-verify-error/).
- **CAA record prevents issuance**: CAA must allow `letsencrypt.org`; see [CAA record prevents issuance](https://ssl.sh/errors/caa-record-prevents-issuance/).
- **Rate limit reached**: repeated test issuances; use `--staging`, see [Let's Encrypt rate limits](https://ssl.sh/errors/lets-encrypt-rate-limit/).
- **acme.sh asks you to register an email with ZeroSSL**: the default CA was not switched; run the `--set-default-ca --server letsencrypt` command from Step 1.
