HHVM and multiple sites

When using HHVM when you come from the PHP world (I'm talking about the binaries, not the language), you can easily get lost when trying to serve multiple sites on one server.

That's why using a single instance of HHVM on one server to serve many sites can be a good idea.

The configuration is not straightforward, here are some tips and tricks

Let's install HHVM, just in case

Oh yeah.
That here.

Let's use Supervisor

Because, well, you need something like it to run hhvm.

On a debian system for instance :

sudo apt-get install supervisor

Then we're going to create a configuration for supervisor in the right place :

vi /etc/supervisor/conf.d/hhvm.conf

Telling it to behave smoothly :

[program:hhvm]
directory=/var/www
command=hhvm --mode server -vServer.Type=fastcgi -vServer.Port=9000
autostart=true
autorestart=true
stdout_logfile = /var/log/hhvm/stdout.log
stderr_logfile = /var/log/hhvm/error.log
redirect_stderr=true

Note here that directory is a global one and not one of a specific site

The rest is quite standard. HHVM runs in fastcgi mode on port 9000. « That's how we do it ».

Configuring HHVM

This being done, we need to configure HHVM correctly. For this, we need two distinct files : config.hdf and server.hdf.

config.hdf

vi /etc/hhvm/config.hdf

Nothing complicated, everything is quite default, except the central repository in /var/run :

Log {
  Level = Warning
  AlwaysLogUnhandledExceptions = true
  RuntimeErrorReportingLevel = 8191
}

MySQL {
  TypedResults = false
}

Repo {
  Central {
    Path = /var/run/hhvm.hhbc.sq3
  }
}

server.hdf

vi /etc/hhvm/server.hdf

Here is the file, below are some details :

PidFile = /var/run/hhvm/pid

Server {
  Port = 9000
  SourceRoot = /home/myUser/www/
  DefaultDocument = index.php
}

VirtualHost {
  * {
    Pattern = .*
  }
}

Repo {
  Central {
    Path = /var/log/hhvm/.hhvm.hhbc
  }
}

Here as well, nothing too fancy, but you got to be careful about what you put as a repo, pidfile and SourceRoot; that's what everything boils down to : you need to indicate a parent directory of all the applications / website you want to run with HHVM.

Server {
  SourceRoot = /home/myUser/www/
}

As for the virtual hosts, same principle, a catch-all to be able to use the same instance for all sites :

VirtualHost {
  * {
    Pattern = .*
  }
}

Almost done !

Of course you can run the whole thing :

sudo supervisorctl start hhvm

What about nginx ?

Glad you asked.
Now that HHVM is running, how about we push it our nginx requests ?

For an easier ride, I create a standard configuration for nginx, that I will be able to include everywhere :

vi /etc/nginx/hhvm.conf

With that :

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_keep_conn on;
    try_files $uri =404;
    fastcgi_split_path_info ^(.+.php)(/.+)$;
    fastcgi_index index.php;
    # NB : the "$document_root" line is a single line :
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_intercept_errors on;
    fastcgi_pass 127.0.0.1:9000;
    fastcgi_read_timeout 300;
}

Note that the 9000 port corresponds to the one we put earlier on, and that fastcgi_param includes the document_root too :

SCRIPT_FILENAME $document_root$fastcgi_script_name;

This little configuration file can be reused anywhere now :

server {
    # Foo bar foo
    # Youpi
    include hhvm.conf;
}

Easy, right.