Install Free SSL with acme.sh on VPS Instead of Certbot
acme.sh is an ACME client written in pure shell script that requires no additional dependencies. It supports Let's Encrypt, ZeroSSL, and Buypass, and includes support for wildcard SSL via DNS challenge integration with Cloudflare, Route53, and over 150 DNS providers. Its key advantages over Certbot are better portability and more flexible configuration options.
Install acme.sh
# Install as a regular user (no root required)
curl https://get.acme.sh | sh -s [email protected]
# Reload shell
source ~/.bashrc
# Verify installation
acme.sh --version
Issue SSL Certificate with HTTP Challenge
# Domain must be pointing to your VPS with webroot
acme.sh --issue -d yourdomain.com -d www.yourdomain.com \
--webroot /var/www/html
# Or use standalone mode (acme.sh binds port 80)
sudo acme.sh --issue -d yourdomain.com --standalone
Wildcard SSL with Cloudflare DNS
# Set Cloudflare API credentials
export CF_Key="your_global_api_key"
export CF_Email="[email protected]"
# Or use API Token (recommended)
export CF_Token="your_api_token"
export CF_Account_ID="your_account_id"
# Issue wildcard certificate
acme.sh --issue -d yourdomain.com -d "*.yourdomain.com" \
--dns dns_cf
# CF credentials are automatically saved for renewal
Install Certificate to Nginx
# Install cert to /etc/ssl/acme/
sudo mkdir -p /etc/ssl/acme/yourdomain.com
acme.sh --install-cert -d yourdomain.com \
--cert-file /etc/ssl/acme/yourdomain.com/cert.pem \
--key-file /etc/ssl/acme/yourdomain.com/key.pem \
--fullchain-file /etc/ssl/acme/yourdomain.com/fullchain.pem \
--reloadcmd "sudo systemctl reload nginx"
# Configure Nginx to use cert from acme.sh
sudo nano /etc/nginx/sites-available/yourdomain.com
ssl_certificate /etc/ssl/acme/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/ssl/acme/yourdomain.com/key.pem;
Verify Auto-Renewal
# acme.sh sets up cron automatically
crontab -l | grep acme
# Test renewal by forcing it
acme.sh --renew -d yourdomain.com --force
# List all certificates
acme.sh --list
~/.acme.sh/. You must back up this entire directory, as losing it requires re-issuing all certificates from scratch.
Verify SSL is Working Correctly
# List all certificates
acme.sh --list
# Check expiry date
openssl x509 -noout -dates -in /etc/ssl/acme/yourdomain.com/cert.pem
# Test HTTPS connection
curl -I https://yourdomain.com
# Check SSL grade
curl -s "https://api.ssllabs.com/api/v3/analyze?host=yourdomain.com&startNew=on" | python3 -m json.tool
--reloadcmd to ensure Nginx/Apache automatically reloads the new certificate after renewal without restarting the entire process.
Common Issues & Troubleshooting
Error: "Verify error: Invalid response from"
HTTP challenge failed because the domain is not pointing to your VPS or port 80 is closed:
curl -I http://yourdomain.com/.well-known/acme-challenge/test
# Should return 404 (better than connection refused)
sudo ufw allow 80
DNS Challenge Failed (TXT Record Not Found)
DNS propagation is slow. Add delay or use a faster DNS provider:
acme.sh --issue -d "*.yourdomain.com" --dns dns_cf \
--dnssleep 120 # Wait 120 seconds before verification
Certificate Not Renewing Automatically
Check cron job and permissions:
crontab -l | grep acme
# If not found, reinstall:
acme.sh --install-cronjob
Nginx Does Not Reload New Certificate After Renewal
Verify that the user running acme.sh has permission to run systemctl reload nginx:
# Add to sudoers:
echo "ubuntu ALL=(ALL) NOPASSWD: /bin/systemctl reload nginx" | sudo tee /etc/sudoers.d/acme-nginx
Frequently Asked Questions
How is acme.sh different from Certbot?
Certbot is the official EFF client and easier for beginners, while acme.sh is a shell script that offers better portability and supports over 150 DNS providers without requiring Python dependencies. It's ideal for servers with limited packages or when you need greater control.
Does acme.sh support ECC (ECDSA) certificates?
Yes, use --keylength ec-256 to issue ECDSA P-256 certificates, which are smaller and faster than RSA 2048, making them suitable for modern servers and clients.
How many domains can be included in one certificate?
Let's Encrypt allows 100 subdomains per certificate with a rate limit of 50 certificates per domain per week. acme.sh supports multiple domains in a single certificate via SAN (Subject Alternative Names) using the -d domain1 -d domain2 flag.