Shurn the Awesomer
Installing Zimbra with Docker

Installing Zimbra with Docker

Written on Tue, 11 October 2016

Installing Zimbra on your own can be quite a daunting task for even experienced administrators. Fortunately, with docker, the process is very much simplified. On top of that, you will also get to have letsencrypt certificates running on your mail server.

The following tutorial is based on Zimbra Community Docker, zextras' docker page, Certbot Installation and Zimbra's letsencrypt installation.

Step 1: Getting Docker


It goes without saying that you must get docker. Check out my tutorial for more information.

Step 2: Getting the docker image


We will be using the image from xextras and also its 8.7.0 version.

docker pull zextras/zimbra8:8.7.0

Step 3: Launch the image


There will be some configuration you need to do.

According to zextras instructions:

  • EXTERNALDNS: Provide your upstream DNS server for resolutions other than the container itself. You can modify configuration later by adding config lines to dnsmasq configuration (/etc/dnsmaq.conf). Default value is 8.8.8.8.
  • MAILBOXD_DEBUG: If set to "yes", copies the zmmailboxdmgr.unrestricted executable over zmmailboxdmgr and applies some magic options (Default value is "no").
  • PASSWORD: no need to go deeper, huh? :-P
  • TIMEZONE: The timezone of the container and the principal domain of Zimbra. It must be specified according to Zimbra timezones. Default Value: "Etc/UTC"

Host name is required. Make sure the DNS mx entry by your DNS provider is pointing to the IP of the machine your are installing. Your hostname should be something like mail.domain.tld. Be sure to replace this with your own hostname.

There will also be many ports to forward. Here's how the command will look like:

docker run -d -p 25:25 -p 80:80 -p 465:465 -p 587:587 -p 110:110 -p 143:143 -p 993:993 -p 995:995 -p 443:443 -p 8080:8080 -p 8443:8443 -p 7071:7071 -p 9071:9071 -h mail.domain.tld -v ${your-authorized_keys}:/root/.ssh/authorized_keys -e TIMEZONE="Asia/Singapore" -e PASSWORD="SUPERSECRETPASSWORD" -e MAILBOXD_DEBUG="no" zextras/zimbra8:8.7.0


This command will take about 5 minutes to complete, depending on your hardward capabilities. Have a cup of drink while you wait.

Browse to your domain, https://mail.domain.tld, on your browser to see if it's working. If you see that your site is insecure, it's due to self-signed certificates. Proceed to next step once you see this.

Step 4: Get Letsencrypt Certificate
We are going to install letsencrypt into the container itself. Let's list out the containers so that we can attach to the container.

docker ps


You will see a big bunch of details due to the number of ports we port forwarded. We need to look out for the container id, which will look like 250a24730351. Let's get attached to this container:

docker exec -it 250a24730351 /bin/bash


Now login to zimbra user

su zimbra


Disable these 2 services.

zmproxyctl stop
zmmailboxdctl stop


Exit back to root user

exit


We need to get the certbot that will issue us certificates.

cd /root
wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto


We must run the certbot script so that it installs all its dependencies to make issuing cert works.

./certbot-auto


Select yes if it prompts you to install additional packages
Let's get the certbot to issue us a cert.

./certbot-auto certonly


When it prompts you how you would like to authenticate, select "Spin up a temporary server (standalone)". Then enter your email so that letsencrypt can contact you for lost key recovery and other urgent notices. Agree to the terms and conditions. Enter the hostname of your server, like mail.domain.tld. Your certificate will be stored in /etc/letsencrypt/live/mail.domain.tld/fullchain.pem.

I highly recommend backing up your certs, up to this point.

Step 5: Installing the cert in Zimbra


Now, we need a proper Intermediate CA plus Root CA in chain.pem file. Open up chain.pem file.

nano /etc/letsencrypt/live/mail.domain.tld/chain.pem


Append the following text to the file. Do not remove previous text. Just add the follow right after the original text ends.

-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
-----END CERTIFICATE-----


Create a folder that Zimbra will read the certs from.

mkdir /opt/zimbra/ssl/letsencrypt


Then we link everything that's in /etc/letsencrypt/live/mail.domain.tld/ to the new folder and set permissions for zimbra to read.

ln -s /etc/letsencrypt/live/mail.domain.tld/cert.pem /opt/zimbra/ssl/letsencrypt/cert.pem
ln -s /etc/letsencrypt/live/mail.domain.tld/chain.pem /opt/zimbra/ssl/letsencrypt/chain.pem
ln -s /etc/letsencrypt/live/mail.domain.tld/fullchain.pem /opt/zimbra/ssl/letsencrypt/fullchain.pem
ln -s /etc/letsencrypt/live/mail.domain.tld/privkey.pem /opt/zimbra/ssl/letsencrypt/privkey.pem
chmod 777 -R /etc/letsencrypt/live
chmod 777 -R /etc/letsencrypt/archive


Let's log in as zimbra and verify the certs

su zimbra
cd /opt/zimbra/ssl/letsencrypt
/opt/zimbra/bin/zmcertmgr verifycrt comm privkey.pem cert.pem chain.pem


Once you see that the certs are valid, we need to link the privkey to the commercial path.

exit
ln -s /opt/zimbra/ssl/letsencrypt/privkey.pem /opt/zimbra/ssl/zimbra/commercial/commercial.key


Now, it's time to deploy!

su zimbra
/opt/zimbra/bin/zmcertmgr deploycrt comm cert.pem chain.pem


We restart zimbra and go to the browser with https in your url to see your achievement!

zmcontrol restart

Congratulations! You have working mail server with a certificate from letsencrypt.

Renewing Cert


So the time has come to renew the certificate. As you need to go through specific steps to renew the cert, we cannot use the automated renewal provided. Here's how to renew certificate, if you have followed the tutorial accordingly.

Login to zimbra user

su zimbra


Disable these 2 services.

zmproxyctl stop
zmmailboxdctl stop

Renew the certificate

cd /root
./certbot-auto renew

We must append the CA to the certificate again as the renewal process removed it.

nano /etc/letsencrypt/live/mail.domain.tld/chain.pem


Append the following text to the file. Do not remove previous text. Just add the follow right after the original text ends.

-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
-----END CERTIFICATE-----

Verify that the certificate works:

cd /opt/zimbra/ssl/letsencrypt
/opt/zimbra/bin/zmcertmgr verifycrt comm privkey.pem cert.pem chain.pem

Then deploy and restart zimbra services.

/opt/zimbra/bin/zmcertmgr deploycrt comm cert.pem chain.pem
zmcontrol restart

That's it! Now you have another 3 months of certificate.

Multiple SSL Certificates per domain each


It is quite common to have multiple domains in a zimbra server. After all, it's cost-efficient and network-efficient to consolidate domains into 1 server. I assume you have already generated your other certificates from the instructions before, and you have already restarted zimbra, but you did not install the certificate.

  • Domain: myawesomedomain.com
  • Mail Server Domain: mail.myawesomedomain.com

Add the virtual host name.

su zimbra
zmprov md myawesomedomain.com zimbraVirtualHostName mail.myawesomedomain.com zimbraVirtualIPAddress 1.2.3.4
exit


Make sure you use your IP address. If you are behind firewall or NAT, make sure you use your public address instead of local address.

We must append the CA to the certificate.

nano /etc/letsencrypt/live/mail.myawesomedomain.com/chain.pem


Append the following text to the file. Do not remove previous text. Just add the follow right after the original text ends.

-----BEGIN CERTIFICATE-----
MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
-----END CERTIFICATE-----

Let's verify that the certificate works:

su zimbra
/opt/zimbra/bin/zmcertmgr verifycrt comm privkey.pem cert.pem chain.pem

We need to merge the certificate and the chain into a single file.

cat cert.pem chain.pem >> myawesomedomain.com.bundle

Now we save the certificate to LDAP.

/opt/zimbra/libexec/zmdomaincertmgr savecrt myawesomedomain.com myawesomedomain.com.bundle privkey.pem


The syntax for this command is:

/opt/zimbra/libexec/zmdomaincertmgr savecrt

Now we deploy the certificates.

/opt/zimbra/libexec/zmdomaincertmgr deploycrts

Let's ensure SNI is enabled in all proxies.

zmprov mcf zimbraReverseProxySNIEnabled TRUE


If you are using other proxies, make sure all of it has SNI enabled.

Restart Proxy.

zmproxyctl restart

That's it! You can now browse to the domain and see your work. Repeat these steps as many times as you have domains.