Revision as of 12:52, 28 October 2023 by JDunphy (talk | contribs) (→‎Step 1: Installation of acme.sh)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Making Letsencrypt Certs with acme.sh

   KB 24593        Last updated on 2023-10-28  

(0 votes)


Letsencrypt is a free, automated, and open Certificate Authority to generate all your PKI certificates. Instead of installing a development environment like other Letsencrypt methods, this article describes a single bash script called acme.sh which uses the acme protocol to issue and verify certificates. It can be installed and operated without being root. Here is how to get Zimbra up and running with Letsencrypt certificates.

Summary of Steps

  • Install and configure acme.sh
  • Issue certficate
  • Deploy certficate
  • Verify automatic renewals work

Step 1: Installation of acme.sh

Zimbra uses a program called zmcertmgr that can verify a certificate and install them. It needs to run as the zimbra user and letsencrypt certificates will be renewed every 60 days automatically. They expire in 90 days if not renewed. The first problem is that /opt/zimbra is owned by root and we want to install this as the zimbra user. We install acme.sh like this:

% su -
# mkdir /opt/zimbra/.acme.sh
# chown zimbra:zimbra /opt/zimbra/.acme.sh
# su - zimbra
% wget -O -  https://get.acme.sh | sh
% ls /opt/zimbra/.acme.sh
account.conf  acme.sh  acme.sh.env  deploy  dnsapi  http.header  notify

At this point we will have /opt/zimbra/.acme.sh populated and need to make a few changes to the defaults to work with zimbra.

% cd .acme.sh
% ./acme.sh --set-default-ca  --server letsencrypt
% ./acme.sh  --set-default-chain  --preferred-chain  ISRG  --server letsencrypt

Next we need to choose a dns provider as acme.sh will create and delete DNS text records as part of the verification process for your certificate.

% ls dnsapi
README.md           dns_dgon.sh           dns_hexonet.sh      dns_mythic_beasts.sh  dns_rcode0.sh
dns_1984hosting.sh  dns_dnsexit.sh        dns_hostingde.sh    dns_namecheap.sh      dns_regru.sh
dns_acmedns.sh      dns_dnshome.sh        dns_huaweicloud.sh  dns_namecom.sh        dns_scaleway.sh
dns_acmeproxy.sh    dns_dnsimple.sh       dns_infoblox.sh     dns_namesilo.sh       dns_schlundtech.sh
dns_active24.sh     dns_dnsservices.sh    dns_infomaniak.sh   dns_nanelo.sh         dns_selectel.sh
dns_ad.sh           dns_do.sh             dns_internetbs.sh   dns_nederhost.sh      dns_selfhost.sh
dns_ali.sh          dns_doapi.sh          dns_inwx.sh         dns_neodigit.sh       dns_servercow.sh
dns_anx.sh          dns_domeneshop.sh     dns_ionos.sh        dns_netcup.sh         dns_simply.sh
dns_artfiles.sh     dns_dp.sh             dns_ipv64.sh        dns_netlify.sh        dns_tele3.sh
dns_arvan.sh        dns_dpi.sh            dns_ispconfig.sh    dns_nic.sh            dns_tencent.sh
dns_aurora.sh       dns_dreamhost.sh      dns_jd.sh           dns_njalla.sh         dns_transip.sh
dns_autodns.sh      dns_duckdns.sh        dns_joker.sh        dns_nm.sh             dns_udr.sh
dns_aws.sh          dns_durabledns.sh     dns_kappernet.sh    dns_nsd.sh            dns_ultra.sh
dns_azion.sh        dns_dyn.sh            dns_kas.sh          dns_nsone.sh          dns_unoeuro.sh
dns_azure.sh        dns_dynu.sh           dns_kinghost.sh     dns_nsupdate.sh       dns_variomedia.sh
dns_bookmyname.sh   dns_dynv6.sh          dns_knot.sh         dns_nw.sh             dns_veesp.sh
dns_bunny.sh        dns_easydns.sh        dns_la.sh           dns_oci.sh            dns_vercel.sh
dns_cf.sh           dns_edgedns.sh        dns_leaseweb.sh     dns_one.sh            dns_vscale.sh
dns_clouddns.sh     dns_euserv.sh         dns_lexicon.sh      dns_online.sh         dns_vultr.sh
dns_cloudns.sh      dns_exoscale.sh       dns_linode.sh       dns_openprovider.sh   dns_websupport.sh
dns_cn.sh           dns_fornex.sh         dns_linode_v4.sh    dns_openstack.sh      dns_world4you.sh
dns_conoha.sh       dns_freedns.sh        dns_loopia.sh       dns_opnsense.sh       dns_yandex.sh
dns_constellix.sh   dns_gandi_livedns.sh  dns_lua.sh          dns_ovh.sh            dns_yc.sh
dns_cpanel.sh       dns_gcloud.sh         dns_maradns.sh      dns_pdns.sh           dns_zilore.sh
dns_curanet.sh      dns_gcore.sh          dns_me.sh           dns_pleskxml.sh       dns_zone.sh
dns_cyon.sh         dns_gd.sh             dns_miab.sh         dns_pointhq.sh        dns_zonomi.sh
dns_da.sh           dns_geoscaling.sh     dns_misaka.sh       dns_porkbun.sh
dns_ddnss.sh        dns_googledomains.sh  dns_myapi.sh        dns_rackcorp.sh
dns_desec.sh        dns_he.sh             dns_mydevil.sh      dns_rackspace.sh
dns_df.sh           dns_hetzner.sh        dns_mydnsjp.sh      dns_rage4.sh

These are text files and inside they list what shell variables will be needed to use them.

% vi account.conf

For example, dns_gd.sh is goddady and it requires that following be added to account.conf


Those values can be found from the godaddy account. Similarily clouldflare dns_cf.sh will work with




Once account.conf has these values for your dns hosting provider, you will be able to issue certificates. The last step is to do the following:

% wget 'https://raw.githubusercontent.com/JimDunphy/acme.sh/master/deploy/zimbra.sh' -O /opt/zimbra/.acme.sh/deploy/zimbra.sh

This script will be called at deploy time and will do zimbra specific calls. It will handle anything required by zimbra to have a working certificate. It will validate the certificate and install it. Finally if everything worked, it will restart zimbra so the new certificate can be used.

Step 2 - Issue Certificate

acme.sh version v3.0.6 and above has switched the default certificate type to ec-256 from rsa certificates. The problem is that zmcertmgr still requires rsa certificates which is specified with the option --keylength 2048.

% acme.sh --issue --keylength 2048 --dns dns_cf -d mail.example.com

If everything worked, you will have a valid certificate that looks like this.

[Fri Oct 20 14:44:02 PDT 2023] Your cert is in: /opt/zimbra/.acme.sh/mail.example.com/mail.example.com.cer
[Fri Oct 20 14:44:02 PDT 2023] Your cert key is in: /opt/zimbra/.acme.sh/mail.example.com/mail.example.com.key
[Fri Oct 20 14:44:02 PDT 2023] The intermediate CA cert is in: /opt/zimbra/.acme.sh/mail.example.com/ca.cer
[Fri Oct 20 14:44:02 PDT 2023] And the full chain certs is there: /opt/zimbra/.acme.sh/mail.example.com/fullchain.cer

Step 3 - Deploy Certificate

We have a valid certificate but nothing has been done to zimbra yet. It has not been installed nor has the certificate been validated. The next step accomplishes this.

$ ./acme.sh --deploy --deploy-hook zimbra --d mail.example.com 

This step will validate the certificate. If that checks out, it will copy the certificate to various locations under the /opt/zimbra tree for postfix/ldap/nginx/mailboxd. It will then restart zimbra so that the new certificate is active.

Step 4 - Automatic Renewal

Letsencrypt certificates expire every 90 days. When you installed acme.sh, it created the following cron job for zimbra:

1 10 * * * "/opt/zimbra/.acme.sh"/acme.sh --cron --home "/opt/zimbra/.acme.sh" > /dev/null

Every night it will check to see if it can be renewed. In 60 days, it can be renewed. What this will do is the following:

  • 1) acme.sh --issue --keylength 2048 --dns dns_cf -d mail.example.com
  • 2) acme.sh --deploy --deploy-hook zimbra --d mail.example.com

If you wish to test it out and renew sooner. Do this:

% "/opt/zimbra/.acme.sh"/acme.sh --cron --force --home "/opt/zimbra/.acme.sh"

If everything goes right, you will have a new certificate and zimbra will have been restarted. If there was a problem in the validation, it will stop and nothing in zimbra will have been changed.


Everything is self contained in /opt/zimbra/.acme.sh and you can copy or backup this folder or move it from machine to machine. Even better, if you created a certificate like this:

% ./acme.sh --issue --keylength 2048 --dns dns_cf -d mail.example.com

The folder /opt/zimbra/.acme.sh/mail.example.com contains everything required for the deploy. You could copy the deploy directory to various machines and then install them like this:

% ./acme.sh --deploy --deploy-hook zimbra -d mail.example.com

More articles written by me, https://wiki.zimbra.com/wiki/JDunphy-Notes

Jump to: navigation, search