Remote access with SWAG
Edit Dec 2023
Following a move to new hardware, I have updated this post to, hopefully, make things clearer and take into consideration everybody’s comments and difficulties. Many thanks to mwav3-Tim for his brillant support.
Introduction
The Home assistant support team sensibly recommend you use a dedicated system. This simplifies support, but limits your possibility to run other stuff. Many people run Home Assistant using docker but getting remote access seemed to me to be a nightmare.
But there is very simple way to get everything done, including Letsencrypt, NGINX, certificate renewal, duckdns, security etc.
It is a docker package called SWAG and it includes a sample home assistant configuration file that only needs a minor tweak.
A basic understanding of Docker is presumed and that Docker-Compose is installed on your machine.
The configuration is minimal so you can get a test system working very quickly. After that, it should be easy to modify your existing configuration.
Rather than upset your production system, I suggest you create a test directory and data volumes;
mkdir ~/swagtest
mkdir ~/swagtest/hass
mkdir ~/swagtest/swag
I have found it simpler to first get the basic system running to test and understand a little what we have. Then we’ll add Home Assistant.
You’ll need shut down your production system ( eg docker-compose down) while testing. Check with docker ps
Port Forwarding
Set up a static ip address for your home assistant machine on your router. Where you see 192.168.X.XXX in the snippets below , change it to your static address.
Forward port 443 through your router to your home assistant server port 443. No need to forward ports 80 or 8123.
DuckDNS
Set up a Duckdns account. This is simple and fully explained on their web site. Keep a record of “your-domain” and “your-access-token”.
docker-compose.yml
Create a docker-compose.yml configuration file as show below for the basic SWAG.
Since docker creates some files as root, you will need your PUID & GUID ( just use the Unix command ‘id’ to find these). The #! indicates change required ( eg your duckdns info ).
version: "3"
services:
swag:
image: ghcr.io/linuxserver/swag
container_name: swag
cap_add:
- NET_ADMIN
environment:
- PUID=1001 #!
- PGID=1001 #!
- TZ=Europe/Paris #!
- URL=YOUR-DOMAIN.duckdns.org #!
- VALIDATION=duckdns
- DUCKDNSTOKEN=YOUR-TOKEN #!
- SUBDOMAINS=wildcard
volumes:
- ~/swagtest/swag:/config #!
ports:
- 443:443
restart: unless-stopped
SWAG first run
To set up SWAG, run
docker-compose up swag
This will download the swag image, create the swag volume, unpack and set up the default configuration. It will take some time to generate the certificates etc.
If all goes well, it should end with
swag | [services.d] starting services |
swag | [services.d] done. |
swag | Server ready. |
Test external access
SWAG has set up a little test web page, you should be able to access it externally (eg on a phone, turn off wifi and use phone network) by typing it’s address into your web browser: https:\www.YOUR-DOMAIN.duckdns.org
If that works, good; certificates, duckdns renewal, port forwarding etc are good to go. If not, check everything for typos. This works for me and others, it should work for you unless you have a weird setup.
If you get warnings about the site being unsafe, I think this is caused by Let’s Encrypt throttling multiple unsuccessful attempts to validate. Wait a while, warnings should go away.
Shut down the SWAG docker dialog gracefully using ctrl-C
Set up Home assistant
Now we want to include home assistant.
There are a couple of things that need to be done.
1) Tell SWAG we want to use home assistant. 2) Tell SWAG the ip address of the home assistant server. 3) Update the docker-compose.yml file to include home assistant and establish a docker network that home assistant can trust. 4) In the home assistant configuration, tell it to accept traffic forwarded to it by SWAG and set up simple ip bans.
1) Activate Home Assistant
SWAG contains lots of pre-configured example configuration files, including for home assistant.
In the directory ~/swagtest/swag/nginx/proxy-confs/ , make a copy of ‘homeassistant.subdomain.conf.sample` and rename it to ‘homeassistant.subdomain.conf’
2) Home assistant IP address
Usually, docker sets up its own network and can connect to the home assistant container. But homeassistant must use mode ‘host’ to connect to everything. So the configuration file needs to be given the static IP address of your server .
So the ip address needs to be entered in the file ‘/home/user/test/volumes/swag/nginx/proxy-confs/homeassistant.subdomain.conf’. The two lines set $upstream_app homeassistant; need to be changed to your static host address set $upstream_app 192.168.X.XXX;
The two lines are a bit difficult to find. This is the homeassistant.subdomain.conf file (with all # comments removed for clarity)
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.XX.XXX;
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.XX.XXX;
set $upstream_port 8123;
set $upstream_proto http;
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
}
}
3) Update docker-compose.yml
In the docker-compose.yml file, we need to specify a docker network so home assistant knows what to trust and add the normal home assistant service.
version: '3'
# Set the default docker network to have a known range so it can be trusted by home assistant.
networks:
default:
ipam:
config:
- subnet: 172.10.0.0/24
services:
hass:
container_name: hass
image: homeassistant/home-assistant
volumes:
- ~/swagtest/hass:/config # Change this
- /etc/localtime:/etc/localtime:ro
# Note: Port mapping is no longer valid with network_mode host
# ports:
# - 8123:8123
network_mode: host
restart: unless-stopped
swag:
image: ghcr.io/linuxserver/swag
container_name: swag
cap_add:
- NET_ADMIN
environment:
- PUID=1001 # Change this
- PGID=1001 # Change this
- TZ=Europe/Paris
- URL=YOUR-DOMAIN.duckdns.org # Change this
- VALIDATION=duckdns
- DUCKDNSTOKEN=YOUR-TOKEN # Change this
- SUBDOMAINS=wildcard
volumes:
- /home/USER/volumes/swag:/config # Change this
ports:
- 443:443
restart: unless-stoppeda
Start home assistant to generate the initial configuration for the test
docker-compose up hass
When everything is finished, shut down using crtl-C.
4) Home assistant configuration
Add the following to you home assistant config.yaml ( ~/swagtest/hass/configuration.yaml).
http: ip_ban_enabled: true login_attempts_threshold: 3 use_x_forwarded_for: true trusted_proxies: - 192.168.X.0/24 # Local Lan - 172.10.0.0/24 # Docker network
Finally-Test it is working
Launch homeassistant and swag
docker-compose up -d
Wait a little.
Then, use your browser to logon from your local network 192.168.X.XXX:8123 and you should get your normal home assistant login.
Finally, use your browser to logon from outside your home https://homeassistant.YOUR-SUB-DOMAIN.duckdns.org
Note: unless your router supports ’loopback’ ( and mine didn’t) you might not be able to connect; in that case use a telephone ( or tor browser) rather than your local LAN connection.
That’s it. You have remote access to home assistant.