Reverse proxy multiple apps (inc HA) via nginx

OK, so I’ve been searching for a couple of weeks now. I’ve read just about all the nginx posts and articles I can find, but simply can’t figure this out.

Per the config below, I’m hosting HA and three other apps behind an nginx reverse proxy. Because HA doesn’t have any sort of url root option, I’m forced to access it via the root on nginx (I’ve tried all the other tricks I can find about giving HA a separate URI of its own on nginx, but none of those work).

The problem is, whenever I access apps 1, 2 or 3, I get the Home Assistant screen (which fails to load under the relevant ‘app’ URI). If I force Chrome to bypass cache (or empty my browser cache), I get the expected app. But, the second I do a regular refresh, I get Home Assistant again.

If I flush my browser cache, everything is fine - until I visit Home Assistant again. Then I have the same problem. The real issue is that there’s no way to bypass cache on a smartphone, except in incognito mode, which means I have to provide my htpasswd login each time - equally annoying.

Has anyone successfully hosted multiple apps (including HA) behind nginx?

Thanks in advance.

PS: the reason I listen on 127.0.0.1 is because I use sslh to have both ssh and ssl on port 443.

server {
	listen 127.0.0.1:443 ssl default_server;
	server_name home.my.domain;
	
	ssl_certificate /etc/letsencrypt/live/home.my.domain/fullchain.pem;
	ssl_certificate_key /etc/letsencrypt/live/home.my.domain/privkey.pem;

	root /var/www/html;

	index index.html;

	location /{
		proxy_pass        	https://192.168.0.16:8443/;
		proxy_set_header	Host $host;
		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 "upgrade";		
		proxy_set_header  	X-Real-IP  $remote_addr;
	    proxy_redirect 		off;
	}
	access_log /var/log/nginx/hass.home.my.domain;
	
	location /app1 {
		proxy_pass        	http://192.168.0.15:8081/app1;
		proxy_set_header  	X-Real-IP $remote_addr;
	        proxy_set_header    	Host $host;
	        proxy_set_header    	X-Forwarded-For $proxy_add_x_forwarded_for;
       	        proxy_set_header    	X-Forwarded-Proto $scheme;
	        proxy_redirect 		off;
		auth_basic 		"Restricted";
		auth_basic_user_file 	/home/pi/.htpasswd;
	}
	access_log /var/log/nginx/app1.home.my.domain;

	location /app2 {
		proxy_pass        	http://192.168.0.15:8989/app2;
		proxy_set_header  	X-Real-IP $remote_addr;
	        proxy_set_header        Host $host;
	        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
       	        proxy_set_header        X-Forwarded-Proto $scheme;
	        proxy_redirect 		off;
		auth_basic 		"Restricted";
		auth_basic_user_file 	/home/pi/.htpasswd;
	}
	access_log /var/log/nginx/app2.home.my.domain;

	location /app3 {
		proxy_pass        	http://192.168.0.15:7878/app3;
		proxy_set_header  	X-Real-IP $remote_addr;
	        proxy_set_header        Host $host;
	        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
       	        proxy_set_header        X-Forwarded-Proto $scheme;
	        proxy_redirect 		off;
		auth_basic 		"Restricted";
		auth_basic_user_file 	/home/pi/.htpasswd;
	}
	access_log /var/log/nginx/app3.home.my.domain;
}

Here’s what worked on mine…seperate out your apps into different server blocks, give each a unique name. You can point dns records for each back to the same IP (or CNAME each to the main home assistant A record, either method should work).

For example, I have:
A record: home.domain.com --> 192.168.x.x (IP of nginx server)
CNAME record: app1.domain.com --> home.domain.com
CNAME record: app2.domain.com --> home.domain.com

contents of /etc/nginx/sites-available/home.conf:

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


server {
 listen 192.168.x.x:8443 ssl;

 # SSL config
 ssl on;
 ssl_certificate /etc/letsencrypt/live/home.domain.com-0001/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/home.domain.com-0001/privkey.pem;

 server_name home.domain.com;

 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
 ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
 ssl_prefer_server_ciphers on;

 proxy_buffering off;

location / {
 proxy_pass http://192.168.x.1:8123;
 proxy_set_header Host $host;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_http_version 1.1;
 proxy_set_header Upgrade $http_upgrade;
 proxy_set_header Connection $connection_upgrade;
 expires off;
 }

}

server {
 listen 192.168.x.x:8443 ssl;

 # SSL config
 ssl on;
 ssl_certificate /etc/letsencrypt/live/home.domain.com-0001/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/home.domain.com-0001/privkey.pem;

 server_name app1.domain.com;

 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
 ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
 ssl_prefer_server_ciphers on;
 proxy_buffering off;

location /app1 {
 proxy_pass http://192.168.x.2:8989/app1;
 proxy_set_header Host $host;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_http_version 1.1;
 proxy_set_header Upgrade $http_upgrade;
 expires off;
 }
}

server {
 listen 192.168.x.x:8443 ssl;

 # SSL config
 ssl on;
 ssl_certificate /etc/letsencrypt/live/home.domain.com-0001/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/home.domain.com-0001/privkey.pem;

 server_name app2.domain.com;

 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
 ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";
 ssl_prefer_server_ciphers on;
 proxy_buffering off;

location /app2 {
 proxy_pass http://192.168.x.3:5050/app2;
 proxy_set_header Host $host;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header X-Real-IP $remote_addr;
 proxy_http_version 1.1;
 proxy_set_header Upgrade $http_upgrade;
 expires off;
 }
}

Thanks for that. Seems to be working now. I did try this method before posting, but suspect I left the HA instance configured with default_server, and visiting the root of the non HA instance sent me there.

Either way, it’s working with the separate name. Thanks for your help.

Hi, I am trying to do the same, will your solution work using duckdns?

I do have just duckdns subdomains (aaa.duckdns.org, bbb.duckdns.org and so on)