1. Blog
  2. Manuals

Free ZeroSSL Certificate with acme.sh

Free ZeroSSL Certificate with acme.sh

ZeroSSL is a certificate authority that, like Let’s Encrypt, issues free 90-day SSL certificates over the ACME protocol. It is useful as an alternative or fallback when Let’s Encrypt is unavailable or you have hit its rate limits.

Two ways to get a certificate

  • Through the zerossl.com website. Fine for a one-off, but the free plan allows only three certificates and they must be renewed by hand.
  • Through an ACME client. No limit on the number of certificates, and renewal is automatic. This is the right option for a server.

The rest of this guide uses the acme.sh client: a single Bash script with no dependencies, with ZeroSSL as its default certificate authority.

Step 1. Install acme.sh

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

Use a working address: the ZeroSSL account is registered to it. The installer creates the ~/.acme.sh directory and a cron job that checks for renewals daily. Reload your shell settings:

source ~/.bashrc

Step 2. Issue the certificate

The domain must point to the server’s IP address, and port 80 must be reachable from the internet. Choose a domain validation method.

The site already runs on Nginx:

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

The site runs on Apache:

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

Any web server, through the site directory:

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

No web server (acme.sh temporarily takes port 80 itself; requires the socat package):

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

Step 3. Install the certificate

Do not use the files in ~/.acme.sh directly: their location may change. Copy the certificate to a permanent place with the dedicated command — it also remembers how to reload the web server after renewal:

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

Step 4. Use it in Nginx

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name example.com www.example.com;

    ssl_certificate /etc/ssl/certs/example.com.crt;
    ssl_certificate_key /etc/ssl/private/example.com.key;

    root /var/www/example.com;
}

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}
sudo nginx -t && sudo systemctl reload nginx

On Nginx versions before 1.25.1, use listen 443 ssl http2; instead of the http2 on; line.

Wildcard certificate

A certificate for all subdomains (*.example.com) can only be issued with DNS validation. acme.sh can create the required record itself through the API of most DNS providers. An example for Cloudflare:

export CF_Token="api_token"
acme.sh --issue -d example.com -d '*.example.com' --dns dns_cf

The list of supported providers and variable names is in the acme.sh documentation.

Renewal and management

Renewal runs automatically from cron. Useful commands:

acme.sh --list                          # all certificates and renewal dates
acme.sh --renew -d example.com --force  # force a renewal
acme.sh --remove -d example.com         # stop renewing
acme.sh --upgrade                       # update the client itself

Switching to Let’s Encrypt

The certificate authority can be changed with one command — the client and all settings stay the same:

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

To switch back, use --server zerossl. For a single certificate, set the authority with --server in the --issue command.

ZeroSSL or Let’s Encrypt

Site visitors see no difference: both certificates are trusted by all browsers. ZeroSSL is handy as a backup authority and has no strict weekly per-domain limits. Let’s Encrypt is more familiar and better supported by ready-made tools such as Certbot — it is used in the Nginx virtual host guide.