Secure internal access to front-end gui with custom certificate authority without breaking other integrations

I am trying to enable HTTPS access to the Home Assistant front-end. I’ve seen various guides that look like they would work for the approach where you register a public domain name (e.g., purchased-domain.net, or my-domain.duckdns.org) and use Let’s Encrypt to generate widely-accepted certificates, then use that domain name internally. What I’m trying to do is to use home.arpa as my domain internally.

I have set up Home Assistant (2025.2.0, on HAOS 14.2, on Proxmox) as homeassistant.home.arpa. Local machines are able to resolve that address (I’m running pihole, and redirecting all dns traffic there, so any local device is able to resolve the name).

I set up a step-ca certificate authority so that I can generate certificates for the home.arpa domain for my local machines. I am using the Let’s Encrypt add-on to request/install/renew the certificates, and I configured the front-end webserver to use those certificates (and to serve the front-end on port 443 instead of the default 8123):

# Configure the front-end webserver
http:
  # Serve on standard https port instead of 8123
  server_port: 443
  # These are the ssl certificate locations that the letsencrypt plugin automatically populates
  ssl_certificate: /ssl/fullchain.pem
  ssl_key: /ssl/privkey.pem

This setup allows me to access the front end via HTTPS at https://homeassistant.home.arpa (once I install my certificate authority’s root certificate on my browser I don’t even get any warnings about the site being untrusted). And many things still work (e.g., Music Assistant can still cast music to devices because that add-on runs its own server on its own port).

But (as I understand it), there is no way to have this HTTPS set up applied to only the front-end — Home Assistant uses the same address and port for integrations. For example, when I use the Default Media Receiver to cast local media to a Google Home device, the device is given the address https://homeassistant.home.arpa/media/local/path/to/song.m4a?authSig=etc (which fails, because the google device won’t trust the private root certificate authority). The settings for Network->Home Assistant URL->Local network won’t allow a non-HTTPS url (like http://homeassistant.home.arpa or http://<ip address of home assistant>) because I “have configured an HTTPS certificate in Home Assistant.”

I can easily imagine that other devices/integrations will be similarly unhappy about my HTTPS certificates in the future, so even if I were able to find some workaround for the Google device, the problem would still be lurking.

Are there any recommended ways to achieve what I want (securing my access to the front-end gui, while leaving the rest of home-assistant’s network configuration as default as possible)?

Using the home.arpa domain name is not a hill I need to die on, but even if the solution turns out to be that I neeed to obtain and use internally a public domain name, I’m still a bit concerned that I might end up with some devices that don’t like HTTPS at all, so the ideal solution would be one that let me separate secure administrative access to the front-end from insecure device access. I have Home Assistant in the same VLAN as my Internet of Things devices, and I don’t want to have to trust that part of my local network enough to just do everything over http.

Any suggestions are appreciated.

Your other devices don’t care.

They don’t enter HA using your Ingress front end. That’s for humans and external Websockets.

The front end is only for the front end and anything that comes in from that side. Stuff inside your firewall and various other devices most likely have thier own transports and things controlled by thier own integration.

Just make sure you’re using good practice building out your PKI and make sure you get the public keys and CRLs in the right place for revocation checking and don’t overthink it.

Thanks for your reply!

I was hoping it would work the way you describe, but I think I’ve found at least one instance where the same address and port is being used: I had an automation set up to play a song from the Home Assistant media library at a certain time. Before I made the transition to using HTTPS certificates, the automation worked and the song played (and my children woke up on time). After the change the song didn’t play, and I found an error message in the log:

Logger: homeassistant.components.cast.media_player
Source: components/cast/media_player.py:405
integration: Google Cast (documentation,issues)

  • Failed to cast media https://homeassistant.home.arpa/media/local/Media/Music%20Files/Jon%20Batiste/Good%20Life%20(From%20_The%20Garfield%20Movie_)/01%20Good%20Life.m4a?authSig=... from internal_url (https://homeassisstant.home.arpa). Please make sure the URL is: Reachable from the cast device and either a publicly resolvable hostname or an IP address

I get the same error in the log when I try to cast media manually from the Media Library (using a player device from the Google Cast integration).

My understanding from that is that the Google Cast integration is serving the media through the same port as the front-end gui, and that the Google Home device is balking at the root certificate. (When I copy the URL from the log error message into my browser, it downloads the song.)

A work-around for this situation is that I can change the automation to use Music Assistant to play the song (and essentially avoid the Google Cast integration entirely). But I was worried that there might be other integrations that also use the front-end port.

Am I misunderstanding what happened, or how common this situation might be?

That is common. Reconfigure Google or use MA.

Google (or any cloud services) fall under what I said about Websockets above. You’re hooking something in front the outside (your firewall) and you just changed how they get there.

From the wording of the Home Assistant URL entry in the Network Settings (“Configure what website addresses Home Assistant should share with other devices when they need to fetch data from Home Assistant (eg. to play text-to-speech or other hosted media).”) I guess that I’ll encounter this problem with any device/integration that 1: uses the URL specified there (https://homeassistant.home.arpa) and 2: doesn’t like my non-established root certificate authority.

So, to make things like that (playing text-to-speech or other hosted media, or casting a dashboard to a Google Cast device) work, I guess what I really want is the ability to have such data served from a different port than the front-end so that I could specify for the Local network URL: (e.g.,) http://homeassistant.home.arpa:<data port>. But that’s not currently possible, as far as I understand.

Anything you can’t get your custom cert on.

This is the benefit to using something like duck. Thier cert chases back to a known PKI. Yours doesn’t.

In your phone and pc you can install the cert. You can’t exactly do that to Google.(which is where the trust chain for thier server lives)

Thats a side effect of personal ca. I don’t think you’ll be able to overcome that. But you might be able to setup Google coming through Nabu Casa instead? That’s a very very advanced config and I’m not a Google person.

I ended up build a hybrid work-around. It’s probably (definitely) not the simplest way to do things, but it evolved from where I was. I can now log into the front-end gui at https://homeassistant.home.arpa:8123 using my internal certificate authority (I might try to get that to work on port 443, but not just yet); devices/services that don’t like my certificates can connect at https://homeassistant.my-domain.duckdns.org (only from inside my network - I haven’t opened external access). In case it is helpful to anyone else, here is what I did:

I got a duckdns subdomain (my-domain.duckdns.org - not it’s real name).

I installed the Duck DNS add-on to use Let’s Encrypt to get a wildcard certificate for *.my-domain.duckdns.org. To get the add-on to do this, I found this workaround: in the Duck DNS configuration, set the domains to *.my-domain.duckdns.org > my-domain.duckdns.org (all the other configuration is standard - I had it name the files my-domain_duckdns_org_fullchain.pem and my-domain_duckdns_org_privkey.pem).

I configured my internal DNS (pihole) to resolve homeassistant.my-domain.duckdns.org to the ip address of my Home Assistant installation.

I installed the NGINX Home Assistant SSL proxy add-on, and use it to proxy homeassistant.my-domain.duckdns.org to homeassistant.home.arpa:8123. To do this while still maintaining HTTPS access at https://homeassistant.home.arpa:8123 I had to do some non-basic configuration:
In the homeassistant/configuration.yaml http: section, I enable SSL with my internal certificate authority certificates:

  ssl_certificate: /ssl/homeassistant_home_arpa_fullchain.pem
  ssl_key: /ssl/homeassistant_home_arpa_privkey.pem

I also enable proxying from the NGINX add-on:

use_x_forwarded_for: true
  trusted_proxies:
    - 127.0.0.1
    - 172.0.0.0/8

In the NGINX Home Assistant SSL proxy add-on, I enable custom configuration of NGINX:
Customize:

active: true
default: nginx_proxy_default*.conf
servers: nginx_proxy/*.conf

I used the Terminal & SSH add-on to create the file share/nginx_proxy/homeassistant_my-domain_duckdns_org.conf:

server {
  # Listen on the standard https port
  listen 443 ssl;
  ssl_certificate /ssl/my-domain_duckdns_org_fullchain.pem;
  ssl_certificate_key /ssl/my-domain_duckdns_org_privkey.pem;

  server_name homeassistant.my-domain.duckdns.org;

  location / {
    # Proxy to the local address
    proxy_pass https://homeassistant.home.arpa:8123;
    # Ignore any ssl verification problems
    proxy_ssl_verify off;
    proxy_set_header X-Forwarded-For $remote_addr;
    proxy_set_header Host homeassistant.home.arpa;
    # Enable websockets:
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
  }
}

The NGINX Home Assistant SSL proxy add-on didn’t like it when I also had homeassistant.my-domain.duckdns.org as the domain name on the basic configuration, so I changed that to something else.

In Home Assistant’s Network Settings, I changed the Home Assistant URL for the Local network to https://homeassistant.my-domain.duckdns.org.

Now, when I (e.g.,) cast music to a Google speaker from the Home Assistant media library (through the Google Cast integration), the speaker happily connects to https://homeassistant.my-domain.duckdns.org and plays the music (without having to externally resolve the URL).