I’ve just spent the best part of a day getting HomeAssistant on a Raspberry Pi to work behind an IIS ARR reverse proxy server. This involved pulling together information from a variety of posts here and elsewhere (thanks to all those who have been here before). Few people will have the same setup as me, but if you’ve got HA running on a Pi and you have a Windows server hanging around too, then you might find this step-by-step useful.
Background
I host a few public websites on a Windows 2019 IIS server, so my router forwards ports 80 and 443 to that server. But HomeAssistant is running on a separate Raspberry Pi, so I had to use a different port number to send traffic to the Pi. Having a reverse proxy on the IIS server avoids this because initially all traffic goes to IIS, and ARR then reroutes HA traffic to the Pi.
I have a domain registered (let’s call it mydomain.com) and I added subdomain ha.mydomain.com for HomeAssistant.
I have an SSL certificate for *.mydomain.com, so that already secures traffic to the IIS server. Another advantage of the reverse proxy is that once within my network, HTTPS is no longer necessary; so the final leg, from the IIS server to HA on the Raspberry Pi, can be simple HTTP, thus saving the need to configure SSL in HA.
Installation steps.
Set up a public DNS A record to point ha.mydomain.com to your router’s external IP address. ON your router, make sure all traffic on ports 80 and 443 is port forwarded to your Windows IIS server.
On the Windows server, install IIS if not already done, and also install the following IIS addons:
- URL Rewrite
- Application Request Routing (ARR)
- Websocket protocol
URL Rewrite and ARR can be installed from here: Application Request Routing : The Official Microsoft IIS Site
The Websocket protocol is a Windows installation option: under Add Roles and Features, go to Server Roles, expand Web Server (IIS), then Application Development, and you’ll see it near the bottom of the list. More here: WebSocket <webSocket> | Microsoft Learn
Configuration of the IIS server
On your Windows server, open IIS, click the top-level entry for the server, and open Application Request Routing. Check Click Server Proxy Settings, and then:
- check Enable proxy.
- under Custom Headers, make sure X-Forwarded-For is entered under Preserve client IP …
- uncheck Include TCP port from client IP
Apply these changes.
Now go to the Default Web Site, and add bindings for ha.mydomain.com for http (port 80) and https (port 443).
For https you will of course need an SSL certificate for *.mydomain.com. You can use a self-signed certificate if you don’t mind the browser errors, or you can buy one for about £5 a year if you shop around. Or (as in my case) your domain registrar may provide one for free, or you can use LetsEncrypt. Once you’ve got your certificate (.pfx format for IIS) install it in IIS (instructions for that are a bit beyond my scope here but are easily found elsewhere). Then make sure you select it for the https binding on your Default Web Site in IIS.
In Default Website on IIS, open URL Rewrite. On the right hand side click View Server Variables, then Add, and add this variable:
HTTP_SEC_WEBSOCKET_EXTENSIONS
Apply that change, then click Add Rules and select a blank rule. Give it a name (e.g. “HomeAssistant redirect to Raspberry Pi”), and then type any old rubbish in the Pattern field under Match URL, and more rubbish in Rewrite URL under Action. This is just to get IIS to create a web.config file if it doesn’t already exist, and to insert the necessary code framework in that file. We will then edit the file directly.
In Explorer, find web.config in your default web site folder (normally c:\inetpub\wwwroot). Open it and replace the URL Rewrite rule entry with this:
<rule name="HomeAssistant redirect to Raspberry Pi" stopProcessing="true">
<match url=".*" />
<conditions>
<add input="{HTTP_HOST}" pattern="^ha\.mydomain\.com" />
</conditions>
<serverVariables>
<set name="HTTP_SEC_WEBSOCKET_EXTENSIONS" value="" />
</serverVariables>
<action type="Rewrite" url="http://X.X.X.X:8123/{R:0}" />
</rule>
Obviously, substitute your domain for mydomain.com (the backslash is required because a period in a regex means “any character”); and substitute the actual local IP address of your Raspberry Pi (or whatever is running HA) for X.X.X.X. This assumes that you’re still running HA on the default 8123 port.
Note that (contrary to what is said in some posts) it is not necessary to have a separate rewrite rule to switch from https to http. The rule above will pick up all traffic to ha.mydomain.com, both http and https, and will forward it to the HA server under HTTP.
If you would like to force all external HA traffic to be under https (recommended), then you can add the following rule before the one above:
<rule name="HTTPS Redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="^OFF$" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" appendQueryString="false" />
</rule>
It’s worth noting here the difference between action type=Rewrite and type=Redirect. The latter causes a response to go back to the user’s browser to instruct it to resubmit the request on the redirected URL (i.e. under https); whereas the former just forwards the request to the new address without telling the browser it has done it - so the browser address bar still contains the ha.mydomain.com URL, not the rewrittten one.
Configuration of the HA server
This bit is easy. Open configuration.yaml and add the following:
http:
use_x_forwarded_for: true
trusted_proxies:
- Y.Y.Y.Y
- 127.0.0.1
where Y.Y.Y.Y is the IP address of your Windows IIS server.
Reboot the HA machine and restart IIS on the Windows machine.
And that’s it. You should now be able to go to https://ha.mydomain.com (and/or http://mydomain.com) and have HA appear.
Good luck!