Disclaimer: I imported this post from WordPress to Jekyll on 9/2/23. Forgive the misformatting until I get a chance to clean it up.
Update 7.19.16: The guide on GitHub has been dramatically updated since the below post was written. I am working on a revised post, but for now, I would recommend just jumping over to the GitHub project rather than spending much time reading this post. Thanks!
When it comes to hosting WordPress, there are more options than ever before. I began, as many others do, using budget shared hosting from GoDaddy and BlueHost. Soon, however, I realized that shared hosting just does not cut it for a site of any decent functionality or size. There is a current batch of WordPress-optimized hosting from companies like WP Engine, StudioPress Sites, or SiteGround that provide an excellent service, but the price usually reflects that. I wanted to host my sites on a modern, cutting edge stack without paying the premium of these providers. I wanted to build a DIY WordPress VPS, something I accomplished for $5/mo. with DigitalOcean.
So, for the last few years, I have been piecing together and updating a guide so that I could remind myself how to build the server. The steps are quite verbose, without any build automation such as Ansible or Puppet, so as to reduce the learning curve and to iterate rapidly without extra overhead. I decided to “open source” the guide on GitHub recently (link at the end of the post), so I hope that it can help a few others as well.
Component | Solution | Notes |
---|---|---|
Development Client | macOS | |
Production Host | DigitalOcean | |
Server | Ubuntu LTS x64 | |
WordPress Management Tools | WP-CLI | |
Database | MariaDB | |
Object Cache Store | Redis | |
PHP Compiler | HHVM | |
Web Server | NGINX | w/microcaching |
Connection | Modern TLS Ciphers HTTP/2 ipv4/ipv6 |
The first inspiration I received to try this stack was Mark Jaquith’s talk, “Next Generation WordPress Hosting Stack.” It is worth a listen, and I based this build guide largely on Mark’s talk.
I selected Ubuntu due to its low barrier to entry and a broad range of support. Other options may have been leaner, but Ubuntu is fast, stable, and well-documented. The current LTS (long term support) version, Ubuntu 14, by default, uses an older kernel, however. I chose to upgrade the kernel to capture some more recent improvements, but some may choose not to do so for stability purposes.
Since I am relatively new to the industry, I did not have a lot of history with Apache. NGINX is being regarded by experts as very responsive, lean, and memory efficient. While none of my sites are very demanding yet, I have found that NGINX does, in fact, perform very well. Implementing micro caching via FastCGI helps reduce the I/O back to the PHP engine, further reducing the latency of NGINX.
I chose MariaDB purely based on others’ opinions that it slightly edges out MySQL in performance, etc. I do not have a strong preference, however, between MariaDB, MySQL, or Percona. Any of them should work fine. It is important to perform at least some basic optimizations on the database server, though, such as enabling query caching. There are a variety of tuning scripts, such as MySQLTuner, which help novice database administrators tweak this further.
The battle between PHP-FPM and Facebook’s newer HHVM for PHP processing is heating up with the recent release of PHP 7. The benchmarks that I see still show HHVM outperforming php7-fpm, though it is much closer than with previous iterations of PHP-FPM.
Object caching via Redis is the last server-side optimization that reduces the server’s latency. Because WordPress relies on large queries to the database every time it serves a page, caching chunks of these query results in memory saves a significant amount of time and load on the database server.
Also, in this guide, I describe how to configure TLS encryption using the new and free Let’s Encrypt service (I have recommended a 4096-bit RSA key because I am a bit of a security nut, but a 2048-bit key should be perfectly fine). Not only is encryption so easy today, and highly recommended since WordPress collects credentials and other personal information, but it paves the way for configuring HTTP/2. NGINX now supports HTTP/2 natively which provides quite a few in-transit optimizations such as compressing headers and handling concurrent requests much more efficiently.
I spent quite awhile testing and using Google’s PageSpeed Module (also available for Apache) to perform optimizations on the front-end DOM contents before leaving the server. Minification, image compression, etc. are all valuable ways of speeding up page load times, but I was never able to get the benefits to justify themselves in my setups. The latency introduced by PageSpeed’s processing outweighed the benefits.
Additional technologies that other hosts use include varnish caching, Apache instead of NGINX, or memcached instead of Redis for object caching. I have not worked with any of these; however, from my research, they are outperformed by the selections currently in the guide.
These are the decisions that I have landed on after some research and testing over the past years, but I fully expect the stack to morph over time as the technologies change. The guide, as I said, is somewhat verbose. If you want to turbocharge your WordPress site on a small budget, give it a shot. If you are experienced in operations and see something that should be improved or changed, please let me know or submit a pull request. wp-vps-build-guide