Reverse proxy using NGINX

Do I need to do anything special to get naba cloud working with nginx?, it use to work but broke a release or 2 ago. Any help appreciated

This is my nginx configuration.
Ubuntu 20.04 Host
HA on kvm vm (hassio)

server {

    # SSL configuration

    listen 10.10.5.15:31566 ssl http2;
    server_name    my.domain.net;
    include snippets  /ssl-my.domain.net.conf;
    include snippets  /ssl-params.conf;
    access_log   /var/log/nginx/access-my.domain.net.log;
    error_log     /var/log/nginx/error-my.domain.net.log;
	

    
	location / {
    
		### force timeouts if one of backend is died ##
               proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
               proxy_set_header        Accept-Encoding   "";
	       proxy_set_header        Host            $host;
	       proxy_set_header        X-Real-IP       $remote_addr;
 	       proxy_set_header        X-Forwarded-Proto $scheme;
	      add_header                  Front-End-Https   on;
              add_header 		   Strict-Transport-Security "max-age=15552000";
              proxy_http_version 1.1;
              proxy_set_header        Upgrade $http_upgrade;
              proxy_set_header        Connection "upgrade";
  
             proxy_pass  http://192.168.110.178:8123;
	     proxy_redirect     off;
	}
   location /api/websocket {

          proxy_pass http://192.168.110.178:8123/api/websocket;
          proxy_set_header        Accept-Encoding   "";
	   proxy_set_header        Host            $host;
	   proxy_set_header        X-Real-IP       $remote_addr;
           proxy_set_header        Host $host;
	   proxy_set_header        X-Forwarded-Proto $scheme;
	   add_header                 Front-End-Https   on;
           add_header 		  Strict-Transport-Security "max-age=15552000";

           proxy_http_version 1.1;
           proxy_set_header Upgrade $http_upgrade;
           proxy_set_header Connection "upgrade";
	      
           proxy_redirect     off;

    
      }
   }
1 Like

Did you add THE iP of your reverse proxy to the trusted proxies? E.g.

http:
  use_x_forwarded_for: true
  trusted_proxies: 
    - 192.168.0.5

Hi Guys.
I have a question. What I need to change in my config when my Proxy Server is in different network than my Home Assistant?

Here is my HA config:

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 172.18.0.2

and here is my proxy conf:

server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name ha.*;

    include /config/nginx/ssl.conf;

    client_max_body_size 0;

    # enable for ldap auth, fill in ldap details in ldap.conf
    #include /config/nginx/ldap.conf;

    # enable for Authelia
    #include /config/nginx/authelia-server.conf;

    location / {
        # enable the next two lines for http auth
        #auth_basic "Restricted";
        #auth_basic_user_file /config/nginx/.htpasswd;

        # enable the next two lines for ldap auth
        #auth_request /auth;
        #error_page 401 =200 /ldaplogin;

        # enable for Authelia
        #include /config/nginx/authelia-location.conf;

        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        set $upstream_app 192.168.160.9;
        set $upstream_port 8123;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;

    }

    location /api {
        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        set $upstream_app 192.168.160.9;
        set $upstream_port 8123;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;
    }

    location /local {
        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        set $upstream_app 192.168.160.9;
        set $upstream_port 8123;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;
    }
}

In the past, when trusted_proxies aren’t needed in HA this configuration worked but now I get:

# 504 Gateway Time-out

Both, Proxy Server and Home Assistant are in docker containers but in different networks (Proxy Server is in proxynet network 172.18.0.0/16 and HA is in vlan network 192.168.160.0/24.

I banged my head on this for a couple hours! The trick was the section in configuration.yaml file for the http setting! Thank you so much!

Thank you for the nice discription.

I run my own private proxy server (Nginx) in my home, connected via my fritz.box to the WWW (https://mypage.spdns.org/). My Homeassistant server is installed on a Raspberry via Docker and it works fine in the home-network (http://192.168.178.35:8123/).

Now I also want to connect the Homeassistant device to the WWW without connecting it to a dyndns via the fritz.box because this way is already blocked for my private server.

This is my concept:

Whats not working is the proxying/routing from https://mypage.spdns.org/hass/ to the internal
https://192.168.178.35:8123/ Could you help me here please?

1. Get a domain name forwarded to your IP
:heavy_check_mark:https://mypage.spdns.org/subfolders/

2022/01/03 21:46:04 [error] 91661#91661: *1 upstream prematurely closed connection while reading response header from upstream, client: 89.14.97.35, server: leisa.spdns.org, request: "GET /hass/ HTTP/2.0", upstream: "http://192.168.178.21:8123/", host: "leisa.spdns.org"

Why?

2 Install NGINX on your server
:heavy_check_mark:Installed my own private proxy server (192.168.178.96)
:heavy_check_mark:Other apps are running fine in different subfolders like https://mypage.spdns.org/phpmyadmin/ or https://mypage.spdns.org/nextcloud/ etc.

upstream php-handler {
    server unix:/run/php/php7.4-fpm.sock;
}

#what is this doing?
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

#########################################
server {
    listen 80 default_server;
    listen [::]:80 default_server;
	server_name XXX.spdns.org 192.168.178.96;
 
	root /var/www;

    location ^~ /.well-known/acme-challenge {
        default_type text/plain;
        root /var/www/letsencrypt;
    }

	location / {
		return 301 https://$host$request_uri;
	}
}
#########################################

server {
	listen 443 ssl http2;
	listen [::]:443 ssl http2;
	server_name XXX.spdns.org;

	# SSL configuration
	# RSA certificates
	ssl_certificate /etc/letsencrypt/xxx.spdns.org/rsa/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/xxx.spdns.org/rsa/key.pem;
	# ECC certificates
	ssl_certificate /etc/letsencrypt/xxx.spdns.org/ecc/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/xxx.spdns.org/ecc/key.pem;

	# This should be ca.pem (certificate with the additional intermediate certificate)
	# See here: https://certbot.eff.org/docs/using.html
	# ECC
	ssl_trusted_certificate /etc/letsencrypt/xxx.spdns.org/ecc/ca.pem;

	# Include SSL configuration
	include /etc/nginx/snippets/ssl.conf;

	# Include headers
	include /etc/nginx/snippets/headers.conf;
.
.
.
	##########################################
	# Homeassistant Wifi
	#
	location ^~ /hass/ {
        proxy_pass https://192.168.178.35:8123/;
        proxy_set_header Host $host;
        proxy_redirect http:// https://;
	proxy_set_header X-Forwarded-Host $host;
	proxy_set_header X-Real-IP $remote_addr;
        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;
	}
	
.
.
.	
}

3. Obtain an SSL certificate
:heavy_check_mark:Installed on my own private proxy server (192.168.178.96) via lets encrypt
There is no root installation of nginx on my raspberry also no ssl encryption in the local lan at the moment

4. Create dhparams file
:heavy_check_mark:works fine on my own private proxy server (192.168.178.96)

5. Install configuration file in NGINX

  1. I don’t get the map to the connection-Variable
  2. Whats differrent to your discription:
  • add_header Strict-Transport-Security max-age is on 63072000
  • ssl_protocols supported: TLSv1.2 AND TLSv1.3
  • ssl_session_cache shared:SSL:50m ANSTEAD of 10m;
  • I don’t have proxy_buffering off;

6. Enable the Home Assistant NGINX configuration
:heavy_check_mark:works fine on my own private proxy server (192.168.178.96)

7. Start NGINX

:heavy_check_mark:other apps work fine on my own private proxy server (192.168.178.96)

? whats not working is https://mypage.spdns.org/hass/

8. Port forwarding

  • 443 and 80 for my own private proxy server (192.168.178.96)
  • Open port for my raspberry homeassistant 192.168.178.35:8123/

My hassio config on my raspberry

http:
  use_x_forwarded_for: true
  trusted_proxies: 
  - 192.168.178.96 #/24
  ssl_certificate: config/certs/fullchain.pem
  ssl_key: /config/certs/privkey.pem

Edit: in a earlier Version a didn’t use SSL-Certificates on my Raspberry. Now I use self signed certificates. But it is still not working

Your network for trusted_proxies needs to be 2 space indented. I’m still haveing Gateway Timeout problems so not 100% sure if this is your issue, but it could be.

trusted_proxies: 
  - 192.168.178.96 #/24

Thank you @Flyguy86, unfortunately it was not the solution.

Any other approach? This is what the Browser Inspector is spitting out:

Hi! I setup home assistant using docker-compose and it works fine when accessing via local ip, however when I setup reverse proxy using nginx, I can’t access the page. In network tab I see 404 errors for websocket and token. What’s wrong with it? This is my nginx config file:

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

server {
    server_name home.mydomain.com;

    listen [::]:80 default_server ipv6only=off;
    return 301 https://$host$request_uri;
}

server {
    server_name home.mydomain.com;

    include /etc/nginx/ssl.conf;

    listen [::]:443 ssl default_server ipv6only=off; # if your nginx version is >= 1.9.5 you can also add the "http2" flag here
    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
    # ssl on; # Uncomment if you are using nginx < 1.15.0
    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:10m;

    proxy_buffering off;

    location / {
        proxy_pass http://127.0.0.1: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;
    }
}

does your router support NAT loopback/hair pinning?

(without it, the router is unlikely to allow you to access anything on your LAN when using the public address of your connection. )

1 Like

@walaj Yes, I successfully setup reverse proxy for many other applications on my server. The only problem is with home assistant. And as you can see most of the requestes are passing, but the problem is with “websocket” and “token” for some reason.

Did you manage to solve this? I’m running into the same thing. The problem is that HomeAssistant is trying to make requests to the root of the nginx server without the /hass prefix, so nginx doesn’t know how to proxy the requests over.

@timwoj I just checked once again and it magically started to work… I don’t know how. I restarted raspberry pi couple of times, maybe that helped, I don’t have idea.

In my special caseI use a FRITZ!Box 7490. In accordance with this guide from AVM I saved the xxx.spdns.org exception in the DNS-rebind-protection area.

Thanks for the hint - unfortunately it was not the solution.

Could you share your config plz? The official documentation and this post doesn’t mentoin a token or a websocket usage.

I don’t think Home Assistant works well with subdirectories. Try a subdomain instead (e.g. hass.example.com instead of example.com/hass/)

1 Like

yup, my config of nginx proxy :

    location /homeassistant/ {
        proxy_pass http://10.8.0.20:8123/;

but it doesn’t work - page wants to fetch scripts from https://my_remote_server/ instead of https://my_remote_server/homeassistant/
It’s pretty ugly bug in page code.

A lot of web applications assume that they’re at the web root, unfortunately. (It’s not just Home Assistant.) On my list is getting a wildcard cert from Let’s Encrypt set up, so I can do https://*.ha.example.org with whatever various names I need.

Hey Guys,
my Problem is, that internally i can access the domain and the certificate works, but externally i get an “network access denied” error message.

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 127.0.0.1

my nginx conf

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

server {
    # Update this line to be your domain
    server_name mydomain.dynv6.net;

    # These shouldn't need to be changed
    listen [::]:80 default_server ipv6only=off;
    return 301 https://$host$request_uri;
}

server {
    # Update this line to be your domain
    server_name mydomain.dynv6.net;

    # Ensure these lines point to your SSL certificate and key
    ssl_certificate /etc/letsencrypt/live/mydomain.dynv6.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mydomain.dynv6.net/privkey.pem;
    # Use these lines instead if you created a self-signed certificate
    # ssl_certificate /etc/nginx/ssl/cert.pem;
    # ssl_certificate_key /etc/nginx/ssl/key.pem;



    # These shouldn't need to be changed
    listen [::]:443 ssl default_server ipv6only=off; 
    # if your nginx version is >= 1.9.5 you can also add the "http2" flag here
    add_header Strict-Transport-Security "max-age=31536000; includeSubdomains";
    # ssl on; # Uncomment if you are using nginx < 1.15.0
    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:10m;

    proxy_buffering off;

    location / {
        proxy_pass http://127.0.0.1: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;
    }
}

Btw I Use HA supervised on Debian 11 and have a DS-Lite connection (only ipv6)

This is more of an observation than a problem, but given that many of us are trying to run a network that can be self-contained and independent of the outside world, I thought I’d bring it up. I’m running HA in a VENV on a mac with Letsencrypt certificates, AdGuard rewrite and NGINX as per the examples. If I shut off the internet connection, to access internally, http://192.168.1.xxx:8123 works fine, but https://subdomain.duckdns.org times out in browsers or in the companion app. For a while I thought that this meant I had proxy_pass set up wrong or something, but then I realized that the NGINX error log shows this:

2022/06/12 11:40:43 [info] 63241#0: *151 SSL_do_handshake() failed (SSL: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown:SSL alert number 46) while SSL handshaking, client: 127.0.0.1, server: 0.0.0.0:443

… which apparently indicates that the browser is trying to verify the site’s certificate but understandably can’t because there’s no internet connection. So, even though all communication is remaining inside and the rewrite & proxy pass are working, HA isn’t accessible via the usual URL because the browser is being obstinate.

I don’t know of another solution than to use the internal ip address for HA if the internet is down. Did I miss something?