Author Topic: Reverse Proxy  (Read 2533 times)

spark

  • NewMember
  • *
  • Posts: 13
Reverse Proxy
« on: October 24, 2015, 08:53:56 AM »
I want to share some learnings with you on how to setup the pi gateway behind a reverse web proxy using Nginx...

After installing my garagemote and my pi Gateway, everything is working great.  Now its time to open this up to the outside world.  However, I already have a home server running Open Media Vault and Ownclowd.   These are already using Nginx to reverse proxy several different applications.  So the answer is to configure a virtual server to proxy the pi gateway.

This is very straightforward, but I hit a snag with socket.io that causes the gateway web application to not be able to open the socket connection, resulting in "waiting for socket connection".   The answer is to add:

Code: [Select]
proxy_set_header Host $host;

This must be added to both your home server nginx configuration, and the nginx configuration running on your pi gateway.  Add this in the same section as the proxy_pass statement.

TL;DR
What's going on here?  The Pi Gateway web application is a .php application.   Inside index.php you will see an io.connect() statement to initialize the sockets connection.  This javascript function uses the PHP global variable $_SERVER['HTTP_HOST'] to define the path to the connection.  PHP uses the Host header in the HTTP request to define this variable.

That's great so far, except that when nginx proxies a site, it rewrite's that header by default to be the host of the new host.  That's a problem, because the host in this case is your raspberry pi located behind your firewall.   Fortunately, there is a simple answer.  By forcing nginx to set this header to the host defined in the URL everything works as expected.

As an example, here is the virtual server definition from my home server (I left my domain name in there - don't hack me!!):

Code: [Select]
server {
    listen [::]:443;
    ssl_certificate /etc/ssl/certs/openmediavault-bcdd5585-47e8-4bc3-a069-b3e21bbcee7e.crt;
    ssl_certificate_key /etc/ssl/private/openmediavault-bcdd5585-47e8-4bc3-a069-b3e21bbcee7e.key;
    server_name a.schulzfamily.org;
    error_log /var/log/nginx/moteino_error.log error;
    access_log /var/log/nginx/moteino_access.log combined;
    location / {
        proxy_ssl_session_reuse off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection upgrade;
        proxy_pass https://10.0.0.8/;
    }

}

And here is the revised section of the nginx virtual host definition on the raspberry pi:

Code: [Select]
  location /socket.io/ {
    proxy_pass http://localhost:8080;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection upgrade;
    proxy_set_header Host $host;
  }

Hope this helps someone else trying to do the same thing.

Next up for my adventure:

- Configure a nodjs application to send/receive SMS messages using Twillo.  This will allow me to monitor/open/close my door via sms!
- Setup a moteino to trigger a door open/close from my motorcycle, probably using the same configuration as @luisr's project.

« Last Edit: October 24, 2015, 08:58:51 AM by spark »