[SOLVED] Serve HA via Apache questions

I have dynamic DNS (I’ll call it dyndns.com in any URLs I discuss) and an Apache server. In Apache I have redirected port 80 to 443 (with SSL configured for Apache). I have a few aliases so I can serve several private websites as https://subdom.dyndns.com/website1 or https://subdom.dyndns.com/website2. One constraint I have is that my ISP blocks incoming port 80 requests, and my workplace blocks all outgoing requests on non-standard ports. So from work, using https on port 443 is pretty much my only option.

I have recently installed HA and it is working fine. I can access it as http://localhost:8123 from home and remotely everywhere except at work I can access it as http://subdom.dyndns.com:8123. But based on my above constraint, this will not work for me when I am at work.

So I would like to access HA through Apache on 443. I tried Apache Proxy but it did not work for me. I actually don’t understand how it works to add “home” in front of my domain name the way the tutorial is written. But the result is that the request doesn’t even make it to my server. I tried to figure out how to use a alias or virtual server in such a way that https://subdom.dyndns.com/hass would redirect to localhost:8123 but I am failing at this and just getting myself more and more confused.

So I would welcome any advice on how to achieve this, or perhaps offer other ways to achieve the same end goal. I thank you in advance.

1 Like

This is not supported by Home Assistant. It only works at the base of a domain. So you can do abc.example.com or xyz.abc.example.com, but you can’t append anything after that. Virtual hosts / aliases are supported here. But the part after the / is not an alias anymore. It’s a specific resource at the given host.

Normally you can’t just add a prefix to your domain name; you can only do this if you had access to the name server configuration.

One way to achieve this is to get your own domain name through a web hoster which allows you to make DNS configurations for your domain name. You could then configure a CNAME entry that points to your existing DynDNS name. And in Apache you would add a virtualhost configuration for the new domain name proxying to HA.

So, I do have my own domain name via Google Domains. And I was using subdomain forwarding to try to get this to work. But based on your response I should be using a CNAME. I have been trying to solve this through Apache but maybe it is my Google Domains configuration that I need to work on. I still don’t fully understand how all these pieces fit together but I will start looking at this from a different angle now.

I have a different provider for my domain, but maybe it helps you to get set if I describe how it can be done.

At my provider I have mydomain.com. Below that I have a subdomain primary.mydomain.com. This subdomain gets updated by my modem on every reconnect to point to the current IP address I have at home.
Additionally I have a subdomain homeassistant.mydomain.com. This one is configured as a CNAME that points to primary.mydomain.com. As a result both of these fqdns return my home-IP when doin a DNS lookup.

In my Apache I then use the following config:

<VirtualHost *:443>
        ServerName primary.mydomain.com

        ServerAdmin [email protected]
        DocumentRoot /var/www/html

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log WithHost

        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>
        <Directory /var/www/html/>
                Options Indexes FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
        </Directory>
        SSLCertificateFile /etc/ssl/certs/mycert.pem
        SSLCertificateKeyFile /etc/ssl/private/mykey.key
</VirtualHost>
<VirtualHost *:443>
        ServerName homeassistant.mydomain.com
        ServerAdmin [email protected]

        SSLProxyEngine on
        SSLCertificateFile /etc/ssl/certs/mycert.pem
        SSLCertificateKeyFile /etc/ssl/private/mykey.key

        ProxyPreserveHost On
        ProxyRequests off
        ProxyPass / https://192.168.1.123:8123
        ProxyPassReverse / https://192.168.1.123:8123
        ProxyPass /api/websocket wss://192.168.1.123:8123/api/websocket
        ProxyPassReverse /api/websocket wss://192.168.1.123:8123/api/websocket

        RewriteEngine on
        RewriteCond %{HTTP:Upgrade} =websocket [NC]
        RewriteRule /(.*)  wss://192.168.1.123:8123/$1 [P,l]
        RewriteCond %{HTTP:Upgrade} !=websocket [NC]
        RewriteRule /(.*)  https://192.168.1.123:8123/$1 [P,l]

        ErrorLog ${APACHE_LOG_DIR}/hassbian_ssl_error.log
        CustomLog ${APACHE_LOG_DIR}/hassbian_ssl_access.log WithHost
</VirtualHost>

With this setup I can browse to primary.mydomain.com or directly the IP and get the content in /var/www/html. If instead I browse to homeassistant.mydomain.com, I get the HASS frontend.
In case it is relevant: my HASS is configured with SSL as well, and I use a wildcard certificate to cover all possible subdomains.

Once this is working you should definitely have a look at fail2ban and maybe also modSecurity. I use both because I’m paranoid. :smiley:

1 Like

@danielperna84, thank you for your reply. I was making a lot of mistakes, many I have now corrected, but I am still not there yet.

I created a CNAME for hass.mydomain.com and created a simple virtual host for apache to match ServerName hass.mydomain.com. I gave it a different DocumentRoot and serve a unique index.html out of it so I can now prove that my CNAME records are working and Apache is correctly matching server names such that I get the expected pages if browsing to mydomain.com or hass.mydomain.com (or any other subdom.mydomain.com that I set up to play around).

However, I still cannot get the Apache to proxy to the HA websocket.

At first I tried this VIrtual Host config:

   <VirtualHost *:80>
        ServerAdmin webmaster@localhost
        ServerName hass.mydomain.com

        ProxyPreserveHost On
        ProxyRequests off
        ProxyPass /api/websocket ws://localhost:8123/api/websocket
        ProxyPassReverse /api/websocket ws://localhost:8123/api/websocket
        ProxyPass / http://localhost:8123/
        ProxyPassReverse / http://localhost:8123/

        RewriteEngine on
        RewriteCond %{HTTP:Upgrade} =websocket [NC]
        RewriteRule /(.*)  ws://localhost:8123/$1 [P,L]
        RewriteCond %{HTTP:Upgrade} !=websocket [NC]
        RewriteRule /(.*)  http://localhost:8123/$1 [P,L]

</VirtualHost>

The above was exactly what is shown in the HA documents for a Apache proxy I noted in my earlier post. But I see you are doing it slightly differently so I tried to emulate yours more closely:

<VirtualHost *:80>
        ServerAdmin webmaster@localhost
        ServerName hass.mydomain.com

        ProxyPreserveHost On
        ProxyRequests off
        ProxyPass / http://192.168.1.81:8123
        ProxyPassReverse / http://192.168.1.81:8123
        ProxyPass /api/websocket ws://192.168.1.81:8123/api/websocket
        ProxyPassReverse /api/websocket ws://192.168.1.81:8123/api/websocket

        RewriteEngine on
        RewriteCond %{HTTP:Upgrade} =websocket [NC]
        RewriteRule /(.*)  ws://192.168.1.81:8123/$1 [P,L]
        RewriteCond %{HTTP:Upgrade} !=websocket [NC]
        RewriteRule /(.*)  http://192.168.1.81:8123/$1 [P,L]

</VirtualHost>

In both cases it fails and I get a 500 Internal Server error. FWIW, I did play around with the ServerAdmin value so I could confirm on the browser’s 500 error page that Apache was still correctly matching the virtual host to hass.mydomain.com.

Any thoughts on how I might proceed to further troubleshoot this. I am now going to start looking for logs, but I don’t really know what logs to target so this may take a while.

BTW, I certainly intend to use SSL and Fail2ban but for now just trying to get this proxy thing sorted out before I add those complexities.

I appreciate the help very much. Thank you.

EDIT: I have found the following in the Apache error.log:
No protocol handler was valid for the URL /. If you are using a DSO version of mod_proxy, make sure the proxy submodules are included in the configuration using LoadModule.

And

No protocol handler was valid for the URL /favicon.ico. If you are using a DSO version of mod_proxy, make sure the proxy submodules are included in the configuration using LoadModule

But I am not too sure what to make of this. I don’t know what /favicon.ico is. And proxy_wstunnel.load us in my mods-enabled folder (running Debian flavor Linux) so it looks good. Not sure how to figure out what other module is missing

SOLVED!

It turns out the last missing piece to the puzzle was that I needed the module proxy_http.

Now it is working and I can move on to the next challenge: SSL (which I have done for several other websites so hopefully this will go well).

I huge thank you to everyone who offered their help to me. Great community!!!

Did you manage to figure out the SSL piece of the puzzle?

I did. I ended up using Let’s Encrypt to get a 3rd party signed cert (eliminates browser warnings under most circumstances but I would recommend starting with just using a self-signed cert as first step). I assume from your question that you are trying to get your SSL working. I don’t really recall any issues getting that working for me (once I got past the original issues proxying HA through Apache). But I will try to help if you have any specific questions.

So, it turns out I had to create the virtual server on my Virtualmin box first, then set-up a reverse proxy, then copy the contents of the cert files to the pem files in HA manually. After doing that, everything seems to be working.

Hi,
Could you share your latest working reverse proxy (virtualhost config) with let’s encrypt SSL for your Hassio? I can make it work for all my other subdomains, but not for Hassio. Latest, when entering url https://hassio.bthofen.com, it displayed the login screen, entering correct login/pass, it tried to display my lovelace for a short moment, but then died.
Thank you.
ps. FYI, I used to use duckdns plugin and it worked fine until lately I have my own domain name and installed a new let’s encrypt certificate for my new domain; then duckdns no longer works. I therefore want to use Apache reverse proxy with my own subdomain instead.
Platform: minipc, ubuntu 18.04, Apache, Hassio

Update: Solved now. I have to enable proxy_wstunnel apache component too.
sudo a2enmod proxy_wstunnel

My latest working config:

<VirtualHost *:443>
        ServerAdmin [email protected]
        ServerName hassio.bthofen.com

        ProxyPreserveHost On
        ProxyRequests off
        ProxyPass / http://192.168.2.xxx:8123
        ProxyPassReverse / http://192.168.2.xxx:8123
        ProxyPass /api/websocket ws://192.168.2.xxx:8123/api/websocket
        ProxyPassReverse /api/websocket ws://192.168.2.xxx:8123/api/websocket

        RewriteEngine on
        RewriteCond %{HTTP:Upgrade} =websocket [NC]
        RewriteRule /(.*)  ws://192.168.2.xxx:8123/$1 [P,L]
        RewriteCond %{HTTP:Upgrade} !=websocket [NC]
        RewriteRule /(.*)  http://192.168.2.xxx:8123/$1 [P,L]
</VirtualHost>
1 Like

Hi,

I have now been following along a bunch of tutorials on how to setup apache reverse proxy for HA. I have not succeeded with any config and was hoping to get some help from you, the experts, as you have got it running.

My setup is as follows:
I have home assistant installed on my ubuntu server running in a docker container. I have a reverser proxy configuration using apache2. This is all working. I can access my websites, services and home assistant from my local network (home assistant via ip and port). I can also access everything EXCEPT home assistant from outside the network.
I am getting the login screen and will be redirected to /lovelace where I am greeted with the message: Unable to connect to Home Assistant followed by a retry button.

My configuration looks as follows:

<VirtualHost *:443>
        ServerAdmin webmaster@localhost
        ServerName example.com

        ProxyPreserveHost On
        ProxyRequests off
        ProxyPass / http://127.0.0.1:8123
        ProxyPassReverse / http://127.0.0.1:8123
        ProxyPass /api/websocket ws://127.0.0.1:8123/api/websocket
        ProxyPassReverse /api/websocket ws://127.0.0.1:8123/api/websocket

        RewriteEngine on
        RewriteCond %{HTTP:Upgrade} =websocket [NC]
        RewriteRule /(.*)  ws://127.0.0.1:8123/$1 [P,L]
        RewriteCond %{HTTP:Upgrade} !=websocket [NC]
        RewriteRule /(.*)  http://127.0.0.1:8123/$1 [P,L]

</VirtualHost>

I have also tried with *:80. Same result here. When checking the network tab in the browser dev tools I can see that a connection attempt is made to wss://example.com/api/websocket. The resulting status code is 400. No matter what i try, this does not change. I have changes the redirects to wss istead of ws and I have also used this config:

<VirtualHost *:80>
        ServerName        homeassistant.adamoutler.com #MODIFY to your host name
        ServerAdmin       [email protected] #MODIFY to your email
        RewriteEngine On
        # This will enable the Rewrite capabilities
        RewriteCond %{HTTPS} !=on
        # This checks to make sure the connection is not already HTTPS
        RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
</VirtualHost>

<IfModule mod_ssl.c>
<VirtualHost *:443>

		#Declare server
        ServerName        homeassistant.adamoutler.com #MODIFY to your host name
        ServerAdmin       [email protected] #MODIFY to your email

        #fix detecting incorrect login IP by proxy server
        RemoteIPInternalProxy 192.168.1.1  #MODIFY to your proxy, or delete if you aren't using a firewall
        RemoteIPHeader X-Forwarded-For

        #proxy server setup
        ProxyPreserveHost On
        ProxyRequests Off
        ProxyPass /api/websocket ws://192.168.1.8:8123/api/websocket #MODIFY to your HA IP:Port
        ProxyPassReverse /api/websocket wss://192.168.1.8:8123/api/websocket #MODIFY to your HA:Port
        ProxyPass / http://192.168.1.8:8123/ #MODIFY to your HA IP:Port
        ProxyPassReverse / http://192.168.1.8:8123/ #MODIFY to your HA IP:Port

        #fix websockets for addons and apis
        RewriteEngine On
        RewriteCond %{HTTP:Upgrade} websocket [NC]
        RewriteRule ^/?(.*) "ws://192.168.1.8:8123/$1" [P,L] #MODIFY to your HA IP address


        #Set security on certan areas(some redacted)
        <Location "/">
                Satisfy any
#               Include /path/to/mySecuritySettings.conf
        </Location>
        <Location "/api">
                Satisfy any
        </Location>

        #HTTPS certs
#        Include /path/to/sites-available/ssl.conf
#        Include /path/to/options-ssl-apache.conf
#        SSLProxyEngine On
#        SSLCertificateFile /path/to/my-chain.pem
#        SSLCertificateKeyFile /path/to/my-cert.pem
</VirtualHost>
</IfModule>

with no success. I of course adapted it to my server.
I have also enabled all the modules for apache that are required but still cannot get a connection. And yes, I also restarted the server everytime I made a change.

Can anyone tell me what I am missing or maybe just a tip where to look next?

Thank you for your help!

Just came across the same whilst configuring my own Apache reverse proxy, I had to enable the web sockets support module for mod_proxy

sudo a2enmod proxy_wstunnel
1 Like

You my friend are a genius!!

Spent hours trying to resolve this issue of Apache Proxy not logging in properly and the need to enable the proxy_wstunnel was the key!!

THANKS