I just made a new version 0.2.1 of Additional CA integration with better Home Assistant OS detection, could you give a try ? Your private CA should be added to the certifi cacert.pem
now
That seems to have done it!
I see the cert now in cacert.pem
, and both the Jellyfin and CalDav integrations seem to be working.
Thank you!
Thanks ben725 for creating this AddOn. My first update without manually importing my ca certs and homematic connected automatically again. Thanks
@ben725 Thank you so much for your Additional CA Add-on and information provided! It is highly appreciated!
FYI, just a small note, your (Github) Quick setup mentioned:
mkdir -p config/additional_ca
cp my_ca.crt config/additional_ca/
I added a preceding root sign to it:
mkdir -p /config/additional_ca
cp my_ca.crt /config/additional_ca/
For all HA users struggling with self signed Keys+Certificates+CA, here is some of my info I stumbled on, and gathered/used on the long way to find some clear and useable information:
Software to manage/store/check Keys+Certificates+CA by UI:
- XCA Key/Cert/CA manager (all credits to mr Hohnstaedt!!).
Very usefull and clear explanations/tutorials (three part series) all about using and understanding this stuff (all credits to OneMarcFifty!!):
- OneMarcFifty X.509 Cerificates explained (Youtube serie first of three).
- OneMarcFifty Cheat Sheet and other snippets (Github).
EDIT: Also shared some of this info to my WTH related topic:
I hope this helps, just to prevent you guys the scattered road I had to walk to get some reliable information and gettings things done…
Worth to mention, since Home Assistant core 2024.12.x and newer, Home Assistant includes Python 3.13 and newer which requires to have Certificate Authority with Basic Constraints marked as critical.
The server certificates need AKID as well. I set up my self-signed infrastructure long ago and was a bit sloppy apparently. Here is what I added to openssl configs when generating:
CA:
authorityKeyIdentifier=keyid,issuer
basicConstraints=critical,CA:true
keyUsage=critical,digitalSignature,cRLSign,keyCertSign
Not sure AKID is needed in the CA but I included it just in case and all is working (for now…)
Server:
authorityKeyIdentifier=keyid,issuer
basicConstraints=critical,CA:false
keyUsage=critical,digitalSignature,keyEncipherment
Obviously, change key usage based on your CA/server needs.
Thank you @ben725 and @inkblotadmirer for your information!
Just a noob question thought, where do I find/how to do this in XCA manager?
Do I (only) have to create a new CA-Key with CA-certificates?
Regarding XCA manager: I don’t use it so can’t answer – I use openssl from the command line with config files.
You don’t need to create a new key for the CA but if it doesn’t have the correct attributes you will need to generate a new certificate using the existing key (and of course import the cert wherever needed as a new trusted authority – OS, browser, certifi, etc).
Do you have info or an URL where I can find a step-by-step description how/what to use?
Tnank you in advance!
To do what? Create certificates (generically google-able). To have HA trust certificates? This thread, or Enable use of self-signed certificates with urllib3 - #2 by inkblotadmirer
If you want HA to add this capability, click the link and vote on the feature request! Note the script in the link is outdated and python version in command line needs to be set to current version used in HA.
A step-by-step noob description of keys and certificates from the beginning, using openssl (I’m using Linux), by starting the creation of a (self-signed) local(domain) network Key (and certificates) and so on, with options explained.
I found these discriptions, mentioned earlier:
Is this a way to do it and/are the commands (still) valid, meaning with your earlier post CA and sever additions?
Sorry for this kind of questions but I’m losing track where/what/how to get it all done. (my fault entirely, I know…)
Try this one: https://www.youtube.com/watch?v=nOSl4dmywe8
Thank you @aedon, is this still valid? Because if is from 12 Oct 2021…
Well I haven’t tested it with HA 'coz I’m using HA just, for what, 3 weeks or so. Someone who knows HA better then me might check if HA needs some addition stuff. That Root-CA Server runs here n a Proxmox’s LXC and provides certificates for all may 49 LXC’s, Proxmox itself and OPNSense.
I made some changes. Compare to the yt-video posted obove. My config supports also Basic Constraints and Extended Key Usage:
Basic Configuration
Create directories for the CA
mkdir -p ca/{private,certs,newcerts,csr}
chmod -v 700 ca/private
Create index and serial files for the CA
touch ca/index
openssl rand -hex 16 > ca/serial
Create the index.attr
file
echo "unique_subject = yes" > ca/index.attr
Create Root-CA
Generate the Root CA Private Key
cd ca
openssl genrsa -aes256 -out private/root-ca.key 4096
Create the CA Configuration File
cd ca
vim root-ca.conf
Insert the following content:
[ ca ]
default_ca = CA_default
# 'man ca'
# Used by the ca command
[ CA_default ]
# Directory and file locations
dir = .
certs = $dir/certs
new_certs_dir = $dir/newcerts
database = $dir/index
serial = $dir/serial
RANDFILE = $dir/private/.rand
# RANDFILE is for storing seed data for random number generation
# Root CA certificate and key locations
certificate = $dir/certs/root-ca.crt
private_key = $dir/private/root-ca.key
# Default message digest, we'll opt for SHA2 512bits
default_md = sha512
name_opt = ca_default
cert_opt = ca_default
default_days = 4758
preserve = no
policy = policy_strict
[ policy_strict ]
countryName = supplied
stateOrProvinceName = supplied
organizationName = supplied
organizationalUnitName = supplied
commonName = supplied
emailAddress = supplied
[ req ]
# 'man req'
# Used by the req command
default_bits = 4096
distinguished_name = req_distinguished_name
string_mask = utf8only
default_md = sha512
# Extensions to use for -x509
x509_extensions = v3_ca
[ req_distinguished_name ]
# Certificate signing request
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
# Defaults
countryName_default = DE
stateOrProvinceName_default = NRW
localityName_default = Foo
organizationName_default = Bar
organizationalUnitName_default = ITSec
commonName_default = RootCA
emailAddress_default = [email protected]
[ v3_ca ]
# 'man x509v3_config'
# Extensions for the root CA
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:TRUE
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ]
# Extensions for client certificates
basicConstraints = critical, CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
[ server_cert ]
# Extensions for server certificates
basicConstraints = critical, CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
Create the Root CA Self-Signed Certificate
openssl req -config root-ca.conf -extensions v3_ca -key private/root-ca.key -new -x509 -days 4758 -out certs/root-ca.crt
Verify the Root CA Certificate
openssl x509 -noout -text -in certs/root-ca.crt
openssl x509 -noout -text -in certs/root-ca.crt | grep -i "basic constraints"
Generate a Server Private Key
openssl genrsa -out private/server.foobar.lan.key 4096
Verify the key
openssl rsa -noout -text -in private/server.foobar.lan.key
Create a Server CSR using a Configuration File
vim csr/server.foobar.lan.conf
Insert the following content:
[ req ]
# 'man req'
# Used by the req command
default_bits = 4096
distinguished_name = req_distinguished_name
req_extensions = req_ext
prompt = no
[ req_distinguished_name ]
# Certificate signing request
countryName = DE
stateOrProvinceName = NRW
organizationName = Foo
organizationalUnitName = ITSec
commonName = server.foobar.lan
emailAddress = [email protected]
[ req_ext ]
subjectAltName = @alt_names
basicConstraints = CA:FALSE
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[ alt_names ]
DNS.1 = server.foobar.lan
IP.1 = 192.168.22.100
Generate the CSR file
openssl req -new -key private/server.foobar.lan.key -sha512 -out csr/server.foobar.lan.csr -config csr/server.foobar.lan.conf
Verify the SAN entry in the CSR
openssl req -noout -text -in csr/server.foobar.lan.csr | grep -A 1 "Subject Alt"
If X509v3 Subject Alternative Name
is missing and if you want a full verification of the CSR structure.
openssl req -text -noout -verify -in csr/server.foobar.lan.csr
Sign the Server Certificate Request (CSR)
openssl ca -config root-ca.conf -notext -in csr/server.foobar.lan.csr -out certs/server.foobar.lan.crt -extensions req_ext -extfile csr/server.foobar.lan.conf
Verify the SAN entry in the server certificate
openssl x509 -text -noout -in certs/server.foobar.lan.crt | grep -A 1 "Subject Alt"
I had some spare time
What about oldschool?
Assumptions:
Host: chaos.foobar.lan
IP: 192.168.100.100
Name of Root-CA Cert: root-ca.crt
SSL
Settings / Add-ons /Advanced SSH & Web Terminal / Config
username: root
password: your secret
authorized_keys: []
sftp: true
compatibility_mode: false
allow_agent_forwarding: false
allow_remote_port_forwarding: false
allow_tcp_forwarding: true
scp chaos.foobar.lan.crt [email protected]:/ssl/
scp chaos.foobar.lan.key [email protected]:/ssl/
cat /config/configuration.yaml
# Loads default set of integrations. Do not remove.
default_config:
homeassistant:
external_url: "https://chaos.foobar.lan"
internal_url: "https://chaos.foobar.lan"
# Load SSL Certs
http:
ssl_certificate: /ssl/chaos.foobar.lan.crt
ssl_key: /ssl/chaos.foobar.lan.key
# Load frontend themes from the themes folder
frontend:
themes: !include_dir_merge_named themes
[...]
https://chaos.foobar.lan:8123
https://192.168.100.100:8123
Root-CA
scp root-ca.crt [email protected]:/ssl/
ssh [email protected]
vim /ssl/install-root-ca.sh
#!/bin/sh
CA_FILE="/ssl/root-ca.crt"
TARGET="/etc/ssl/certs/ca-certificates.crt"
if [ -f "$CA_FILE" ] && [ -w "$TARGET" ]; then
if grep -Fq "$(head -n1 "$CA_FILE")" "$TARGET"; then
echo "[=] Root-CA already present in $TARGET"
else
echo "[+] Appending Root-CA to $TARGET"
cat "$CA_FILE" >> "$TARGET"
fi
else
echo "[!] Cannot append: file missing or not writable"
fi
chmod 755 /ssl/install-root-ca.sh
cd /ssl
la
total 16K
-rwxr-xr-x 1 root root 389 Mar 21 11:30 install-root-ca.sh
-rw-r--r-- 1 root root 2.1K Mar 21 09:33 chaos.foobar.lan.crt
-rw-r--r-- 1 root root 3.2K Mar 21 09:33 chaos.foobar.lan.key
-rw-r--r-- 1 root root 2.1K Mar 21 10:45 root-ca.crt
Now in Settings / Add-ons /Advanced SSH & Web Terminal / Config add the following as:
init_commands:
/ssl/install-root-ca.sh
Reboot and check the log of Advanced SSH & Web Terminal
[...]
-e PTRN Pattern to match
-f FILE Read pattern from file
[+] Appending Root-CA to /etc/ssl/certs/ca-certificates.crt
s6-rc: info: service init-user successfully started
[...]
via SSH, Search for your localityName, in my case it’s “L=Bochum”
awk 'BEGIN {i=0; out="cert"i".crt"} /BEGIN CERTIFICATE/ {in_cert=1} {if(in_cert) print > "/tmp/cert"i".crt"} /END CERTIFICATE/ {in_cert=0; i++}' /etc/ssl/certs/ca-certificates.crt && \
for f in /tmp/cert*.crt; do if openssl x509 -in "$f" -noout -subject | grep -q "L=Bochum"; then echo "$f:"; openssl x509 -in "$f" -noout -subject; fi; done
Then cleanup
rm /tmp/cert*.crt
Enjoy
Heads-up for users of self-signed certs
Home Assistant 2025.7 will likely ship with Python 3.13, which enforces stricter SSL validation. If your intermediate certificate doesn’t have basicConstraints = critical, Python (via certifi) may reject it.
I ran into this while testing HACI—my builds against dev and rc homeassistant containers kept failing until I updated my test certs.
This mainly affects setups using integrations with local services over HTTPS. If that’s you, double-check your CA chain.
More info:
Python 3.13.x SSL security changes - Python Help - Discussions on Python.org