How to manually set SSL certificates?

My question in short: How can I set the SSL certificates that Home Assistant OS uses?

In longer:

I am running Home Assistant OS on a Raspberry Pi. My domain setup is a bit complicated: I use DuckDNS in order to get a a subdomain name, let’s say it is example.duckdns.org.

My domain provider allows me to edit the nameserver (but sadly I cannot use Let’s Encrypt with the DNS challenge), so I set a CNAME entry to have a subdomain of my own domain point to example.duckdns.org, lets call it: myserver.example.org.

That is the reason why I cannot simply use the DuckDNS integration: I do not want an SSL certificate for example.duckdns.org, I want an SSL certificate for myserver.example.org.

For various other things, I have a local server running that obtains Let’s-Encrypt certificates for various other subdomains, and that works fine. I have set it up to also obtain an SSL certificate for myserver.example.com, and that also works fine.

Now, Home Assistant OS is running on a different machine.

How can I make it use these certificates? Can I copy them somewhere where they are found?

I find nothing on this in the documentation, it just says “use the DuckDNS add-on”…

2 Likes

Alright, I found it. Basically: You need to tell Home Assistant in configuration.yaml in the http: section, like this:


http:
  ssl_certificate: /ssl/fullchain.pem
  ssl_key: /ssl/privkey.pem

Then, I installed the SSH add-on, and on my main server I set up a routine that copies the SSL certificates over to Home Assistant via SCP, like this:

scp -i /path/to/private_key /etc/letsencrypt/live/myserver.example.org/cert.pem root@homeassistant:ssl/

5 Likes

It seems if you update the cert in this manner you still need to restart the web server associated with HA to get the updated information read. Did you do something like “ha core restart” or something else?

Yes, you are right! I found that out later.

Unfortunately, since my issue is that the server obtaining the SSL certificates is not running on the machine that home assistant runs on, I cannot just issue the shell command “ha”, I need to do it remotely.

Originally, I tried to use ssh to send the “ha core restart” command. Turns out: You cannot just do it like that. You have to specify the “Supervisor token” in your ssh request or the command will fail. This appears to be a security feature.

While it is possible to get ahold of this supervisor token (it’s available inside a terminal session on the home assistant), it appears to be changed with every restart of the home assistant instance, so using it in a script on my server turned out not to be a functional way, because after a restart of the home assistant, the token will no longer be valid and the command will fail to restart ha.

I did, however, find a way: Using the REST api (see REST API | Home Assistant Developer Docs). As far as I can tell, this is also the recommended way of doing this, so I recommend using this.

If you issue a HTTP(S) request to your home assistant instance under the api sub-key, like this:

http://your.homeassistant.tld:8123/api/...

you can access various functions, and especially all services. From the command line/in a bash script on my server, I now do the following:

  curl -X \
    POST -H "Authorization: Bearer *LLA-TOKEN*"
    -H "Content-Type: application/json"
    https://your.homeassistant.tld:8123/api/services/homeassistant/restart

As you can see, you also need a token (where “LLA-Token” is), but this is a persistent one, it is a “long-lived access token”, and you can easily get one of these via the home assistant web gui - follow this manual here: Authentication - Home Assistant

Hope that helps!

3 Likes

Thanks for the information it’s very helpful. I run the supervisor version of HA on armbian which gives a lot more control over scripting on the HA box. At this point I’m running a script outside of HA, but still on the HA controller hardware to update the letsencrypt cert. I generate a wildcard cert, update HA and then push it to three other servers I have running on my home network. This enables the HA companion app to display the GUI for these services within a web card. Once you move HA to ssl any service you integrate with a web card also has to also use ssl. It kind of makes things a pain. I really wish on HA you could just restart the web interface, without restarting core. On the other three servers I have I just restart apache or tomcat. It’s the way all other products work. Not sure why HA doesn’t do something similar. It would be great if rest API had a restart-web command. It would also be great if I could tunnel the companion App access to other home services presented in the web card across nabu casa. Maybe some day. Once again thanks for the additional information. Now I’m on to building a whole home audio system. I needed this wildcard cert stuff working so I can provide direct access to the mopidy interface withing HA. That’s another thing that I find surprising about HA is that there is a very limited integrated capability for controlling a media player. I figure after basic light control and home security the next item a smart home should have complete control over is your home Audio and Visual services. There’s plenty of room for growth in the AV area for HA. Take care.

I sure hope you are still here. What was your intent on adding certs to HA?? Why do I ask? I am trying to get local ssl working. Lan to lan, no internet. So I need to set certs and keys on the HA server. That seems to be more difficult than I realized. I was expecting a linux type config. Yours is the first post that seems to get me down the right path. What was your original post addressing?

Heya, avgjoeCO, yes, I am still here.

What did I try to accomplish? Basically, a secure connection ^^ For starters, I had issues with the Android app which did not want to connect to my HA instance without a valid certificate, and in general I want to make sure the connection is always covered by a valid SSL certificate.

I am accessing HA via a fixed domain name that is a subdomain of a domain name I own. Since my internet provider does not give out permanent IP addresses, my home IP address regularly changes, so I use a DynDNS service to which I point my own subdomain via a CNAME entry in the DNS entry of my domain.

So it basically is: subdomain.example.tld points to subdomain.dynamicdnsservice.tld which resolves to my home IP address.

And since I have multiple services running in my home network that ware accessible from the web, I cannot just give the RasPi that runs my HA instance the port forwarding for port 80 – but that is what is required for the recommended HA plug-ins to handle the obtaining of Let’s-Encrypt certificates.

So I need to generate the certificates on a different machine (the one also running the nginx instance that handles port 80 requests coming from the outside), then push these certificates to HA and then restart HA for the change in the certificates to go into effect.

Now, I think that does not in the slightest help you with your issue, because I would imagine your issue probably is the fact that you need self-signed certificates, and for that need to make the Home Assistant installations trust your self-signed root CA, right? The best approach to this I could find would be described in this thread: Let Home Assistant trust a personal certificate authority - #5 by krich11 but it appears it’s rather sketchy and might break a lot…

1 Like

You put your key and certificate here. Here’s the example configuration.yaml entry for http from the docs:

# Example configuration.yaml entry
http:
  server_port: 12345
  ssl_certificate: /etc/letsencrypt/live/hass.example.com/fullchain.pem
  ssl_key: /etc/letsencrypt/live/hass.example.com/privkey.pem
  cors_allowed_origins:
    - https://google.com
    - https://www.home-assistant.io
  use_x_forwarded_for: true
  trusted_proxies:
    - 10.0.0.200
    - 172.30.33.0/24
  ip_ban_enabled: true
  login_attempts_threshold: 5

For lan to lan SSL you have 3 options.

  1. If you run a DNS server on your LAN, use a dynamic DNS service like DuckDNS or buy your own domain and set up something to keep the IP in sync as yours changes. Add a DNS rewrite rule to resolve a subdomain of the domain you picked to the LAN IP of HA for devices on your LAN. Use Let’s Encrypt to obtain an SSL certificate on that subdomain and add it to HA.

    • :white_check_mark: SSL on your LAN with a valid and publicly verifiable certificate.
    • :warning: if you want to do no port forwarding you’ll need to set up an alternative type of challenge, not the default http one. Can be tricky with DuckDNS or a similar free service
  2. If don’t run a DNS server on your LAN but are willing to purchase a domain you can add a DNS entry for a subdomain of a LAN IP (HAs LAN IP in this case). Not all hosting services let you do this, I know cloudflare does (because I do this) but ymmv on others. Then use Let’s Encrypt with a DNS challenge to obtain a certificate on that subdomain.

    • :white_check_mark: SSL on your LAN with a valid and publicly verifiable certificate and no ports forwarded.
  3. Create a self-signed certificate using openssl (or the tools of your choice) and add it to HA.

    • :warning: to use this successfully every app/device you need to talk to HA will need to be able handle a self-signed certificate. Either by uploading the certificate to it’s trust store or telling it to not verify the certificate. This will need to be done manually for every device and if one doesn’t have either of these options then it simply can’t talk to HA.
    • :information_source: If you’re considering this option I would recommend setting up a reverse proxy in front of HA. Add the self-signed cert to that and leave an option for devices to talk to HA directly using HTTP. Set up as many things as possible to talk to the reverse proxy but then there’s still a workaround for those that can’t handle a self-signed cert.

If you want more info on #2, vaultwarden publishes a guide on that particular approach. It’s for vaultwarden but most of the steps work for anything since they’re just describing what to do in cloudflare. Any service could be on the other end.

2 Likes

How do you make HA itself recognize such a self-signed certificate as valid? How do you add the certificate of your own root CA to Home Assistant?

You mean so you can generate ssl certificates for all your other applications from that CA and have HA automatically recognize and validate that certificate when it talks to them? To my knowledge there is no way to do that universally. Some integrations have added options to provide a custom ca certificate to use to verify the certificate presented, for example Mqtt and influxdb.

It’s not a common request to my knowledge, you’re welcome to add a #feature-requests though. So users that need it can vote it up.