Zach Adams Web Developer and Programmer

Making your own WPEngine-Like High Performance WordPress Server

January 16, 2015

Recently WPEngine released a new Vagrant machine called Mercury designed specifically for testing development WordPress sites with WPEngine’s specialized High Performance servers. WPEngine has been well known for a long time to provide specialized WordPress Servers which can handle an insane amount of traffic on even the most complex WP sites. For the average Joe who doesn’t know a lot about servers or the details of hosting a popular site this is the perfect setup since WPEngine handles the complicated server stuff and Joe only has to worry about adding content and such. Even for most web development agencies this is a good deal. However WPEngine has one major letdown, it’s expensive as all hell. Now for most people it’s well worth the money and if your site’s popular enough to warrant the specialization WPEngine provides you can easily make it back, but if you’re like me you want that same performance and specialization without the cost. WPEngine uses a lot of customized server setups, however Mercury gives us a glimpse into how WPEngine provides the kind of performance it does, and allows us to replicate it (on a much smaller scale).

An important note before we go any further. This guide is based off of the Mercury Vagrant machine released by WPEngine which was only designed to allow developers to test their WordPress sites before pushing them to WPEngine’s specialized environment. It contains only some of the technologies used by WPEngine, which is why I said WPEngine-Like, however it should get us most of the way to their high performance levels without too much technical stuff.

Picking a Server

The rest of this guide doesn’t matter if your hardware can’t keep up. The reason WPEngine can charge so much is that their servers are top-of-the-line and well-maintained, however we need the same high performance without paying an arm and a leg. For 95% of setups, I would recommend a simple VPS. Personally I would recommend Linode as I find that their support and service to be excellent however I know many people who swear by Digital Ocean and I’ve also never had a problem with them.

Linode (Referral CodeNon-Referral Code)

Digital Ocean (Referral CodeNon-Referral Code)

Vultr

We also want to be able to scale this server in line with our traffic, however since we’re going for the cheapest we can let’s compare the cheapest plan for both:

Linode VPS Servers

Linode: $10/month

CPU: 1 Core

Storage: 24GB SSD

Transfer: 2 TB

Digital Ocean VPS Servers

Digital Ocean: $5/month

Memory: 512 MB

CPU: 1 Core

Storage: 20GB SSD

Transfer: 1000GB

Vultr VPS Servers

Vultr: $5/month

CPU: 1 Core

Memory: 768 MB

Storage: 15GB SSD

Transfer: 1000 GB

IMO go for Linode since it provides you with a little more control over your servers, however both with work fine for our purposes.

Please use Ubuntu 14.04 LTS for the time being!

High Performance Setup

Once you have your VPS up and running and you’re connected through SSH we can start making some magic! I’ve setup two versions for you to choose from:

Full

This one includes:

  • Percona DB (MySQL)
  • HHVM (Default)
  • PHP-FPM (Backup)
  • Nginx
  • Varnish (Running by default)
  • Memcached and APC
  • Clean WordPress Install (Latest Version)
  • WP-CLI

Basic

This one includes:

  • Percona DB (MySQL)
  • HHVM (Default)
  • PHP-FPM (Backup)
  • Nginx
  • Clean WordPress Install (Latest Version)
  • WP-CLI

Installation

You can find the installations instructions in each Github Repository:

Full Version

Basic Version

Once it’s done remember to remove the cloned git directory from your server as it’s no longer needed.

If the server is still not running you may need to restart Varnish and Nginx. You can do so with:

sudo service varnish restart && sudo service nginx restart

You’re good to go! A new WordPress install running HHVM should be waiting for you at your hostname!

Speed/Stability Results

All load tests are run with Blitz.io (Referral Link, Regular Link) on a $10/month Linode server with a barebones install of WordPress (Full has W3 Total Cache installed and configured but nothing else). The test is run over 60 seconds and sends a total of anywhere from 15,000 to 25,000 hits to your server.

Basic Setup

Running:

  • Nginx
  • HHVM
  • Percona
  • No Caching Plugins

Report Link

Oh dear. That won’t do at all. As soon as the server took any kind of traffic it spluttered out and threw errors. And that’s even with HHVM! This is exactly the kind of things we need to prevent.

Full Setup

Running:

  • Nginx
  • HHVM
  • Percona
  • Varnish
  • APC & Memcached (Only Memcached used)
  • W3 Total Cache

Report Link

That’s more like it! Our tiny little $10/month server took 25,000 hits over 60 seconds and only had 1 error! This is exactly the kind of high performance we were looking for.

Security

I highly recommend installing fail2ban, a program which should stop most SSH brute force attacks. You can read on how to install it here. I also recommend a security plugin such as iThemes Security for more WordPress oriented security.

Conclusion

By the end you should have a server that runs close to the high performance of WPEngine, but rather then paying $30/month you’re now paying $5/10 and you can scale at your own rate. It’s also good to remember that YOU are in charge of your own server now, so it’s important to keep it well-maintained and updated.

Let me know if you have any questions or issues!

Comments

Ahmad Awais says:
January 16th 2015 at 12:00am
Didn't understand this part "IMPORTANT: Change your settings inside all with vim|nano|emacs group_vars/all"
Philby says:
January 17th 2015 at 12:00am
thanks for the interesting read. I'm currently playing around with various VPS setups (mostly on Vultr – they 're even better price-wise), and will try your install soon. What I'll probably change is: full page caching using NGiNX instead of Varnish, and object cache with Redis, no W3 Total Cache. Should be plenty fast, hopefully almost on the Kinsta performance level.
Hamish says:
January 19th 2015 at 12:00am
Can you diagnose what went wrong with the basic setup? It shOuldn't have responded that badly should it?
Mark Kelnar says:
January 19th 2015 at 12:00am
Zach, this is great. I'm one of the lead developers at WP Engine and the Mercury project. I'm pleased to see someone already take the open source code and put your own twist on it. This is exactly one of the purposes of the open source project, to lower the bar or entry and some of the technical hurdles of setting up Nginx, HHVM, Varnish, Peronca, etc. A note, HHVM is only supported on at least version 14.04 of Ubuntu. They dropped support for 12.04 a few months back, but you could probably skip the HHVM role completely when not on Ubuntu 14, in playbook.yml with a condition like - { role: hhvm, when: ansible_lsb.major_release | int >= 14 } And PHP-FPM should still install and in your /etc/nginx/wp.conf, make sure to pass to the php upstream.
Ahsan Parwez says:
January 21st 2015 at 12:00am
Hi Zach, Impressive performance and setup. But I am doubtful that it is suitable for all kinds of WP deployments? I am unable to find "real users" who are using HHVM to host all of their WP sites, maybe they are using it for some sites, but to make all their sites working with this kind of setup will take a lot of time debugging. Well I work with a different kind of stack, using Nginx, Varnish, Apache, Memcache and I think it delivers exceptional performance and stability. Would you be interested in checking its performance comparing it with your setup?
Pescadito says:
January 29th 2015 at 12:00am
Awsome!!!, It worked like a charm, i prefer revert back to PHP-FPM (because i have some issues when uses wordpress import plugin that stoped probably by timeout. next i changed to php-fpm and after increasing php memory_limit, upload_max_filesize, post_max_size and max_execution_time it worked very well. I really apreciate 'Ansible' that let me run it without experience. Please, could you point a ref or add you a 'Ansible' playbook to de-configurate/eliminate the lasted executed playbook to revert the dropbox to the initial state?. Also i woud apreciate if you point some ref about a workflow to load/reset/reconfigure and a reload this type of droplet config. Do you think 'Ansible' or 'Dokku' are the most apropiate tool for doing this?
J. Mayfield says:
February 22nd 2015 at 12:00am
Thanks for this. Just wanted to add for ssl, this setup is easily can easily be tweaked. You can run pound in front of varnish to interpret the ssl or you can setup nginx as a front end to interpret the ssl as well. I prefer nginx in front as its one less app to debug and easier to configure ssl options such as stapling and caching.
Miksiii says:
March 8th 2015 at 12:00am
I highly recommend installing fail2ban, a program which should stop most SSH brute force attacks. You can read on how to install it HERE. I also recommend a security plugin such as iThemes Security for more WordPress oriented security. -> The hyperlink HERE is throwing 404 error.
Daman says:
March 9th 2015 at 12:00am
First of all I want to thank you for writing this awesome article. I was looking for HHVM setup with WordPress and found this. I've successfully installed WordPress along with HHVM 3.5.1 version. I'm a newbie and a question. I hope you won't mind answering it :) How can I keep this server updated?: I'm running running Full installation. I want to know how to keep HHVM and other packages updated? Will running sudo apt-get update && sudo apt-get upgrade command will keep HHVM updated too? Please explain me.
Yaron Guez says:
March 12th 2015 at 12:00am
Great article! I'm strongly considering trying this out as a solution for our hosted sites. One question, can you recommend an application that offers functionality similar to cPanel that is compatible with this setup that offers a GUI for managing new websites, and server administration?
Evagelos says:
April 11th 2015 at 12:00am
Hello guys, I have tried your coniguration to setup a wordpress site. And YES, is very fast but i have a couple problems. Where is the admin bar and why if I am logged there is no edit link on posts/pages? Thanks and Zach you are doing great work
Damanjit Singh says:
April 12th 2015 at 12:00am
Thanks for your reply Zach! Please tell me which is the best way to backup a server? My VPS provider has provided me 15GB offsite backup space which I can access using FTP also I have plenty of free storage space available on the main server (where the HHVM is installed). As you said, updating server can break things, how can I take backup and restore it easily? Any solution you recommend? Thanks!
Yuri Perchey says:
April 17th 2015 at 12:00am
Hi Zach, thanks for your article, it's gonna be very useful in a project we're working on. I was wondering if you could recommend a machine that could work as well as the linode cloud services ? We'd like to host our site on premises without access to the Internet (except for updates of course), we'd have max 1.000 users a day and need to host multimedia content (mostly audio, a few videos). Thank you again for the article, I can't wait to test your configuration :-) Regards, Yuri
Senti says:
May 18th 2015 at 12:00am
Thank you so much for your article. I followed the MariaDB version on a Vultr VPS 2GB. on Step 3: Update Apt with sudo apt-get update && sudo apt-get upgrade Don't do suo apt-get upgrade (this appears to upgrade to Ubuntu to 15.04) and this fall over at nginix step. I had to reinstall the os and skipped this step. Also there are errors on wp-config step. (It does not replace the salt properly). I skipped this step and did it manually. Now everything is setup. But I have an issue. When I put my vps ip address I was hoping to see the new wordpress installation but I get connection refused on the browser (ERR_CONNECTION_REFUSED). 1. Why is the website is not loading by ip-address even though I can see all installation from ssh. 2. Should I point the name servers to the VPS ip address? I not a linux expert, I am used to cPanel hosting now trying out VPS. hhvm.conf location ~ \.(hh|php)$ { fastcgi_keep_conn on; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } server { listen 8080; server_name jobsincanberra.com.au; root /var/www/html/jobsincanberra.com.au; index index.html index.htm index.php; access_log /var/log/nginx/my-domain.com.au.access.log; access_log /var/log/nginx/my-domain.com.au.apachestyle.access.log apachestandard; error_log /var/log/nginx/jobsincanberra.com.au.error.log; location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } location = /apple-touch-icon.png { access_log off; log_not_found off; } location = /apple-touch-icon-precomposed.png { access_log off; log_not_found off; } location ~ /\. { deny all; access_log off; log_not_found off; } location / { try_files $uri $uri/ /index.php?q=$uri&$args; } location ~ \.php$ { proxy_intercept_errors on; error_page 500 501 502 503 = @fallback; fastcgi_buffers 8 256k; fastcgi_buffer_size 128k; fastcgi_intercept_errors on; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass hhvm; } location @fallback { fastcgi_buffers 8 256k; fastcgi_buffer_size 128k; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass php; } location ~* .(css|js|png|jpg|jpeg|gif|ico)$ { expires 1d; } } Help is greatly appreciated.
Senti says:
May 21st 2015 at 12:00am
That worked. Thank you so much. Do you think this playbook will work on Centos?
Senti says:
May 23rd 2015 at 12:00am
Hi Zach, My results are pretty consistent with your test. VentraIP VPS: 4GB RAM, CentOS7, Cpanel, Apache, Wordpress, Mysql Load test: 200 Users for 2 mins Result: 11,203 hits with 267 errors & 83 timeouts Vultr VPS: 2GB RAM, Ubuntu 14.04, HHVM, NGINX, Varnish, Wordpress, MariaDB Load test: 200 Users for 2 mins Results:1 1,900 hits with 0 errors & 0 timeouts Both servers were hosted in Sydney and load tested from Sydney. Vultr with half the memory has outperformed.
Mat_ says:
May 24th 2015 at 12:00am
Hi ! Great tool thanks ! One dumb question, is there a way to connect ftp users ? Some users might need it to manage their WP install. Thanks !
Mario says:
May 28th 2015 at 12:00am
Hi Zach, thanks for the awesome playbook. Have you ever tried to deploy on an Amazon EC2 Ubuntu 14.4 LTS Image? I managed today, but somehow can´t access the server via my web browser.... Best, Mario
Lars says:
June 26th 2015 at 12:00am
Hi Zach, thanks a lot for your awesome post! I'm a happy digitalocean customer (I can testify their support is also swift & competent) so I'm really impressed that $5/month and your recommended setup can withstand that amount of requests. However I wonder what other tweaks are possible in combination with the full setup. Before I found your recommendation I used to tweak swap-size, amount of worker processes and other little things here and there. Would you recommend to still do this or is the full setup already tuned for optimum performance (e.g. I read somewhere that swap doesn't play well with memcached). I also wonder how forced site-wide SSL impacts your stats. Besides that - your whole blog is a pretty cool read so you have a new follower here :)
Alexandros says:
July 9th 2015 at 12:00am
Your playbook is brilliant. A thousand thanks. I tried the MariaDB version, and had great success. A few notes: 1. In local-config.php, $memcached_servers is misspelled as $memecached_servers the first time around. 2. Running WordPress, I got the error message "Warning: mysql_connect(): Headers and client library minor version mismatch. " I fixed it by installing php5-mysqlnd. 3. I don't really understand Varnish yet, but I found that it was stripping a cookie I needed to see the admin bar on the front end. I fixed it by commenting out line 64 of default.vcl ("unset req.http.cookie;"). That seems to work, but perhaps you'll have a better solution. 4. sendmail isn't installed or configured by your playbook. It might be neat to add that in. So there were a few bumps, but that said, this is an extremely clever installation routine. Thanks for making it available! Alexandros
Ray says:
July 29th 2015 at 12:00am
Hi zach, Nice setup! I have 1 problem, if i login i see the that im at domain.nl:8080/wp-admin. The admin dashboard works as it should. But if i visit the front -end and if i ga to a page it tells me to login. I can fix this to set the site url and wp adres url in settings/general in de dashboard to domain.nl:8080. Now the session works and wordpress don't log me of. But is i visit the website then there is :8080 after my url. How can i fix this problem? Kind regards! Ray
Thomas says:
August 7th 2015 at 12:00am
Hey, very awesome job! :D I'm loving it <3 only really one question: Why use a caching plugin? Isn't it unnecessary?
Pavel says:
October 24th 2015 at 12:00am
Zach, this is awesome. You've done an incredible job putting all this software together, thanks to you and the people of WPEngine, you guys rock!!
Michael says:
November 5th 2015 at 12:00am
Hi. Is there a similar/updated playbook for Ubuntu 15.04 ?
Mijo says:
November 24th 2015 at 12:00am
Hi Zach, I use your configuration on my server and I think is great, it works flawlessly. I have question regarding some caching issues. I have a views counter on my Wordpress website/theme and the counter uses my custom function for unique views. Is there any way I can exclude that part of my page/code from being cached, because I figured out that because of caching my counter doesn't work. I use your Full setup without W3 Total cache plugin. So, maybe you could explain how to do this for me and for future users with same problems. Thanks in advance.
RazvanS says:
November 27th 2015 at 12:00am
Hi Here's a new and very cool plugin for implementing Varnish Cache on Wordpress. https://wordpress.org/plugins/vcaching/screenshots/ It's the only Varnish Cache plugin with this many options for Wordpress. Hope you like it.
Kingsley says:
April 15th 2016 at 12:00am
This is great, please try and reply
Shawn says:
April 29th 2016 at 12:00am
Hi Zach, What is the use of memcache or APC for this install? it seems its just sitting there doing nothing. I maybe wrong. Thanks.
matthewmiao says:
May 30th 2016 at 12:00am
hi, Zach, Thank you for your excellent work. I have one issue with the High performall full package. Brand new Digital ocean server, 14.04, follow exactly your tutorials. But I am having problems, TASK [percona : Install Percona server] **************************************** The Task takes very much time, and at the end of that, it prompts one fatal error.
Daniel says:
June 16th 2016 at 12:00am
Hey Zach, Thank you very much for this. It works really good. I'm trying to do something and going crazy with it. I've installed the full version (with varnish and other stuff) I try to redirect www.example.com to example.com (www to non-www). I add to the nginx config: return 301 $scheme://example.com$request_uri; When I added, it makes an infinite loop and sometimes show me other internal website (other site). Maybe is a problem with VARNISH? What's wrong? Some people in our team it's trying to solve it but we absolutely don't know. I hope you can help us, Thanks
Lux Interior says:
April 11th 2018 at 12:00am
Great article Zach! Do you have any updates for setting up an optimum WP server in 2018? Thanks - Lux

Leave a Reply

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