acme.sh Commands

Pure shell script ACME protocol client for automated certificate management from Let's Encrypt and other ACME CAs.

Installation & Setup

Install acme.sh

Quick installation to ~/.acme.sh:

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

Manual installation

Clone and install from GitHub:

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

Upgrade acme.sh

Update to latest version:

acme.sh --upgrade

Enable auto-upgrade

Automatic updates via cron:

acme.sh --upgrade --auto-upgrade

HTTP-01 Challenge (Webroot)

Issue with webroot

Use existing web server's document root:

acme.sh --issue -d example.com \
  -w /var/www/html

Multiple domains

Issue certificate for multiple domains (SAN):

acme.sh --issue -d example.com -d www.example.com \
  -w /var/www/html

Standalone mode

Built-in web server on port 80 (requires stopping web server):

acme.sh --issue -d example.com --standalone

Standalone TLS-ALPN

Use port 443 with TLS-ALPN challenge:

acme.sh --issue -d example.com --alpn

DNS-01 Challenge (Wildcard Certificates)

Manual DNS mode

Add TXT record manually (acme.sh shows what to add):

acme.sh --issue -d example.com -d '*.example.com' \
  --dns --yes-I-know-dns-manual-mode-enough-go-ahead-please

CloudFlare DNS API

Automatic DNS validation with CloudFlare:

export CF_Token="your-cloudflare-api-token"
export CF_Account_ID="your-account-id"

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

Route53 DNS API

AWS Route53 automatic validation:

export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"

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

Google Cloud DNS

Google Cloud DNS API:

export CLOUDSDK_ACTIVE_CONFIG_NAME="your-config"

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

Other DNS providers

acme.sh supports 100+ DNS providers:

# See full list:
acme.sh --help dns

# Popular providers:
# dns_azure, dns_gandi, dns_namecheap, dns_digitalocean,
# dns_linode, dns_he, dns_dynu, dns_duckdns, etc.

Certificate Installation

Install to nginx

Install certificate and reload nginx:

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"

Install to Apache

Install certificate and reload Apache:

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

Install with custom path

Install to custom location:

acme.sh --install-cert -d example.com \
  --key-file /path/to/key.pem \
  --fullchain-file /path/to/cert.pem \
  --reloadcmd "your-reload-command"

Certificate Renewal

Auto-renewal via cron

Automatic renewal is set up during installation:

# Cron job automatically created:
# Checks daily, renews if <30 days remaining

# View cron entry:
crontab -l | grep acme.sh

Manual renewal

Force renewal before expiration:

acme.sh --renew -d example.com --force

Renew all certificates

Renew all managed certificates:

acme.sh --renew-all

Check renewal status

List all certificates and expiration:

acme.sh --list

Certificate Management

Show certificate info

Display certificate details:

acme.sh --info -d example.com

Remove certificate

Delete certificate from acme.sh:

acme.sh --remove -d example.com

Revoke certificate

Revoke certificate with CA:

acme.sh --revoke -d example.com

Deactivate account

Deactivate ACME account:

acme.sh --deactivate-account

Advanced Configuration

Use staging server

Test with Let's Encrypt staging for debugging:

acme.sh --issue -d example.com \
  -w /var/www/html \
  --staging

Use different CA

Switch to ZeroSSL, Buypass, or other ACME CA:

# ZeroSSL (default since v3.0)
acme.sh --set-default-ca --server zerossl

# Let's Encrypt
acme.sh --set-default-ca --server letsencrypt

# Buypass
acme.sh --set-default-ca --server buypass

# Google Trust Services
acme.sh --set-default-ca --server google

Custom key length

Specify RSA or ECC key size:

# RSA 4096
acme.sh --issue -d example.com -w /var/www/html --keylength 4096

# ECC 384
acme.sh --issue -d example.com -w /var/www/html --keylength ec-384

Pre and post hooks

Run commands before/after issuance:

acme.sh --issue -d example.com --standalone \
  --pre-hook "systemctl stop nginx" \
  --post-hook "systemctl start nginx"

Notification hooks

Get notifications via email, Slack, Discord, etc.:

# Email notification
export NOTIFY_EMAIL="[email protected]"
acme.sh --set-notify --notify-hook mail

# Slack notification
export SLACK_WEBHOOK_URL="https://hooks.slack.com/..."
acme.sh --set-notify --notify-hook slack

Web Server Integration

Nginx mode

Automatic nginx configuration detection:

acme.sh --issue -d example.com --nginx

Apache mode

Automatic Apache configuration detection:

acme.sh --issue -d example.com --apache

Deploy to multiple servers

Deploy certificate via SSH:

acme.sh --deploy -d example.com --deploy-hook ssh \
  --ssh-user root \
  --ssh-server 192.168.1.100 \
  --ssh-key-file /path/to/ssh/key \
  --ssh-cert-file /etc/nginx/ssl/cert.pem \
  --ssh-key-file /etc/nginx/ssl/key.pem \
  --ssh-backup /etc/nginx/ssl/backup

Troubleshooting

Enable debug mode

Verbose logging for troubleshooting:

acme.sh --issue -d example.com -w /var/www/html --debug 2

Check log files

View acme.sh logs:

tail -f ~/.acme.sh/acme.sh.log

Test HTTP challenge

Verify challenge file is accessible:

# acme.sh creates files in:
# /var/www/html/.well-known/acme-challenge/

# Test accessibility:
curl http://example.com/.well-known/acme-challenge/test-file

Clear challenge cache

Force fresh challenge:

acme.sh --issue -d example.com -w /var/www/html --force

Important Notes

Pure Shell Script:

acme.sh is written entirely in shell script (bash/sh) - no Python, no dependencies beyond common Unix tools.

Default CA Changed:

Since v3.0, acme.sh defaults to ZeroSSL instead of Let's Encrypt. Use --server letsencrypt to switch back.

Auto-Renewal:

Cron job installed automatically. Checks daily, renews when <30 days remaining. Customize with --days parameter.

Rate Limits:

Let's Encrypt has rate limits (50 certificates/week per domain). Use --staging for testing to avoid hitting limits.

DNS API Support:

100+ DNS providers supported for automated DNS-01 challenges. See wiki for provider-specific setup.

ECC Certificates:

acme.sh supports both RSA and ECC (ECDSA) certificates. ECC is more efficient and recommended for modern deployments.

Security:

Account keys and certificates stored in ~/.acme.sh/ - protect this directory with proper file permissions.

Documentation:

Official wiki: github.com/acmesh-official/acme.sh/wiki - comprehensive guides for all DNS providers and deployment scenarios.

See Also