Using Dokku with Let's Encrypt wildcard certificate
Tags: dokku, wildcard, certificate, letsencrypt
Published: 2021-03-21 17:07:18

[Wildcard certificates](https://en.wikipedia.org/wiki/Wildcard_certificate) are handy and this was the first time when I needed to use them with [Dokku](https://dokku.com/). It was a little bit harder than I expected, but luckily, it is doable even with automatic renewal.

Right now (when I wrote this post), there is no wildcard support from [dokku-letsencrypt](https://github.com/dokku/dokku-letsencrypt/issues/189) plugin. Luckily, Dokku itself can use certificates from other sources.

## Creating wildcard certificate with Certbot

For a wildcard certificate, you need to use a different challenge with Let's Encrypt called `DNS-01` where you need to change DNS to prove, you are the owner of the domain.

I used [this tutorial](https://www.digitalocean.com/community/tutorials/how-to-acquire-a-let-s-encrypt-certificate-using-dns-validation-with-acme-dns-certbot-on-ubuntu-18-04) from [Jamie Scaife](https://www.jamieweb.net/) to install all needed to set up [Certbot](https://certbot.eff.org/) to use `acme-dns`. When you finish, you should have the wildcard certificate created. 

Now, we need to tell Dokku to use our new wildcard certificate within our app.

## Adding to Dokku

To add a certificate to Dokku for a certain app, we will use [`dokku certs:add`](https://dokku.com/docs/configuration/ssl/) command.

I found out, that it is easier to use a `tar` file with all related files, so we need to create one.

Create a new file, eg. `/root/dokku-certs/app/install` where the `app` should be the name of your application. I will use `example.com` as an example domain. Open it in your favourite editor and add this content:

```bash
rm -rf server.crt
rm -rf server.key
rm -rf certs.tar

cp /etc/letsencrypt/live/example.com/fullchain.pem server.crt
cp /etc/letsencrypt/live/example.com/privkey.pem server.key

tar cvf certs.tar server.key server.crt

dokku certs:add app < certs.tar
```

The First 3 lines will ensure, we will use only fresh files.

Line 5 and 6 copies needed files from the `letsencrypt` folder, where `certbot` creates the certificates for us. You will need to change them with the correct path.

Line 8 creates a `tar` file that is then imported to Dokku using the last command. You will need to change `app` to your own Dokku app.

The last step is marking the script as executable:

```bash
chmod +x /root/dokku-certs/app/install
```

Now, you can call the script and verify, that everything works as expected:

```bash
/root/dokku-certs/app/install
```

You should see something like this:

```bash
server.key
server.crt
-----> Unsetting DOKKU_PROXY_PORT
-----> Unsetting DOKKU_PROXY_SSL_PORT
-----> Setting config vars
       DOKKU_PROXY_PORT_MAP:  http:80:5000
-----> Setting config vars
       DOKKU_PROXY_PORT_MAP:  http:80:5000 https:443:5000
-----> Configuring *.example.com...(using built-in template)
-----> Creating https nginx.conf
       Enabling HSTS
       Reloading nginx
```

## Renew the certificate

We will use Certbot's `--renew-hook` within `crontab` (for automatic renewal). 

Open the `crontab` using `crontab -e` command and add this line below:

```bash
0 0 */10 * * certbot renew --renew-hook "/root/dokku-certs/app/install" > /var/log/letsencrypt/renew-errors.log
```

This will call the `certbot renew` command with our script in the `renew-hook`. When there will be a renewal, it will trigger the hook and call our script, which will copy the new certificate into the Dokku app.

I hope, there is an easier way how to do it, but the script above works well.

If anything goes wrong, you will receive an email about the domain expiration from the Let's Encrypt bot. So you should definitely add a working email when you are creating certificates with Let's Encrypt.