Problems Running emonCMS Behind Reverse Proxy with SSL on Separate Raspberry Pi

I have several Raspberry Pi web servers running various things, including one that runs emonCMS (emonSD-26Oct17 version). I’d like to set up a reverse proxy behind my home router, running on a dedicated Raspberry Pi that can route traffic to the correct Pi based on domain. Thus I’d like to be able to run emonCMS behind a reverse proxy running on a different machine.

I have had success doing this with both NGINX and Apache2 running the reverse proxy, as long as I stick with http. As soon as I try to enable SSL I get results that suggest to me that emonCMS can no longer parse the inbound URL to find which script it should run.

Here is what I see:

Here is the VirtualHost I am running. Can anyone help?

<IfModule mod_ssl.c>
    <VirtualHost _default_:443>
            ServerAdmin [email protected]

            DocumentRoot /var/www/html

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

            SSLEngine on

            SSLCertificateFile       /etc/letsencrypt/live/
            SSLCertificateKeyFile  /etc/letsencrypt/live/

            ProxyPass /
            ProxyPassReverse /


In addition to your normal settings I use:

            UseCanonicalName On

            SSLProxyEngine On

            ProxyPreserveHost On
            ProxyRequests Off
            RequestHeader set X-Forwarded-Proto "https" env=HTTPS

            ProxyPass /emoncms http://emonpi/emoncms
            ProxyPassReverse /emoncms http://emonpi/emoncms

Some of the above may be for the other sites behind my proxy, like node-red, the mqtt relay etc.

I don’t recall changing anything on the emonpi, but…

That worked. Thank you!

1 Like

Another question. Did you have any luck putting node-red behind a reverse proxy with SSL? I haven’t been able to. It seems like the socket connection gets lost.

You need to forward the web socket, ala:

            ProxyPass /nodered/comms wss://emonpi:1880/comms
            ProxyPassReverse /nodered/comms wss://emonpi:1880/comms
            ProxyPass /nodered https://emonpi:1880
            ProxyPassReverse /nodered https://emonpi:1880

if you want an easier setup than NGINX, have a look at caddy uses letsencrypt automatically and the config files are much simpler

Except all the above is Apache…

Now the reverse proxy works and stays connected, but it never asks for a password. It seems like the socket between the reverse proxy and the node-red server has been authenticated and now it doesn’t ask for it again. Maybe it is better to move authentication to the reverse proxy server? Or I need to forward more information from the reverse proxy to the node-red server?

More detail …

This worked. I did need to enable ws_tunnel for it to work.
sudo a2enmod proxy_wstunnel

I also needed to change “wss” to “ws”, since I’m not running SSL on the node-red server itself, so the communication from the reverse proxy to node-red is over ws, not wss.

ProxyPass /comms ws://
ProxyPassReverse /comms ws://	
ProxyPass /
ProxyPassReverse /

Thanks. I’ll check that out, too.


I just thought I’d mention I have a similar set up working.

I’m using emonCMS from a docker container and I want to proxy it from a sub-path in my existing Apache server.

I had a fair amount of trouble but nothing too unusual.

I can confirm that if you want emonCMS to spit out “https” URLs you need the:

RequestHeader set “X-Forwarded-Proto” “https”

because mod_proxy doesn’t add that by default. “core.php” will use that header.

I had a problem where emonCMS in the Docker container is running at “/” and many of the generated URLs ended up hitting the root of my web server so that was bad.

I used this hack to fix it.

First of all I stopped mod_proxy including the host forwarding header using this blunt instrument (because unset didn’t work):

ProxyAddHeaders Off

Then I added this abomination:

RequestHeader set “X-Forwarded-Host” “

so that when core.php writes the URLs they include the sub-path I’m using on my Apache server. Without this it just appends the simple “script path” to the host name.

Finally, I already has Basic auth on the web server and so that was getting passed down and causing “Invalid Key” because it wasn’t valid in emonCMS.

I was able to stop it passing through like this:

RequestHeader unset Authorization

and now I have to login to emonCMS and it creates a session cookie which is good.

Hope that helps someone one day.

David Bowen