Skip to content

Using nginx as front server to HipHop

imd23 edited this page Mar 4, 2011 · 8 revisions

As a HipHop user, you may need to use extras features like SSL support, faster static cache files, gzip compression, geolocalisation, DoS evasion or just a server to do load balancing.
It can also be useful to show a nicer error message in case HipHop is failing (HipHop is still under development).

This tutorial will help you to setup a basic reverse proxy using latest nginx.
This configuration has been tested with millions of requests per day.

In this example, we suppose HipHop is running locally on port 4247.
Make sure all requests to port 4247 are blocked from outside, otherwise this can allow some persons to fake their source IP address.

Required Packages

  • cmake
  • g++/gcc
  • zlib
  • openssl
  • nginx

Building

To build nginx, use the following:
./configure --with-http_ssl_module --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx_error.log --http-log-path=/var/log/nginx_access.log

If you want to use geolocalisation, add to the command line: —with-http_geoip_module
If you want to get statistics from the server, add to the command line: —with-http_stub_status_module
On Debian / Ubuntu systems, it is preferable to add —prefix=/usr to the command line; it means the software is going to be installed in /usr.

Once this is done:
make && make install

Configuration

Open /etc/nginx/nginx.conf

In most cases, it is preferable to set worker_processes to the number of cores of your server.

/etc/nginx/nginx.conf


user  www-data;
worker_processes  2;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    server_tokens	off;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  10 10;

    gzip  on;
    gzip_comp_level 6;
    gzip_proxied any;
    gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript image/png image/gif image/jpeg image/jpg;
    gzip_disable     "MSIE [1-6]\.";

    log_format main '$remote_addr - $remote_user [$time_local] '
    '"$request" $status  $body_bytes_sent "$http_referer" '
    '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx_access.log  main;
    error_log  /var/log/nginx_error.log debug;
    include  /etc/nginx/sites-enabled/*;
}

You can change debug value of error_log to fail if you want to reduce verbosity.

Beware, a lot of guides on the Internet are telling you that you should use access_log off; to disable logging.
In fact, writing access_log off; means that all requests are wrote in a file called off (default on /usr).
Because the / partition will likely be filled quickly, this can lead to a full crash of the system.

/etc/nginx/sites-enabled/default

mkdir -p /etc/nginx/sites-enabled/

Create file /etc/nginx/sites-enabled/default and put


server { listen *:80 default; server_name _;

location / {
deny all;
}
}


This will setup a default vhost that denies all requests.
It happens that some people buy a domain name and points their CNAME www to your domain name.
In consequence, you get penalized by Google for duplicate content. This rule prevents this.

Next step is configurating your domain name (in this example, facebook.com)

/etc/nginx/sites-enabled/facebook.com


server {
        listen *:80;
        server_name *.facebook.com facebook.com;

       location / {
           root   __SERVER_ROOT__;
           index  index.html index.php index.htm;
       }

       location ~ \.php$ {
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header Host www.facebook.com;
        proxy_pass   http://localhost:4247;
      }
}

# SSL part, you can remove everything below if you don't want HTTPS support
server {
	listen 443 default ssl;
        server_name *.facebook.com facebook.com;

	ssl_certificate      _PATH_TO_YOUR_SSL_CRT_FILE_;
	ssl_certificate_key   _PATH_TO_YOUR_SSL_CRT_KEY_;

       location / {
           root   __SERVER_ROOT__;
           index  index.html index.php index.htm;
       }

       location ~ \.php$ {
        proxy_set_header   X-Real-IP        $remote_addr;
        proxy_set_header Host www.facebook.com;
        proxy_pass   http://localhost:4247;
      }
}

This configuration will pass all requests ending with php to HipHop server and serve directly other content.

Because HipHop is now called by nginx and not by the final user you shall use $_SERVER['HTTP_X_REAL_IP'] in your PHP scripts instead of $_SERVER['REMOTE_ADDR'].

We do not use X-FORWARDED-FOR header because this could lead to confusion in chained load-balancers environment.

(Optional) Setting REMOTE_ADDR to the client IP value.

This hack is not recommended, but may save you if you have a large PHP codebase that you are not allowed to change (because of a lot of updates, etc…).

In HipHop source-code, open src/cpp/base/server/http_protocol.cpp

Search for the line

server.set("REMOTE_ADDR", String(transport->getRemoteHost(), CopyString));

and replace it with:


string realIP(transport->getHeader("X-Real-IP"));
if (realIP.empty()) {
  server.set("REMOTE_ADDR", String(transport->getRemoteHost(), CopyString));
} else {
  server.set("REMOTE_ADDR", String(realIP));
}