The cool thing about technical howtos like this is the ability to share with other folks who get just as excited. Looking to save costs on our blog hosting, Amazon’s announcement of a 12 month free usage tier put us in the short list for migration. As Matthias did the bulk of the joyent public cloud & linode migrations, it was high-time I got my hands dirty. Without further ado, here’s how I migrated AWO to our first Amazon EC2 instance. Let’s get our geek on!
Choosing bitnami
My initial plan was to grab some Debian based Amazon Machine Image (AMI) and follow the various “howto config wordpress on lamp” posts out there, but Matthias asked if I’d had a look at bitnami. I’d never heard of it before and, truth be told, it actually sounded like some kind of BitTorrent client to me. Digging in a little deeper, I soon understood what all the hoopla was about and was soon sold on a nicely contained, pre-configured bitnami WordPress AMI. With Ubuntu and RedHat distros to choose from, you can even use an AMI which launches via Elastic Block Storage (EBS) – how’s that for easy?
Just in case you don’t know what EBS is good for – an Instance Store EC2 server doesn’t come with a disk for storing your data. Meaning if you plan on making changes to your AMI at runtime that you’d like to see after a reboot, you need to attach a disk (EBS in Amazon AWS speak).
Setting up a new EC2 instance on AWS
One of the catches for a 12 month, free EC2 instance is a new Amazon account, so be sure to register a new email address or you might get a surprise bill next month! And, yes, you will also need a valid credit card to open your account, because if your instance exceeds the free usage tier limits, you will be charged.
For those of you running multiple WordPress blogs, bitnami even offers preconfigured MultiSite AMIs!
You should definitely spend a few minutes considering the region in which to launch the instance. If you’re using Google Analytics, checkout your “Audience -> Geo -> Location” to see the regions sending your blog the most visits. Our primary traffic comes from the U.S. West Coast, but there are significant visits throughout the Continental U.S. and Europe.
We ultimately went with the mid-point “U.S. East” region.
Once you decide on a region and an instance type, just click on the desired bitnami WordPress AMI. You’ll be automatically forwarded to the AWS Console for launching that instance in the desired region:
The only change you’ll need to make to the default settings, is to add HTTP port 80 to the default security group. The Wizard will even give you the option of locking this down to your current IP address which I certainly recommend for the initial setup & config.
Click “Launch” and you’ll be prompted to create and/or download a public/private keypair in a .pem file (hereinafter referred to this howto as ‘my_aws_ec2.pem’) – this is your SSH keypair to get in the backdoor of your new instance:
After your instance launches, click on it in the AWS Management Console. The description tab below will list a “Public DNS” (hereinafter referred to in this howto as ‘public_dns.amazonaws.com’):
Point your browser to this URL and you’ll see the bitnami Welcome page with a few links including your new WordPress install. Not too shabby – a running blog on a new virtual server all in the space of about 5 minutes!
Last, but not least, make an EBS snapshot of your running instance so you have a known fallback before entering the next phase of the migration. Don’t forget about this capability – at every step where you feel you’ve accomplished an important step, back it up!
Migrating Your WordPress Blog
On your existing blog, dump your database and tarball your WordPress htdocs path.
$ mysqldump -uwordpress -p awo > awo_wp.sql $ tar -cjf awo_htdocs.bz2 /home/awo/public
Now, let’s get those dumps copied over to your new EC2 instance:
$ scp -i my_aws_ec2.pem awo_wp.sql awo_htdocs.bz2 bitnami@public_dns.amazonaws.com:/home/bitnami/originals/
And, don’t forget to copy over any releveant configurations and performance tweaks in your Apache (apache2.conf
, httpd.conf
) and MySQL (my.cnf
, conf.d/*.cnf
) setups.
Moving on to the IP address. Goto the Elastic IP’s entry in your AWS console. Allocate New Address and associate it with your newly created (and probably only) EC2 instance. While we’re waiting for the DNS to catch up, edit your local (meaning the computer you’re using to do the migration) /etc/hosts accordingly, overriding your blog domain with this new IP address.
$ sudo vi /etc/hosts ... www.agileweboperations.com
On the new instance do something like the following (remembering your EBS snapshot above ;)),
$ rm -Rf /opt/bitnami/apps/wordpress/htdocs/ $ tar -xjf ~/originals/awo_htdocs.bz2 /opt/bitnami/apps/wordpress $ mysql -uroot -pbitnami bitnami_wordpress < ~/originals/awo.sql
Note the location of the bitnami wordpress, and the MySQL root password and wordpress database schema.
Now, let’s setup a virtual host to point to your new blog:
$ sudo vi /opt/bitnami/apache2/conf/httpd.conf ... # Virtual hosts Include conf/extra/httpd-vhosts.conf ... $ sudo vi /opt/bitnami/apache2/conf/extra/httpd-vhosts.conf ... DocumentRoot "/opt/bitnami/apps/wordpress/htdocs" ServerName agileweboperations.com ServerAlias www.agileweboperations.com ErrorLog "logs/awo-error_log" CustomLog "logs/awo-access_log" common ...
Any special apache configuration (KeepAliveTimeout
, ServerTokens
, etc.) can be edited @ /opt/bitnami/apache2/conf/extra/httpd-default.conf
. Be sure to include these edited files in the base apache conf:
$ sudo vi /opt/bitnami/apache2/conf/httpd.conf ... # Server-pool management (MPM specific) Include conf/extra/httpd-mpm.conf ... # Virtual hosts Include conf/extra/httpd-vhosts.conf ... # Various default settings Include conf/extra/httpd-default.conf
Finally, remember your canonical redirects! No duplicate content here:
$ vi /opt/bitnami/apps/wordpress/htdocs/.htaccess RewriteEngine On RewriteCond %{HTTP_HOST} . RewriteCond %{HTTP_HOST} !^www.agileweboperations.com RewriteRule (.*) https://www.agileweboperations.com/$1 [R=301,L]
Restarting processes with bitnami is accomplished using the ctlscript.sh
. To restart Apache, just run sudo /opt/bitnami/ctlscript.sh restart apache
.
MySQL my.cnf may be edited @ /opt/bitnami/mysql/my.cnf
and the restart is accomplished in much the same way : sudo /opt/bitnami/ctlscript.sh restart mysql
.
You can also use ctlscript.sh
to check out your apache & mysql status:
$ sudo /opt/bitnami/ctlscript.sh status apache already running mysql already running
Gotchas & Caveats
Installing ec2-api-tools
is not possible on a t1.micro Ubuntu instance. However, if you do need AWS CLI tools, checkout … well, there are AWS CLI tools which run on python right out of the box!
the “Public DNS” name will dynamically change upon restarting an instance. Don’t go hardcoding this into your /etc/hosts
file and bookmarking it for all eternity!
For those spend-thrifty types, just starting an instance immediately costs you 1 hour of computing time, so don’t be surprised to see a bit more usage ($$$) than you’d expect if you do this a few dozen times over a weekend of experimentation.
YMMV, but the bitnami:daemon
user:group which owned /opt/bitnami/apps/wordpress/htdocs
was not sufficient for performing any “inline” wordpress upgrades/installs – meaning trying to upgrade/install a plugin asked for FTP access information. Performing a sudo chown -Rf daemon:daemon /opt/bitnami/apps/wordpress/htdocs
did the trick, however. Anyone more familiar with bitnami, please feel free to step in and clarify.
MySQL died the first night after relaunch. A strange “Killed” showed up in the /opt/bitnami/mysql/data/mysqld.log
:
101229 15:41:33 [Note] /opt/bitnami/mysql/bin/mysqld.bin: ready for connections. Version: '5.1.50' socket: '/opt/bitnami/mysql/tmp/mysql.sock' port: 3306 MySQL Community Server (GPL) Killed 101230 00:15:51 mysqld_safe Number of processes running now: 0 101230 00:15:51 mysqld_safe mysqld restarted 101230 0:15:53 [Note] Plugin 'FEDERATED' is disabled. Killed 101230 00:15:54 mysqld_safe mysqld from pid file /opt/bitnami/mysql/data/ip-10-112-91-108.pid ended 101230 07:32:02 mysqld_safe Starting mysqld.bin daemon with databases from /opt/bitnami/mysql/data ...
Turns out, the bitnami image makes use of Linux’s OOM Killer which takes a heavy-handed approach to potential Out of Memory issues before they over swap the server. The problem was I forgot to include the httpd-mpm.conf file I had altered so carefully above in the httpd.conf, so there were a bunch more simultaneous clients than this micro server could manage.
After you get an elastic IP setup, you may have to rerun the /opt/bitnami/scripts/init/updateip
file. To manually set the wp_options values to your blog’s domain name:
$ mysql -uroot -p bitnami_wordpress mysql> update wp_options set option_value = 'https://www.agileweboperations.com' where option_name in ('siteurl', 'home'); Query OK, 2 rows affected (0.00 sec)
Our “free” year worked out great for such little effort (~1 day) and was well worth the savings. Check out where the rubber meets the road – our Pingdom response times before and after the relaunch:
Professional Grade Virtual Computing for “Free”
-
In case you missed my other posts on acquiring, maintaining, backing-up and monitoring your virtual server, here’s the complete list:
- Performance : WordPress Caching For High Performance EC2 Micro Instances
- Backups : Poor Man’s Automated Snapshots for EC2
- Monitoring : Cloudkick Monitoring for EC2