Let's Encrypt using DNS on Cloudkey 2+ & Backups
Update: 16/02/2021 – For CK2+ off controller backups see this great how-to: https://lazyadmin.nl/home-network/backup-unifi-controller-to-cloud/
Update: 22/12/2020 – Use this script instead: https://glennr.nl/s/unifi-lets-encrypt
Stolen from the UI community site, but copied here in case Unifi change their forums again or it gets lost to the mists of time (Original URL: https://community.ui.com/questions/How-To-Lets-Encrypt-with-Cloud-Key-and-DNS-Challenge/)
Uses the domain my-domain.xyz, one shortcoming is that my current external DNS provider doesn’t have an API, so I have to manually complete the challenge every 3 months, but the whole process takes just a few minutes so I’m not too concerned.
All steps are performed directly on the Cloud Key.
First, install Git and obtain the Let’s Encrypt code:
cd /home sudo apt-get update sudo apt-get install git git clone https://github.com/letsencrypt/letsencrypt
Next, generate a certificate, specifying that you want to use a DNS challenge for proving ownership of the domain.
certbot certonly --manual --preferred-challenges dns --email firstname.lastname@example.org --domains unifi.my-domain.xyz
In this example, unifi.my-domain.xyz is an internal hostname that resolves to my cloud key, and email@example.com is an email address where I’d like Let’s Encrypt to send me a reminder when the certificate is about to expire.
Since we are using a DNS challenge, you will be prompted to create a TXT record with your DNS provider. Let’s Encrypt will confirm that the DNS record is visible from their cloud infrastructure, thus proving you own the domain, and it will grant your certificate.
Next, stop unifi, since we’re about to mess with its certificates:
service unifi stop
Next, make a backup of the existing certificate data and remove it:
mkdir cert_backup cp -r /etc/ssl/private/ cert_backup rm /etc/ssl/private/cert.tarrm /etc/ssl/private/ssl-cert-snakeoil.key
Next, export your newly-granted Let’s Encrypt certificate into a format that Unifi understands:
cd /etc/letsencrypt/live/unifi.my-domain.xyz/ openssl pkcs12 -export -in fullchain.pem -inkey privkey.pem -out cert.p12 -name unifi -password pass:your_certificate_password
Here, your_certificate_password is a temporary password of your choosing to protect the exported certificate.
Next, import the Let’s Encrypt certificate into the Unifi keystore:
keytool -importkeystore -deststorepass aircontrolenterprise -destkeypass aircontrolenterprise -destkeystore /usr/lib/unifi/data/keystore -srckeystore cert.p12 -srcstoretype PKCS12 -srcstorepass your_certificate_password -alias unifi
Note that aircontrolenterprise is the Unifi keystore password; it is not a password of your choosing.
In this command, /usr/lib/unifi/data/keystore is actually a symlink pointing to the /etc/ssl/private directory from earlier.
At this point, the Unifi Controller will work with your Let’s Encrypt certificate, but recall that the Cloud Key has a separate internal nginx-based webserver to handle OS configuration options.
Next, replace the default certificates in the location nginx is expecting them, and make sure the permissions are correct:
cp fullchain.pem /etc/ssl/private/cloudkey.crt cp privkey.pem /etc/ssl/private/cloudkey.key chown root:ssl-cert /etc/ssl/private/* chmod 640 /etc/ssl/private/* tar -cvf cert.tar * chown root:ssl-cert cert.tar chmod 640 cert.tar
Finally, restart nginx, protect and start the Unifi controller.
service nginx restart service unifi-protect restart service unifi start
At this point, they should come up and be using your Let’s Encrypt certificate.
Set a calendar reminder for ~2 months from now so you don’t forget to redo this before the certificate expires!
This guide simply re-arranges the hard work that others have done into a solution that fits my specific needs. The author (pcoldren) used bits and pieces from the following resources while writing it: