Page 1 of 1

Redundant Hosting with Apache & nginx Rate Topic: -----

#1 no2pencil  Icon User is online

  • Professor Snuggly Pants
  • member icon

Reputation: 6557
  • View blog
  • Posts: 30,699
  • Joined: 10-May 07

Posted 31 December 2014 - 08:51 AM

Redundant Hosting with Apache & nginx

Who this tutorial is geared towards :
Anyone looking to provide reliable hosting, or anyone looking to leverage the speed of nginx without configuring nginx to also handle server side.

What :
Redundant Hosting with Apache & nginx, on Linux/Unix architecture : aka LAMP stack.

Where :
Depending on your specific requirements, this hosting setup is less than $30 per month. This is the cost of the 2 vps systems through Digital Ocean.

Why I chose this setup :
For those not familiar with nginx, in short it is a light-weight web server that is quick to serve non-dynamic sites. Where as Apache will hold open a socket for the client until Apache determines they are no longer coming back, nginx simply serves the request & is done. Add to that a fault-tolerant system configuration by running in tandem.

This tutorial assumes that you already have servers in place of which you can log in with root or sudo access. It is intended for someone with an existing hosting setup, that is proficient with Linux & Apache, & that is looking to improve their hosting setup. This tutorial is not intended for someone that has installed Apache & does not have the ability to hand edit config files.

As a jumping off point, lets assume that you currently have Apache installed, & it is binding to port 80. For the core Apache configuration (httpd.conf) & all of your vhosts, we are going to need to move off of this default port. The reason for this, is that the plan is to have nginx accept all traffic, serve what it can, & forward the rest. This way nginx is acting as a reverse proxy.

Step 1 : Setting up the Services
edit /etc/httpd/conf/httpd.conf
Change the Listen port :
Listen 8081

Also change any & all Virtual Hosts :
<VirtualHost 127.0.0.1:8081>
...
</VirtualHost>


Keep in mind, when you restart Apache, your websites will be off line. Before restarting Apache, lets setup nginx :

edit /etc/nginx/nginx.conf
Setup the upstreams :
    upstream hosting {
      server 192.168.1.101:80 fail_timeout=20s;
      server 192.168.1.102:80 fail_timeout=20s;
    }



In the above code, 101 is the other server, & 102 is this server. My reason for doing it this way is to forward traffic to the 2nd server, & use yourself as a failover. If the web server is unable to answer it's own requests, how is it going to forward it?

For each of the virtual hosts that we are passing onto Apache, we need to setup similar to the following :
    server {
        proxy_cache_valid 200 20m;
        listen       192.168.1.102:80;
        server_name example.com;

        root /var/www/html/example/;
        index   index.php index.html index.htm;
        location ~*^.+.(jpg|gif|png|ico|css|zip|tgz|gz|rar|doc|xls|pdf|txt|tar|js)$ {
          access_log off;
          expires 30d;
        }
        location / {
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header      Host            $host;
          proxy_pass            http://localhost:8081;
        }
    }



Where localhost:8081 will serve as our internal proxy. nginx binds to port 80, answers requests, & in this situation, hands that request to localhost port 8081, where Apache is configured to answer for the requested server name. To use the failover servers from above, as configured within nginx.conf we repalce the localhost proxy pass with the name "hosting" that we provided :

        location / {
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          index  index.html index.htm;
          proxy_pass http://hosting;
        }



One thing to keep in mind, is that on a failover, session data will not automatically be available. So if your client has authenticated on one server & then blindly is forwarded to another, the 2nd server is going to see it as a new instance. As such, I only use the failover within nginx for html sites, & allow each server to handle it's own Apache session. With more experience & exposure, I may expand upon that.

For a non-Apache service website configured with nginx, we can just serve the content :

    server {
        proxy_cache_valid 200 20m;
        listen       192.168.1.102:80;
        server_name example.com *.example.com;

        root /var/www/html/example/;
        location / {
           try_files $uri $uri/ $uri.html index.html = 404;
        }

        error_page  404              /404.html;
        error_page  500 502 503 504  /index;
    }



Good, now replicate the above onto our 2nd server, switching the ip's where relevant.

To further leverage failover, I'm using CloudFlare for both CDN & for dns. As such, for the http://hosting failover sites with nginx, I provide both ip's as A records with the domain dns in CloudFlare.

Attached Image

Quote

$dig c4bmore.com

; <<>> DiG 9.8.3-P1 <<>> c4bmore.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 1973
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;c4bmore.com. IN A

;; ANSWER SECTION:
c4bmore.com. 227 IN A 104.28.20.16
c4bmore.com. 227 IN A 104.28.21.16

;; Query time: 2 msec
;; SERVER: 10.16.72.9#53(10.16.72.9)
;; WHEN: Wed Dec 31 10:19:41 2014
;; MSG SIZE rcvd: 61


As a proof of concept, we tail the logs for both servers for our target website :

Quote

[31/Dec/2014:15:20:34 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0
[31/Dec/2014:15:20:52 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0
[31/Dec/2014:15:20:57 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0
[31/Dec/2014:15:21:00 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0

With content being served, we stop the primary webserver :

Quote

$ sudo service nginx stop
Stopping nginx: [ OK ]

[30/Dec/2014:19:22:56 +0000] "GET / HTTP/1.1" 200 93 "-" "Swiftbot (2.4.0, ruby 2.0.0 (2013-11-22))"
[31/Dec/2014:15:21:44 +0000] "GET / HTTP/1.1" 200 93 "http://c4bmore.com/" "Mozilla/5.0
[31/Dec/2014:15:21:51 +0000] "GET / HTTP/1.1" 304 0 "http://c4bmore.com/" "Mozilla/5.0
[31/Dec/2014:15:21:53 +0000] "GET / HTTP/1.1" 304 0 "http://c4bmore.com/" "Mozilla/5.0
[31/Dec/2014:15:21:55 +0000] "GET / HTTP/1.1" 304 0 "http://c4bmore.com/" "Mozilla/5.0

& we notice that traffic picks up right where it left off. Lastly we show that the service is still in a down state on the primary server :

Quote

$ sudo service nginx status
nginx is stopped


Lastly, I would like to note that this is redundant with html traffic through nginx across multiple servers. The overall goal is to provide redundancy with all traffic, which will include memory/session sharing between servers, & eventually database load-balancing, in order to provide redundant Apache/Database websites like WordPress or Drupal.

I welcome any questions or comments!

Is This A Good Question/Topic? 0
  • +

Page 1 of 1