Nginx Reverse Proxy Set Up Guide – Docker

Tags: #<Tag:0x00007fc3ea26c928>

if hassio is restarting then you have another problem. what’s causing to restart?

First of all, I appreciate your support!

It seems that the supervisor installation starts a systemd service which causes hassio to restart, no matter how you set the restart policy in docker.

So in theory i could start Nginx Proxy Manager but now i get the following errors:

From db:
standard_init_linux.go:211: exec user process caused "exec format error"

And from app:
[4:17:17 PM] [Global ] › ✖ error getaddrinfo ENOTFOUND db

Any idea? Do I have to set up MySQL myself?

that’s correct. hassion uses systemd to start the containers.
I just saw that there’s a community addon for nproxy manager. That may be easier.
in any case this is my compose for nproxy

  nproxy:
    container_name: nproxy
    image: jlesage/nginx-proxy-manager
    restart: unless-stopped
    hostname: UNRAID  
    volumes:
    - /mnt/cache/appdata/nproxy:/config:rw
    environment: 
    - USER_ID=99
    - GROUP_ID=100
    - TZ=Asia/Dubai
    - DISABLE_IPV6=1
    - UMASK=000
    ports:
    - "7818:8181"
    - "180:8080"
    - "1443:4443"

Im using the default sqlite, no need to create another database

1 Like

Thanks for sharing, you saved me A LOT of time! Cheers mate

1 Like

This is the best explanation I found so far, look like it required

There appears to be a new “block” on reverse proxies that will require an extra config entry for this Nginx Reverse Proxy to work properly. According to the latest release notes - 2021.6: A little bit of everything - Home Assistant

HTTP (using reverse proxies)

Home Assistant will now warn when a misconfigured reverse proxy, or misconfigured Home Assistant instance when using a reverse proxy, has been detected.

These warnings will become an error in Home Assistant 2021.7.

If you are using a reverse proxy, and see these warnings, please make sure you have configured use_x_forwarded_for and trusted_proxies in your HTTP integration configuration.

For more information, see the HTTP integration documentation.

(@frenck - #51332)

I had to add the following to my config using this NGINX/Swag container to clear the log error:

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 172.21.0.2

Not exactly sure why I had to use 172.21.0.2, when most posting on this thread Reverse proxy error needed 172.21.0.1 . The 172.21.0.2 is listed in Portainer under “networks” and then when I click the “swag container” it is towards the bottom. Maybe someone who knows a little more about Docker and networks can chime in on why.

Posting this here as according to the log error, its a warning for now, but coming in the July release, it will block reverse proxy requests if you do not set the http options in the config.yaml file like mentioned here - HTTP - Home Assistant . I get this is an important security update, but it definitely adds another layer of complication to setting up a reverse proxy when running Home Assistant in a container and I imagine a lot of people will be caught off guard by it when it just stops working next month without the extra http config settings being added.

Update - I also wanted to chime in on the fastcgi settings. I saw that someone posted about it recently above, and in the beginning I always saw fastcgi errors in my nginx error logs, and also noticed a lot of issues with my Ring and Blink integrations which I believe use fastcgi to send videos to home assistant. I previously had changed this to the IP address of the host machine which was causing the issues. Aparently NGINX can’t handle fastcgi on its own, so needs a “helper” which in this case is PHP. The Swag container has PHP and can actually handle fastcgi requests within its own port 9000. So, in the default config, the fast CGI is setup this way:

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include /etc/nginx/fastcgi_params;
    }

You DO NOT want to change anything in this block. Do not change the IP address of 127.0.0.1 to your host machine. This IP address is the “loopback” or “home” address of the actual Swag container itself, and is necessary to reference PHP for fastcgi to process properly. If you change it to your hostip (192.168.0.whatever), fastcgi requests won’t work because you’re not maping port 9000 out of the Swag container (only port 443 which is Https and port 80 which is http are mapped out) and not getting it to the right place anymore. Since port 9000 is not mapped out of the Swag container it will only exist locally within that container and not outside it, and even if you run portainer mapped to port 9000 on the host machine, you still should not have a conflict with this setting.

The specifics under 172.16.0.0/12 network would be different from one setup to another - depends on your environment and how you do your dockers or install types.

So maybe consider this?

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 127.0.0.1       # in case the reverse proxy being on the same IPv4 as the HA
    - ::1             # in case the reverse proxy being on the same IPv6 as the HA
    - 172.16.0.0/12   # in case the reverse proxy being under the same docker environment as the HA, and in case the docker IP would change after reboot/restart
    - xxx.xxx.xxx.xxx # specifying the IP of the reverse proxy, if none of the above applies

… and maybe one would need multiple lines under trusted_proxies: to work, depends on the setup.

Thanks @k8gg . So I never really payed attention to docker network settings before, but with the new requirement to add the IP address of the trusted proxy to Home Assistant’s config now it matters. If that trusted IP is wrong the reverse proxy will fail on the next release.

So here are my Docker network settings for all my containers:

And specifics for the Swag container

The 172.21.0.2 is what I had to add to my home assistant config as a trusted proxy which was specified in the swag_default network. This cleared any log warnings about the proxy. Based on your post, I assume these IP’s are going to be different for everyone depending on the number of containers/installation order or otherwise somehow specifying network settings in docker. My questions would be:
1- Will these IP’s randomly change for the containers if not “statically” set somehow - ie upon docker restart, other containers restarting, or deleting/adding the containers like after an image is updated?
2- If they might change, how should I set them up so the IP addresses/network settings stay the same all the time? Anything that I can just configure right through portainer?

Gents, i dont believe the solution is to widen the trusted_proxies: list. Seems counter intuitieve.
What I did was give the proxy (here swag) a static address like so:

    networks:
      mynet:
        ipv4_address: 172.10.0.10    # set up static ip to prevent HA blocking

Add that snipet to corresponding docker-compose entry, associated to a docker network I created with the following:

networks:
  mynet:  # set up static ip to prevent HA blocking
    driver: bridge
    driver_opts:
      com.docker.network.enable_ipv6: "false"
    ipam:
      driver: default
      config:
      - subnet: 172.10.0.0/24 # 

then add only this line:

  trusted_proxies:
  - 172.10.0.10 #as set up in docker-compose for Nginx/Letsencrypt
  - ::1
1 Like

Thanks @juan11perez . I was having some issues with trying to change the IP address to something new, thinking it’s probably browser and app caching issues of the old settings, or it was conflicting with something else. I ended up just specifying the IP address of 172.21.0.2 in the compose for the default swag network (which is what it was randomly given already) so it remains static and won’t change on me upon restarts/re-installs based on your post. Hopefully I’m not missing something here, but my whole compose if it helps:

version: "2.1"
services:
  swag:
    image: linuxserver/swag
    container_name: swag
    restart: unless-stopped
    cap_add:
    - NET_ADMIN
    volumes:
    - /home/tim/docker/swag/config:/config
    - /etc/localtime:/etc/localtime:ro
    environment:
    - PGID=1000
    - PUID=1000
    - [email protected]
    - URL=yourdomain.duckdns.org
    - SUBDOMAINS=wildcard
    - VALIDATION=duckdns
    - TZ=yourtimezone
    - DUCKDNSTOKEN=yourtoken
    - MAXMINDDB_LICENSE_KEY=yourkey #this is optional for location based IP banning
    ports:
    - "80:80"
    - "443:443"
    networks:
      default:
        ipv4_address: 172.21.0.2

Then these lines in my home assistant config

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 172.21.0.2

I left out ::1 since I’m not using IPV6 at all for anything, but may need to add that later

Hi all!
First of all thank @juan11perez for the great guide!
Unfortunately I’m facing some issues with setting this thing up.

I got the swag container running and I can acces the nginx main page from mydomain.duckdns.org.
But, when I try to access homeassistant by going to hass.mydomain.duckdns.org I’m getting a 504 Gateway Time-Out error…

This is my docker-compose setup -

version: '3'
services:
  homeassistant:
    container_name: hass
    image: homeassistant/home-assistant
    volumes:
      - ./hass-config:/config
      - /etc/localtime:/etc/localtime:ro
    restart: unless-stopped
    network_mode: host
    depends_on:
      - mariadb
      - mosquitto
  swag:
    image: linuxserver/swag
    container_name: swag
    restart: unless-stopped
    cap_add:
    - NET_ADMIN
    volumes:
    - /etc/localtime:/etc/localtime:ro
    - /home/pi/homeassistant/swag/config:/config
    environment:
    - PGID=${PGID}
    - PUID=${PUID}
    - [email protected]
    - URL=mydomain.duckdns.org
    - SUBDOMAINS=wildcard
    - VALIDATION=duckdns
    - TZ=Asia/XXXX
    - DUCKDNSTOKEN=XXXXX
    ports:
    - "80:80"
    - "443:443"
    networks:
      default:
        ipv4_address: 172.10.0.100

And this is my default nginx file -

## Version 2021/04/27 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/default

error_page 502 /502.html;
server_names_hash_bucket_size  64;

# redirect all traffic to https
server {
    listen 80;
    server_name mydomain.duckdns.org;
    return 301 https://$host$request_uri;
}

# main server block
server {
    listen 443 ssl default_server;

    root /config/www;
    index index.html index.htm index.php;

    server_name mydomain.duckdns.org;

    # enable subfolder method reverse proxy confs
    include /config/nginx/proxy-confs/*.subfolder.conf;

    # all ssl related config moved to ssl.conf
    include /config/nginx/ssl.conf;

    client_max_body_size 0;

    location / {
        try_files $uri $uri/ /index.html /index.php?$args =404;
    }

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
	    fastcgi_pass hostip:9000;
        #fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        include /etc/nginx/fastcgi_params;
    }

}
server {
	listen 443 ssl;

	root /config/www;
	index index.html index.htm index.php;

	server_name hass.mydomain.duckdns.org;

	include /config/nginx/ssl.conf;

	client_max_body_size 0;

	location / {
#		auth_basic "Restricted";
#		auth_basic_user_file /config/nginx/.htpasswd;
		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 "upgrade";
		proxy_buffering               off;
		proxy_ssl_verify              off;
#		include /config/nginx/proxy.conf;
		proxy_pass http://hostip:8123;
	}
}



# enable subdomain method reverse proxy confs
include /config/nginx/proxy-confs/*.subdomain.conf;
# enable proxy cache for auth
proxy_cache_path cache/ keys_zone=auth_cache:10m;


I also added the following in my home assistant config -

http:
  ip_ban_enabled: true
  login_attempts_threshold: 3
  use_x_forwarded_for: true
  base_url: hass.mydomain.duckdns.org
  trusted_proxies:
    - 192.168.31.0/24  # Local Lan
    - 172.10.0.0/24  # Docker network

What am I doing wrong?

Thanks :slight_smile:

not sure this is your problem, but base_url does not go under http. You need to remove that.

you probably need to add the following:

  internal_url: http://192.168.1.xx:8123 # introduced with HA 110.0
  external_url: hass.mydomain.duckdns.org

it goes under homeassistant

unfortunately it’s still not working… I think it’s something to do with swag…
home assistant is using network_mode = host while swag sits on the docker network…
maybe I didn’t set this up correctly and swag just can’t reach the host network?

this is the error I get in swag’s logs -

2021/07/08 15:49:42 [error] 502#502: *16 upstream timed out (110: Operation timed out) while connecting to upstream, client: 192.168.31.1, server: hass.mydomain.duckdns.org, request: "GET / HTTP/1.1", upstream: "http://192.168.31.5:8123/", host: "hass.mydomain.duckdns.org"

On this line in your nginx config towards the end to reference home assistant:

proxy_pass http://hostip:8123

Are you actually putting in the ip address of the host machine or leaving it “hostip”? You cannot reference it by “hostip” since Home-assistant runs in host network mode and swag doesn’t. In host mode, home assistant is not running on the same docker network as swag/nginx. If you have a container in bridge network mode (like swag) you can’t reference another docker container running in host network mode (like home assistant) by 127.0.0.1, localhost, hostip, or container name. You have to type out the whole ip of the host machine home assistant is running on, like

proxy_pass http://192.168.0.146:8123

Replacing with your machine’s ip on your lan of course.

If you are spelling out the IP and it still doesn’t work, are there any log errors when you startup swag?

Also, in Home assistant config, just try to reference the container’s IP itself and not the whole docker network. Not sure if it matters, but that’s how mine is setup and working with the new proxy block implemented in the 7.2021 release.

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 172.10.0.100

thanks @mwav3 for the reply…

I am using the full ip of home assistant (192.168…)
As for the logs when swag startsup, there are no errors there… and as I mentioned, I can indeed access the swag main page by going to mydomain.duckdns.org without the subdomain at the start.

Tried setting a constant ip in the http trusted_proxies section of home-assistant… still doesn’t work :confused:

Its probably just the default NGINX default conf file. A lot in what you posted looks different then mine. You can try mine if it helps. Just replace your “mydomain.duckdns.org” with your actual duckdns domain and the IP address under Home Assistant with your actual machine’s IP address. Leave all the other IP references alone as those are loopbacks within the Swag container itself (for fast CGI and resolver)

## Version 2020/05/23 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/default

# redirect all traffic to https
server {
	listen 80 default_server;
	listen [::]:80 default_server;
	server_name mydomain.duckdns.org;
	return 301 https://$host$request_uri;
}

# main server block
server {
	listen 443 ssl http2 default_server;
	listen [::]:443 ssl http2 default_server;

	root /config/www;
	index index.html index.htm index.php;

	server_name mydomain.duckdns.org;
	
	# enable subfolder method reverse proxy confs
	include /config/nginx/proxy-confs/*.subfolder.conf;

	# all ssl related config moved to ssl.conf
	include /config/nginx/ssl.conf;

	# enable for ldap auth
	#include /config/nginx/ldap.conf;

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

	# enable for geo blocking
	# See /config/nginx/geoip2.conf for more information.
	#if ($allowed_country = no) {
	#return 444;
	#}

	client_max_body_size 0;

	location / {
		try_files $uri $uri/ /index.html /index.php?$args =404;
	}

	location ~ \.php$ {
		fastcgi_split_path_info ^(.+\.php)(/.+)$;
		fastcgi_pass 127.0.0.1:9000;
		fastcgi_index index.php;
		include /etc/nginx/fastcgi_params;
	}


}


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

    server_name hass.*;
    
    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;

    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 /login;

        include /config/nginx/proxy.conf;
        resolver 127.0.0.11 valid=30s;
        set $upstream_app homeassistant;
        set $upstream_port 8123;
        set $upstream_proto http;
        proxy_pass http://192.168.0.184:8123;

    }

    location /api/websocket {
        resolver 127.0.0.11 valid=30s;
        set $upstream_app homeassistant;
        set $upstream_port 8123;
        set $upstream_proto http;
        proxy_pass http://192.168.0.184:8123;

        proxy_set_header Host $host;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
# enable subdomain method reverse proxy confs
include /config/nginx/proxy-confs/*.subdomain.conf;
# enable proxy cache for auth
proxy_cache_path cache/ keys_zone=auth_cache:10m;
1 Like

Does anyone have this working still in Home Assistant 2021.7? I’ve added the


http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 172.18.0.18:

To my config and it works in 2021.6.6 but not with 2021.7 I keep getting a 400 Bad Request. I’m guessing I need to tweak something in the NGINX now but after spending a few hours on it I’ve given up and just went back to 2021.6.6. Curious if any of you guys had to make any changes to keep it working going to 2021.7?

Yes it is working fine for me still with 2021.7. Take a look at my posts above with my docker compose, NGINX config, and home assistant config to see if you have any differences you need to change. The only thing that I had to add were the same lines you just posted to the home assistant config for http: settings to keep this working. It’s possible there was something else missing in your docker compose or NGINX config though that didn’t matter before but is creating a problem for you now.

1 Like

… actually I did get it to work with your config in NGINX Proxy Manager, I just put the entire locations in the Advanced section of the Proxy Host in Nginx Proxy Manager and then it came back online and was able to pass the traffic correctly. I was trying to just put the individual nginx variables at first. This is what I put in my Advanced section and it starting working again. Thanks for the quick confirmation that it works and for providing your example!

location / {
        set $upstream_app homeassistant;
        set $upstream_port 8123;
        set $upstream_proto http;
        proxy_pass http://192.168.1.104:8123;

    }

    location /api/websocket {
        set $upstream_app homeassistant;
        set $upstream_port 8123;
        set $upstream_proto http;
        proxy_pass http://192.168.1.104:8123;

        proxy_set_header Host $host;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
3 Likes

@mwav3 Still nothing…
I set up a new home assistant instance from scratch without all the other services I use to see if that’s the issue but I get the same results…

I used your docker-compose example and your swag config -

docker-compose -

version: '3'
services:
  homeassistant:
    container_name: hass
    image: homeassistant/home-assistant
    volumes:
      - ./hass-config:/config
      - /etc/localtime:/etc/localtime:ro
    restart: unless-stopped
    network_mode: host
  swag:
    image: linuxserver/swag
    container_name: swag
    restart: unless-stopped
    cap_add:
    - NET_ADMIN
    volumes:
    - ./swag/config:/config
    - /etc/localtime:/etc/localtime:ro
    environment:
    - PGID=1000
    - PUID=1000
    - [email protected]
    - URL=MYDOMAIN.duckdns.org
    - SUBDOMAINS=wildcard
    - VALIDATION=duckdns
    - TZ=yourtimezone
    - DUCKDNSTOKEN=MYTOKEN
    ports:
    - "80:80"
    - "443:443"
    networks:
      default:
        ipv4_address: 172.11.0.2

networks:
  default:  # set up static ip to prevent HA blocking
    driver: bridge
    driver_opts:
      com.docker.network.enable_ipv6: "false"
    ipam:
      driver: default
      config:
      - subnet: 172.11.0.0/24 # 

swag default -

## Version 2020/05/23 - Changelog: https://github.com/linuxserver/docker-swag/commits/master/root/defaults/default

# redirect all traffic to https
server {
	listen 80 default_server;
	listen [::]:80 default_server;
	server_name MYDOMAIN.duckdns.org;
	return 301 https://$host$request_uri;
}

# main server block
server {
	listen 443 ssl http2 default_server;
	listen [::]:443 ssl http2 default_server;

	root /config/www;
	index index.html index.htm index.php;

	server_name MYDOMAIN.duckdns.org;
	
	# enable subfolder method reverse proxy confs
	include /config/nginx/proxy-confs/*.subfolder.conf;

	# all ssl related config moved to ssl.conf
	include /config/nginx/ssl.conf;

	# enable for ldap auth
	#include /config/nginx/ldap.conf;

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

	# enable for geo blocking
	# See /config/nginx/geoip2.conf for more information.
	#if ($allowed_country = no) {
	#return 444;
	#}

	client_max_body_size 0;

	location / {
		try_files $uri $uri/ /index.html /index.php?$args =404;
	}

	location ~ \.php$ {
		fastcgi_split_path_info ^(.+\.php)(/.+)$;
		fastcgi_pass 127.0.0.1:9000;
		fastcgi_index index.php;
		include /etc/nginx/fastcgi_params;
	}


}


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

    server_name hass.*;
    
    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;

    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 /login;

        include /config/nginx/proxy.conf;
        resolver 127.0.0.11 valid=30s;
        set $upstream_app homeassistant;
        set $upstream_port 8123;
        set $upstream_proto http;
        proxy_pass http://192.168.31.5:8123;

    }

    location /api/websocket {
        resolver 127.0.0.11 valid=30s;
        set $upstream_app homeassistant;
        set $upstream_port 8123;
        set $upstream_proto http;
        proxy_pass http://192.168.31.5:8123;

        proxy_set_header Host $host;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
# enable subdomain method reverse proxy confs
include /config/nginx/proxy-confs/*.subdomain.conf;
# enable proxy cache for auth
proxy_cache_path cache/ keys_zone=auth_cache:10m;

homeassistant configuration.yaml -

# Configure a default setup of Home Assistant (frontend, api, etc)
default_config:

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 172.11.0.2

I also tried moving home-assistant into the docker network and not setting it with network_mode=host but still nothing =/