Remote Access - Login Errors? (non-Nabu Casa)

I can’t figure out what I’m doing wrong. I am unable to login remotely (either Safari web based or HA app based) via my iPhone. I get to my DuckDNS url fine, and to the login screen for HA pops. But it gives me “Unable to connect to Home Assistant” error when I enter credentials.

Symptoms:

  • iOS app connects fine when on local wifi, although App Configuration/Connection shows Connected via External URL.
  • Off wifi, browser to https://mydomain.duckdns.org takes me to the login page just fine. But when logging in, it gives me “Unable to connect to Home Assistant” error
  • In the iOS app, App Configuration/Connection - the External URL defaults to http://192.168.1.107:8123. Internal URL is blank.

What I’ve Tried:

  • Entering in the proper Internal URL and External URLs into the iOS app Connection settings, no joy. Also tried updating in Home Assistant section under Configuration/General.
  • Reset app, deleted. Removed Refresh Tokens. Reinstalled app, run through setup. It sees http://192.168.1.107:8123 and allows me to login.

For reference, my setup involves:

  • Home Assistant in Docker on Ubuntu machine (not sure what this install method is called, I have Supervisor, Add-On store etc…)
  • DuckDNS/Let’s Encrypt/Nginx all handled outside of Home Assistant, on a separate physical machine. All seems good here, as I can reach my duck URL and certs are valid. I just can’t log in.

Check your nginx.conf file. Make sure it looks something like this with your specific info:

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}


server {

    server_name your.HA.FQDN;

       access_log /var/log/nginx/hass.access.log;
       error_log /var/log/nginx/hass.error.log;
       ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
       ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;

       ssl_dhparam /etc/ssl/certs/dhparam.pem;


    listen 443 ssl http2;
    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
    ssl_protocols TLSv1.2;
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:50m;

    proxy_buffering off;

    location / {
        proxy_pass http://your.HA.ip.address:8123;
        proxy_set_header Host $host;
        proxy_redirect http:// https://;
        proxy_http_version 1.1;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

I mean, my config file looks a little different, and uses different some different options. But given I can get to the Home Assistant login screen using my DuckDNS domain, wouldn’t that suggest the reverse proxy is fine? For reference, here is my config with example domains. Sorry for the formatting, code not cooperating with forum…

#user nobody;
worker_processes 1;

events {
worker_connections 1024;
}

http {
include mime.types;
default_type application/octet-stream;
server_names_hash_bucket_size 64;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;

# HTTP re-direct to HTTPS
server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  EXAMPLEOMBI.ddns.net EXAMPLEHASS.duckdns.org;
    
    return 301 https://$host$request_uri;
    
    location / {
        root   html;
        index  index.html index.htm;
    }
}


# OMBI - HTTPS with SSL
server {
    listen       443 ssl;
    listen       [::]:443 ssl;
    server_name  EXAMPLEOMBI.ddns.net;

    ssl_certificate      C:/some_path/EXAMPLEOMBI.ddns.net-chain.pem;
    ssl_certificate_key  C:/some_path/EXAMPLEOMBI.ddns.net-key.pem;

    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;

    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_set_header    Host                $host;
        proxy_set_header    X-Real-IP           $remote_addr;
        proxy_set_header    X-Forwarded-Host    $server_name;
        proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto   $scheme;
        proxy_set_header    X-Forwarded-Ssl     on;
    }
}


# HASS - HTTPS with SSL
server {
    listen       443 ssl;
    listen       [::]:443 ssl;
    server_name  EXAMPLEHASS.duckdns.org;

    ssl_certificate      C:/some_path/EXAMPLEHASS.duckdns.org-chain.pem;
    ssl_certificate_key  C:/some_path/EXAMPLEHASS.duckdns.org-key.pem;

    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m;

    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;

    location / {
        proxy_pass http://192.168.1.107:8123;
        proxy_set_header    Host                $host;
        proxy_set_header    X-Real-IP           $remote_addr;
        proxy_set_header    X-Forwarded-Host    $server_name;
        proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
        proxy_set_header    X-Forwarded-Proto   $scheme;
        proxy_set_header    X-Forwarded-Ssl     on;
    }
}

}

Looks like you are missing the statements to proxy websocket headers:

Add these lines to your nginx.conf as shown in mine:

map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}


        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;


Interesting, I will give this a try. I assumed this section below was doing my http > https upgrade, then the line of proxy_set_header Host $host; was passing it.

#HTTP re-direct to HTTPS with SSL
server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  EXAMPLEOMBI.ddns.net EXAMPLEHASS.duckdns.org;
    
    return 301 https://$host$request_uri;
    
    location / {
        root   html;
        index  index.html index.htm;
    }
}

It’s not just about proxying HTTPS for HA.
HA uses websockets for its API - which also needs to be proxied.
Here’s a good tutorial on configuring nginx to proxy websockets

Thank you. Going to play around with this now. Quick question, I can add the 2 proxy_set_headers into my HASS server block. But the map $https_upgrade… statement should go at the top of my config and not in the server block? If so, will that affect my other working host in the file (using 1 config file for 2 separate services).
Super appreciate this.

No, just above your HASS server block…as shown in my config. It’s only needed for HASS
I’m using my nginx.conf for about 20 different services…I only have the mapping for hass

Working! Can’t thank you enough!

You’re welcome :+1: