“After climbing a great hill, one only finds that there are many more hills to climb.”
acme.sh script to apply for a free Wildcard certificate and configure automatic renewal. We highly recommend using a Cloudflare API Token for DNS verification, as it is currently the most secure and convenient solution.
What is acme.sh?
acme.sh is an ACME protocol client written purely in Shell. Compared to the official Certbot, it has the following significant advantages:
- Lightweight: No dependencies, no need to install Python.
- Compatibility: Supports almost all Linux distributions.
- Feature-rich: Automatically handles cron tasks, supports auto-injection of certificates into Nginx/Apache, and supports Docker deployment.
- DNS Support: Built-in API support for 100+ DNS providers.
Step 1: Install acme.sh
The installation process is very simple, requiring only one command. It is recommended to switch to the root user to execute.
# Replace with your real email, used for receiving certificate expiration reminderscurl https://get.acme.sh | sh -s email=my@example.comAfter installation is complete, the script will automatically perform the following operations:
- Install acme.sh to the
~/.acme.sh/directory. - Create an
alias acme.sh=~/.acme.sh/acme.shalias. - Automatically create a daily Cron Job to check if certificates need updating.
Make the Command Effective
After installation, you need to refresh your Shell environment:
source ~/.bashrcStep 2: Switch Default CA (Recommended)
acme.sh uses ZeroSSL as the default Certificate Authority. If you are more accustomed to using Let’s Encrypt, you can switch at any time:
acme.sh --set-default-ca --server letsencryptStep 3: Apply for Certificate (DNS Method Recommended)
acme.sh supports both HTTP verification and DNS verification. DNS verification is strongly recommended because:
- It supports Wildcard certificates (like
*.example.com). - It does not rely on a Web server and does not require a public IP (can be used on intranet servers).
- If you don’t use API auto-verification, manually resolving TXT records every 3 months is extremely cumbersome.
Preparation: Get DNS API Credentials
We will use Cloudflare as an example. For security reasons, we no longer use the Global API Key, but rather a restricted API Token.
- Log in to the Cloudflare dashboard -> My Profile -> API Tokens.
- Click Create Token.
- Select the Edit zone DNS template.
- Zone Resources: Select
Include -> All zonesor specify your domain. - Generate and copy your
Token. - Simultaneously, find your
Account IDon the right side of the dashboard homepage.
Execute Application
Import the credentials we just obtained into the terminal:
export CF_Token="Your_API_Token"export CF_Account_ID="Your_Account_ID"
# Apply for a wildcard certificate (including main domain and all subdomains)# --keylength ec-256 means applying for a more modern, faster ECC certificateacme.sh --issue --dns dns_cf -d example.com -d *.example.com --keylength ec-256Note: After the script finishes executing, your ID and Token will be automatically encrypted and saved in
~/.acme.sh/account.conf, so you won’t need to enter them again during auto-renewal.
Step 4: Install Certificate to Web Server
Do not ever directly point your Nginx/Apache configuration files to the files within the ~/.acme.sh/ directory. The structure of that directory could change at any time.
You should use the --install-cert command to copy the certificates to a specified location, and instruct the script to reload the Web service.
Nginx Example
Assume your Nginx SSL directory is at /etc/nginx/ssl:
mkdir -p /etc/nginx/ssl
acme.sh --install-cert -d example.com --ecc \--key-file /etc/nginx/ssl/server.key \--fullchain-file /etc/nginx/ssl/fullchain.cer \--reloadcmd "systemctl force-reload nginx"Nginx Configuration Reference
In your Nginx configuration file (e.g., /etc/nginx/conf.d/example.com.conf), ensure the paths are consistent with the above:
server { listen 443 ssl http2; server_name example.com;
# Certificate path configuration ssl_certificate /etc/nginx/ssl/fullchain.cer; ssl_certificate_key /etc/nginx/ssl/server.key;
# Recommended SSL security parameters ssl_protocols TLSv1.2 TLSv1.3; ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
# ... Other configurations}Advanced: How to Update Certificates?
Automatic Update (No Operation Required)
acme.sh will automatically check certificates every 60 days. If it finds a certificate is about to expire, it will automatically:
- Call the API to re-verify DNS.
- Reissue the certificate.
- Copy the new certificate to
/etc/nginx/ssl/. - Execute
systemctl force-reload nginxto reload the service.
You don’t need to worry about it at all.
Updating the Script Itself
It is recommended to turn on the auto-upgrade feature of the acme.sh script to remain compatible with the latest ACME protocols:
acme.sh --upgrade --auto-upgradeCommon Troubleshooting
-
Unknown error (DNS verification failed)
- Check if the API Token permissions are correct (must include Edit permission for Zone.DNS).
- Check if the DNS server is effective. Sometimes propagation is delayed; you can add
--dnssleep 60parameter to let the script wait a little longer.
-
Web verification failed
- Ensure port 80 is open and not blocked by a firewall.
- If you are just temporarily verifying and don’t have Nginx, you can use the
--standalonemode (requires temporarily stopping services occupying port 80).
Disclaimer
The tutorial provided in this project is for educational and testing purposes only.
- Before using the script to modify production environment configurations, it is recommended to backup related configuration files first.
- Please keep sensitive information such as Tokens and Keys safe and do not leak them.
- The author bears no responsibility for service interruptions or data loss caused by improper use.
If this article helped you, please share it with others!
Some information may be outdated





