Install WordPress on an Amazon AWS EC2 Linux instance with persistence to Amazon EBS

I figured that it was finally time for me to roll up my sleeves and get my hands dirty with WordPress running on an Amazon Web Services (AWS) EC2 Linux Micro instance. I know you can use a preinstalled image but I wanted to understand what was going on under the hood so decided to start from scratch. I also wanted to ensure that all data would be persisted to Elastic Block Storage should there be an issue with the EC2 instance. My main coding background is in ASP.NET though I have been managing a team in a Java environment for the last 18 months so this was a reasonably steep learning curve. So I figured that in the spirit of open source and since I was creating a blog that I would share my experiences. My goals were the following:

  • Create Amazon Web Services (EC2) Micro Instance
  • Setup Apache and MySQL
  • Install WordPress
  • Ensure all data is persisted to Amazon Elastic Block Storage (EBS)
  • Install WordPress Multisite
  • Map multiple domains to Multisite

Amazon very kindly give you an initial free 12 months on one of their micro instances so thought this would be a good place to start. Here are a couple of things to note:

  • EC2 image data does not persist if the image is terminated (either by user or an issue on Amazon)
  • You can attach an EBS volume to create persistant storage and attach to an EC2 instance

Step 1: Launch an Amazon EC2 Micro Instance and attach EBS and Elastic IP

  • After registration login to AWS Management Console and go to the EC2 dashboard
  • Select the closest Amazon region to where most of your traffic will come from (top left)
  • Select EC2 then Launch Image
  • I used quick launch the selected Amazon Linux AMI 32bit
  • Create new security key and download it to a memorable place
  • Then select Elastic Block Storage – Volumes
  • Create Volume and make sure it is in the same zone as your Ec2 server
  • Attach EBS to your EC2 (note the name that it gives your storage)
  • Select Elastic IP’s and allocate new address then associate the address with the Ec2 instance (note IP)

Step 2: Login to your server via SSH and start setup

I am using a Mac so I just fired up the Terminal and the steps I took are below though if you are using Windows you can follow a tutorial for PuTTY here.

  • Fire up Terminal and go to the directory with your .pem key inside
  • Change the file permissions of the .pem key to 400 by running the below
chmod 400 [keyname].pem
  • You can now login to your server with the following command
ssh -i [keyname].pem ec2-user@[elasticip]

Being a newbie to Linux I had to have a quick look around for the basics of navigation and here are a couple of very basic commands.

  • To see the files in a directory listed in alphabetical order
ls -l
  • to change directory to a path
cd /var/www/html/
  • to remove a directory or file
rm -f -r [file-name]
  • change user to root so you don’t have to type sudo each time
sudo su

Step 3: Setup MySQL with its data persisting to ECB

Login then change your account to root, then run the server updates.

sudo su
yum upgrade

Install MySQL.

yum install mysql mysql-server

Create a filesystem on the attached EBS volume as it currently doesn’t have one (I used XFS as the demo I was following did the same) . My EBS volume was called xvdf rather than sdf which the management consoles said  so use what you noted down when setting this up. XFS isn’t installed out of the box you need to install and register before you can create the filesystem.

yum install xfsprogs
modprobe xfs
mkfs.xfs /dev/xvdf

We now need to make sure that this volume is mounted every time we boot the machine by running the following. We then create and mount the drive in this case I have called it vol.

echo "/dev/xvdf /vol xfs noatime 0 0" | tee -a /etc/fstab
mkdir -m 000 /vol
mount /vol

We now want to create data directories on /vol so MySQL can use these for data storage as they sit on EBS they will be persisted should the instance have an issue.

mkdir /vol/etc /vol/lib /vol/log

We now need to move the required MySQL files and folders from their default locations to the new one that we have created on /vol.

mv /etc/my.cnf /vol/etc/
mv /var/lib/mysql /vol/lib/
mv /var/log/mysqld.log /vol/log/

Now that the files have move we can create symbolic links (shortcuts) from where the default files were installed to their new locations on /vol.

ln -s /vol/lib/mysql /var/lib/mysql
ln -s /vol/etc/my.cnf /etc/my.cnf
ln -s /vol/log/mysqld.log /var/log/mysqld.log

Hopefully everything should be in the right place and we can now start MySQL.

service mysqld start

If anything goes wrong then check the logs. I would also check the data directories that you created to make sure that you can navigate to them.

tail -f /var/log/mysqld.log

We now need to change the MySQL root password to be something nice and secure and then run the secure installation as this will be a production environment.

/usr/bin/mysqladmin -u root password '[newpassword]'
/usr/bin/mysql_secure_installation

Now we need to log into WordPress and create the required tables

mysql -p
mysql> CREATE DATABASE wpdb;
mysql> GRANT ALL PRIVILEGES ON wpdb.* TO wpuser@localhost
-> IDENTIFIED BY "another-new-password";
mysql> FLUSH PRIVILEGES;
mysql> exit

Step 4: Setup PHP, HTTP and download WordPress

Now it is time to get HTTP and PHP installed by running the following.

yum install httpd
yum install php php-mysql
yum install php-gd

We need to enable the Apache mod_rewrite module for WordPress to run correctly. I used the command line text editor vim and you can find the cheat sheet here. You need to change AllowOveride None to AllowOveride All inside the DocumentRoot Directory Directive, normally <Directory “/var/www/html”>

vim /etc/httpd/conf/httpd.conf
  • vim Cheats
  • i enables edit mode
  • esc finishes editing
  • :wq! writes and saves file

We now want to create the html folder on /vol so all of our web files will also be on an EBS volume. We can then do the same as we did for MySQL and remove the folder before creating a symlink from EBS to our EC2.

mkdir /vol/html
rm -f -r /var/www/html
ln -s /vol/html /var/www/

Now we have a web folder we can download WordPress

cd /vol/html
wget http://wordpress.org/latest.zip
unzip latest.zip

As I wanted to run a MultiSite Multiple Domain site I needed to have the WordPress files in the root of the web server so the following moves them from html/wordpress to /html and then deleted the /wordpress folder to keep things nice and clean. I also renamed wp-config-sample.php to wp-config.php for ease of editing.

cp -rpf ./wordpress/* .
rm -rf latest.zip
rm -rf wordpress
cp wp-config-sample.php wp-config.php

Step 5: Setting up WordPress

WordPress is a pretty damn easy thing to setup however you do need to edit quite a few files in this step so I thought it would be a good thing to connect via SFTP to allow easy manipulation. Here is a quick guide to how to connect to FileZilla, once you have done that go to in FileZilla.

/vol/html

At this stage you will be able to connect and view files within FileZilla but most likely unable to write or create them. This is due to the fact you created all of the files whilst using the root account and the ec2-user doesn’t have any permissions to change them. You will need to change permissions of each of the files and folders, you need to use Terminal to all users to write and update them.

cd /vol/
chown ec2-user -R html
chmod 755 -R html

You will need to change this back at the end anyways but here is the WordPress documentation on file permissions to understand what is going on and the risks that you pose should you not.

You can now download wp-config.php and make the below changes

define('DB_NAME', 'wpdb');
define('DB_USER', 'wpuser');
define('DB_PASSWORD', 'new-password');
define('AUTH_KEY', 'xxx');
define('SECURE_AUTH_KEY', 'xxx');
define('LOGGED_IN_KEY', 'xxx');
define('NONCE_KEY', 'xxx')
define('AUTH_SALT', 'xxx');
define('SECURE_AUTH_SALT', 'xxx');
define('LOGGED_IN_SALT', 'xxx');
define('NONCE_SALT', 'xxx');
$table_prefix = 'wp_';

WordPress provide a very nice helper for the Salts here.

Now we need to allow the apache user access to html so WordPress can update plugins and files and change our file and folder permissions to what WordPress recommends here.

cd /vol/
chown -R apache:apache html
find /vol/html/ -type d -exec chmod 755 {} \;
find /vol/html/ -type f -exec chmod 644 {} \;

Now lets fire up httpd.

service httpd start

It is also worth using the below to ensure that httpd and MySQL run on startup.

ntsysv

Finally you will also need to add a Custom TCP rule to your security groups using the AWS console for port 80 to allow traffic.

Now for the moment of truth, browse to your Elastic IP, should you have any issues you can look at the logs by using the following.

tail 100 /var/log/httpd/error_log

There is no way I could have achieved the above with out some similar great guides and here they are.

There are a couple of great guides for Multisite and Multi Domain Mapping below which worked fine for me with WordPress 3.3.

Further Reading

Since writing this post I have done a lot to my server to optimise the running of WordPress here is some additional reading:

Music to Write this Code to

So finally we need some music to code this to. Post Dubstep moody tunes but with a decent beat is the perfect type of music to be navigating command lines.

Leave a Reply

Your email address will not be published. Required fields are marked *

39 comments on “Install WordPress on an Amazon AWS EC2 Linux instance with persistence to Amazon EBS

  1. Great guide, thanks! A couple of issues, though:
    1) How do I get the changes to /etc/fstab to persist?
    2) How do I get the yum-installed packages to persist?

    • Geppy, If the command I wrote doesn’t work you should be able to edit fstab using vim and add this line “/dev/xvdf /vol xfs noatime 0 0” below whatever is already there. The yum packages should persist by default when you install as they should cause files on the machine to be updated that will be referenced the next time you boot.

      • Must be an issue with the AMI that I used (I went with one of the 64-bit ones): any packages I install or any changes I make in /etc are cleared on shutdown. I’ll try again with a different AMI and try to make sure to ensure that the root isn’t deleted on boot.

        Thanks!

    • If you have connected via PuTTY you don’t need to Login as: ssh … as you are already on the box just go to the next step. The user is ubuntu if you are using ubuntu and only ec2-user if you are using Amazon Centos.

  2. i’m stuck at:

    Fire up Terminal and go to the directory with your .pem key inside
    Change the file permissions of the .pem key to 400 by running the below

    chmod 400 [keyname].pem

    You can now login to your server with the following command

    ssh -i [keyname].pem ec2-user@[elasticip]

    Being a newbie to Linux I had to have a quick look around for the basics of navigation and here are a couple of very basic commands.
    ———–
    spent more than 4 hours 🙁

    1. cmd , cd d:/folder/folder chmod 400 keyname.pem – does not working with [] how it is an example..does not working also
    2. cmd chmod 400 – wrong command
    3. cmd , cd d:\\folder\folder chmod 400 keyname.pem – does not working
    4. total commander – change attributes.. but in new 8.0 version it can only remove archive attribute..or hide attribute (
    5.
    >ire up Terminal and go to the directory with your .pem key inside
    i tried to guess what it is..how it is … probably from they Putty ..no putty does not have command line and i still cant log in to the server.

    6. http://stackoverflow.com/questions/8193768/trying-to-ssh-into-an-amazon-ec2-instance-permission-error
    here same..

    HOW TO SET chmod 400 [keyname].pem PLEASE HELP

  3. I really don’t see a point in using ebs, doesn’t that cost extra money? You can make backups in wordpress. Just a pondering, let me know what you think.

    • Here is my error log, still elastic IP is not getting through. Grr.

      [Fri May 03 01:42:37 2013] [notice] suEXEC mechanism enabled (wrapper: /usr/sbin /suexec)
      [Fri May 03 01:42:37 2013] [notice] Digest: generating secret for digest authent ication …
      [Fri May 03 01:42:37 2013] [notice] Digest: done
      [Fri May 03 01:42:37 2013] [notice] Apache/2.2.24 (Unix) DAV/2 PHP/5.3.23 config ured — resuming normal operations

      The browser gives this log:

      The connection was reset
      The connection to the server was reset while the page was loading.

      • Brandon, it might be worth trying to work through making sure Apache and your Elastic IP are working before going on to the WordPress steps. You should be able to create a small html file in your root of you apache folder and browse to that. You could do this before moving any files or changing the location of any directories. Once you are certain that Apache is serving files and your Elastic IP is attached you can then go onto the rest of the steps.

    • The reason for EBS is that the resources that come with an EC2 instance don’t persist. So if something goes wrong and your instance gets terminated you will loose all of your data, the same would happen if you wanted to increase your instance size. If you use EBS you can just reattach that to the new larger instance and go from there. You can definitely take regular backups and this will mitigate though in my experience it is never quite as simple as it should be doing a full restore. EBS is such a low cost that I think it is worth the effort from the benefits it provides.

      • What is the ip address supposed to redirect to? My guess is index.html but where does this file go? And maybe when I put in my ip address I am not loading wordpress because I haven’t put any extensions on my address like /wordpress ..

        I have no clue. I will keep trying. Err.

        Thanks again man.

        • Brandon, you considered using one of the off the shelf AMI’s that have WordPress and everything setup on them? I haven’t used them personally but know a few people that have to good success. With regards to the above you would need to put the index.html in the root of the folder that apache points at for web serving this is defined in your httpd.conf try “grep -i ‘DocumentRoot’ /etc/httpd/conf/httpd.conf”, this will most likely be “/var/www/html”. Then at least you should be able to see if your IP and apache are working, sounds to me like you might need to change some settings in httpd.conf to get that working before you move on.

    • I have assigned them, but I have no idea what a CNAME is to my domain. I have two instances now as I have tried to use two different tutorials. One goes to the tomcat server congratulations I have installed it page, the other says connection reset when I go to that ip address.

      • Brandon, if I was you I would start from scratch with your server and just follow one tutorial until it works. A CName is a alias for an IP address which allows you to call it whatever you want. i.e. blog.david-jensen.com is a CName to the IP address which is the actual address of this blog. Contact the people that control your domain and they should be able to change this record for you.

        • Do I have to use a cName for it to work? I am just trying to get it to work with elastic IP addresses for now. I follow from step 3 onward? I am going to try to start from scratch like you say. I am not sure what my problems are, I am not using a mac or the console, I am using putty. I should be able to get everything to work using putty hopefully. I appreciate your commitment and patient that you spend helping others. I’ll get back to you with my results. I really wish I could narrow the error down to one thing so I know what in the world I was doing wrong.

          Thanks,

          Brandon

  4. Whenever I navigate to my elastic IP I get a tomcat installation page. I try to navigate to my blog and I keep getting a 404 error. Can someone help?

  5. Hi while setting up mysql-server . i somewow created a loop in the symbolic links while mounting the volume since the volume was already binded to the instance im running linux. I can’t access mysqld.log or mysql file because of that… can someone help please i can’t start another instance since i have valuable data on the instance

  6. Great post David! Helped out greatly with my install and definitely made me put your blog on my feed! Quick typo correction in the section where you are deleting the /var/www/html folder … you have a space between the “-” and the “r” option in this command: rm -f -r /var/www/html.

    Again thanks sooooooo much for this post!!

  7. David –

    First of all – big THANKS! I am trying to migrate my old CMS to WordPress on EC2 using Linux. I am running into issues here :

    1. The block store could be found cat /proc/partitions
    /dev/xvdf is /dev/xvdf1 for me.

    2. As root, service mysqld start FAILED. I looked at /var/log/mysqld.log
    I get these ERRORS
    [ERROR] Can’t open the mysql.plugin table. Please run mysql_upgrade to create it.

    [ERROR] Can’t start server : Bind on unix socket: Permission denied
    121110 4:54:06 [ERROR] Do you already have another mysqld server running on socket: /var/lib/mysql/mysql.sock ?
    121110 4:54:06 [ERROR] Aborting

    Do you have any clue?

    Thanks. Jack – amateur web monkey

    • Hey Jack, whilst getting this blog post together and getting my server setup I had to start again quite a few time for each of the elements. The whole process took me around 5 days of backwards and forwards. Here is my best stab at the two issues you have.

      1. This sound to me like something has gone wrong with the EBS attachment, I would trying detaching and attaching again even if it means a bit of rework.

      2. Firstly I would run mysql_upgrade as it seems like something has gone wrong with the installation. Would then stop and start and see if anything else pops up. If not I would uninstall MySQL and install again.

      Let me know if that helps, good luck with it.

    • SOLVED – I had the same issue – it’s the rights are too strict on the /vol directory.
      mkdir -m 000 /vol is too strict. Need to loosen it so that files can be changed.

  8. Very helpful post (and as a side note, I love the blog style). Just one warning for folks migrating blows to Micro Instances… they can tip over in a hurry if you get linked to from a major site! 🙂 Happened to me recently and I wrote a quick blog post on the topic: http://www.etherealbits.com/?p=97. Thought that a few of the folks here may find it useful.

    • Tyson, you got to love the power of the cloud it has got us out of a few binds at work. Micro instances are definitely pretty prone to falling over if they receive a decent amount of traffic and the unpredictability of the internet can throw you a surprise. Best to setup some simple email monitoring of your instance so you find out ASAP and fix it as you have described.

  9. Thanks so much for writing this up! I too had been searching for information regarding WP and AWS. You did a fantastic job explaining the process. Can I ask what you’re costs have been so far for your hosting on AWS? Is Music to Write Code To hosted there?

    Thanks again!

    • Matt so far I haven’t gone over the usage off the free tier on the micro instance I am running so I haven’t paid anything. Once that has run out I worked it out to be roughly US$13 a month if you go for a reserved Micro Instance over a year contract. I am also running my wife’s site of this as well so is a pretty cheap for the flexibility and learning that it provides.

  10. Wow, absolutely wow. I have always been curious about AWS, afraid to jump in (due to costs). In the last couple of weeks I’ve been looking into AWS and can barely find information on the individuals running WP on AWS. I only know Blake from Earmilk, but he seems like a busy fella. Thank you for writing this, I am going to look at it deeper and play with the 12 month free. (I was not aware of micro being, how I want to say, “free-to-play!”) 😉

    Followed you on Twitter, perhaps if I run into issues I can bring them up with you.

    Thanks again.