Skip to content

Blog Deployment & Migration

Ethan edited this page Jun 8, 2015 · 5 revisions

(Re)creating the Blog instance on EC2

  1. Launch an EC2 instance with the pre-made "WordPress powered by Bitnami (HVM)" configuration, which is available on the AWS Marketplace. The instance should be a t2.micro. Copy the initial bitnami randomly-generated password, and optionally change it, so you can sub it in later.

  2. Add it to the existing "blog" VPC and Subnet, and give it the "blog" IAM role. Among other things, that IAM role is associated with a policy that grants write access to the "overview-blog" bucket on S3, for backups.

  3. Disable the banner from the bitnami install: https://wiki.bitnami.com/Components/Bitnami_info_page

  4. If applicable, restore our Wordpress customizations and the blog database. (See below.)

  5. Set up backups to run in the future, as follows:

  6. SSH into the server, using bitnami's standard instructions.

  7. Install modules that the backup script needs, and create the tmp directory:

apt-get install python-pip
pip install boto
pip install FileChunkIO
mkdir /home/bitnami/tmp
  1. Create the backup script in /home/bitnami/scripts/ and call it backup.py. The content's of the script should be:
#!/usr/bin/python

import sys
import os
import boto
import math
import smtplib
from email.mime.text import MIMEText
from subprocess import check_call, CalledProcessError
from boto.s3.key import Key
from datetime import datetime
from filechunkio import FileChunkIO

# Create an email helper we'll use if the backup fails
def email_error(error_string):
      from_addr = "[email protected]";
      to_addr = "[email protected]";
      msg = MIMEText("The exact error was: " + error_string)
      msg['subject'] = "Overview Blog Backup failed!";
      msg['From'] = from_addr;
      msg['To'] = to_addr;

  	SMTP_USERNAME=PUT_SMTP_USERNAME_HERE
  	SMTP_PASSWORD=PUT_SMTP_PASSWORD_HERE


      smtpObj = smtplib.SMTP("email-smtp.us-east-1.amazonaws.com")
      smtpObj.starttls()
      smtpObj.login(SMTP_USERNAME, SMTP_PASSWORD)
      smtpObj.sendmail(from_addr, [to_addr], msg.as_string())
      smtpObj.quit();
      sys.exit("encountered an error...emailing it and terminating")

# Create the backup files in tmp.
# Note: path names aren't portably joined, but who cares.
dir = os.path.abspath(os.path.dirname(__file__))
wordpress_src_glob = os.path.normpath(dir + "/../apps/wordpress/*")
wordpress_tar_dst = os.path.normpath(dir + "/../tmp/wordpress-app-with-certs.tar.gz")
sql_dump_dst = os.path.normpath(dir + "/../tmp/db-dump.sql")

try:
      check_call("sudo mysqldump --user=root --password=PASSWORD_FOR_DB bitnami_wordpress > " + sql_dump_dst, shell=True)
      check_call("tar -cvzf " + wordpress_tar_dst + " " + wordpress_src_glob + "", shell=True)

except CalledProcessError as e:
      email_error('"{0}" returned with code {1}'.format(e.cmd, e.returncode))

# Connect to S3
s3 = boto.connect_s3()
bucket = s3.get_bucket('overview-blog')

# Do the S3 uploads, in chunks
def do_multipart_upload(source_path):
      try:
              chunk_size = 52428800
              source_size = os.stat(source_path).st_size
              chunk_count = int(math.ceil(source_size / float(chunk_size)))

              mp = bucket.initiate_multipart_upload(os.path.basename(source_path))

              for i in range(chunk_count):
                      offset = chunk_size*i
                      bytes = min(chunk_size, source_size - offset)
                      with FileChunkIO(source_path, 'r', offset=offset, bytes=bytes) as fp:
                              mp.upload_part_from_file(fp, part_num=i + 1)

              mp.complete_upload()
              return True
      except:
              email_error("Problem uploading to s3; check the backup file to debug further.");

do_multipart_upload(wordpress_tar_dst)
do_multipart_upload(sql_dump_dst)

Of course, you need to sub in the password for the database where it says PASSWORD_FOR_DB above.

  1. Register the above script as a cronjob: 1. crontab -e 2. Add the line: 0 3 * * * /home/bitnami/scripts/backup.py

  2. That's it!

Restoring from a Backup

Assuming you're starting with a default bitnami install (per above), all you have to do is:

  1. Replace the contents of /home/bitnami/apps/wordpress with the latest version of wordpress-app-with-certs.tar.gz from the S3 overview-blog bucket
  2. Restore the bitnami_wordpress database from the latest version of the db-dump.sql file from S3.

If you need to restore from an older backup (i.e. not the latest version), those can be accessed through S3's versioning system.

Migrating to a Different Domain

Other than re-pointing DNS, future migrations will require adding a redirect from the old URIs to the new ones. A simple way to do this is to leave the old domain name pointing to the new blog instance as well, but add some redirects in .htaccess for the old TLD. Additionally, you may want to edit the URIs in the body of the post's themselves, though this isn't strictly necessary if the aforementioned redirect is in place. However, if you do decide to edit the URIs, make sure the resulting URIs remain absolute (just pointed to the new domain). Yes, this is a bit of a pain, since using relative URIs would prevent the need for future rewrites, but absolute uris are needed in some rss readers that don't properly honor xml:base, which wasn't originally discussed in the RSS 2 spec.

Clone this wiki locally