The default installation of Ubiquiti’s UniFi Video software uses a self signed certificate for the web interface. As a result users will notice a certificate warning in their browsers when they connect to the page.
In UniFi Video version 3.7.0 Ubiquiti added experimental support for importing custom certificates. This allows you to import a certificate signed by a trusted root certificate authority and make the browser certificate errors disappear.
Unfortunately the process still isn’t very easy. Below is the process I used to install a signed certificate in UniFi Video.
Note that I’m running the UniFi Video software on Centos which isn’t officially supported by Ubiquiti. As a result some of my paths might be slightly different from other distributions but the general process is the same.
Generating the Certificate Signing Request (CSR)
In order to make Chrome happy the certificate must contain the Subject Alternative Name field (SAN). Chrome now ignores the CN field and will display certificate errors if the SAN field is not present.
It turns out this field is actually useful since you can list multiple different DNS names in the same certificate. This allows you to list both an internal and external DNS name for the same server within the same certificate.
In order for the SAN fields to be present they must be specified in the CSR. I performed these steps on a linux system with openSSL installed. It can be done from Windows but the commands may vary and I won’t get into that in this post.
Create a new file called san.cnf. You will need to edit 7 of the lines and replace them with your own information. Enter your two digit country code, state name, locality, org name, DNS.1, and DNS.2. If you only want to specify DNS.1 then that is fine, you can also use more than 2.
[ req ]
default_bits = 2048
distinguished_name = req_distinguished_name
req_extensions = req_ext
prompt = no
[ req_distinguished_name ]
countryName = YourCountryCode
stateOrProvinceName = YourState
localityName = YourCity
organizationName = YourOrg
commonName = YourFQDN
[ req_ext ]
subjectAltName = @alt_names
DNS.1 = YourFQDN
DNS.2 = YourDN
Next generate the certificate request that references the san.cnf file created in the previous step. Run this command from the same directory as the san.cnf file (or specify the full path).
openssl req -out request.csr -newkey rsa:2048 -nodes -keyout private.key -config san.cnf
When the process completes you will have two files, request.csr which contains the certificate request and private.key that contains the associated private key.
To verify that the SANS extension is in your CSR run the command below. You should see the DNS names specified from the alt_names section of the san.cnf file.
Use the command below to convert the private key into a format that UniFi Video will accept. If you are seeing errors in your server.log file complaining about “Failed to import private key” or “algid parse error, not a sequence” then your private key is probably in the incorrect format. The server will only accept the key in DER format.
openssl pkcs8 -topk8 -inform PEM -outform DER -nocrypt -in private.key -out private.key.der
Getting the certificate signed
At this point you should have a properly formatted private key (private.key.der) and certificate request (request.csr). The next step is to have the certificate request signed by a trusted root certificate authority. In my case the trusted CA is a Microsoft Enterprise PKI server running on my network. In your case it could be a public CA such as Namecheap or one of the many others.
For Microsoft PKI servers you can initiate a certificate request by accessing the certificate services web interface (http://yourca/certsrv/). Click on advanced request and paste the full contents of the request.csr file in the top box.
If all goes well you will see the screen shown below which presents the option to download the certificate. Unfi Video requires the certificate be DER encoded so select that option and download the certificate. In some cases you may need the entire chain but in my I did not since all of my clients already trust this root CA.
Installing the certificate and private key on the server
Create the certificates folder. Your path may be /usr/lib/UniFi-Video/ or something else depending on where your base installation lives. On my Centos installation it’s in /opt/UniFi-Video.
mkdir -p /opt/UniFi-Video/data/certificates
Copy the signed certificate and private keyinto the certificates folder and rename them:
- ufv-server.cert.der (signed certificate)
- ufv-server.key.der (private key file)
Change the permissions on the newly created directory and the files inside.
chown -R unifi-video:unifi-video /opt/UniFi-Video/data/certificates/
At this point the contents of the certificates directly should look like this:
Stop the unifi-video service. The command may very depending on your operating system.
systemctl stop unifi-video.service
Modify the system.properties file to enable custom certificates.
Add the line below to the file and save the changes.
Make a backup the existing trust store in case something goes wrong.
cp /opt/UniFi-Video/data/ufv-truststore /opt/UniFi-Video/data/ufv-truststore.backup
Next delete the existing trust store.
rm -rf /opt/UniFi-Video/data/ufv-truststore
Start the unifi-video service.
systemctl start unifi-video.service
If everything works correctly the private key and certificate inside the certificates directory will disappear and a new trust store file will be created that contains them. The new certificate should be active in the web server at this point. From within chrome you can press Ctrl + shift +I to inspect the certificate.
If it’s not working check the log file for any errors (/opt/UniFi-Video/logs/error.log). Even if your custom certificate is not successfully imported the UniFi software will automatically regenerate a new trust store so you’ll have to repeat part of the process in order to test a new certificate if you encounter problems.