Remote access with Docker

EDIT: had a typo on port forwarding, wrote 433 and not 443 :man_facepalming:
After that I’ve used @maxime1992 solution to add the error address to trusted_proxies and it worked.

First of all, thanks for the guide!

I can’t seem to get it to work properly, but I feel like I am one step away…
In the SWAG logs I don’t see any errors.

Any advice on how to start and debugging my issue?

Port forwarding on router: 443 to 443. Protocol = TCP and UDP.

Something to start with maybe:
If I go to “mydomain.duckdns.org” from my local network I am reaching my router page, same behavior as if I go to 192.168.1.1.
My home assistant server sits on 192.168.1.133.

Thank you :slight_smile:

Hey guys, I can clarify a bit and actually give a better solution that what I said in my last post because it kept breaking from time to time.

Instead here’s what I’ve done.

In my docker-compose on the swag container I’ve added these lines at the end:

    networks:
      default:
        # fixing this IP address so that home assistant list of trusted proxies doesn't
        # need to be updated every time we recreate that container
        # https://community.home-assistant.io/t/nginx-reverse-proxy-set-up-guide-docker/54802/289?u=maxime1992
        ipv4_address: 172.10.0.10

and in my configuration.yaml here’s what I now have

http:
  ip_ban_enabled: true
  login_attempts_threshold: 5
  use_x_forwarded_for: true
  trusted_proxies:
    # local IP
    - 192.168.1.100
    # IP fixed for the swag docker container so that we don't have
    # to update it every time the swag container is rebuilt
    - 172.10.0.10

Please note the IP 172.10.0.10 is the same in both configs ofc.

I haven’t had any issue ever since I made that change :slight_smile:

1 Like

Great write up! I’ve gotten much farther with this than anything else I’ve played around with.

I have a similar issue. Trying all kinds of different variations of what’s written up here, but when I go to homeassistant.xxxxx.duckdns.org I get a “404 bad request”.

The HomeAssistant GUI is starting in safe mode and just showing the log when I login.

home-assistant.log shows all kinds of "setup failed for dependencies : " errors and the below message

“2022-11-11 17:57:51.505 ERROR (MainThread) [homeassistant.components.http.forwarded] A request from a reverse proxy was received from 172.10.0.2, but your HTTP integration is not set-up for reverse proxies”

I’m a newbie at all of this, so any help would be appreciated

http:
  use_x_forwarded_for: true
  trusted_proxies:
    - 172.30.0.0/16

Hi,

I’ve followed the steps outlined above but I’m running into some problems.

  • I’m running an ISP modem/router/AP combo in bridge modus to my router/firewall.
  • It seems the ISP device hands an IP of 192.168.178.185 to the WAN port of my router/firewall. According to the ISP, bridge modes disables firewall, portforwarding and everything. It should even expose the external WAN IP from the ISP to the router/firewall. But an 192.xx IP might indicate CGNAT.
  • checking whatismyip.com gives an external IPv4 IP which is not in private space. 94.xx.xx.xx
  • Port 80 and 443 have been forwarded in the router/firewall. Homeassistant is (locally) on 192.168.1.2.

I was able to compose swag and get it up and running, I’ll post the files below. It was able to communicate the external IP to DuckDNS, passing the external IP. Except connecting to homeassistant.[subdomain].duckdns.org leads to timeouts, not a HomeAssistant login page.

docker-compose.yaml

version: '3'
services:
  homeassistant:
    container_name: homeassistant
    image: "ghcr.io/home-assistant/home-assistant:stable"
    volumes:
      - /home/[user]/hass:/config
      - /etc/localtime:/etc/localtime:ro
    restart: unless-stopped
    privileged: true
    network_mode: host

  swag:
    image: ghcr.io/linuxserver/swag
    container_name: swag
    cap_add:
      - NET_ADMIN
    environment:
      - PUID=1001
      - PGID=1001
      - TZ=Europe/[region]
      - URL=[subdomain].duckdns.org
      - VALIDATION=duckdns
      - DUCKDNSTOKEN=[token]
      - SUBDOMAINS=wildcard
    volumes:
      - /home/[user]/swag:/config
    ports:
      - 443:443
      - 80:80
    restart: unless-stopped


# set trusted docker internal network
networks:
  default:
      ipam:  
        config: 
         - subnet: 172.10.0.0/24

hass/configuration.yaml

# Loads default set of integrations. Do not remove.
default_config:

homeassistant:
  auth_mfa_modules:

http:
  ip_ban_enabled: true
  login_attempts_threshold: 3
  use_x_forwarded_for: true
  trusted_proxies:
    - 192.168.1.0/24  #Local Lan
    - 172.10.0.0/24  #Docker network

duckdns: 
 domain: [subdomain **without .duckdns.org suffix**]
 access_token: [token]

# Text to speech
tts:
  - platform: google_translate

automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

running ip a gives a couple networking adapters, with docker0 on 172.17.0.1 and an br-d0758f95adee on 172.10.0.1.

homeassistant.subdomain.conf

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

    server_name homeassistant.*;

    include /config/nginx/ssl.conf;

    client_max_body_size 0;

    location / {
        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        set $upstream_app 192.168.1.2;
        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.1.2;
        set $upstream_port 8123;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;
    }
}

Interestingly though, I’ve installed Tailscale VPN in the mean time, and when I put the VPN IP-address(100.x) of my server in the browser of my phone, I get presented with the swag webpage!

It appears your nginx config is not properly setup for websockets which home assistant relies on to connect/stay open.

See my sample config here, the important thing to add I believe are these lines to “upgrade” the connection and keep websockets open.

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";
    }

Websocket config is explained more in this article

https://www.google.com/amp/s/www.nginx.com/blog/websocket-nginx/amp/

I will try this, thank you for the quick reply. I’ll definitively read out the websocket explanation.

Other than that I just found out my ISP modem/router is apparently not in bridge mode after all… I will fix this first before delving further in nginx. Although I’ve requested this more than a week ago at my ISPs customer service…

Try adding the config for reverse proxies posted by nikito7 to your home assistant default configuration.yaml file. Many older guides don’t mention this since the requirement to add that to the config was more recent in the June 2021 release

Hi mwav3,
Sorry to bother you again but I have replaced my nginx config within the swag docker with your version, making the mydomain.duckdns.org and local HA instance IP-address changes as required. Restarted the container or even the machine.

I’ve also had the ISP finally put the modem in bridge mode, which took 2 phone calls before they finally did it.
I feel like I have done everything as they were described in the guide above and your comment(s), but it doesn’t work…

  • I can access the HA login page on my phone through 4G on homeassistant.[subdomain].duckdns.org and [subdomain].duckdns.org

  • adding a https:// prefix only leads to “… can’t find server” errors

  • When on the local network, I can go to https://[Local IP of HA], which presents the landing page of SWAG.

  • I cannot go however to https://[Local IP of HA]:8123 and use HA locally with HTTPS, leading to another “… can’t find server” error.

Could you please help me? Thanks so much in advance!

Go into you nginx default conf file and be sure that any http connection coming in on port 80 is automatically upgraded to https on port 443. The following lines should be in the file uncommented

# 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;
}

This should make any connection work and be secure https regardless of whether it starts with http, https, or you don’t specify either.

That’s what should happen. Swag is running on port 443 which is your https connection, so it will just go to swag, not home assistant. To use swag as a reverse proxy on the local lan requires more configuration I’m not familiar with. I only use swag for external connections, and not internally

That is expected. Swag only runs on ports 80 and 443. Anytime you’re on the lan and specify a different port, the connection isn’t going through swag and won’t go to https. Ie specifying the :8123 will go direct to home assistant and bypass swag. I don’t use https to access Home Assistant on the local network (just http), and not sure how you can configure that. Putting home assistant behind ssl on the local lan will probably block many local integrations from working properly.

I’ve not omitted any part of your nginx configuration, and the server{} section is definitively in the config file, uncommented and with the required changes made…

I’ve dropped into the docker shell and ran nginx -t which was recommended to me by somebody else, and it returned:

root@[docker id]:/config/nginx# nginx -t
nginx: [emerg] "server" directive is not allowed here in /config/nginx/nginx.conf:4
nginx: configuration file /etc/nginx/nginx.conf test failed

Perhaps this could help in finding out where the problem is.

I have little to no desire to run https on HA locally, I was only trying to give a complete insight in the experienced behavior of HA and swag right now to give complete information in order to solve the problem :+1:

There’s definitely a problem with the nginx config based on that command.

I looked into the configs further and it appears there were recent updates to the default nginx configs in swag in the September release, so that could be causing some conflicts with the original post and my config I gave you earlier.

If you are going to use the homeassistant.subdomain.conf.sample file, nginx configs are spread across multiple files (default.conf, nginx.conf, proxy.conf, ssl.conf, and homeassistant.subdomain.conf) and a problem with any of these will cause an issue. Because it becomes difficult to track the config across multiple files, I followed the advice in this guide, Nginx Reverse Proxy Set Up Guide – Docker and my whole config is in the default.conf file, and I just make changes there, and don’t use the homeassistant.subdomain.conf file.

If you don’t go the route in that guide to put everything in one config, and since I don’t know where the issue is on your config, what you can try doing is restore the default configs. To do that, backup everything, stop swag, and delete any of the changed files in the volume (default.conf, nginx.conf, proxy.conf, ssl.conf, and homeassistant.subdomain.conf). Restarting swag will then restore these config files back to the default ones. Then try to change the name of homeassistant.subdmain.conf.sample to drop the .sample, and see if that works.

You also need to replace the line

set $upstream_app homeassistant;

With

set $upstream_app 192.168.XX.XXX;

Using the ip of the machine running home assistant. Since Home Assistant is in host networking mode, it can’t be reached on the docker network by container name and you need to spell out the ip

I’ve spent another entire day on it, and it seems like I’m making progress.
I just nuked swag (a couple times) and found out what (some) of my initial faults were.

Firstly, I had forwarded 80 and 443… to port 8123, which should have been 80 to 80 and 443 to 443, something that wasn’t clear in some of the posted guides. This caused the LetsEncrypt certification validation to fail; the LetsEncrypt servers couldn’t connect to port 80 and verify ownership of the domain, which in turn I suspect caused problems with nginx. Okay, so with that fixed, I was quickly able to reach the SWAG page with HTTPS enabled from the WAN. After that I changing the required variables in nginx.conf and homeassistant.subdomain.conf, just as the linked Nginx Reverse Proxy Guide dictates. Doing it all in one file makes it a bit more difficult for me and my limited knowledge I think, so I just followed what was dictated there.

I did another check with docker exec + nginx -t and it reported “test successful”.
I was able to reach the home assistant login page with HTTPS on homeassistant.[subdomain].duckdns.org on my phone from the WAN without any problems.

Then I had some problems with the iOS app not wanting to accepting the LetsEncrypt certificate when changing the “external URL” field in settings. I removed the whole server and re-added it, which seemed to fix it! It did gave me a couple warnings about the certificate containing errors, something about the SSL-hostname not matching the name(s) in the certificate. I don’t know if that happens to everyone using letsencrypt, or if still messed up somewhere. But it works now!

I still have to set-up push notifications, which was the whole reason I went down this path. And I still have to setup cert renewal somewhere/somehow, but that’s for another weekend. Thanks for your support so far! I am very grateful.

I have an IOS phone and haven’t received this warning, did it only come up at the initial setup or is it something you are seeing continuously? It’s possible that because you are using a wildcard cert that its not seeing an “exact” match between the website and certificate and sending out an error. It sounds like you are able to get through it though and get everything working though, so I doubt there is any issue with the config on your end.

Also glad you were able to confirm using the homeassistant.subdomain.conf file still works.

1 Like

hi,
I have no knowledge of qnap.
I assume you can ssh into the system ok but are having difficulty creating the docker-compose.yml file. What text editor qnap has (vim, nano,…) I don’t know.
But in any case trying to create the file using eg nano is a nightmare unless you are a unix enthusiast.
I use my android phone to connect and create the file. The file manager program CXExplorer ( free from playstore) can establish a SFTP network connection (port 21) that allows you to browse the remote file system thru SSH.
Where you create the file isn’t critical , but run the docker-compose command from the directory you created it in.
Hope that helps

hi thanks for the reply. I found the folder and compiled the file with nototepad++ based on the .yml on the first post and put it in the folder. I ran the docker-compose config command to validate and view the file and it seems to return no errors (first it gave an error for bad indentation). however still there are steps that elude me… the folders mentioned on the first post /home/user/volumes/hass and
/home/user/volumes/swag
do i have to create them manually?

yes, create them manually. Docker will create them if they dont exist, but then you will have permission problems as docker owns thrm, noy you

I tried the docker-compose command without creating the folders but nothing happened and nothing was created! I think I’m doing something wrong but I don’t know what I’m doing wrong.

I just wanted to say thanks a lot!
its working had to adjust the docker network but it is working!

Thanks for the info.
Could you let me know what change you made for the network.
I have recently installed another system and found that I didn’t need the network. ( My other system is not ‘usual’, running PostmarketOS on a old Nexus5 )
Maybe my guide could do with an update