Double reverse proxy breaks item state connection

Hi,
I was trying to set up an installation using two nginx reverse proxies, the first proxy (being a server) providing encryption and forwarding this specific domain to the second proxy (being on the same raspberry that hosts OH), which adds basic auth before passing the request off to OH. I can’t easily combine those two proxies but rather want to pipe the request trough either only the raspberry when connecting internally or both the server and the raspberry when connecting externally.

If I use the internal IP to directly access the raspberry everything works as intended (no encryption but basic auth), but when I use the external address to access the server OH isn’t able to show item states and logs updateTrackingList: No connection id, not calling the API. Authentication works in this case as well.

I didn’t fully understand why those rules are needed yet, so I might have made a mistake when piecing them together from various guides.

Raspberry config

events {
  worker_connections  1024;
}

http {
  server {
    auth_basic "Anmeldung";
    auth_basic_user_file /etc/nginx/passwords;

	# Cross-Origin Resource Sharing
    add_header 'Access-Control-Allow-Origin' '*' always;
    add_header 'Access-Control-Allow_Credentials' 'true' always;
    add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range' always;
    add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH' always;

	add_header Set-Cookie X-OPENHAB-AUTH-HEADER=1;

    location / {
      proxy_pass http://openhab/;
      proxy_redirect off;
	  proxy_set_header Authorization "";
	  
	  proxy_set_header Host                 $http_host;
	  proxy_set_header X-Real-IP            $remote_addr;
	  proxy_set_header X-Forwarded-For      $proxy_add_x_forwarded_for;
	  proxy_set_header X-Forwarded-Proto    $scheme;
	  proxy_read_timeout                    3600;
    }
  }
}

Server config

server {
    listen 443;
    server_name wg.example.org raspberrypi;
    access_log /var/log/nginx/raspberrypi_access.log;
    error_log /var/log/nginx/raspberrypi_error.log;

    include snippets/enable_ssl.conf;

	# Cross-Origin Resource Sharing
    add_header 'Access-Control-Allow-Origin' '*' always;
    add_header 'Access-Control-Allow_Credentials' 'true' always;
    add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range' always;
    add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH' always;

	proxy_set_header Authorization "";
	add_header Set-Cookie X-OPENHAB-AUTH-HEADER=1;
	
    location / {
		proxy_pass http://10.0.0.4;
        proxy_redirect off;
		
		proxy_set_header Host                 $http_host;
		proxy_set_header X-Real-IP            $remote_addr;
		proxy_set_header X-Forwarded-For      $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto    $scheme;
		
        expires off;
        proxy_cache off;
		proxy_read_timeout      3600;
        proxy_connect_timeout   3600;
    }

    ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.pem; # managed by Certbot
}

API-Security settings

Thank you in advance!

This forum is on openHAB not nginx.
Please follow the guide on posting.

How to ask a good question / Help Us Help You - Tutorials & Examples - openHAB Community

Disclaimer: if you find any private information (ip-address, domain name, etc.) I encourage you to immediately inform me to delete these information. Thank you!

Hi @Malspherus and welcome to the openHAB community,

I’m using a similar setup to yours just with one exception that I don’t automatically add the authenitification to the connection for logging into openHAB. (if this is your use case). My second NGINX uses standard username and password methods to authenticate a user and give her/him access to the openHAB instance. To get into the administration panel of the openHAB frontend the user has to log in with the appropriate credentials.

My setup consists of two NGINX servers. The Main-Proxy has a static IP-address which is publicly reachable. This Main-Proxy is connected via VPN to my local server. On this server I have my Local-Proxy to manage my local setup which consists of different services. (databases, experiments, openHAB, etc.) and also to provide the basic username/password functionality.
I use SSL for the connections. You will notice this in my setup files.

As you said you have problems getting the item state. I had a similar problem with the connection between the frontend in the web browser and the openHAB instance behind two NGINX proxies. In the NGINX log files I found the net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK). I was able to solve this problem with following setting (it is also included in the Main-Proxy settings):

# NGINX SSE error
# net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK)
# https://waglerocks.com/issues-and-fixes/solvedneterr_incomplete_chunked_encoding-200-ok/?__cf_chl_jschl_tk__=pmd_f1d9c9e2b7e2b71e8973056e40d25da61ff332e3-1626816675-0-gqNtZGzNAiKjcnBszQii
# prevent it with:
proxy_buffering							off;

I changed my private settings to place holders. For example: >>XXXX<< is your domain address like wikipedia.com. (don’t forget the top level domain!). >>MY-PRIVATE-IPADDRESS<< is my private IP address of the Local-Proxy in the VPN network. >>LOCAL_IP_ADDRESS<< is my private IP address of the openHAB instance in my local network setup.

In the code below there are a lot of /characters and these little things are easily overseen! Please look closely because they have a big impact on NGINX location settings. I had sometimes problems with them just by missing them writing. For example in the >>Local-Proxy<< part there is the location setting:

proxy_pass                            http://LOCAL_IP_ADDRESS/;

Don’t oversee the / after you replaced the >>LOCAL_IP_ADDRESS<< with your valid IP-address.

Main-Proxy
#
###### Configurations file for Main Proxy #######
#

###########################################
# Some variables

upstream projectServer {
    # Seriennummer: 
    server MY-PRIVATE-IPADDRESS;
}



################################################################################
#################### Normal http server ##################
################################################################################
server {
    listen 80;
    listen [::]:80;
    root /var/www/XXXXX_V1/public_html;
    index index.html;
    server_name XXXX www.XXXXX;
    access_log /var/log/nginx/XXXX_V1.access.log;
    error_log /var/log/nginx/XXXX_V1.error.log;

    # Server Test Connection
    location /connection_test {
		return 200 'Gangnam style! Your project controller is online!';
    	add_header Content-Type text/plain;
    }

    # Redirect to https!
    location / {
        if ($scheme != "https"){
	      return 301 https://$host$request_uri;
		}
    }
}

################################### Secure Server
server {
	listen 443 ssl;
	listen [::]:443 ssl;
	root /var/www/XXXX_V1/public_html;
	index index_Secure.html;
	server_name XXXX www.XXXX;
	access_log /var/log/nginx/XXXX_V1.access.log;
	error_log /var/log/nginx/XXXX_V1.error.log;

	ssl_certificate "/etc/letsencrypt/live/XXXX/fullchain.pem";
	ssl_certificate_key "/etc/letsencrypt/live/XXXX/privkey.pem";
	# It is *strongly* recommended to generate unique DH parameters
	# Generate them with: openssl dhparam -out /etc/pki/nginx/dhparams.pem 2048
	#ssl_dhparam "/etc/pki/nginx/dhparams.pem";
	ssl_session_cache shared:SSL:1m;
	ssl_session_timeout 10m;
	ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
	ssl_ciphers HIGH:SEED:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!RSAPSK:!aDH:!aECDH:!EDH-DSS-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA:!SRP; 
	ssl_prefer_server_ciphers on;
	# Load configuration files for the default server block.
	# include /etc/nginx/default.d/*.conf;


    # Server Test Connection
    location /connection_test {
		return 200 'SECURE gangnam style! Your project controller is securely online!';
    	add_header Content-Type text/plain;
    }


	location / {
        proxy_pass                            http://projectServer/;
		proxy_redirect off;
        proxy_set_header Host                 $http_host;
		proxy_set_header Upgrade 			  $http_upgrade;
		proxy_set_header Connection 		  "upgrade";
        proxy_set_header X-Real-IP            $remote_addr;
        proxy_set_header X-Forwarded-For      $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto    $scheme;


		# NGINX SSE error
		# net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK)
		# https://waglerocks.com/issues-and-fixes/solvedneterr_incomplete_chunked_encoding-200-ok/?__cf_chl_jschl_tk__=pmd_f1d9c9e2b7e2b71e8973056e40d25da61ff332e3-1626816675-0-gqNtZGzNAiKjcnBszQii
		# prevent it with:
		proxy_buffering							off;


		# Cross-Origin Resource Sharing.
		add_header 'Access-Control-Allow-Origin' '*' always;
		add_header 'Access-Control-Allow_Credentials' 'true' always;
		add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range' always;
		add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH' always;

		# openHAB 3 api authentication
		add_header Set-Cookie X-OPENHAB-AUTH-HEADER=1;
    }
}
Local-Proxy
server {
    server_name localhost;
    listen 80;
    listen [::]:80;
    root /usr/share/nginx/html;
    index index.html;
    
	# Endpoint for Testing
	location /abc {
		return 200 'Gangnam style!';
    	add_header Content-Type text/plain;
    }
        

    location / {
        proxy_pass                            http://LOCAL_IP_ADDRESS/;
		proxy_redirect off;
        proxy_set_header Host                 $http_host;
		proxy_set_header Upgrade 			  $http_upgrade;
		proxy_set_header Connection 		  "upgrade";
        proxy_set_header X-Real-IP            $remote_addr;
        proxy_set_header X-Forwarded-For      $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto    $scheme;
		proxy_set_header Authorization          "";
		auth_basic                            "Username and Password Required";
        auth_basic_user_file                  /etc/nginx/.htpasswd;

		# NGINX SSE error
		# net::ERR_INCOMPLETE_CHUNKED_ENCODING 200 (OK)
		# https://waglerocks.com/issues-and-fixes/solvedneterr_incomplete_chunked_encoding-200-ok/?__cf_chl_jschl_tk__=pmd_f1d9c9e2b7e2b71e8973056e40d25da61ff332e3-1626816675-0-gqNtZGzNAiKjcnBszQii
		# prevent it with:
		proxy_buffering							off;


		# Cross-Origin Resource Sharing.
		add_header 'Access-Control-Allow-Origin' '*' always;
		add_header 'Access-Control-Allow_Credentials' 'true' always;
		add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range' always;
		add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH' always;

		# openHAB 3 api authentication
		add_header Set-Cookie X-OPENHAB-AUTH-HEADER=1;
    }
}

I hope my presented information can help you to solve your problem!

1 Like

@mstormi Thank you for your feedback, I posted the question here as it felt closer to OH than to nginx. Most of my configuration is coming from official OH guides and I then suspected my problem to be caused by the OH-specific authentication configuration.

@secureHAB Thank you very much for your solution, just adding proxy_buffering off; to the location part of the servers config worked for me as well!