My first blog was launched from my university dorm room in 2001, using my personal computer as the web server for a long-forgotten XML-based CMS.   Over the next 16 years, I’ve created new sites using over a dozen different blog and content management platforms.  The websites I’ve created have had hosting costs from a few dollars to a few thousand dollars per month: from a few dozen to a few million visitors per month.  I’ve also been fortunate to work on larger projects serving tens of millions of users – Match.com and projects for an ad agency (VML).

Most of my projects during the last five years have used either WordPress or the Umbraco CMS.   I’ve written about when I choose either one, but in this guide, I want to focus on hosting your own WordPress instance on small to medium servers.  I used the practices to host blogs and online publications, including Liberty.me, TheObjectiveStandard.com, and the FreeCapitalists.org blog network.

There are a lot of guides for specific technical steps, so here I focus on high-level choices and practices for your site:

1: Don’t host your own WordPress site unless you absolutely have to

Hosting a blog yourself only makes sense for a small minority of sites – everyone else is better off using:

  • Wix for beautiful site templates
  • Medium for powerful community network, great writing and sharing platform
  • WordPress.com for personal blogs and sites with no custom plugin needs
  • WP Engine for larger sites
  • WordPress VIP for high-traffic blogs with big budgets

Why hosting your own blog is a bad idea:

  1. You need to upgrade the blog and operating system on a regular basis or your blog will inevitably be hacked and taken over by spammers.
  2. Sometimes your blog will be hacked anyway (because one of your admins used a weak password or had his computer hacked, or you installed a vulnerable plugin) and you need the expertise to fix it.
  3. Data loss can happen for many reasons – human error, Russian hackers, hardware crash, and much more.  If you haven’t been keeping regular backups all along, you just lost your entire site.
  4. Your site may work fine 99.9% of the time, but if it’s unable to handle a traffic spike from a sudden burst of publicity, you will go down at the most crucial time.  The third party hosts above can either dynamically allocate resources, or quickly scale them up for you.

When you must host your site yourself:

  1. You need to heavily customize your instance using plugins or integrations that are not supported by a shared host.
  2. You have a very small budget relative to the expected traffic, and you have to optimize performance beyond what a managed host can provide.

For example,

  • With Liberty.me, WP Engine could not handle 100+ plugins + 1600 blogs + BuddyPress, even with their biggest plan.
  • With FreeCapitalists.org, I run several dozen sites for organizations I support for free – each of them would have to pay something like $100/year with WordPress.com.
  • With TheObjectiveStandard.com, I need a Git-based development/deployment process that works with a distributed team, with an integrated e-commerce platform, and a sizable media catalog.  Note: WP Engine supports this, but it would cost a bit more.

In short, hosting your own site assumes a higher risk and a much higher degree of technical knowledge that a typical website, so be sure this path is for you!

2: Choose the right stack: Apache vs Nginx and MySQL vs MariaDB/Aurora/etc

The LAMP (Linux Apache, MySQL, PHP) has been the traditional stack for hosting WordPress and other PHP-based applications.  It’s also near-universal platform for shared hosting (where you do not get access to the underlying operating system on the server).  Traditional LAMP is best for hosting small projects or applications that require Apache.  If shared hosting or a simple LAMP stack for your blog or CMS would suffice for you, you should go with option 1 – let someone else host your blog.  On the other hand, if you need a server which can handle massive traffic with limited resources, then you should probably go with Nginx.   Nginx allows small servers to handle many more connections with faster response times and far less memory.

3: Simplify new server configuration with Easy Engine

Easy Engine is a tool for Ubuntu and Debian which automated configuration and management of WordPress sites.  It automates all the hard work of setting up a new Nginx-based WordPress server:

1: Install Easy Engine

2: Create site

Creating a new site is as simple as:

sudo ee site create example.com

3:  Install an SSL certificate for free with Let’s Encrypt with a single command.

ee site update example.com –letsencrypt

You can configure a cron job to renew it periodically.

4: Configure git-based deployment

I use a git post-commit hook to deploy changes to my development and production environments on commit.

Adding Caching – Page, Object, & Fragment Caching with Redis

There are three main kinds of caching in WordPress:

Page Caching: Provided by plugins like WP Super Cache, page caching stores the entire output of pages.  This works well for simple sites that do not require customizing the output of pages for individual users.  It doesn’t work so well when you have a lot of dynamic content – such as ecommerce or community sites.

Object Caching: WordPress can cache data which may be computationally expensive to regenerate, such as the result of complex database queries.  I use the Redis Object Cache plugin for this.  This will dramatically speed up complex pages that require many queries to render.

Fragment Caching:  a fragment cache is a partial cache of the render output of a web page.  I used it extensively with http://liberty.me/ to cache bits and piece of pages that were otherwise customized for each user.

4: Scale up to high-availability with cloud-scale architecture

The above covers the basics of setting up a WordPress site, and will be fine for the majority of sites hosting small businesses and personal blogs.  If you need to support a higher volume of visitors or the site must stay online no matter what, you will need to scale out the architecture beyond a single server.  You can scale up one component at a time or go for a full-blown high availability website that can dynamically add resources as traffic grows and has no single point of failure.  This means that any of the hardware hosting your website can fail without any data loss or the end users experiencing more than a momentary outage.

A high-availability website is not for everyone – while it does not have to cost much more, it makes everything more complex.   It’s not very difficult to set up, and Amazon has a guide.  However, maintaining a high-availability environment takes a lot more work than a single-server design, so it’s only worthwhile if you really need it.

Scaling out is not an all or nothing alternative.  You can and probably should scale out in staging.   Here is how I scaled out Liberty.me with Amazon Web Services:

Database:  Use a managed database solution instead of running the DB on your web server.  For Liberty.me, I used Amazon Aurora, a drop-in replacement for MySQL.  It supports replication with failover-recovery, so your database never goes down.  It also eliminates the need for maintenance, automates backups, and more.  I created a custom parameter group for Aurora to optimize performance for our 20,000+ table database.

Caching: Next, I switched to ElastiCache for the Redis cache instance, so that all the web services shared the same cache

Media Storage:  I used WP Offload S3 to offload media storage to Amazon S3.   This worked for the default WordPress media storage, but not several third party plugin which handled uploads for BuddyPress features.  I had to hire developers to implement providers for WP Offload.

Load-balanced web services: Once all the data was removed from the web server, I implemented EC2 load balancing and ran the website from multiple instances.  I used the git-based deploy process described above to sync the code between them.

Here is what a highly-available setup for Liberty.me looked like in 2016: