matb33.me

Mathieu Bouchard

Setting up WordPress on an Amazon EC2 micro instance

I've had some success running WordPress (3.3) on an EC2 micro instance. After much research into tuning a LAMP stack under a low memory environment (EC2 micro only carries 613MB of memory), I believe I have a pretty solid setup going.

Note that these instructions assume that you are creating a server dedicated to a single installation of WordPress (i.e. no virtual hosts).

Create a Micro EC2 Instance

The settings you're looking for are as follows:

  • Amazon Linux AMI 64 bit
  • Micro (t1.micro, 613MB)
  • Prevent against accidental termination (up to you, but it's a safe bet to turn this on)

Generate a keypair

This should be possible via the step-by-step wizard you're following when creating your EC2 instance. I suggest calling it wpuser, but feel free to use a different username and substitute throughout the instructions.

Save wpuser.pem to a folder such as ~/.ec2 on your local machine. You'll be using this keypair to connect to your server (FileZilla only likes the ppk format, but that's not too difficult to obtain from the pem file). The ssh command line has the -i parameter, which you can feed it the pem file:

ssh -i ~/.ec2/wpuser.pem ec2-user@ec2-xxx-xxx-xxx-xxx.compute-1.amazonaws.com

You'll also need to setup a security group for your new EC2 server. Make sure whichever security group you choose (or create), has the following rules:

HTTP (port 80) Source 0.0.0.0/0
SSH (port 22) Source 0.0.0.0/0

Login to the instance

Next up, using your keypair, login to your instance using a terminal client (Windows users will need to convert the pem file to ppk in order to use Putty).

ssh -i ~/.ec2/wpuser.pem ec2-user@[Public DNS for your EC2 instance]

Note that we're logging in automatically as ec2-user. If you're using Putty and haven't configured an auto-login, just enter ec2-user as your username. You shouldn't be prompted for a password, as the keypair takes care of this for you.

Run any updates as necessary:

sudo yum update

Create a 1GB swap file:

This should help prevent running out of memory (and subsequently grinding the server to a halt) in case our MPM prefork settings are somehow overrun. We'll be configuring these prefork settings further down.

sudo /bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024
sudo /sbin/mkswap /var/swap.1
sudo /sbin/swapon /var/swap.1

The only issue with this is that it may cost you a little bit more to run your instance. The reason is that reads & writes to memory are free, but reads & writes to disk (EBS volume, which your swap file sits on) are not.

Install MySQL:

sudo yum install mysql mysql-server mysql-libs
sudo /etc/init.d/mysqld start
sudo chkconfig --levels 235 mysqld on
mysqladmin -u root password 'typeinapasswordofyourchoosing'

Tweak MySQL InnoDB settings:

Let's cut down on the buffer pool size that InnoDB tries to take, all the way down to 8MB. I'm going that low because we don't use InnoDB for WordPress, only MyISAM.

Edit /etc/my.cnf, and within the [mysqld] section, add the following line:

innodb_buffer_pool_size=8M

Then, restart MySQL to have this setting kick in:

sudo /etc/init.d/mysqld restart

Install Apache and PHP:

sudo yum install httpd php php-mysql php-gd php-imap php-ldap php-odbc php-pear php-xml php-xmlrpc
sudo /etc/init.d/httpd start
sudo chkconfig --levels 235 httpd on

Configure Apache:

Edit /etc/httpd/conf/httpd.conf

Within the <Directory "/var/www/html"> section:

Replace AllowOverride None with AllowOverride All. This will allow .htaccess files to do their thing (such as rewriting URL's).

Within the <IfModule prefork.c> section:

Replace all values to match the following, more appropriate, values:

StartServers 10
MinSpareServers 10
MaxSpareServers 10
ServerLimit 10
MaxClients 10
MaxRequestsPerChild 1000

These values are more sensible than the defaults, as an EC2 micro instance only carries 613MB of memory. WordPress, being the memory hog it is, is commonly known to spawn processes in excess of 50MB each.

Install ssh2 for PHP:

sudo yum install php-devel
sudo yum install gcc
sudo yum install libssh2-devel
sudo yum install make
sudo pecl install ssh2

You will likely get an error message similar to: Failed to download pecl/ssh2 within preferred state "stable", etc. Look for the channel://... URL. Select and copy that URL, then try this instead, substituting the channel://... URL for the one you were given:

sudo pecl install channel://pecl.php.net/ssh2-0.11.3

When it asks for "libssh2 prefix?" just hit enter for autodetect. Moving on:

sudo sh -c 'echo "extension=ssh2.so" > /etc/php.d/ssh2.ini'
sudo /etc/init.d/httpd restart

Setup authorized_keys

Using the wpuser.pem keypair you used during EC2 creation, extract the public key from it. I suggest uploading this file to /home/ec2-user/ so that the instructions below make sense:

chmod 600 /home/ec2-user/wpuser.pem
ssh-keygen -y -f /home/ec2-user/wpuser.pem > /home/ec2-user/wpuser.pub
sudo mkdir -p /home/apache/.ssh
sudo mv /home/ec2-user/wpuser.p?? /home/apache/.ssh
sudo touch /home/apache/.ssh/authorized_keys
sudo chown ec2-user:ec2-user /home/apache/.ssh/authorized_keys
sudo cat /home/apache/.ssh/wpuser.pub > /home/apache/.ssh/authorized_keys
sudo chown -R apache:apache /home/apache
sudo chmod 600 /home/apache/.ssh/*

WordPress

First, set some permissions to allow uploading our WordPress codebase:

sudo chown ec2-user:ec2-user /var/www/html

Next, using an SSH file-transfer client like FileZilla (and logged in as ec2-user), transfer the codebase over to /var/www/html. Once the file upload is completed, set some further permissions:

sudo chown -R apache:apache /var/www/html/wp-content/uploads

Create database and user for WordPress

For the sake of example, I'm having you create a database called "wpdb" and a user "wpdbuser".

mysql -u root -p

(enter mysql root password)

CREATE DATABASE wpdb;
GRANT ALL PRIVILEGES ON wpdb.* TO 'wpdbuser'@localhost IDENTIFIED BY 'chooseapassword';
exit

Updates via SSH

Edit wp-config.php and add the following lines (I added them below the database config lines):

define('FS_METHOD', 'ssh2');
define('FTP_BASE', '/var/www/html/');
define('FTP_CONTENT_DIR', '/var/www/html/wp-content/');
define('FTP_PLUGIN_DIR ', '/var/www/html/wp-content/plugins/');
define('FTP_PUBKEY', '/home/apache/.ssh/wpuser.pub');
define('FTP_PRIKEY', '/home/apache/.ssh/wpuser.pem');
define('FTP_USER', 'ec2-user');
define('FTP_HOST', '[Public DNS for your EC2 instance]:22');
define('FTP_SSL', false);

Make sure to update the FTP_HOST line with your Public DNS for your EC2 instance.

This will allow you to install plugins from the wp-admin section via SSH (no need to have FTP).

That's it!

My instructions are probably not perfect, as I wrote my notes when importing an existing WP installation. If this post gains any traction, I'll take the time to actually follow these instructions on a brand new EC2 instance with a new WordPress installation to see what adjustments I need to make.

If you've done this for me already, please share!