Operations 12 min read

Wildcard Certificates + acme.sh: Automating Multi-Subdomain SSL Management

This guide demonstrates using wildcard SSL certificates with acme.sh to automate issuance, renewal, and deployment across multiple subdomains via DNS API validation and fixed Nginx certificate paths.

Code of Duty
Code of Duty
Code of Duty
Wildcard Certificates + acme.sh: Automating Multi-Subdomain SSL Management

Problem: Managing Multiple Subdomain Certificates

When running multiple services under subdomains like blog.example.com, www.example.com, api.example.com, and admin.example.com, requesting a separate certificate for each domain creates fragmented maintenance. Each certificate requires individual application, download, placement, configuration, and renewal — with potentially different expiration dates. Over time, certificate management shifts from infrastructure to burden.

Solution: Wildcard Certificate + acme.sh

A wildcard certificate ( *.example.com) covers all first-level subdomains. To also secure the apex domain ( example.com), include both in the request:

-d example.com
-d '*.example.com'

This single certificate serves all subdomains, drastically reducing operational overhead.

Wildcard Certificates Require DNS Validation

The CA requires a TXT record like _acme-challenge.example.com to prove DNS control. Manual TXT record creation works for initial issuance but fails for automated renewal. DNS APIs enable automatic record creation and cleanup.

acme.sh: ACME Client for Automation

acme.sh

is a shell script that supports wildcard certificates, DNS APIs, scheduled renewal, installation to a fixed path, and post-renewal reload commands. The key requirement: certificates must auto-renew and the production Nginx must reload the new certificate.

Cloud Provider Authorization

Create a RAM User with Minimal Permissions

Create a sub-user in the cloud console and grant only one permission : DNS record management. This limits blast radius if the API key leaks.

Create API Key and Secret

Generate an API Key/Secret pair for the RAM user. Store securely (shown only once). Rotate periodically to reduce exposure risk. If the DNS provider supports per-domain or per-record-type authorization, use the narrowest scope.

Installing acme.sh

Official install:

curl https://get.acme.sh | sh -s [email protected]

Or via Git:

git clone https://github.com/acmesh-official/acme.sh.git
cd ./acme.sh
./acme.sh --install -m [email protected]

For China network issues, see the wiki at https://github.com/acmesh-official/acme.sh/wiki/Install-in-China. Installation creates ~/.acme.sh/ and a cron job. Reload shell and verify with ~/.acme.sh/acme.sh --help.

Configuring DNS API Credentials

Each DNS provider uses different environment variable names (e.g., Alibaba Cloud uses Ali_Key and Ali_Secret). Consult the provider's DNS API documentation. Example for Alibaba Cloud:

export Ali_Key="your-api-key"
export Ali_Secret="your-api-secret"

Persist across reboots by appending to ~/.bashrc and sourcing it.

Issuing the Wildcard Certificate

Run the issuance command with your DNS plugin:

acme.sh --issue \
  -d example.com \
  -d '*.example.com' \
  --dns dns_ali

Replace dns_ali with your provider's plugin name (e.g., dns_cf for Cloudflare). On first run, acme.sh will:

Connect to the DNS provider via API

Create the TXT validation record

Request the certificate from Let's Encrypt

Delete the TXT record

If issuance fails, diagnose the error (common causes: wrong credentials, insufficient permissions, incorrect plugin name, domain not managed by this DNS provider, TXT propagation delay, CA rate limits) — do not blindly retry.

Deploying the Certificate to Production

Do not point Nginx directly at ~/.acme.sh/ — its internal structure may change. Use --install-cert to copy to a stable, self-managed path. In this setup:

mkdir -p /opt/coduty/nginx/certs/example.com
acme.sh --install-cert -d example.com \
  --key-file /opt/coduty/nginx/certs/example.com/privkey.pem \
  --fullchain-file /opt/coduty/nginx/certs/example.com/fullchain.pem \
  --reloadcmd "docker exec global-nginx nginx -s reload"

Critical flags: --fullchain-file (Nginx needs the full chain) and --reloadcmd (ensures the running Nginx loads the renewed certificate). Without reload, the old certificate persists.

Nginx Configuration Example

Each virtual host references the same fixed certificate paths (container-internal paths shown):

server {
  listen 443 ssl;
  server_name blog.example.com;

  ssl_certificate /etc/nginx/certs/example.com/fullchain.pem;
  ssl_certificate_key /etc/nginx/certs/example.com/privkey.pem;

  location / {
    proxy_pass http://blog-app:8000;
  }
}

Verification

Test Nginx config: docker exec global-nginx nginx -t Reload: docker exec global-nginx nginx -s reload Check cron job: crontab -l (acme.sh installs a daily renewal check)

Manual renewal test: acme.sh --cron or force renew: acme.sh --renew -d example.com --force Verify via browser or CLI:

curl -I https://blog.example.com
openssl s_client -connect blog.example.com:443 -servername blog.example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -subject -issuer

Troubleshooting: if apex works but subdomains fail, ensure -d '*.example.com' was included; if subdomains work but apex fails, ensure -d example.com was included.

Summary: Benefits and Risks

Benefits

Multiple subdomains share one certificate

Fixed certificate path

Automated renewal

Adding a new subdomain only requires DNS and Nginx config

Consistent global Nginx container architecture

Risks

Wildcard private key compromise affects all covered subdomains

DNS API credentials must be tightly protected

Automated renewal should be periodically verified reloadcmd must be correct and executable *.example.com does not cover deeper subdomains like

a.b.example.com
Wildcard certificates solve multi-subdomain coverage, DNS APIs solve automated validation, acme.sh handles issuance, installation, and renewal, and a global Nginx provides unified entry and certificate reference.
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

DevOpsNginxSSL/TLSacme.shLet's Encryptcertificate automationDNS APIwildcard certificates
Code of Duty
Written by

Code of Duty

"Code of Duty" — Every line of code has its own mission. We avoid shortcuts and quick fixes, focusing on authentic coding reflections and the joys and challenges of technical growth. The journey of learning matters more than any destination. Join us as we humbly forge ahead in the world of code.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.