How to Host Your WordPress Site on Multiple AWS Server Instances
You’ve almost definitely heard about Amazon Web Services. And, given that you’re on this site, I’m going to make the obvious assumption that you’ve heard about WordPress, too. But what you might not have heard about is combining WordPress with Amazon Web Services (AWS) for web hosting.
Articles about hosting WordPress on shared hosting, CPanel hosting, managed hosting and what have you are a dime a dozen. Yet AWS is yet another infrastructure that can be used to host your WordPress site. Not only that, but given that an AWS infrastructure is elastic, it’s a great place to set up a WordPress installation that can be autoscaled to meet demand.
So in this article, let’s get down to the business of setting up a WordPress site on multiple instances of AWS servers.
Note: Here’s a quick guide on how to install WordPress on a single AWS instance (like the one that comes with its Free Tier account). Once you know how to set up a WordPress installation on AWS, check out our articles on setting up WordPress for autoscaling to multiple instances to be able to handle spikes in traffic.
Step 1: Registering an AWS Account
First things first: If you still haven’t ever tried Amazon Web Services, head to https://aws.amazon.com and click on Create an AWS account.
You can use your regular Amazon account to log in, but following the normal login you’re going to have to go through a process for verifying that there is an actual human behind the person registering the account. You’ll go through the process of filling in your details, actually verifying the account through a phone call, setting up a credit card for billing purposes and a whole host of other standard registration stuff.
Once you get through the registration process, you should finally get access to the AWS Services Dashboard, which looks a little bit similar to this:
If it’s the first time you’re getting access to this it’s a little overwhelming. There’s so much stuff to choose that you’ll actually get pretty confused if you’re not used to this.
Let me run you through a few quick explanations of the most common instances you can use. Truth be told, I don’t even know what half of the services mean, but doesn’t have to worry me (or you) much!
EC2 – the Amazon Workhorse
Amazon Elastic Compute Cloud (Amazon EC2) is a web service that provides resizable compute capacity in the cloud. It is designed to make web-scale cloud computing easier for developers. In more simple terms, this is computing power on tap. You can simply start instances of virtual machines here which can be used for whatever you need to run.
S3 – Storage on Demand
Amazon Simple Storage Service (Amazon S3) is object storage (or disk space) with a simple web service interface to store and retrieve any amount of data from anywhere on the web. It is designed to deliver 99.999999999% durability, and scale past trillions of objects worldwide. Simply put, it is very reliable and can get very very big (should you need to). Services such as DropBox are powered by S3.
RDS – Relational Database in the Cloud
Amazon Relational Database Service (Amazon RDS) makes it easy to set up, operate, and scale a relational database in the cloud. Amazon RDS provides you six familiar database engines to choose from, including Amazon Aurora, PostgreSQL, MySQL, MariaDB, Oracle, and Microsoft SQL Server.
CloudFront – Amazon’s Content Delivery Network
Amazon CloudFront is a global content delivery network (CDN) service that accelerates delivery of your websites, APIs, video content or other web assets. It integrates with other Amazon Web Services products to give developers and businesses an easy way to accelerate content to end users with no minimum usage commitments.
SES – Simple Email Service
Amazon Simple Email Service (Amazon SES) is a cost-effective email service built on the reliable and scalable infrastructure that Amazon.com developed to serve its own customer base. With Amazon SES, you can send and receive email with no required minimum commitments – you pay as you go, and you only pay for what you use.
Step 2: Designing Your AWS WordPress Infrastructure
How do these servers relate to our AWS WordPress setup?
We will be using EC2 to create a web server instance to power our AWS WordPress installation. We can also use this to install a MySQL database to power our WordPress database.
RDS services are optimized database instances for running database based applications. We will be using one of these instances for our database since these are highly optimized for performance and scaling.
A CDN goes hand-in-hand with WordPress performance, so using CloudFront will give us a CDN powered by Amazon Web Services for our WordPress site.
Our media will be stored on S3 instances and distributed via the CloudFront CDN.
Whilst you may choose to use your EC2 instance for sending mail, we typically opt to use Simple Email Service instances because, once again, since these are optimized for sending email, we won’t run into such issues as bad neighborhoods and other mail delivery issues. This is particularly relevant if you plan to send mass mailings.
Designing Your Infrastructure: Scaling Out vs Scaling Up
There are hundreds of ways you can set up your WordPress infrastructure. If you want a small instance to host your small site, we’re going to discuss LightSail later on, which is Light VPS which Amazon have launched very recently. You can also set up all of your WordPress instance including server, PHP and MySQL database on a single EC2 instance. However, this is not going to take your performance very far – once you hit the physical server limit, you’re done.
So what’s this scaling out vs scaling up jargon? There are two primary ways of increasing the throughput / performance of your website.
- Scaling up aka scaling vertically – this means increasing the actual hardware / memory resources used to power your website. Essentially, you increase the RAM, CPUs and other hardware allocated to your website. If you’re on a shared server, you go to a VPS. If you’re on a VPS, you increase the RAM and / or CPUs allocated to your server. If you’ve reached the maximum hardware on shared hosting, you buy a dedicated server. When you’ve exhausted the dedicated server, you switch to a more powerful server with better hardware.
- Scaling out aka scaling horizontally – as I’ve hinted slowly in the previous paragraph, you might notice that scaling up has an actual physical limit – the hardware running your website. If your website is exhausting the physical hardware its hosted on, you’ve run into a problem. Scaling out, rather than throwing more hardware at the server, throws more servers at the website. Essentially, we farm out each component of the website to a different server. That, of course, allows our website to handle a much heavier load because we have multiple servers handling the load.
Our setup is designed with scaling out in mind. For this reason, we’re going to use different instances for each component of WordPress. This will allow us to scale up (increase the computing power) and scale out (increasing the number of instances doing the work) as part of our infrastructure to handle additional load.
In particular, we’re going to use multiple web servers to be able to handle large amounts of traffic. We will also be setting up a load balancer, which will determine which server to send requests to.
This means we’re going to be creating at the very least the following difference instances:
- A database component using RDS
- (Multiple) WordPress installation component(s) using EC2
- A mailing service component using SES
- (Optional) A CDN component using S3 and CloudFront
There are also multiple ways of actually designing this infrastructure. AWS also has pre-defined Application Containers. The idea is that certain specific common applications development environments have pre-defined instances which can be activated at the click of a button.
A word of warning: Amazon has so many possible configurations and setups possible, that it is quite difficult to understand them without lots of experience, let alone explain them in a single blog. For this reason, we’ll be taking some shortcuts and not explain everything in detail. For further reading, refer to the AWS documentation.
Scaling Out a Database
Scaling out a database to multiple instances is possible, however, the complexities of performing such a configuration are way beyond such a blog.
We’re thus going to restrict our infrastructure to a single instance of the database. Now, although this may seem like a limitation, in reality, having a server instance dedicated solely to the database means that the website would be able to handle significant amounts of traffic.
We will also be using Aurora DB, Amazon’s own build of MySQL which is optimized for performance and for the cloud.
This, coupled with the fact that our database instance can get pretty high-speced in terms of performance should ensure that the database would never become a real bottleneck.
To ease the load of the database components further, one would also enable WordPress caching to ensure that database hits are kept to a minimum.
All-in-all, our decision to keep a single instance of the database should be sufficient for most website loads, unless your website will be handling tens of thousands of hits per second. In that case, you can probably afford to hire an expert to configure your website!
Step 3: Setting up Your WordPress Database Instance
To set up a WordPress installation on Amazon Web Services, you’re going to need a few components. The first you’re going to need is a database service, so go to RDS and launch a MySQL instance.
If you’re just testing out stuff, you can choose to create a DEV/Test environment. On the other hand, if this is your production environment, you have two choices:
Option 1: MySQL
This uses a multiple Availability Zone (i.e. you will have a Primary instance and a secondary instance on standby in case of failure of the primary instance). The creation and failover to the secondary standby instance is completely transport – it is of course designed for High Availability and Provisioned IOPS Storage for fast, consistent performance.
Option 2: Aurora DB
This is the recommended configuration. Whilst this is not strictly MySQL, Aurora DB is a custom build created by Amazon, specifically optimized for higher performance and better reliability. Tests have shown that instances of WordPress on Aurora DB run up to 3 times faster. This is also classified as Enterprise level performance, so if you want absolutely top-notch performance, you should go for this option.
Once you’ve selected Aurora DB, you need to specify some basic configurations. You’ll need to figure out what the right DB Instance Class for you is. Besides actual throughput, you’ll also need to consider DB Instance pricing.
Take note of the of settings you are using, particularly names, because we’re going to need them later on when we’re creating the WordPress instance.
Step 4: Creating and Setting up Your Web Server Infrastructure
Once our database has been created, we’re now going to set up our web server. We’re be using an EC2 instance to run our WordPress web server.
Once again, you’ve got various options to install WordPress on an EC2 instance. If you head over to the AWS MarketPlace, you’ll find preconfigured instances of WordPress which you can get up and running in next to no time. These come with the added benefit of using a tried and tested configuration.
The AWS MarketPlace also allows you to install very specific WordPress configurations. For example, if you want to push performance to the limit, you might want to use an Nginx web server rather than an Apache web server. There are various Nginx configurations available on the AWS Marketplace.
To create a new EC2 instance, access the AWS Management Console and click the EC2 tab:
- Choose an Amazon Machine Image (AMI) in the wizard: a good choice for WordPress would be Amazon Linux AMI 2016.09.0 (HVM), SSD Volume Type 64-bit.
- Choose the Instance types details: Once again, this is something that depends on two main things: the expected traffic, and consequently, the throughput and performance you need, together with what you are prepared to pay for them. You can learn more about EC2 Instance types here. Select the Instance Type you want to use.
- Create a new key pair. Enter a name for your key pair (i.e. WordPress_AWS) and download your key pair (i.e. WordPress_AWS).
- Select the quick start security group.
- Launch your instance.
Woohoo! You’ve got our main components setup!
Setup correct inbound and outbound rules to be able to access the server through HTTP. Using the security groups, you can edit the inbound and outbound rules to add firewall rules as necessary to allow traffic to the various instances you have created.
Step 5: Install Apache Web Server + WordPress
So now that our actual server instances are up and running, we need to get all of our software components in place.
Install the Web Server
We’re going to skim through a few steps which we’re going to assume are pretty standard stuff.
- SSH into your web server instance (EC2)
- Install the Apache web server (sudo yum install httpd)
- Start the web server server (sudo service httpd start)
Test whether the server is up and running (Access http://ec2-54-202-202-135.us-west-2.compute.amazonaws.com – you’ll actually need to enter the public DNS name of your EC2 instance). If you are unable to connect you’ll need to make sure that the security groups have been set correctly to allow inbound HTTP traffic.
Install PHP on the Web Server
- Install the PHP package specifically for MySQL (sudo yum install php php-mysql)
- Restart the Apache Web Server (sudo service httpd restart)
- Create a test.php file which simply runs phpinfo()
type i to start the insert mode in VI
Type <?php phpinfo() ?>
Type :wq to write the file and quit vi
Open a browser and access test.php to test your PHP installation: http://ec2-54-202-202-135.us-west-2.compute.amazonaws.com/test.php (Use your actual public DNS name).
Great, so now we know our web server is up and running with PHP5.
Download, Install and Setup WordPress on the Amazon Web Server
Given that PHP is working on our web server, we need to download and install WordPress. Let’s download and configure our WordPress installation.
- Go to the public HTML folder of the server where we will be installing WordPress (cd /var/www/html)
- Download the latest version of WordPress (wget http://wordpress.org/latest.tar.gz)
- Uncompress the file we’ve downloaded (tar -xzvf latest.tar.gz)
- This will uncompress WordPress in its a directory called “wordpress” directory. We will rename this to something which makes more sense, so that we can set up more stuff on the web server. Let’s rename it to blog. (mv wordpress blog)
- Create the WordPress wp-config.php file and modify the database connection parameters as follows – of course, you’ll need to use your own set of parameters which you’ve used when creating the Aurora DB instance
Type “i” to start insert mode.
Edit with the correct parameters.
Type “:wq” to write the file and quit “vi.”
If you’re not sure of what values you’ll need to enter, you can find the details you’ll need to use by using the details found on your Aurora Database instance.
Open a Browser and access your new WordPress website blog: http://ec2-54-202-202-135.us-west-2.compute.amazonaws.com/blog (Use your actual public DNS name).
This should trigger the WordPress configuration process. If you get an error establishing a connection to your database, you either have some of the database details which are incorrect or possibly you need to ensure you’ve setup a correct security group with the correct firewall rules (this is a bit outside the scope of this blog).
Run through the 5-minute install (which should actually take much less, since everything should be nearly done), setup a WordPress administrator, a strong password and you should be good to go.
Once you’re done you should get a nice fresh, new install of WordPress!
Step 6: Setup an Amazon Mailer (SES) Instance with WordPress
SES or Simple Email Service is just that – a way of sending email where you pay as you go based on the volumes you send. If you’re planning to send newsletters or other mass mailing to thousands of users, SES is a good, reliable, cheap choice, if you just need a volume sending server. If you’re looking at more complex stuff for sending emails, we make a few great recommendations for growing your email list and sending emails here.
To be able to send emails using SES, you’ll need to verify that you own and are able access to the domain you’ll be sending emails from. You can do this by creating DKIM DNS entries to your domain.
Follow the AWS SES domain verification process:
Once you’ve created and verified the domain through your DNS settings, you’ll need to setup an identity (email address) to send from. Again, there is a verification process associated with creating an identity, so follow that through to verify you have access to the email address.
We’re not ready yet – we need to create credentials to be able to access the SES server via SMTP. To do this, go to SMTP Settings and create a new set of SMTP credentials of our WordPress website.
This will involve creating a new IAM user which will have an SMTP Username and SMTP password.
Now, using SMTP with WordPress requires the installation of the WP Mail SMTP Plugin.
Copy the username and password and put them directly into the WordPress SMTP settings plugin details. You will only be shown these details once – a safety precaution meant to keep access to the SES servers limited.
Step 7: Serve WordPress Media from Amazon’s CloudFront CDN (Optional, But Recommended)
Since we’re on the subject of boosting performance, integrating Amazon’s CloudFront CDN would help scale out our setup further, allowing the site to achieve better levels of performance. As we’ve discussed on this blog (and elsewhere), a CDN gives your website a performance boost by serving static, heavy resources from a location which is closer to your website’s visitor.
To integrate the WordPress site with CloudFront, you can use the Amazon S3 and CloudFront WordPress plugin, to store the media folder onto Amazon S3 and then serve it through Amazon CloudFront. This has been already been covered in detail by our very own Daniel, so have a look at How to Move WordPress Media Folder to Amazon S3.
Step 8: Connect EC2 Instance with Your Domain
To be able to use the AWS WordPress installation with our domain, we need to associate a public IP address to our instance and then map our domain name to that IP address.
Associate an IP Address to an EC2 Instance
- In the AWS EC2 Management Console, click Elastic IPs (left navigation bar)
- Allocate New Address, and confirm by clicking the Allocate button
- Right-click the newly allocated IP address and select Associate in the popup menu. Select the WordPress EC2 instance we created above and click Associate
Setup DNS records for your domain with Route53
Route53 is a DNS service from AWS, which will essentially be used to translate the domain name to the elastic IP we have just created. It’s quite cheap, at about $.50/month.
- Create a hosted zone, with the name of your domain (without www). This will create four name servers, one master and three slaves.
- While still in the hosted zone, unselect all records and then click on Create Record Set. Create a new A record (for example www.worpressaws.com) pointing to the Elastic IP record you created in the previous step.
With the above, we now know that a domain lookup of www.wordpressaws.com will resolve to the EC2 elastic IP.
The final step is to map your domain from the registrar to your Route53 name server. In GoDaddy or wherever you have registered your domain to point to the name of your master DNS server (e.g. ns-1329.awsdns-38.org.)
You’ll need to wait a few hours (sometimes up to 48 hours) to check whether your IP is resolving correct. You can check the progress of the domain name propagation using a service such as What’s my DNS.
Once DNS has propagated correctly, go to WordPress General Settings in the WordPress management console and make sure the WordPress Address and Site Address are specified correctly using your domain name.
Using Amazon LightSail VPS
A few weeks ago, AWS launched a new service, LightSail. Essentially, these are virtual private servers priced at a very cheap $5 per month.
- You simply click on the instance of the application you’d like to host.
2. Select how much resources you want to allocate.
And AWS LightSail will spin up an instance for you with WordPress and a database pre-installed. You can then SSH into as a regular EC2 instance and tweak as necessary.
Phew, We’re Done! But Are We Really…?
That was pretty taxing to set up! Getting it all up and running smoothly is not for the faint-hearted. Keeping everything up and running in tip-top shape is going to take a continuous effort of monitoring states of the various instances, making sure we’re not running up costs on large instances. We also need to monitor whether the servers are coping with demand – where necessary we can stop an instance and allocate more resources to it as necessary.
We’ll also be discussing in another post, how to actually setup autoscaling on AWS such that traffic spikes will automatically create new instances of the web server we have created to be able to handle loads as necessary.
Why Not Leave It All to the Experts?
As you might have seen from the above, setting up and maintaining an AWS WordPress infrastructure is not an easy task. Keeping it up and running is also going to need constant investment in time, and of course the billings on AWS itself.
Whilst AWS gives you quite a lot of control, literally you can configure bits and pieces as necessary for your infrastructure, we do believe this is only for those who have very specific needs.
On the other hand if you run an enterprise website and want top performance right off the bat, why not go for managed WordPress hosting with WPMU DEV? It gives you the same performance and scaling, without all the headaches that come with managing a server. Get scaling!
WIN a Share of $5K
Subscribe to our blog this #hostingmonth for a chance to win one of 5 prizes of $1,000 WPMU Dev credit! Learn More.