Whip-Snapping Fast WordPress with Nginx and HHVM-Part 2

hhvm and nginx oh my
Everyone watched as the Wicked Witch spanked out some wicked HHVM.

Nginx and HHVM and WordPress, oh my!

Nginx is a relatively young web server that is picking up popularity.  The reason it’s becoming so popular is that it doesn’t use a lot of resources, and it’s blistering fast at delivering static content like images and text.  Nginx doesn’t do PHP itself.  For that you need to run PHP through something like fastcgi or PHP-FPM….Or, the new wicked fast HHVM.

HHVM (HipHop Virtual Machine) is a new alternative PHP engine crafted by magic elves at Facebook to help speed up their code and use fewer servers.  The way it works is HHVM uses JIT (Just in Time) Compilation to compile your PHP code into native code as it’s run.  This doesn’t speed it up too much, the first time it’s run.  But the next time the code is accessed, there’s compiled code ready to run, which is way faster than running interpreted code or even optcode caching.

The HHVM team recently released HHVM fastcgi mode.  Which means you can run HHVM-fastcgi as a PHP backend for your Nginx server.  It’s fast, it’s easy to set up, and it works easily with WordPress url rewrites.  This is our first key to a fast WordPress site.

[Note that it is possible to run the full HHVM server behind Nginx and reverse proxy calls to HHVM for PHP calls.  But I wouldn’t recommend it.  It’s harder to set up, will probably consume more RAM, and HHVM’s rewrite engine doesn’t currently seem to work with a proxied url–at least not in the way it’s documented on their blog or in their docs.  Fastcgi mode is what you want.]

Installing Nginx

First let’s install Nginx:

sudo apt-get install nginx

Done.  Now let’s get some configuration done.

We want to set up our file location on our server.  We’ll go with /var/www/sitename.com/public.  Also, we’ll want to give ownership to our file location to the web server.

sudo mkdir /var/www/sitename.com/{public,private,logs}

sudo chown -R www-data:www-data /var/www/sitename.com

Now we need to configure Nginx and set it up to serve our site.  First, let’s go through the nginx config and set up global values and gzip compression.

sudo nano /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  3;

  gzip  on;
  gzip_comp_level 6;
  gzip_proxied any;
  gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript image/png image/gif im$
  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/*;

}

Now we want to set up our per site configuration.  First stop, let’s hit the default site file.

sudo nano /etc/nginx/sites-available/default

server {
  listen *:80 default;
  server_name _;
  location / {
    deny all;
  }
}

This ensures that only our main site (which we’re setting up next) get’s served by our web server.  Anyone trying to reach anything else gets a big fat error page.

Now let’s set up our individual site.

sudo nano /etc/nginx/sites-available/sitename.com

server {
  listen 80;
  server_name www.sitename.com;
  rewrite ^ http://sitename.com/$1 permanent;
}

server {
  listen *:80;
  server_name sitename.com;
  location / {
    root /var/www/sitename.com/public;
    index index.php index.html index.htm;
    try_files $uri $uri/ /index.php?q=$uri&$args;
  }

  # Here is where the HHVM proxy info will go

}

Now the way Nginx deals with multiple virtual hosts, at least the way we have it set up, is it runs any site configurations it finds in the /etc/nginx/sites-enabled directory.  But you see we’ve created this file in the sites-available directory.  Did we make a mistake?  Nope.  This is how you can have built out configurations and then easily enable them by just creating a symlink to the sites-enabled directory.  Let’s do that now.

sudo ln -s /etc/nginx/sites-available/sitename.com /etc/nginx/sites-engabled/sitename.com

Restart Nginx with the command

sudo service nginx restart

Now our web server is running.  Let’s test it.  Create an empty file index.html in the web site root.

sudo nano /var/www/sitename.com/public/index.html

<strong>Hello, Mr. Clemens.</strong>

This way, if Mark Twain comes across our site while we’re still building it, he will have a nice personal greeting.  Hit your site in a web browser to confirm.

Installing HHVM

Now it’s time to add some HHVM to our recipe.  The HipHop team at Facebook has created some fastcgi packages for different repositories.  If you’re using something besides Ubuntu 13.10, check their fastcgi page for details.  Otherwise, sing along.

First add their repository to your sources list.

echo deb http://dl.hhvm.com/ubuntu precise main | sudo tee /etc/apt/sources.list.d/hhvm.list
sudo apt-get update
sudo apt-get install hhvm-fastcgi

That installs HHVM with fastcgi goodness.  But now how do you set it up to play with Nginx?  Well, since we installed Nginx first, HHVM automagically created a file with the correct fastcgi calls.  You may have seen some text fly by to that effect if you were watching your terminal as you installed.  It stuck the file in /etc/nginx/hhvm.conf.

The only thing, if you open the file, is that it expects your web root to be at /var/www.  But we may want to use this server for multiple sites, so we’ve set ours up at /var/www/sitename.com/public.  We could change the root in this file and then include it in our site, but then what if we want to set up another site?  We’d have our HHVM site root set to sitename.com/public.

There is a way to use server directives in Nginx, that are sort of like variables.  But for now, I want you to just copy everything in that file to your clipboard.  Now open up your /etc/nginx/sites-available/sitename.com.  See that commented line we left in there before?

# Here is where the HHVM proxy info will go

Paste your HHVM clipboard text in there.  Change the site roots to match your configuration.  Your completed file should look like this:

server {
  listen 80;
  server_name www.sitename.com;
  rewrite ^ http://sitename.com/$1 permanent;
}

server {
  listen *:80;
  server_name sitename.com;
  location / {
    root /var/www/sitename.com/public;
    index index.php index.html index.htm;
    try_files $uri $uri/ /index.php?q=$uri&$args;
  }

  # Here is where the HHVM proxy info will go
  location ~ \.php$ {
    root /var/www/sitename.com/public;
    fastcgi_keep_conn on;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /var/www/sitename.com/public$fastcgi_script_name;
    include fastcgi_params;
  }
}

Create a test file:

sudo nano /var/www/sitename.com/public/test.php

Now restart Nginx and go to your web site (assuming you’ve set your domain to point at your server already).  You should see your php page being served up HHVM style.  (If you don’t, and instead see a ‘Bad Gateway’ message from Nginx, HHVM may not have been started when you installed it.  Run the following to get it running:)

sudo hhvm --mode daemon -vServer.Type=fastcgi -vServer.Port=9000

Time for a break. Have some cookies. In our next post, we’ll talk about getting our MySQL MariaDB database server installed.

6 thoughts on “Whip-Snapping Fast WordPress with Nginx and HHVM-Part 2”

Leave a Reply

Your email address will not be published. Required fields are marked *