Install Nginx

Since we don't want to end up doing things manually, and also be able to use standard web ports, we need to set up a reverse proxy in front of Kerio Connect. This is an established practice for all kinds of web applications. It enables us to let the certificate process run without interaction — with the added benefit of being able to host other services and websites on the same server, should we want to.

First, we need to create a web root.

mkdir -p /var/www/mail
chown www-data:www-data /var/www/mail

Then we install nginx and the ssl-cert package, so we have easy access to a self-signed SSL certificate.

apt-get install nginx ssl-cert

Create a file called /etc/nginx/sites-available/kerio-connect.conf with the following content:

server {
    listen      80;
    server_name mail.example.com;
    server_name_in_redirect off;
    rewrite     ^ https://$server_name$request_uri? permanent;
}

server {
    listen      443 ssl;
    server_name mail.example.com;

    ssl_certificate     /etc/ssl/certs/ssl-cert-snakeoil.pem;
    ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;

    location /.well-known {
        alias /var/www/mail/.well-known;
    }

    location / {
        proxy_pass       https://localhost:8843;
        proxy_set_header Host                 $host;
        proxy_set_header X-Real-IP            $remote_addr;
        proxy_set_header X-Forwarded-For      $proxy_add_x_forwarded_for;
        proxy_set_header X-Remote-Port        $remote_port;
        proxy_set_header X-Forwarded-Proto    $scheme;
        proxy_redirect  off;
    }
}

Link the file to make it an active site.

ln -s /etc/nginx/sites-available/kerio-connect.conf /etc/nginx/sites-enabled/kerio-connect.conf

Check if the configuration is correct.

nginx -t

If there are no errors, restart Nginx.

systemctl restart nginx.service
Get Certbot
wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto

Run it once without any parameters to check for dependencies.

./certbot-auto
Create the Certificate

Here, we set a webroot for Certbot to put the test files in so it won't need to open up the ports 80 and 443, which would fail as they are now in use by Nginx.

./certbot-auto certonly --webroot -w /var/www/mail -d mail.example.com

If you're running this the first time, you'll need to enter your email address for emergency usage like revoking a certificate. This only needs to be done once.

Congratulations, you now have a valid SSL certificate on your server.

Actually Using the Certificate

Edit /etc/nginx/sites-available/kerio-connect.conf and change

ssl_certificate     /etc/ssl/certs/ssl-cert-snakeoil.pem;
ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;

to the location of our real certificate

ssl_certificate     /etc/letsencrypt/live/mail.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mail.example.com/privkey.pem;

Restart Nginx.

To make renewal easy for Kerio Connect, just link the created certificate and key to the appropriate folder inside the Kerio Connect hierarchy.

ln -s /etc/letsencrypt/live/mail.example.com/fullchain.pem /opt/kerio/mailserver/sslcert/mail.crt
ln -s /etc/letsencrypt/live/mail.example.com/privkey.pem /opt/kerio/mailserver/sslcert/mail.key

Now open the admin panel, select Configuration > SSL Certificates and see your certificate appear. Select it and set as active.

That's it.

Renewal

Just run:

./certbot-auto renew

Since we want to automate renewal, set up a cronjob to run periodically. If the certificate is close to expiring, it will be renewed automatically, otherwise it will be kept until the next run.

First copy Certbot to a convenient location. I recommend /usr/local/bin.

cp certbot-auto /usr/local/bin/

Services need to be restarted after a successful renewal to pick up the new certificate. Create a script /root/certbot-post-hook.sh with the following content:

#!/bin/sh
systemctl restart nginx.service
systemctl restart kerio-connect.service

Make it executable and secure it.

chmod 500 /root/certbot-post-hook.sh
chown root:root /root/certbot-post-hook.sh

Create a cronjob file at /etc/cron.d/certbot:

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

0 3 * * * root perl -e 'sleep int(rand(3600))' && certbot-auto -q renew --post-hook "/root/certbot-post-hook.sh"

This entry will run once a day at 3 am as root, sleep for a random number of minutes and run Certbot. The --post-hook parameter is run only when the certificate was in fact replaced, effectively restarting Nginx and Kerio Connect only when needed. The Certbot website recommends running the renewal command two times a day. However, in a production setting, restarting a mail server process as heavy as that Java behemoth Kerio Connect during work hours is often not feasible. Adjust the timing as needed. More than two times a day is overkill and won't make your certificate renewal more reliable.