TLS Certificate for Unifi with certbot/Let’s encrypt

I have a nifty new Unifi setup. Typically it runs on TLS with a self-signed certificate that won’t pass verification.

For things like guest network splash page, it can be quite helpful to have a TLS-capable Unifi server. In this case, the server runs on a LAN and is not by default routable from the outside world. Nor is it easy to provision a TLS cert to a private domain (e.g. nick-unifi.summerwind.local, which is what the server would ordinarily DNS by).

To do this, it was a bit of a kludge:

  1. Provision a routable domain name e.g. nick-awesome-unifi.example.org and set up DNS properly.
  2. Get a certbot certificate — set up Apache and certbot to do their magical handshake thing.
  3. I found someone who had written a handy script to slurp the Let’s Encrypt cert into Unifi, which I ran.
  4. Provision a local DNS entry such that your ordinarily public domain resolves to a local IP.

Thus the magic: your Unifi server will now sign requests on the local network under a public domain with a valid TLS certificate.

Provisioning a suitable hostname

Head on over to your DNS provider/server for a valid domain, and then set the IP there to match your public IP.

Set up forwarding through your NAT router on 80 and 443.

Then you should be able to (from outside your LAN) reach a web server.

Set up Apache

You’ll want to install apache and openssl and all the related bits. Make sure at this point you can reach the Apache server and get the test page.

Set up Certbot

I used snap to install certbot, and then ran certbot, providing it with the public domain as ready.

Run Unifi slurp script

You’ll need to modify a few of the parameters (I run Ubuntu locally, so uncomment those lines and change it to let’s encrypt mode.

Set up local DNS resolution for the public domain

This was made a little bit more annoying by my recent adoption of a Unifi security gateway as my primary router. The EdgeRouter line had a handy CLI and config tree that allowed you to easily set static mapping of domain names to IP addresses. However, although the USG has the same command line interface, it is apt to be re-provisioned by the controller at any time which will overwrite the configuration if you do it through the CLI.

The correct way to configure these options (that are not available in the CLI) is to set a special config.gateway.json file with your extra options. This file (on Ubuntu) goes in /usr/lib/unifi/data/sites/default/config.gateway.json (I had to create the ./sites/default directories), and then dump the following into the file:

{
    "system": {
         "static-host-mapping": {
             "host-name": {
                  "nick-awesome-unifi.example.org": {
                       "inet": [
                           "10.5.2.1"
                       ]
                   }
              }
         }
    }
}

Then head on over to your Unifi setup, navigate to Devices, your gateway, then gear menu and click “force provision” in the side bar:

Lower box there, under “Devices” => Your router => Gear menu

After this miraculous series of steps, try to execute a dig on your local network:

nickandre-macbookpro:~ nickandre$ dig nick-awesome-unifi.example.org

; <<>> DiG 9.10.6 <<>> nick-awesome-unifi.example.org
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 62867
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4096
;; QUESTION SECTION:
;nick-awesome-unifi.example.org.	IN	A

;; ANSWER SECTION:
nick-awesome-unifi.example.org.	0	IN	A	10.5.2.1

;; Query time: 139 msec
;; SERVER: 10.5.1.1#53(10.5.1.1)
;; WHEN: Thu Aug 27 15:54:12 PDT 2020
;; MSG SIZE  rcvd: 64

And you should get something like that. I had to wait a short while for my DNS cache in my browser to expire (I always set the TTL to like 600 for this reason) and then I was able to access unifi over TLS.

Now go ahead and set up Unifi for TLS splash page under Settings => Hotspot => Advanced. I checked:

  1. Use secure portal
  2. HTTPS redirection
  3. Redirect using hostname (fill out your public domain)

Then you should be good to go! Make sure to set up renewal and the crontab for the cert.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.