Running WordPress on EC2 with a little help from Bitnami

Running WordPress on EC2 with a little help from Bitnami

Recently I upgraded a few of my WordPress websites to run on Amazon’s EC2, thanks in no small part to Dan Ackerson’s wonderful guide on how to migrate your WordPress blog to EC2. This is probably the point where I wax poetic about the wonder of cloud services, and how Amazon has enabled even a small team of a few people to release an Internet scale service. But alas, for now I’ll have to satisfy myself with writing my own, small guide on how to get started. Despite how helpful Dan’s guide was there was still a few things that weren’t obvious to me that I had to discover. Hopefully this will be helpful to others like myself who are less experienced with EC2, and serve as a good reminder should I ever attempt something like this again.

You probably already know what Amazon EC2 is, but may be wondering about Bitnami. Bitnami is an easy way to run open source stacks on cloud services like EC2. As one example, Bitnami provides free images for WordPress, Drupal and others. For a monthly fee they’ll offer to setup and maintain your EC2 instance, but that’s not quite as fun as setting it up ourselves.

Before Getting Started

Setting yourself up with the right tools will make the the upgrade to Amazon EC2 a whole lot smoother and more enjoyable. If you’re on Windows, start by installing Putty which you’ll use to SSH in to your instance, and Filezilla which you’ll use to SFTP. You’ll also, quite obviously, need to signup for Amazon Web Services.

Setting Up The EC2 Instance

To get started, choose a region from the left nav. If in doubt, select US east – it’s closest to most of the US, and a good mid point between the West coast and Europe. Click Launch Instance, select the My AMIs tab, and then switch to view All Images and search for bitnami wordpress. You’ll then see a list of instances to launch. Click Select on the latest version of the Ubuntu WordPress AMI.

Create InstanceClick Continue, on the next screen choose the Micro instance and select Launch Instance. You can change the instance type later by saving images and creating a new, larger instance.

Choose InstanceClick Continue, for Advanced Options, I like to enable Monitoring and Prevent against accidental termination. Be aware that there is an additional charge for monitoring, but in my opinion well worth it.

Click Continue, add a value to the name field to help you find this instance again and click Continue.

If this is your first instance, you’ll need to create a new key pair. Keep this key in a safe place, you’ll use it when accessing your instance.

Click Continue.  It’s important to create a new security group, with SSH, HTTP and HTTPS ports open.

Security

Click Continue. Review your settings, take note of the URL, and then click Launch.

If you navigate to the URL, you’ll find your WordPress instance up and running. You’ll want to login (default username: user, default password:bitnami) and change your password.

Take a moment now to create a new image before you start modifying. That way you’ll be able to easily return to this state if needed. Don’t forget to do this as you make progress.

Save InstanceSetup Elastic IP

To stake your claim on the Internet you need to get your own IP address, and Amazon’s Elastic IP makes that almost trivially easy. Allocate a new IP address and associate it with your shiny new EC2 instance. If you’ve added a name to the instance it’ll be easy to locate the right one.

Be aware that stopping or terminating an instance will disassociate the IP address with that instance, so you’ll need to redo this again if you terminate an instance.

SSH To Your Instance

To connect to your instance you’ll first need to generate a key that can work with Putty using Puttygen.
Launch Puttygen, and then Load the .pem key file you saved (in a safe place, right?) when you launched your EC2 instance. Enter a password and then Save a private key. This key(.ppk) file will be used in Putty. While you’re in Puttygen, Export an OpenSSH key from the same .pem file (this will be used to connect in FileZilla).

Putty Keyword Generator

Launch Putty. Create a saved session using the new IP address and your newly created .ppk file (Connection/SSH/Auth/Browse…).  You can find more detailed instructions for making your .pem key Putty compatible here if you need.

Login with the default username bitnami and use the password you created when saving the .ppk key. and you’re in! The bitnami user can sudo to root, which if you’re not familiar with Linux, is a way to temporarily elevate privileges similar to ‘Run as Administrator’ under Windows.

A Quick Note About Testing

If you’re moving a blog that’s currently up and running I recommend picking a new subdomain to test from (e.g. test.yourdomain.com) so that you can set everything up beforehand, and then just flip a few settings once everything looks good.

Configure Your WordPress Blog to the Right Domain

In WordPress admin, go to settings, general, and set your WordPress address to http://www.yourdomain.com/wordpress, and your site address to http://www.yourdomain.com. You need to set this before you start futzing around with virtual hosts and such so you can still configure WordPress.

Get Your Instance Ready

Setup a virtual host to point to your new blog

sudo pico /opt/bitnami/apache2/conf/httpd.conf
...
#Virtual hosts
Include conf/extra/httpd-vhosts.conf

If you search for virtual hosts (Ctrl+W in pico) you’ll find the line above, and you only need to uncomment it by removing the #.

Also make sure to uncomment two other includes:

# Server-pool management (MPM specific)
Include conf/extra/httpd-mpm.conf
...
# Various default settings
Include conf/extra/httpd-default.conf

While you’re there, add compression support for all files served from apache using mod_deflate. Make sure the following line is present (it should be), and then add the location directives to compress this content type

LoadModule deflate_module modules/mod_deflate.so
...
<Location />
 AddOutputFilterByType DEFLATE text/plain
 AddOutputFilterByType DEFLATE text/xml
 AddOutputFilterByType DEFLATE application/xhtml+xml
 AddOutputFilterByType DEFLATE text/css
 AddOutputFilterByType DEFLATE application/xml
 AddOutputFilterByType DEFLATE image/svg+xml
 AddOutputFilterByType DEFLATE application/rss+xml
 AddOutputFilterByType DEFLATE application/atom_xml
 AddOutputFilterByType DEFLATE application/x-javascript
 AddOutputFilterByType DEFLATE application/x-httpd-php
 AddOutputFilterByType DEFLATE application/x-httpd-fastphp
 AddOutputFilterByType DEFLATE application/x-httpd-eruby
 AddOutputFilterByType DEFLATE text/html
</Location> 
DeflateCompressionLevel 9

Next you want to set your domain to point to your blog, rather than the bitnami page

sudo pico /opt/bitnami/apache2/conf/extra/httpd-vhosts.conf
...
<VirtualHost *:80>
    DocumentRoot "/opt/bitnami/apps/wordpress/htdocs"
    ServerName yourdomain.com
    ServerAlias www.yourdomain.com
    ErrorLog "logs/awo-error_log"
    CustomLog "logs/awo-access_log" common
</VirtualHost>

I also like to link up admin.yourdomain.com to point to the WordPress admin dashboard. Add an A record on DNS to point to your IP, and another virtual host pointing to the wp-admin file.

Remove duplicate content by editing .htaccess file

sudo pico /opt/bitnami/apps/wordpress/htdocs/.htaccess
...
RewriteEngine On
RewriteCond %{HTTP_HOST} .
RewriteCond %{HTTP_HOST} !^www.yourdomain.com
RewriteRule (.*) http://www.yourdomain.com/$1 [R=301,L]

Restart apache, which is done by running the bitnami script:

sudo /opt/bitnami/ctlscript.sh restart apache

Update the permissions to allow inline updating (of WordPress and plugins) using:

sudo chown -Rf daemon:daemon /opt/bitnami/apps/wordpress/htdocs

The painful thing about doing this is that you need to switch ownership back to bitnami to upload any files through sftp. I’m sure there’s some solution to this, but I’m not adept enough with Linux permissions to know how [I want the Windows equivalent of right click | Properties | Security].

Point Your Domain To Your IP

Go to your domain host (I use Amazon’s Route 53 via the Interstate 53 management interfce and rely on wwwizer for naked domain redirection) and point test.yourdomain.com to your IP address by creating a new A record.

Testing and Turning On Your New EC2 Powered WordPress Experience

So you’ve diligently tested your blog on test.yourdomain.com, now it’s time to go live. First, update all the places in apache that you entered your domain name and restart apache.

Your WordPress settings in the dashboard (remember those?)
sudo pico /opt/bitnami/apache2/conf/extra/httpd-vhosts.conf
sudo pico /opt/bitnami/apps/wordpress/htdocs/.htaccess
sudo /opt/bitnami/ctlscript.sh restart apache

As I discovered a few times (thanks to Dan and my own forgetfullness), after you get an elastic IP setup, delete the /opt/bitnami/updateip file. If you don’t you’ll find your WordPress wp_options values helpfully reset. I’m not sure why this is the default behavior, but anyway.

Moving a Blog Over

Dan offers one way to move a blog over, essentially copying and replacing wholesale. I prefer more of a ‘clean install’ approach, only bringing the settings that are actually necessary. This is a lot easier if you copy the settings before switching over domains (you can always override this by setting your local hosts file to redirect to your old IP address, but that’s just a pain). Be sure to grab:

  • All the config settings from WordPress and plugins – if you rewrite post URLs and wonder why clicking on the posts gives a 404, go back to WordPress admin dashboard and look for the snippet you need to copy into your .htaccess file. Bitnami doesn’t configure this to be accessible to WordPress by default.
  • Export the posts/pages [If this is more than 2MB, you’ll need to change php.ini to allow an import over 2MB in size – sudo pico /opt/bitnami/php/etc/php.ini]
  • Blogroll
  • Plugins – I used Filezilla to copy plugins from remote to my local hard drive and on to the new server.
  • Media – most of my media files are already hosted on S3 and CloudFront, so this was a noop.

Setting up Caching

Finally, set up W3 Total Cache to get the most performance out of your blog. I also like to set this up first, since it tends to conflict the most with other settings on the server. W3TC recommends APC opcode caching, install with:

apt-get install autoconf
apt-get install gcc
pecl install apc

You’ll also need to copy across the configuration W3TC offers from: /opt/bitnami/apps/wordpress/htdocs/wp-content/plugins/w3-total-cache/ini/apc.ini to /opt/bitnami/php/etc/php.ini

You should now be able to set APC opcode caching with W3TC.

And this is where my problems began…

Httpd Is Hungry, Consumes 100% of CPU

To my great dismay, my CPU utilization graph looked something like the below, and a quick look at top showed the culprit to be httpd.

Apache httpd cpu pegsThe website was constantly timing out when trying to access it. All the promise of EC2 and W3 Total Cache and it was worse than the VPS I’d come from.

I first tried to follow the advice here to Optimize Apache for WordPress. This made it much worse. Timeouts every few minutes became near constant. I’ll admit I had no idea what I was doing adjusting the various settings, and removing modules from Apache, but still…

I had some luck by disabling Pretty Link Pro, but it didn’t fix the problem, only made it slightly less severe. I tried optimizing the database tables (using WP-phpMyAdmin), but that had no effect. Finally I found some respite disabling minification in W3 Total Cache, and disabling object caching. I then reenabled Pretty Link Pro, and things have been okay since then.

I’m still perplexed as to why minification would cause such an issue, especially considering APC should cache this. For now I’m resigned to manually minifying and copying over to cloudfront.

For reference, the site in question gets about 5000 page views a day, and other plugins installed include: Digg Digg, Advanced Excerpt, Akismet, Facebook Comments for WordPress, FeedBurner FeedSmith, Global Translator PRO, Google XML Sitemaps, Platinum SEO Pack, Pretty Link Pro, W3 Total Cache, WP-Polls, WP Render Blogroll Links, WP-phpMyAdmin.

If anyone has a solution to the apache cpu issues I’d love to hear it!