IIS Reverse Proxy to Hyper-V Hosted HA Server

Here’s what I have:

  1. Windows Server 2016 running a bunch of services
  2. Hyper-V running a backup pi-hole and a few other VMs
  3. Dynamic hostname management through IIS
  4. A Netgear Nighthawk and a good internet connection

Here’s what I did:

  • Downloaded the HA VHDX image and got it installed
  • Created the virtual machine and assigned it a static ip address
  • Logged in, accessed the server, confirmed all seems good, enabled advanced configuration
  • Set the External URL to https://my.domain.com/ha
  • Set the Internal URL to http://ip.ad.dre.ss:8123/
  • Installed web sockets and AAR on Windows Server
  • Added a reverse proxy rewrite rule to web.config
  • Tested access - which failed

Here’s my web.config section:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <clear />
                <rule name="ReverseProxyInboundRuleHomeAssistant" stopProcessing="true">
                    <match url="ha(/)?(.*)" />
                    <action type="Rewrite" url="http://ip.add.re.ss:8123/{R:1}" appendQueryString="true" />
					<conditions>
                        <add input="{CACHE_URL}" pattern="^(.+)://" />
					</conditions>
 					<serverVariables>
                        <set name="HTTP_SEC_WEBSOCKET_EXTENSIONS" value="" />
 					</serverVariables>
                </rule>
            </rules>
            <outboundRules>
                <rule name="ReverseProxyOutboundRuleHomeAssistant" preCondition="ResponseIsHtml1">
                    <match filterByTags="A, Form, Img" pattern="^http://ip.add.re.ss:8123/(.*)" />
                    <action type="Rewrite" value="https://my.domain.com/ha/{R:1}" />
                </rule>
                <preConditions>
                    <preCondition name="ResponseIsHtml1">
                        <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/(.+)" />
                    </preCondition>
            </outboundRules>
        </rewrite>
	<security>
		<requestFiltering>
			<requestLimits maxQueryString="32768" />
		</requestFiltering>
	</security>
    </system.webServer>
</configuration>

As you can see, I’ve cleared the web socket extensions and made sure the forwarded for information is included. I even tried to manage the cache url too. I’ve done some digging on this.

With this configuration, if I go to https://my.domain.com/ha or https://my.domain.com/ha/ I get “Unable to connect to Home Assistant.” with a retry link. If I am on my local network and go to http://ip.add.re.ss:8123/ I am able to access Home Assistant.

So, based on the fact that I have many other services successfully served up on my server with internet information services, does anyone have and tips on how to access homeassistant through IIS?

Here are my new rules:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <clear />
                <rule name="InboundRuleHomeAssistant" enabled="true" stopProcessing="true">
                    <match url="(homeassistant)(.*)" />
                    <action type="Rewrite" url="http://my.ip.add.ress:8123{R:2}" appendQueryString="true" logRewrittenUrl="true" />
 					<serverVariables>
                        <set name="HTTP_SEC_WEBSOCKET_EXTENSIONS" value="" />
 					</serverVariables>
                </rule>
            </rules>
            <outboundRules>
				<rule name="Restore Encoding" preCondition="Restore HTTP_ACCEPT_ENCODING">
					<match serverVariable="HTTP_ACCEPT_ENCODING" pattern="^(.+)" />
					<conditions logicalGrouping="MatchAll" trackAllCaptures="true" />
					<action type="Rewrite" value="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" />
				</rule>
                <rule name="OutboundRuleHomeAssistant" preCondition="ResponseIsHtml1">
                    <match filterByTags="None" pattern="http://my.ip.add.ress:8123/(.*)" />
                    <action type="Rewrite" value="https://my.domain.com/homeassistant/{R:1}" />
                </rule>
                <preConditions>
                    <preCondition name="ResponseIsHtml1">
                        <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/*" />
                    </preCondition>
                    <preCondition name="Restore HTTP_ACCEPT_ENCODING">
                        <add input="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" pattern=".+" />
                    </preCondition>
                </preConditions>
            </outboundRules>
        </rewrite>
 		<webSocket pingInterval="00:00:20" enabled="true" receiveBufferLimit="4194303" />
 		<staticContent>
 			<mimeMap fileExtension="." mimeType="text/plain" />
 		</staticContent>
		<security>
			<requestFiltering>
				<requestLimits maxQueryString="32768" />
			</requestFiltering>
		</security>
        <tracing>
            <traceFailedRequests>
                <add path="*">
                    <traceAreas>
                        <add provider="WWW Server" areas="Rewrite" verbosity="Verbose" />
                    </traceAreas>
                    <failureDefinitions timeTaken="00:00:00" statusCodes="200-399" />
                </add>
            </traceFailedRequests>
        </tracing>
		<httpErrors errorMode="Detailed" />
		<asp scriptErrorSentToBrowser="true" />
	</system.webServer>
	<system.web>
		<customErrors mode="Off" />
		<compilation debug="true" />
	</system.web>
</configuration>

This configuration lives in C:\inetpub\wwwroot\web.config alongside similar rules for other sub-sites.

When I use https://my.domain.com/homeassistant I get a blank page in the Home Assistant colours, and view source shows me that the server has responded with values - they’re just not being displayed.

When I use https://my.domain.com/homeassistant/ (with a trailing slash) I get a “this site cannot be reached” error.

Can anyone assist?