Skip to content

Instantly share code, notes, and snippets.

@ljack
Created November 30, 2025 23:20
Show Gist options
  • Select an option

  • Save ljack/37e407ac834e70d9e792f1e2d7a2e851 to your computer and use it in GitHub Desktop.

Select an option

Save ljack/37e407ac834e70d9e792f1e2d7a2e851 to your computer and use it in GitHub Desktop.
πŸ” Creating UniFi-Friendly TLS Certificates Using mkcert
UniFi devices (UDM/UDM-SE/CloudKey) are unusually strict about TLS certificates.
They require:
A valid Common Name (CN)
Correct Subject Alternative Names (SAN)
A matching private key
No missing SANs (or the UI will break)
This guide shows how to create a fully working UniFi certificate using mkcert plus some OpenSSL refinements.
1. Install mkcert
macOS:
brew install mkcert nss
mkcert -install
Linux:
sudo apt install mkcert
mkcert -install
mkcert installs its local CA into your trust store.
2. Generate a UniFi-compatible certificate
UniFi requires a CN that looks like a public hostname, even if it’s internal.
Example recommended CN:
unifi.internal.test
Generate a certificate with proper SANs:
mkcert unifi.internal.test unifi.home.arpa dream-machine-se.local 10.0.0.1
This produces:
unifi.internal.test.pem – certificate
unifi.internal.test-key.pem – private key
CN is the first argument, SAN contains all listed names.
3. (Optional) Fix or re-sign certificates using OpenSSL
If mkcert omitted the CN or you want to adjust SANs without generating a new key, you can re-sign the certificate yourself.
Step 3.1 β€” Create an OpenSSL config
unifi-cert.conf:
[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = v3_req
[ dn ]
CN = unifi.internal.test
[ v3_req ]
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[ alt_names ]
DNS.1 = unifi.internal.test
DNS.2 = unifi.home.arpa
DNS.3 = dream-machine-se.local
IP.1 = 10.0.0.1
Step 3.2 β€” Create a CSR from the key
openssl req \
-new \
-key unifi.internal.test-key.pem \
-out unifi.csr \
-config unifi-cert.conf
Step 3.3 β€” Re-sign using mkcert CA
Find mkcert CA:
CAROOT=$(mkcert -CAROOT)
Sign:
openssl x509 \
-req \
-in unifi.csr \
-CA "$CAROOT/rootCA.pem" \
-CAkey "$CAROOT/rootCA-key.pem" \
-CAcreateserial \
-out unifi-final.pem \
-days 825 \
-sha256 \
-extfile unifi-cert.conf \
-extensions v3_req
Now you have:
unifi-final.pem – corrected certificate
Same private key as before
This version includes a valid CN and correct SANs.
4. Install into UniFi
UI method:
Settings β†’ System β†’ Advanced β†’ Device SSH & Certificates β†’ Custom Certificate
Upload:
Certificate β†’ unifi-final.pem
Key β†’ unifi.internal.test-key.pem
Then:
unifi-os restart
Your controller will now serve fully trusted HTTPS + WSS on all SAN hostnames.
5. Verify certificate + key match
Certificate modulus:
openssl x509 -in unifi-final.pem -noout -modulus
Key modulus:
openssl rsa -in unifi.internal.test-key.pem -noout -modulus
If modulus values match β†’ certificate + key are a valid pair.
βœ”οΈ Result
You now have a UniFi-friendly TLS setup that:
Works for multiple internal hostnames
Fully satisfies Chrome/Safari/Firefox
Avoids UniFi’s CN restrictions
Ensures WebSockets (wss://.../events) work without warnings
Is easily renewable with mkcert or OpenSSL
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment