SSL certificates

Issue SSL certificates with acme.sh (a lightweight Certbot alternative)

Install acme.sh, issue certificates with webroot, standalone or DNS API validation, choose a CA, install certificates into Nginx, Apache or HAProxy with reload commands, and renew automatically.

IntermediateLinux VPS2 min read

acme.sh is a pure shell ACME client: no Python, no system packages, runs as a normal user, and supports DNS APIs for well over a hundred providers. It is a popular alternative to Certbot, especially for wildcard certificates and minimal servers. This guide shows how to use acme.sh.

Before you start

  • A Linux server with curl or wget, cron and socat (for standalone mode).
  • DNS pointing to the server, or an API token for your DNS provider for DNS validation.

Install acme.sh

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

It installs into ~/.acme.sh/ and adds a daily cron job for renewals. Reload your shell (source ~/.bashrc) to use the acme.sh command. Read the installer script first if you prefer, or clone the official repository.

Choose a certificate authority

acme.sh's default CA has changed over time. To use Let's Encrypt explicitly:

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

Issue a certificate

  • Webroot (a web server is already serving the domain):
    acme.sh --issue -d example.com -d www.example.com -w /var/www/example.com/public
  • Standalone (nothing on port 80):
    acme.sh --issue --standalone -d mail.example.com
  • DNS API (wildcards, servers without port 80) – example with Cloudflare:
    export CF_Token="your-api-token"
    acme.sh --issue --dns dns_cf -d example.com -d '*.example.com'

    acme.sh saves the credentials for renewals. Use a token limited to DNS edits on that zone.

ECDSA keys are the default in current versions; add --keylength 2048 for RSA.

Install the certificate into your web server

Never point servers at files inside ~/.acme.sh/ directly – copy them with --install-cert, which also sets the reload command used after each renewal:

acme.sh --install-cert -d example.com \
  --key-file       /etc/nginx/ssl/example.com.key \
  --fullchain-file /etc/nginx/ssl/example.com.crt \
  --reloadcmd      "systemctl reload nginx"

For HAProxy, which wants key and chain in one file, use a reload command that concatenates them first.

Renewal

  • List certificates: acme.sh --list
  • Force a renewal test: acme.sh --renew -d example.com --force
  • Check the cron entry: crontab -l | grep acme

Upgrade and remove

  • Keep acme.sh updated: acme.sh --upgrade --auto-upgrade
  • Stop renewing a certificate: acme.sh --remove -d example.com (files stay; delete them yourself).

Troubleshooting

  • Verify error / 404: wrong webroot path or a redirect blocks /.well-known/acme-challenge/.
  • DNS validation fails: wrong API token permissions or slow DNS propagation – add --dnssleep 120.
  • Permission denied writing to /etc: running as a normal user – use paths that user can write, or run as root.
  • Debug output: add --debug 2 to any command.

FAQ: acme.sh

acme.sh or Certbot?

Both are solid. acme.sh is lighter and has more DNS API integrations; Certbot integrates with Nginx/Apache configuration automatically.

Can acme.sh and Certbot run on the same server?

Yes, but manage each certificate with only one client to avoid confusion.

Does acme.sh need root?

No, but it needs permission to write certificate files and reload services, which often means root or sudo.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.