The Ultimate Guide to WordPress on AWS EC2

A Primer for Complete Beginners!

Amazon Web Services (AWS) is an incredible option for hosting WordPress sites; it’s almost exclusively what I use these days when setting up hosting for my own clients. For new users, however, getting started with AWS can be insurmountably daunting, especially if they don’t have a experience with command-line Linux administration!

If that’s you, I have good news: This comprehensive guide will introduce you to AWS and guide you, step-by-step, through setting up your own server and installing WordPress.

Before we get started, be aware that AWS really isn’t for everybody. The question is: is AWS right for you? Well, that depends.

Is AWS Right for You?

TL;DR: If you’re planning to launch a commercial website of any kind, the answer is yes. However, a certain comic book character once said: “With great power comes great responsibility”.

When you host WordPress on AWS you get a lot of power and flexibility and a tremendous value, but you also take on a lot of responsibility normally shouldered by your web host – you are now your own (and only) IT person.

You set up everything. You configure everything. You maintain everything. If something goes wrong, you are the one that has to fix it. You’re on your own.

And if you are not comfortable with the idea of configuring or managing a Linux system via command line, you could very well find yourself in the Ninth Circle of Technological Hell.

That said, the positives are the same as the negatives: you set up everything, you configure everything, and you maintain everything. You get exactly what you want, the transparency and flexibility available to you is limitless, the performance is spectacular, and best of all: the price is a value unmatched in all of hosting. Your basic AWS WordPress configuration will run you about $7/month… but it’s free for the first year to new users.

To enjoy those benefits, you just need to be able to handle the complexity of setting up and maintaining the server yourself. From scratch. Over a command line.

Fortunately for you, that is what this primer is all about!

Important AWS Lingo

AWS has a lot of proprietary lingo and concepts that can make it hard for new users to handle. So before we get to all the configuration, I want to familiarize you with some of the important terms. You don’t need to memorize this, but if you read it at least once, it will save you from a fair bit of confusion later.

“Elastic Cloud Compute” – this is the AWS service that handles Amazon’s virtual servers.
“Amazon Machine Image” – this is an image (like an ISO) that contains a configured server. You use these to launch new server instances.
An “instance” is a virtual server; more specifically: a single instance of an AMI. You can customize an instance and save it as a custom AMI.
terminate  [an instance]
When you “terminate” an instance, you are destroying/deleting it (like Arnold in the venerable horror/action movie). Only do this when you are completely sure that you want the server and all it’s data to disappear forever.
stop [an instance]
When you “stop” an instance, you are simply powering it down, virtually. You can boot it back up at any time, data intact (minus anything in memory or “ephemeral storage” of course).
“Elastic Block Storage” – this is the AWS service that handles data/file storage your instances… it’s where all your virtual hard drives, or “volumes”, are kept.
Individual EBS volumes act like virtual hard drives. Each of your instance will likely have an EBS volume associated with it.
A snapshot is a static backup of a volume. They can belong either to a custom AMI you’ve saved or an EBS volume.
This is Amazon’s DNS service. Each domain you configure (which are called “hosted zones”).
This is Amazon’s monitoring service. You can use this to track resource usage and/or be notified of server trouble or downtime.
Elastic IP
This is Amazon’s term for a static IP address. Any elastic IP you control can be reassigned on a whim, hence “elastic”.
Security Groups
This is essentially the firewall configuration for your server. They can be used to restrict access by port, ip address, protocol, etc.

There are plenty of other things on AWS for you to feel overwhelmed by if you stray off the beaten path (like load balancing and spot instances), but I don’t want you worrying about those right now because if you’re reading this… you don’t need them.

AWS Billing Concepts

One thing to keep in mind at all times is cost. AWS charges for every. little. thing. you. use. This means that if you are careful, you can keep your costs down… and if you are really negligent, you can literally bankrupt yourself. I’ll explain some of the most critical considerations before we move on.

Software Licenses

Amazon offers a wide variety of AMI’s for you to choose from when creating your own instances. Some (such as Windows servers) have additional costs due to licensing. For this tutorial we will be using Amazon Linux (which is a custom version Red Hat Enterprise Linux 5/6 ), which has no additional costs.

Instance Locations & Sizes

When you create your instance, you will be able to choose which datacenter to use (you select from a list of geographic locations) and also an instance type and size (AMI’s follow a type.size naming convention).

You pay for your instances by the hour – and the rate is slightly different for each datacenter. For this tutorial, I highly recommend you select a t2.micro instance – which is not only very inexpensive, but free for the first year to new users.

Elastic IP Addresses

Unlike other services, Amazon doesn’t charge at all for a static IP address if it is attached to a running instance.


There are two ways you will end up with a snapshot – either by saving a custom AMI (which automatically creates a snapshot) or by manually creating a snapshot of one of your EBS volumes (which is how you would backup your server). In either case, each snapshot will cost you about 11¢ GB/month, as of the time of this writing.

Route53 / DNS

DNS will cost you 50¢/month per “hosted zone” (e.g. per domain) plus a few cents per one million hits. Unless you run a very popular site, you can estimate this to be about 51¢ per month.

Additional Costs

There are some other potential costs to be aware of… EBS storage is free below a certain usage level, but incurs costs if you go above that. This shouldn’t happen in most typical WordPress use-cases. There are also data transfer costs, which should be near-zero (we’re talking cents) unless you are running some sort of download service (such as a WooCommerce site with digital products)… but if you are, you really should consider S3 as an alternative.

Provision an Instance

Before we can do anything else, we have to provision (create and start) your instance.

To start provisioning your instance, log into your AWS console and select “EC2” from the list of AWS services to get to your “EC2 Dashboard”.

On your EC2 Dashboard click the big, blue “Launch Instance” button in the middle of the page.

The AWS EC2 Dashboard - Launch Instance

Alternatively, you can select “Instances” (in the menu on the left) and then “Launch Instance”.

1. Select Region

Before you get any further, make sure you are operating in region (i.e. data center) that you want. You can’t change this later, so decide now. You can change your region in the upper right of the screen.

AWS Select Region

2. Select AMI

For this tutorial, we want to use Amazon Linux (64bit) as our AMI. Find the “Amazon Linux” (also, make sure it’s 64 bit by looking under the “Select” button on the right) and click “Select” to continue.

AWS Choose Your AMI

3. Select Instance Type & Size

Select the t2.micro instance. “t2” is Amazon’s general purpose instance type, while “micro” is a general indication of that instance’s resources (in this case, very low CPU and memory allocation).

AWS Select Instance Size

4. Configure Instance Details

You don’t need to change most of these settings, as the defaults should be perfectly fine for now. That said, the two settings I want to draw your attention to are Enable termination protection and Monitoring.

AWS Review Configuration

Enable Termination Protection

For WordPress sites, I highly recommend checking the Enable termination protection option. If you ever want to delete your instance, it will add a couple steps, but it will also protect you from accidentally selecting “Terminate” at some point when you really mean “Stop”.


If you check the box next to Monitoring, you are opting into AWS’s “detailed” CloudWatch monitoring service, which costs $3.50/instance/month.

All instances include basic CloudWatch monitoring for free… which checks your server every 15 minutes for things like CPU usage, disk I/O, downtime, etc. When you enable detailed monitoring, these checks occur as frequently as every minute (which is really useful when paired with a status check / downtime alert).

5. Configure Storage Options

Next, you need pick some storage options for your EBS volume. You really just have two important decisions to make here… how much space do you need, and what kind of storage device (volume type) do you want?

AWS Storage Options


Remember, you pay for everything on AWS. When it comes to storage, Amazon tracks storage size (in Gigabytes) and IOPS (input-output operations per second). To stay in the “free tier” you just have to stay under 30GB. Set this for 8, which is more than enough for now.

Volume Type

You have 3 options here. For this tutorial, I recommend “General Purpose (SSD)”. Here’s a very brief explanation of the choices:

Type 1: General Purpose (SSD)

This keeps your data on very fast solid-state drives, which generally provides great performance. The tradeoff is that you are at the mercy of the system’s IOPS limits.

In the screenshot above, we are guaranteed a baseline of 24 IOPS (this is based on the storage size we’ve entered), with bursts up to 3,000 IOPS to deal with sudden, temporary spikes. This is ideal for most small WordPress sites, but be aware that poorly configured caching plugins or PHP extensions can wreak havoc on your IOPS limits and run your server into the ground.

If you need more sustained IOPS, you can either reserve more storage space or you can choose one of the other two Volume Types…

Type 2: Provisioned IOPS (SSD)

This keeps your data on the same solid-state drives as above, but you specify exactly how many IOPS you need. Keep in mind that this comes at a higher cost ( 6.5¢ per IOPS / month PLUS 12.5¢ per GB / month ).

Type 3: Magnetic

This keeps your data on old-fashioned magnetic hard drives. These give you about 100 IOPS on average (sustained!) but you lose the extreme bursting capabilities of General Purpose (SSD).

6. Tag Instance

AWS tags are used in a number of cloud computing scenarios, but they won’t do anything at all for you, Mister or Missus WordPress aficionado. Skip this page and just click “Next”.

7. Security Groups

The last step in launching a new server instance is configuring your Security Group (basically, your virtual firewall). You will have more options later, but right now this page is only concerned with inbound traffic allowances.

We need to set up two rules right now.

For the first rule:

  1. Under Type, select “SSH”.
  2. Under Source, select “My IP” from the dropdown.

This will allow you to access your instance over SSH from only your current IP address (highly recommended for security reasons)… Remember, we still have a lot of configuration to do once this instance is launched!

For the second rule:

  1. Click “Add Rule” on the lower left.
  2. Under Type, select “HTTP”.
  3. Under Source, leave “Anywhere” selected

This allows visitors to access your website over HTTP from any address. If you don’t include this rule, your website will be inaccessible.

When you’re finished, click the blue “Review and Launch” button… we’re almost there!

AWS Security Groups

8. Review & Launch

We’re almost there… you have one last chance to review all your settings before you launch. If you’ve been following this tutorial, you should be just fine. Find that blue “Launch” button in the lower-right and click it!

9. Set Up a Key Pair

Hey, what’s this popup!?

AWS Select Peypair

Don’t worry, this is the last step: you now need to create an authentication key pair that will allow you SSH access to your server.

DO NOT SKIP THIS. An unprotected server is a dangerously vulnerable server.

AWS makes it easy. Simply open the first dropdown and select “Create a new key pair”. Give your key pair a friendly name like “AWS WordPress” and then click “Download Key Pair” to get your private key (which will let you access your instance over SSH).

You will need to save this private key somewhere safe. On OSX, the correct location is ~/.ssh (you will also need to restrict permissions to 700) – on Windows or Linux it’s… I’m not really sure. Sorry.

When you’re ready, click “Launch Instances”!

It will take a minute for your instance to launch. Click “View Instances” to go back to your dashboard. Stay on this page, you’ll need information from it in a minute.

Before We Get Started

With all that out of the way, we’re finally ready to set up our own WordPress-friendly LAMP stack on AWS EC2.

Configuration Prerequisites

Before you can get access to your new server instance, you still need to do a couple things: ensure you have access to an SSH client and set permissions on your private key file to 400, 600, or 700 (it shouldn’t be accessible to anyone else or you won’t be able to connect using it).


If you are on OSX, then Terminal is built-in to the operating system, and you are good to go.

If you are on Linux, you just open a command prompt.

If you are on Windows, you will need some SSH software like PuTTY.

Private Key Permissions

Now we need to secure the private key, or we won’t be able to use it to connect. The commands below cover OSX, but Linux users should be able to easily tweak this.

Windows doesn’t use Unix style permissions, so unfortunately you’re on your own there.

First, do you remember your key name? It ended with .pem. You’re going to need it.

  1. Open Terminal
  2. Type cd ~/.ssh
  3. Type chmod 0400 your_key_name.pem
  4. If prompted, enter your OSX password.

Database Software

I am no proponent of the clunky, hideous, artifact from another age that is PhpMyAdmin and I won’t discuss how to install it. Instead, you should download one these fantastic pieces of software:

On OSX, grab yourself a copy of SequelPro – it’s free!

On Linux or Windows, use MySQL Workbench – also free!

Configuration Time!

Open up Terminal or your equivalent command prompt… it’s time to get down and dirty with all that exciting server configuration over SSH!

Step 1: Connecting to an Instance

Before you can connect, you need to make a note of your server’s IP address (write it down!). Go back to your EC2 Control Panel and find your Public IP address. It’s the area that’s highlighted in the screenshot below…

AWS Find Your IPNext, you will need to connect using the following command (note that you’ll need to replace my placeholder bits with your own)…

$ ssh -i ~/.ssh/your_key_name.pem ec2-user@your_ip_address

Let’s break this down… you are connecting via ssh, you are using the -i modifier to specify a specific private key, and you are logging in using your username “@” your ip address.

Step 2: Set Your Timezone

To find your timezone using the interactive, step-by-step timezone utility, run the following command:

$ tzselect

Make a note of the timezone code (e.g. America/Los_Angeles).

Edit your system clock settings…
$ sudo nano /etc/sysconfig/clock

In the clock file, change ZONE="UTC" to your own timezone and then set UTC to false. For example…


Finally, run a command to create a symlink to your timezone information (be sure to replace YOUR_TIMEZONE below with your own timezone code)!

$ sudo ln -sf /usr/share/zoneinfo/YOUR_TIMEZONE /etc/localtime

Step 3: Install Updates

Just because your server is new doesn’t mean you won’t need some updates. Before we do anything else, let’s make sure everything is up-to-date.

$ sudo yum -y update

You may be asked to confirm a download. If so, type y to accept and hit enter. Then you just have to wait for the updates to finish.

Step 4: Install Apache, Php, MySQL, etc

Next, we need to install all of your web server packages: Apache, Php, MySQL, ImageMagick, etc. I won’t waste your time explaining what each of these are, they’re mostly self-explanatory-ish – you can Google the more mysterious ones if you are so inclined.

Run the following commands, in-order.

$ sudo yum install -y gcc make
$ sudo yum install -y httpd24 php56
$ sudo yum install -y php56-devel php56-mysqlnd php56-pdo php56-mbstring
$ sudo yum install -y php-pear
$ sudo pear install Log
$ sudo yum install -y pcre-devel
$ sudo yum install -y php56-opcache
$ sudo yum install -y re2c
$ sudo yum install -y mod24_ssl
$ sudo yum install -y memcached
$ sudo yum install -y php56-pecl-memcached
$ sudo yum install -y ImageMagick
$ sudo yum install -y ImageMagick-devel
$ sudo pecl install imagick

Step 5: Configure PHP

Next, we need to ensure that ImageMagick is loaded with PHP. This involves manually editing the php.ini file.

To edit the file, type:

$ sudo nano /etc/php.ini

Scroll to the very end of the file and add the following line:

Hit Ctrl + X to exit the Nano editor, and be sure to save when it asks you.

Step 6: Start Apache

Now we need to start the Apache web server. Type:

$ sudo service httpd start

If Apache is already running, restart it with:

$ sudo service httpd restart

Step 7: Set Apache to Auto-start

You don’t want to have to manually start Apache every time you have to restart your instance, so let’s configure it to autostart. Type…

$ sudo chkconfig httpd on

Step 8: Test Apache!

Before we go any further, let’s make sure that Apache is running and accessible in a web browser.

First, let’s create a phpinfo file…

$ sudo -i
$ echo "<?php phpinfo();" > /var/www/html/phpinfo.php

Now, type your instance’s ip address into your web browser followed by /phpinfo.php – if you see a phpinfo page, you’re golden!

Finally, remove the phpinfo.php file with…

$ rm -f /var/www/html/phpinfo.php

Step 9: Install MySQL

To install and start MySQL on your EC2 instance, type the following:

$ sudo yum install -y mysql-server
$ sudo service mysqld start

Step 10: Configure MySQL

Next we have to configure and secure MySQL. Run the following command to start the MySQL configuration process:

$ sudo mysql_secure_installation

Be sure you carefully read and follow the directions that the installer presents in your command line client.

Finally, let’s make sure that MySQL auto-starts when the instance boots (just like Apache). Type:

$ sudo chkconfig mysqld on

Step 11: Enable .htaccess Overrides

This is the last configuration step. If you want to be able to enable “Pretty URLs” in WordPress, you need to enable overrides in your httpd.conf. Type the following…

$ sudo nano /etc/httpd/conf/httpd.conf

In here, you need to find the directory block for /var/www/html. For me, it’s around line 130. It will look like this…

# Further relax access to the default document root:<br />
<Directory "/var/www/html"><br />
#<br />
# Possible values for the Options directive are "None", "All",<br />
# or any combination of:<br />
# Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews<br />
#<br />
# Note that "MultiViews" must be named *explicitly* --- "Options All"<br />
# doesn't give it to you.<br />
#<br />
# The Options directive is both complicated and important. Please see<br />
#<br />
# for more information.<br />
#<br />
Options Indexes FollowSymLinks</p>
<p>#<br />
# AllowOverride controls what directives may be placed in .htaccess files.<br />
# It can be "All", "None", or any combination of the keywords:<br />
# Options FileInfo AuthConfig Limit<br />
#<br />
AllowOverride None</p>
<p>#<br />
# Controls who can get stuff from this server.<br />
#<br />
Require all granted<br />

See the line in there for AllowOverride None?

Simply change it to AllowOverride All.

As with Nano before, press Ctrl+X to exit, and follow the directions to save the file.

Next, we just need to restart Apache one more time so that your htaccess files are being used. Type this at the command prompt:

$ sudo service httpd restart

Optional: Configure Virtual Hosts

If you want to host multiple websites on a single instance, now would be a good time to set up your vhosts (or virtual hosts), which enable this.

Click here for a guide to setting up vhosts on your AWS instance →

Deploying WordPress!

Congratulations, your server is fully configured! Now, we just need to connect to connect to it with our database software and install WordPress.

Connecting to MySQL

We need to do two things right now… connect to the MySQL server and create a new database for our WordPress install.

This part of the tutorial is client software agnostic, but I’m a huge fan of Sequel Pro for OSX, which is what I use on a day-to-day basis. If you’re on Windows or Linux, you’ll want to use MySQL Workbench instead.

To create the connection…

  1. Start by creating a new connection in your database client.
  2. For your connection method, you want to select the “SSH” option.
  3. For your SSH hostname, enter your instances public ip address.
  4. For SSH user, enter ec2-user (remember, that is always your default user).
  5. For authentication, you will need to point your client to the private key you downloaded earlier (this is the file that ends in .pem).
  6. Your MySQL host should be and your port is 3306
  7. Your MySQL username should be root.
  8. Your MySQL password is whatever you personally specified earlier (when we ran the command: $ sudo mysql_secure_installation)

With that done, you should now be able to connect to your MySQL server! Go ahead, try it.

Creating a New Database

Now that we’re connected, go ahead and create a new database/schema so that we can install WordPress.

You can name the database whatever you like (I like to prefix mine with wp_ to let me know it’s a WordPress schema), but your encoding should be utf8 and collation should be utf8_general_ci.

Creating a New MySQL User

Next, we’ll want to create a new MySQL user whose access is limited to only the database you just created, and with limited privileges.

Why? Because, if anyone malicious were to gain access to your site’s file system, you wouldn’t want your root password readily visible in your wp-config.php file. This is best-practices stuff.

You are free to skip this step and move on with your root login, but I really don’t recommend it.

The process is different depending on your client. In SequelPro, you will find the user options under Database > User Accounts. In MySQL Workbench, you’ll find this in the toolbar on the left under “Users and Privileges”.

In either case, you want to implement the following for this user:

  • Only allow connections from localhost or
  • Only grant access to the single schema you just created
  • Give the user full schema privileges
  • Do not give the user any administrative privileges

And don’t forget to save that password someone safe, like an encrypted password locker (1Password or LastPass are good choices). I recommend using only extra-long (30+ character) machine-generated passwords.

Deploying WordPress

At this point, you have two options… you can copy WordPress onto your server via SFTP or you can deploy it via command line.

Uploading via SFTP

If you want to copy files via SFTP, you would configure your FTP client very closely to how we configured the MySQL client:

  1. Select SFTP as the connection method (sometimes called “Secure FTP” or “FTP over SSH”)
  2. Connect using your instances public IP address
  3. For user, enter ec2-user
  4. For authentication, select your private key (the one that ends in .pem

Your site files should be uploaded to /var/www/html – so start uploading and knock yourself out!

Downloading via Command-line

I prefer this method. It’s faster and there’s no waiting for files to upload. Just enter the following commands…

$ cd /var/www/html
$ wget
$ tar -xzvf latest.tar.gz
$ mv wordpress/* .
$ rm -rf wordpress
$ rm -f latest.tar.gz

Fix WordPress Permissions

At this point, you may need to fix your WordPress permissions to ensure that everything works as expected (media uploads, plugin installs and updates, etc). Run the following commands to repair your WordPress permissions…

First, we want to change the ownership of the html folder…

$ sudo -i
$ cd /var/www
$ chown ec2-user:apache html

Next, we need to recursively change the ownership and permissions of WordPress’s files and folders…

$ cd /var/www/html
$ find . -type d -exec chmod 0755 {} \;
$ find . -type f -exec chmod 0644 {} \;
$ chown -R ec2-user:apache .
$ chmod -R g+w .
$ chmod g+s .

The idea here is this: by giving the ec2-user user ownership, you can use SFTP to modify your files (since there are virtually no SFTP clients that support sudo – not even Transmit); And by granting apache group access, you can use media uploads, auto-updates, etc.

Wrap It Up!

Finally, visit your public ip address in your browser to complete that famoud 5-minute WordPress install! Don’t forget to use that special MySQL user we set up, when you do.

After that, you’re done. Mazel tov! You are now running a WordPress AWS website on EC2!

Related Articles



Minor error in tutorial at:
“echo ” /var/www/html/phpinfo.php”

Better is:
“echo “” > /var/www/html/phpinfo.php”


This is SUCH a great tutorial! I have this page bookmarked and I refer to it every time I’m setting up a site on AWS/Wordpress. Just wanted to say thanks!


Hi, I have followed the tutorial (both this and multisite), and everything works great, except the files permissions… I can already see the files as owned by ec2-user and the group is apache, but still I can’t do anything without wordpress asking for a ftp user and password.

What am I missing?

Leave a Comment

You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>