Sunday, July 20, 2014

Hiding Services Behind Apache

Some Background


Skip to the bottom of this post if you just want instructions.

When you set up a service like Sickbeard or Couchpotato, you connect to it via an IP/Port address, like say 192.1.168.100:8080.  The 192.1.168.100 part is the IP number, while the 8080 part of the address is the port number.  For simplicities sake, think of the port number as a little bit like the street number on a physical address.  Each service on your server, listening for incoming traffic, needs it's own unique port identifier to distinguish from other services on the server.  Just like different houses in a street require individual street numbers to distinguish themselves from other houses in the street.

Most web servers, by default, will listen to port 80 (for HTTP traffic) or port 443 (for HTTPS traffic).  So if you server has a standard web interface (like Open Media Vault), port 80 is usually where it will be listening for an incoming connection (unless you change the default settings).  Of course, since port 80 and port 443 are defaults, you'll rarely need to specify them when typing a web address in most browsers.  That is, 192.168.1.100:80 is functionally the equivalent of 192.168.1.100.

There are a couple of problems with port numbers.

Firstly, as you set up more and more services on your server, trying to remember them all starts to become a headache.  I know of people running sabnzbd, transmission, sickbeard, couchpotato, headphones, htpc-manager, subsonic and calibre... all on the same server.  And of course, there are plenty of other really cool open source server tools out there.  Wouldn't it be a bit easier to be able to use an address like 192.168.1.100/sickbeard instead of trying to remember that your sickbeard port is 8080?

Secondly, running these services on different ports can cause headaches with firewalls.

Firewalls


For the time being, I'm going to assume you are running your server in a hosted environment, OR you are hosting your server at home and have correctly set up port forwarding on your modem (and, are aware of the potential risks).

So you are outside of your home network, and trying to connect to your sickbeard instance and it keeps failing.  Why?  In a lot of corporate environments, and a lot of public Wi-Fi situations, it's pretty common for non-standard ports to be blocked.  That is, traffic via port 80 and 443 will work, but the 8080 port your sickbeard instance is listening to will be blocked.  Of course, you could change settings for sickbeard so it listens to port 80 instead.  But now your OMV management page won't work.  And of course, what about other services on your server? 

Apache to the Rescue


The Open Media Vault management page is hosted via a webserver called Apache, and it's pretty cool.  When I said that OMV is listening to port 80, what I really meant is that Apache is listening to port 80.  And when it gets a connection, it serves up the OMV management pages.  However, we can configure Apache to re-direct certain traffic.

What does this mean?


Let's look at our scenario above, where we type in the address 192.168.1.100/sickbeard.  Your web browser interprets this as 192.168.1.1.100:80/sickbeard, and sends it off to your server.  Being that this request comes in via port 80, Apache picks it up and tries to interpret the remainder of the address "/sickbeard".  Now, Apache hasn't be configured to understand this part of the address so you'll get a HTTP 404 error.

Alternatively, you could instruct Apache to redirect this request to the correct location (or more specifically in our case, the correct port).

The advantage in doing this, is that the request is transmitted via port 80.  It only gets forwarded to port 8080 after it has been received by Apache.  That is, after, it has passed through firewalls (and, after it has been port-forwarded by your modem). 

Instructions


There are a variety of ways of doing this, depending on the service and your server configuration.  These instructions are for Open Media Vault (which is based on Debian Squeeze).  But they will probably work on other installations of Apache on Debian.  If you're not sure, backup any config files before editing.  If you are using Ngix, you'll need to follow different instructions.

Go to the directory

/etc/apache2/mods-available

And find the file proxy.conf.  If it's not available, you'll need to create a new file.  In the file, insert the following code;

<Location /sickbeard>
order deny,allow
deny from all
allow from all
ProxyPass
http://localhost:8080/sickbeard
ProxyPassReverse http://localhost:8080/sickbeard
</Location>

Of course, substitute port 8080 for whatever port your instance of sickbeard is running on.  If you have other services, like couchpotato, just add additional sections to the file, like;

<Location /cp>
order deny,allow
deny from all
allow from all
ProxyPass
http://localhost:8082/cp
ProxyPassReverse http://localhost:8082/cp
</Location>

Again, substitute port 8082 for whatever port your instance of couchpotato is running on.

Once these configuration changes have been made, save the file and then restart the Apache server;

sudo service apache2 restart

In most instances, using localhost to refer to your server should work fine.  But in a couple of cases, I found this didn't work.  I still haven't worked out why it works in some instances and not others.  The simple solution is to just substitute "localhost" for the IP address of your server (ie, like 192.168.1.100).

Just out of interest, it took me a while to figure out you would modify a configuration file in the directory mods-available and not in the directory mods-enabled.  If I looked a little closer, I would have seen that the files in mods-enabled are just symbolic links to mods-available.  Hopefully this makes a little bit more sense.

I believe this way of setting up Apache configurations is unique to Debian.  So for other distributions, you may need to google to find the best place to add these changes.  Typically, it will be in the httpd.conf file, which will be found in /etc/httpd/conf/ or somewhere similar.

EDIT: Read my new post on using HAProxy to achieve the same thing.