Select Page
This entry has been published on 2017-05-13 and may be out of date.

Last Updated on 2017-05-13.



You have some webservers or mailservers in your LAN which you want to work with the Let’s Encrypt SSL service. It provides the creation of free SSL certificates which are known by most browsers.

The only drawback is, they are valid for only 90 days. So if you do not want to renew manually every 3 months, you can automate most parts of the process.

In this tutorial, we will create a certificate server which provides always up-to-date certificates, so they can be fetched by other servers in your LAN.


Certbot, the LetsEncrypt utility for getting certificates e.g. under Ubuntu, basically needs an open outgoing Port 80 TCP, and also an incoming Port 80 TCP. I didn’t want to open outgoing internet for all of the servers, so I decided to create a separate LetsEncrypt certificate server which runs certbot regularly.

Create a new Ubuntu Server virtual machine: Default setup, install Samba/CIFS, Apache2 and certbot.


  • Apache’s ports.conf and 000-default.conf to only listen on port 81, docroot: /share
    • (Do not use port 80 because certbot needs it later)
  • Samba’s smb.conf: Add a public read-only share “certs” for /share

You might already have another Apache webserver running which listens on your router’s public port 80, so we have to redirect certain request from there to the new cert server.

Modify every virtual host config of Apache which needs SSL certificates like in this example:

<VirtualHost *:80>
    DocumentRoot "/var/www"
    ServerName www
    ServerAlias *
    ErrorLog "/var/log/apache2/error.log"
    CustomLog "/var/log/apache2/access.log" common

    ProxyPass /.well-known/acme-challenge/ http://certs/.well-known/acme-challenge/
    ProxyPassReverse /.well-known/acme-challenge/ http://certs/.well-known/acme-challenge/

Note: In this example, certbot always uses port 80! Make sure to consider all of your subdomains, e.g. also for your mailserver etc.

The following script can be run as a cronjob (crontab -e), it gets and renews the certificates from LetsEncrypt and creates password protected zip files for easy local distribution:

#!/bin/bash, 2017-05
#creates pw protected zip archives containing certificate files

[email protected]

declare -a DOMAINS=(
                " -d"

#halt on any error
set -e

#clean share
rm -rf $SHARE/*

for DOMAIN in "${DOMAINS[@]}"
        MAINDOMAIN=`echo $DOMAIN | head -n1 | cut -d " " -f1`
        #echo $MAINDOMAIN
        certbot certonly --standalone -d $DOMAIN --preferred-challenges http --agree-tos -n -m $EMAIL --keep-until-expiring

        #create file for ms exchange server
        openssl pkcs12 -export -in $CERTPATH/$MAINDOMAIN/cert.pem -inkey $CERTPATH/$MAINDOMAIN/privkey.pem -out  $CERTPATH/$MAINDOMAIN/cert.p12 -password pass:$PW
        zip -er --password $PW $SHARE/$ $CERTPATH/$MAINDOMAIN -j


The main part is done, we should be able to get the certificate zip files via CIFS and browser (port 81).

Now we want the “client” servers to fetch the certificates from the local certs server.

Example script for an Ubuntu Apache webserver “client”

#!/bin/bash, 2017-05
#gets SSL certificates from local certs server and replaces the existing/old ones


declare -a DOMAINS=(

mkdir -p $TMPPATH

#halt on any error
set -e

for DOMAIN in "${DOMAINS[@]}"
        wget -O $TMPPATH/$ $REMOTECERTPATH/$
        unzip -o -P $PW $TMPPATH/$ -d $CERTPATH/$DOMAIN/

apachectl configtest
service apache2 restart

Make sure your Apache certificate config and the script’s certpath point to the same directory.


Example for MS Exchange 2010/2013/2016

This is not a functional Powershell script, but some useful commands to create one:

//Load zip file from \\certs\certs or http://certs:81, then:
Get-ExchangeCertificate -> you get the Thumbprint
Enable-ExchangeCertificate -> SMTP,IIS,IMAP,POP + Thumbprint from above
(Alternative: Import-ExchangeCertificate)