Skip to content

Creating root CA and enabling HTTPS in HomeAssistant

petkov edited this page Jan 2, 2025 · 2 revisions

Background

By default, Home Assistant is accessible through HTTP. In most cases, that is acceptable if you trust your local network and don't plan to access HA from outside. As I have many devices connected to the same Wi-Fi network, I wanted to guard HA. To set up HTTPS, trusted certificates should be created.

Unfortunately, it is not possible to create such certificates using local IPs or local DNS names (like homeassistant) using services like Let's Encrypt. There was a workaround that used a public DNS and a record in /etc/hosts to resolve that DNS to the local IP, but that seemed too complicated.

So, I decided to create my own root CA. There is a good tool called minica, but unfortunately, it doesn't allow restricting the root CA to only specific DNS names. This means that if the root CA gets compromised, an attacker can create a server certificate for www.google.com, which your browser will happily accept.

Therefore, the obvious choice was to use openssl and create certificates from scratch. There is a good instruction on how to do it, but it also lacks the PermittedDNSDomains option and uses RSA keys, which are slower than Elliptic Curve.

So, I decided to educate myself and write yet another guide.

Prerequisite

If you are on Mac, make sure to install OpenSSL with Homebrew and run it using /opt/homebrew/bin/openssl, instead of openssl, or create a link to it. Out of the box, Mac has LibreSSL, which won't work.

To make sure you use the correct OpenSSL CLI, run:

openssl version

It should output something like this:

OpenSSL 3.4.0 22 Oct 2024 (Library: OpenSSL 3.4.0 22 Oct 2024)

Creating self-signed root CA

First, generate a private key that will be used to sign the root CA. Use the elliptic curve algorithm as it is faster than RSA:

openssl ecparam -name secp384r1 -genkey | openssl ec -out home-network-root-ca.key -aes256

Now, generate the root CA certificate and self-sign it. This root CA certificate will only allow end-entity certificates for specific domains specified in nameConstraints. Make sure to update homeassistant DNS to whatever name you use and add/remove additional DNS names.

openssl req -x509 -new -key home-network-root-ca.key -sha384 -days 3650 -out home-network-root-ca.crt -subj "/CN=home network root ca" -addext "keyUsage=critical,digitalSignature,keyCertSign" -addext "extendedKeyUsage=critical,serverAuth" -addext "basicConstraints=critical,CA:TRUE" -addext "nameConstraints=critical,permitted;DNS:homeassistant,permitted;DNS:homeassistant-2"

Creating end-entity certificate

Time to generate the end-entity certificate. First, generate the private key:

openssl ecparam -name prime256v1 -genkey -out homeassistant.key

If you want the key to be encrypted, run instead (keep in mind that HA requires unencrypted key):

openssl ecparam -name prime256v1 -genkey | openssl ec -out homeassistant.key -aes256

Now, let's create the CSR. Before running the command, make sure that -subj "/CN=homeassistant" and subjectAltName=DNS:homeassistant have the correct DNS. This DNS should match the DNS specified in the root CA.

openssl req -new -sha256 -key homeassistant.key -out homeassistant.csr -subj "/CN=homeassistant" -addext "keyUsage=critical,digitalSignature,keyEncipherment" -addext "extendedKeyUsage=critical,serverAuth" -addext "basicConstraints=critical,CA:FALSE" -addext "subjectAltName=DNS:homeassistant"

And finally, create the certificate and sign it with the root CA:

openssl x509 -req -in homeassistant.csr -CA home-network-root-ca.crt -CAkey home-network-root-ca.key -CAcreateserial -out homeassistant.crt -days 365 -sha256 -copy_extensions copyall

Verification

You can verify certificates by running:

openssl x509 -text -noout -in home-network-root-ca.crt

The root CA should look like:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            ??:??:??:??:??:??:??:??:??:??:??:??:??:??:??:??:??:??:??:??
        Signature Algorithm: ecdsa-with-SHA384
        Issuer: CN=home network root ca
        Validity
            Not Before: Jan 1 00:00:00 2024 GMT
            Not After : Jan 1 00:00:00 2034 GMT
        Subject: CN=home network root ca
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (384 bit)
                pub:
                    ??:??:??:??:??:??:??:??:??:??:??:??:??:??:??
                    ??:??:??:??:??:??:??:??:??:??:??:??:??:??:??
                ASN1 OID: secp384r1
                NIST CURVE: P-384
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                ??:??:??:??:??:??:??:??:??:??:??:??:??:??:??
            X509v3 Authority Key Identifier:
                ??:??:??:??:??:??:??:??:??:??:??:??:??:??:??
            X509v3 Key Usage: critical
                Digital Signature, Certificate Sign
            X509v3 Extended Key Usage: critical
                TLS Web Server Authentication
            X509v3 Basic Constraints: critical
                CA:TRUE
            X509v3 Name Constraints: critical
                Permitted:
                  DNS:homeassistant
    Signature Algorithm: ecdsa-with-SHA384
    Signature Value:
                    ??:??:??:??:??:??:??:??:??:??:??:??:??:??:??
                    ??:??:??:??:??:??:??:??:??:??:??:??:??:??:??

And end-entity certificates like this:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            ??:??:??:??:??:??:??:??:??:??:??:??:??:??:??
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: CN=home network root ca
        Validity
            Not Before: Jan 1 00:00:00 2024 GMT
            Not After : Jan 1 00:00:00 2025 GMT
        Subject: CN=homeassistant
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    ??:??:??:??:??:??:??:??:??:??:??:??:??:??:??
                    ??:??:??:??:??:??:??:??:??:??:??:??:??:??:??
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: critical
                TLS Web Server Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Alternative Name:
                DNS:homeassistant
            X509v3 Subject Key Identifier:
                ??:??:??:??:??:??:??:??:??:??:??:??:??:??:??
            X509v3 Authority Key Identifier:
                ??:??:??:??:??:??:??:??:??:??:??:??:??:??:??
    Signature Algorithm: ecdsa-with-SHA256
    Signature Value:
                    ??:??:??:??:??:??:??:??:??:??:??:??:??:??:??
                    ??:??:??:??:??:??:??:??:??:??:??:??:??:??:??

To print the content of the CSR for debugging:

openssl req -text -noout -in homeassistant.csr

Installing certificates

Mac

To add the root CA to Mac, refer to this guide

Android

To add the root CA to Android:

  • Copy the home-network-root-ca.crt certificate to Google Drive.
  • On your Android device, go to Settings -> Security & privacy -> More security & privacy -> Encryption & credentials -> Install a certificate -> CA certificate -> Install anyway
  • Select the certificate file from Google Drive. If this doesn't work, download the file and install it from the Downloads folder.

Home Assistant

To install the certificates in Home Assistant, follow the instructions in this guide

After HA is restarted, a warning will appear in Settings stating that the HA URL is not configured. Follow the instructions in the warning and use the DNS name from your certificate.

Now HA should only accept HTTPS requests and the browser should show secure connection.