Configuring A Load Balanced WordPress Website With The Rackspace Cloud

I’ve been playing around with the Rackspace Cloud hosting offerings, and as of right now I’ve got this very blog running load balanced on a set of servers. And while it’s a little more complicated than just setting up a single server, it really isn’t that hard. In fact, I’ll walk you through the process.

So why exactly would you need a load balanced website? Well, a single server can only handle so many connections. After a certain point it just can’t handle any more users, and the website starts to slow down or even become unreachable. A load balancer is a device that can spread those visitors over a bunch of different servers, allowing the “load” of those visitors and their requests to be “balanced” over a number of different devices. Especially with the Rackspace Cloud, creating more servers to handle increased load is remarkably simple. Even if you don’t have that much traffic to worry about, in the event that your server crashes a load balancer will let you spin up new servers and immediately start sending traffic their way instead of having to wait for the DNS records to update (which could take 24 hours to 48 hours).

Simple analogy: a single server is like a single twig and will easily break, but a load balancer allows you to tie a whole bunch of twigs together to make a stronger solution.

Before we get started, here’s a quick overview of the steps we’re going to take:

1. Spin up and configure a complete WordPress server.
2. Duplicate the WordPress server and set up as SQL server.
3. Force WordPress server to use remote SQL server.
4. Configure cloud storage solution for images and uploaded files.
5. Configure Load Balancer and DNS records.

OK, here we go!

1. Spin up and configure a complete WordPress server

The easiest way to configure the load balanced system is to start with a complete and functioning server with everything running just the way you like it, and then slice it up from there. So the first step is to spin up a new server. Windows, Linux, whatever — it doesn’t really matter. But for the purposes of this walk-through we’re going to be using Fedora Linux 16. Rackspace already has a great article about how to set up a cloud server instance, so I’m not going to go over that again.

Once you have your server set up you need to have the following things running:

  • Webserver (IIS / Apache)
  • SQL Server (Microsoft SQL / MySQL)
  • PHP

Personally, I’m an Apache/MySQL/PHP kind of guy as they’re much easier to configure for me, but pick your own poison. Again, Rackspace has some good articles on how to do it or you can scour Google. I also like to slap PHPMyAdmin on there because it makes administrating MySQL a whole lot easier.

At this point you should have everything squared away on your server — MySQL up and running, WordPress installed and properly configured, firewall allowing HTTP access and the operating system fully updated. If you have a domain name for the WordPress site you should point it to the server now and make sure everything is working using the domain instead of the IPs — this will save you some trouble down the road. Go ahead and take a quick image of this server (another Rackspace article there) so that if everything goes sideways you still have something to work with.

2. Duplicate the WordPress server and set up as SQL server

Now we need to slice out the MySQL server and set it running on a standalone system.

“Wait, WHAT?!” I hear you cry, and there’s a good reason for it. Putting the SQL server on a different system makes the traffic susceptible to sniffing and requires you to open up the SQL port in the firewall, but it needs to be done. But first, the reason it needs to be done.

WordPress uses the SQL database to store just about everything, including the text of your posts and the comments. When you have a single server it makes sense to have the SQL server on the same box, but when you have multiple servers running the same website the only way to have them all running and showing the exact same content simultaneously is to have a single central SQL server with the “master” copy of the database. You’ll still need to replicate the uploaded files (pictures and so forth) across the different web servers, though.

So, now that everything is running you will need to spin up a new server to act as the central SQL server. Take an image of the running server that you have and spin up a new one from that image (see article here).

Now that you have an identical server running we need to slice some things out to slim it down and improve performance, as well as allow other servers to use it.

1. Set the permissions on the MySQL Database for your WordPress installation to allow connections from anywhere and not just the local system. This is best accomplished using the “Permissions” tab in PHPMyAdmin.
2. Disable Apache on the system. Don’t uninstall it (as you’ll need it for the PHPMyAdmin system), simply disable it. Use this command: sudo service httpd stop

We also need to open the firewall to allow MySQL connections (port 3306). This traffic should never leave the Rackspace network, but since it is still technically a public connection you should still pick a good username / password combination to protect the server. Open the iptables config file in a text editor (sudo vi /etc/sysconfig/iptables) and pop the following line at the top of the config:

  • -A INPUT -p tcp –dport mysql -j ACCEPT

Save the file and reboot the server for good measure.

3. Force WordPress server to use remote SQL server

You now have one working COMPLETE server, and one working SQL-only server. The next step is to tie the two together.

WordPress uses a file called “wp-config.php” to keep track of the MySQL connection information. The file is stored in the root directory of the WordPress installation. Since we created the SQL server based off the existing running complete server, we can assume that the username and password combination in this file is correct and the rest of the database is compatible. The only thing we need to change is the address of the server.

When we’re picking the IP address we want to connect to, we have a choice. We can either use the public IP of the server (listed on the Rackspace Cloud control panel page for the server) or we can find the private IP of the server and use that instead. The private IP address will force the connection to route over Rackspace’s internal network instead of going over the public Internet and so makes the connection less likely to be sniffed (especially if the servers are in the same datacenter). You can find the private IP address of the SQL server by SSHing into the computer and running “ifconfig.” The private IP will usually be a 10.x.x.x address on eth1.

Here’s the corrected line you need to update in wp-config.php using either the public or private IP:

  • define(‘DB_HOST’, ’′);

Where is the IP address of your SQL server. If you have a DNS record for the SQL server you can slap that in there instead and pop some single quotes around it. Like so:

  • define(‘DB_HOST’, ‘’);

There are a couple errors that could arise once you make the change to the WordPress configuration, and thanks to my own idiotic stumblings I’ve experienced most of them. Thankfully I also have a solution. So, if you get the following errors on your WordPress site when trying to load it after making the switch, this is what’s going on:

  • Unable to establish a connection… : The WordPress installation is trying to connect to the newly designated MySQL server, but can’t get it to work. This specific error is indicative of the network connection itself being unable to make it between the servers. Ensure that the IP address or domain name of the server that you specified in the wp-config.php file is correct and responding to pings from the web server itself. Also ensure that the firewall on the SQL server is allowing the traffic.
  • HTTP 500 Error: Also known as the “internal server error,” this indicates that the connection to the SQL server is up and working, but something else is amiss. Make sure that the account (username and password combination) you’re using in the wp-config.php file is granted the right permissions on the SQL server for the database for the WordPress tables, and also that the account is allowed to be accessed from any IP address and not just the local host.
  • The site isn’t the latest version: If you spun up the SQL server instance using an older image of your single complete server (for example, if you’ve published new stuff since then) you might not have all of the articles in the SQL server’s database. You can either type them in on the new system or spin up and configure a new SQL server from an image of the current server being sure to tell your writers to hold their horses for a bit.

At this point you should be looking at one server running Apache and PHP with the WordPress files on it, and one server with MySQL and the WordPress content on it, and they should be working together to serve the website.

4. Configure cloud storage solution for images and uploaded files

The next issue is with the images and other files associated with your WordPress site. In a normal configuration all of the media files are stored on the webserver itself, but because we now have multiple webservers running it’s very hard to duplicate the files across both servers efficiently. Thankfully Rackspace’s Cloud Files solution offers a great alternative storage method for all the images you want to post on your blog, and a WordPress plugin is available to do all of the hard work for you. CDN Tools is a third party plugin that will automatically upload all of your files to the Rackspace Cloud Files service and do the magic to make them appear in your posts. An added benefit is that because the images are being served from a content delivery network — instead of the server itself — it reduces the load on your webservers and makes the site load faster.

5. Configure Load Balancer and DNS records

Now we just need to set up the load balancer.

Think of your server configuration as a straight line. On one end you have the Internet, where your readers will come from to visit the site. The first thing they should hit on their way into your network is the load balancer, which will direct their traffic to the appropriate server based on some parameters we’ll set up. Next in line are the web servers, the dumb systems that simply serve static HTML or PHP pages and respond on port 80. Those systems talk to the “brains” of the operation, which is last in line, the SQL server that listens on port 3306. The SQL server sends the webservers whatever content the reader wants to see; the webservers spice it up and make a presentable web page based on the WordPress files; and the load balancer remembers where the traffic came from and sends it right back to them. Now that we have the infrastructure spun up to handle a load balancer, we need to spin up the load balancer itself.

Rackspace has a great article on how to spin up a load balancer, and you should follow it to configure the LB. Set the webserver we’ve spun up (the one with Apache still running) as the only node behind the LB for now.

With the load balancer up and running you now have a complete solution. Using the public IP address of the load balancer you can change your DNS records to point your various domains to that LB. Remember to setup Apache with a virtual server in the configuration files of the SERVERS (nodes) for each domain name you want to point towards your load balancer, as the LB will blindly pass the traffic along without altering it and allow you to run as many sites off that one configuration as your heart desires.

At this point you should take an image of the webserver (the node) that is running behind the load balancer. If you see your server starting to slow down, all you have to do is spin up a new instance of that server and designate it as a node in the load balancer’s configuration. Traffic should be balanced between the servers automatically and your site will remain up and responding.

And that’s how you set up WordPress in a load balanced environment with Rackspace Cloud. Well, at least that’s how I did it. And I think I did a damn fine job.

Nick Leghorn was a network security administrator for Rackspace. He graduated from Penn State's Security and Risk Analysis program and spent some time working for a government contractor before being hired by Rackspace to work on its network security team. In his spare time he writes for The Truth About Guns, the most widely read firearms blog on the Internet, and recently published his first book which is now available on Amazon as a paperback and on Kindle. For more information visit or follow @nickleghorn on Twitter.


  1. Interesting article but surely configuring MySQL to allow remote connections and then opening Port 3306 to EVERYONE is terrible practise?

    You should only allow remote connections from your “S1” and “S2” instances surely? And this is easily done using the MYSQL Host permissions and the IPTables firewall rules. The IPTables rules can block connections on eth0 (the public cloud network interface) and only allow on eth1 (the private cloud network interface) helping to further secure the traffic from snooping.

    I recognise this is a “quick” guide but to not make reference to this fairly large security hole you’re leaving seems a bit careless.

    • Simon,

      Its entirely possible to setup the SQL server so that only connections from your WordPress servers are allowed, but the main issue I see there is when it comes time to quickly spin up a bunch of servers. You would need to add each one individually to the iptables access list. The way to take advantage of the APIs available for the cloud, specifically some that will spin up new servers to meet demand automatically, is leaving that port open.

      There are many, many things you can do to harden your SQL server. The most important by far, and the one that made it into my article, is picking a good combination of username and password. Strong passwords, patched systems and automatic backups is enough to thwart the vast majority of attacks out there.


  2. Depending on requirements, you may also want to factor a 2nd database server into the equation and configure replication. For low volume, master-master will work nicely, but larger volume, likely master-(read-only)slave with a little DNS magic to determine the correct node.

    You might also need to think about sticky sessions (LB configuration) to ensure users don`t bounce between webservers and lose logins.

  3. I understand the configuration, but I want to make sure I understand a couple of things not touched upon. When it comes to files associated to the load balancer. Lets say I do not want to use a separate place for image files, but the physical server, this would mean I would have to duplicates files each time on each server? Also what about changes to files not associated to the database. Does the load balancer keep these files in sync? For example if I make a css change on the “s1” server, do I also have to make these changes to “s2” as well? Would it be better just to re-image the server each time with the newest updates? Seems a littler cumbersome? or should I boot up a 3RD server with the newest image, once that is up delete the “s2” server?

    • Hey Carlos,

      The load balancer doesn’t sync the configuration between the servers. So if you make a change to one server, you’d have to make it on the other server as well.

      If you want to only serve content from one of the servers (say, you want all images to come from s1) you can make a subdomain for that server’s IP address and use the URL of the image instead of uploading the image to WordPress. That would bypass the load balancer and ensure that all images come from the same place.

      Example: = (LB) = (S1 Direct)

      You may have to edit the Apache config to enable this subdomain to work on your server in addition to the standard domain name.

      The best solution if you don’t want to use something like cloud files is to replicate all of the images in a folder on your server. Something like /images in the www directory. You can link directly to images in there from WordPress ( as long as the two servers are identical it will correctly serve the images.

      What I’ve found to be the best is to think of one server as the “master” server and the others as clones. Every once in a while, or whenever you do some major work on the code, simply image the “master” server, delete the old clones and make some new ones. keeps everything nicely in sync.

      Hope that helps!

    • Assuming that you are using Cloud Files, you can make the css change there and it should appear or sync across all of your nodes automatically. Correct?

  4. at 2. Duplicate the WordPress server and set up as SQL server

    I tried to the following:
    1. Set the permissions on the MySQL Database for your WordPress installation to allow connections from anywhere and not just the local system. This is best accomplished using the “Permissions” tab in PHPMyAdmin.

    <<< Can you elaborate more on how to do it?

    2. Disable Apache on the system. Don’t uninstall it (as you’ll need it for the PHPMyAdmin system), simply disable it. Use this command: sudo service httpd stop

    <<< Stop httpd fail, I am not sure why.

    We also need to open the firewall to allow MySQL connections (port 3306). This traffic should never leave the Rackspace network, but since it is still technically a public connection you should still pick a good username / password combination to protect the server. Open the iptables config file in a text editor (sudo vi /etc/sysconfig/iptables) and pop the following line at the top of the config:

    -A INPUT -p tcp –dport mysql -j ACCEPT

    <<< I manage to add in the lines. But how should i save and exit? Do i need to restart?

  5. I question the benefits of load balancing the web server, but then having a single database server become the single point of failure. Seems like load balancing 2 servers, both running web+mysql then working out the replication between them is safer, and a cheaper solution requiring only 2 servers.

    I guess load-balancing in this case is really just load balancing, and not fault-tolerance.

    • Most cloud services (like Rackspace used here) provide a virtualised database cluster, so you’re not really relying on one database. You might be able to do something similar by setting up your own cluster of MySQL instances, one on each compute node, but that’d probably result in a lot of internal changes to WordPress, as they’d have to know which one was the master (for writes) and which were the read-slaves it could round-robin amongst.

      The real problem is that WordPress wasn’t designed to be load-balanced. Installing an addon via the admin interface will only install it to one compute backend; some plugins (looking at you W3 Total Cache) store their configuration on disk, so if you configure it once in the backend, it’s only ever applied to a single node.

  6. We have 4 VMs set up behind a cloud load balancer. We installed WordPress on all 4 VMs. Each WordPress instance connects using its own User in MySQL. MySQL is on one of the VMs. All 4 nodes are enabled. Now the issue is, after few seconds or a minute, the other 3 VM’s are getting connection errors with MySQL. However the VMS where MySQL is installed is always fine and able to connect. So we are get a working instance after few tries, followed periodically by a “Error establishing a database connection”. Any ideas on how to help?

  7. I saw that issue coming as well in my setup. I run everything behind A10 load balancers on virtualized web and DB servers. I created an NFS export on our NetApp filer, mounted it to all of the web servers and installed WordPress there. It is pointed to a central DB server. All of the web servers are able to access and serve up WordPress and in the event of updates or installs, any of the servers in the pool can perform the task and all receive the update since they see the same source.

  8. I think its better to store web on network file system.
    I have it as following: Web servers ‘www1′,’www2′,’www3’ – they have directory /var/www mounted to ‘storage1’ server via GlusterFS. Its super easy to scale, when i want more power i just clone the instance and write one line to load balancer.

  9. How do you suggest to configure wp-admin?

    I mean, any file changes (media, plugin) done through wp-admin will be done on one of the web servers, not on both. Is there a way of changing wp-admin location to subdomain ( and pointing that to other admin node which won’t go through Load Balancer. Instead, this admin node will sync up with both web nodes.

    Let me know what you think.


  10. Hey I am so grateful I found your webpage, I really found you by accident, while I was searching
    on Askjeeve for something else, Regardless I
    am here now and would just like to say kudos for a remarkable post and a all
    round entertaining blog (I also love the theme/design), I don’t have time to browse it all
    at the moment but I have book-marked it and also included your
    RSS feeds, so when I have time I will be back to read more, Please do keep up the fantastic work.

  11. Can I just say what a relief to discover someone that truly understands what they’re talking about
    on the web. You certainly know how to bring a problem to light and make it important.
    More people ought to look at this and understand this side of the story.
    I was surprised you’re not more popular since you most certainly have the

  12. Skype has established its web-based client beta on the entire world,
    right after establishing it largely from the U.S.
    and U.K. earlier this month. Skype for Online also now supports Chromebook and Linux for instant online messaging connection (no voice
    and video yet, these need a connect-in set up).

    The increase from the beta contributes assist for a longer listing of different languages
    to aid reinforce that overseas functionality

  13. Hi Nick, thanks for the details.
    When we use centralized database how can we store multiple WordPress environments URL’s (siteurl and home fields) information in WordPress database (wp_options) table. To be specific each WordPress environment has it’s own URL, how can we configure siteurl and home fields information for each instance? Your prompt response would be much appreciated. Thanks in Advance.



Please enter your comment!
Please enter your name here