Google assistant not speaking via tts

I see these all the time, but nothing else when Google doesn’t work.

My SSL cert (via the DuckDNS addon) seems to be working fine when I hit my external base_url.

ssl.SSLError: [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown (_ssl.c:1076)
2019-08-07 13:42:31 ERROR (MainThread) [homeassistant.core] Error doing job: SSL handshake failed
Traceback (most recent call last):
  File "uvloop/sslproto.pyx", line 500, in uvloop.loop.SSLProtocol._on_handshake_complete
  File "uvloop/sslproto.pyx", line 484, in uvloop.loop.SSLProtocol._do_handshake
  File "/usr/local/lib/python3.7/ssl.py", line 774, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: HTTP_REQUEST] http request (_ssl.c:1076)

Ah DuckDNS addon strikes again, I’m not sure how to get around this issue. I use a Nginx proxy and let that handle the SSL certs while my internal Home Assistant runs just http keeping everything open for Google Home/Chromecast/etc.

I think there’s a thread about this on the forum, try searching I’m sure you’ll find it.

Did you restart HA?

yes, I modified the tts to have base_url of “http://local_ip:8123” ,restarted HASS, still nothing.
What I don’t understand is why the Google Assistant device beeps (so I know HASS is able to talk to it), when I hit my external HASS over https, the cert works shows good without error in my browser. I think SSL handshake is red haring.

if your router does loopback-NAT, this might work:

base_url: https://your.duckDNS.domain.org:8123

For a little background: Setting the tts: platform base_url to a non-TLS IP (http://) negates any certification validation between the tts: component and HA instance (hence why base_url: https://... wouldn’t seem to serve any purpose in your scenario).
So with base_url: set to http://..., nothing you’re seeing in your browser over https:// should be relevant to the tts: platform configuration.

As a side note: Self-signed certificates are considered ‘non-trusted’. I’m guessing you receive a “Your connection is not private” warning in your browser when navigating to HA over https://…? This would also prevent the tts component from being able to reach your HA instance (if you were using TLS). As a little more complex but comprehensive solution, you could either try what firstof9 suggested, or generate a free trusted (a.k.a. “Green Bar”) certificate from https://zerossl.com/ and negate any need for configuring base_url: (as well as getting rid of the warnings in your browser and logs).

Right, that seems to confirm that the URL Ha is using is correct – which should be the base_url: configured under tts:, assuming there are no typos, syntax errors, etc. (your original codeblock looks correct) – but the actual TTS data is not getting through. I think the most likely cause would be that Google’s TTS API can’t reach HA’s tts: component, which would likely be related to the certification errors you’re seeing in your log.

Edit: fixed typo
Edit2: more typos :roll_eyes:

Hi, I do have a valid trusted SSL cert installed and when I hit the external interface for my HA in my browser, the cert looks fine. I also know this to be true because Google Assistant (free) integreation works and that wouldn’t be the case using a self assigned cert.

If I remember back a few weeks ago, when I first setup my HA, it auto discovered my Google Home devices (I never had to set them up in HA or authenticate through Google). At that time, the google speak worked through HA and I believe this was all before my SSL cert was installed. So, knowing that, why does HA tts even need an SSL cert if HA makes the connection to the external translate.google.com API? That API isn’t making a call back to my HA, right? The HA is making the source connection. A network flow diagram of the tts steps here would be nice :slight_smile:

Flow as follows:

  1. You Input TTS Text
  2. HA contacts translate.google.com and downloads the generated mp3 of the text you entered
  3. HA then pings the media player you’ve selected via the chromecast protocol
  4. HA sends the base_url to the media player as the URL to play media from via the chromecast protocol
  5. Your media player plays the file (if it’s supported)

Now if your base_url is HTTPS your SSL Cert needs to be installed as well, BUT if the base_url doesn’t match the domain name the SSL Cert has, it will be rejected by a Google Home as it’s being sent a url that doesn’t match the cert, aka invalid. Thus the suggestion I posted earlier of using your duckDNS.org url as the base_url.

Your issue is occuring because you have Home Assistant handling the SSL directly. I use a Nginx reverse proxy to get around bottlenecks such as this, still keeps my exterior connections encrypted but my internal connections open.

Thanks for the details. I’ll look into Nginx I guess but it seems like some room for enhancement in HA. What would be nice is to be able to have HA listen on 8123 https, but also on 8124 (or whatever port) on http, then be able to pass that http local non-secure port has the base_url in tts.

This seems to bring us full circle, back to why I asked my first question:

In the tts component, base_url is not a requirement. Have you tried simply removing it?

Just to follow up with jparthum’s reply with technical detail on that, not setting the tts base_url will make it default to the base_url defined in the http component.

In case it’s brought up :wink:

1 Like

Removing base_url from tts: does not make a difference, which makes sense because without it, the base_url from http: is used, which is "https://<public_addr>8123. We know that without NAT loopback, the google devices can’t reach the external address to download the tts mp3 files.

Like I mentioned above what’s the likelihood of a 2nd listening hass port to be enabled within a future release, which would allow for non-ssl on that port?

OK then I’d leave that removed to simplify troubleshooting.

Now, do you have base_url set in the HTTP integration? ← Oops, I overlook where you specified “base_url from http:”. Can you use a phone over a cellular connection (disconnected from your local network) to reach HA using the exact URL specified as your HTTP base_url (including port number)?

yes, hitting my base_url address listed in the HTTP section (https://xxxxx.duckdns.org:8123) externally works fine. But with no NAT Loopback option, my Google Home can’t reach it.

I’m wondering if the port number in your base_url is being dropped (omitted) by Google.

If you’re not already running another web server you could remove the port from base_url (IE: “https://xxxxx.duckdns.org/”) and set your router to forward external port 443 to internal port 8123.

but regardless of the port, isn’t the problem that the local Google Home devices can’t reach https://xxxx.duckdns.org to download the tts mp3 file and the only current way around that is to turn off ssl on hassio and have something else do my SSL termination and it forwards inbound external requests to hassio http? Then I change my tts base_url to http://local_dns_of_hassio:8123 so the Google Home devices don’t get an SSL error and can download the local tts mp3 file?

The above must be true becuase I got it to work. Seems like alot of workaround if there was just another way to have HA listen on http on a different port.

  1. update hassio configuration.yaml to remove ssl, make sure you can reach HA locally over http
  2. turn off DuckDNS add-on in hassio
  3. install the nginx proxy add-on in HA, configure https with port you want nginx to list to (i.e. 8124).
  4. On the modem, port forward 8124 to nginx/hassio
  5. In ngix web ui (configured from step2), add a new Proxy Host to your HA instance and on the SSL tab, add a new SSL cert.

This worked for me. The one gotcha was in nginx when I ordered a new SSL cert (which it does through Let’s Encrypt), the cert would expire at the time I ordered it, which caused the Proxy Host entry to show Offline. The workaround was to grab the /ssl/* files from HA and nginx, create a new SSL but from the new dropdown, select Custom and use these ssl files (which the DuckDNS let’s encrypt add-on created).

Not based on what you’ve mentioned in this thread; you’ve always had a port number specified. They couldn’t reach https://xxxxx:8123 and https://xxxx.duckdns.org:8123.

So do you now access HA externally at https://xxxx.duckdns.org:8124?

Port number or not, devices on my local lan couldn’t reach my external facing address that required https that was defined in my base_url http section. And the local hassio interface didn’t have a matching cert name so https failed for google.

Correct, now I have my nginx external as https://xxxx.duckdns.org:8124 which forwards the request to my local hassio instance on port 8123 (no ssl), like @firstof9 suggested originally…

1 Like

The only other solution to this would be loopback-NAT support on your router or creating an iptables/firewall rule.