Wednesday, April 27, 2016

Heroku and Wordpress: The Migration Process

My post day-before-yesterday begun the story of my migration from a home-hosted website to Heroku. Here's part two: The Migration Process

Step: Move my Media Library content into S3

First off, the uploaded photos should not be under version control; so they shouldn't be in the repository and in the ephemeral filesystem.

This was a tedious process of a few hours since I had about 130 images.
  • I set up the S3 plugin I mentioned above, made a few tests and confirmed that it's sweet.
  • I SFTP'd into my Wordpress site's wp-content/uploads folder and grabbed everything.
  • Then deleted everything from my Media Library,
  • Then uploaded it all again and watched it load into S3 and leave my uploads folder empty.
  • Then went through every posting and replaced all of the images, which of course were now broken. Annoying, but fortunately I only had 35 pages with images and did it in about 2 hours.

Step: Init repo

I'm a fan of Gitlab. They offer unlimited private repositories for free, which is really excellent. I created the repository, then followed their simple instructions to load my Wordpress files into the repo and basically turn my site into a clone.

I also created a .gitignore file with these two entries for some folders I'll be creating in a little bit. The private is where I'll do some other work I don't want in version control, e.g. working files and database dumps that I want to keep close. The vendor would be generated by composer later on, trust me.

Step: Add Heroku as a Secondary Master

The trick in allowing git push to push to deploy to Heroku, is that you tell your repo clone to use your Heroku as a secondary master.

heroku git:remote -a your-server-name

As of now, when pushing you will need to distinguish between git push origin master and git push heroku master. One pushes into your git repository (Gitlab, Github) and the other would redeploy to Heroku.

Step: Wordpress Updates

I then noticed that some updates were available for some plugins and for Wordpress itself. So I ran those, and after each one noted that git status reported exactly what I would expect from each upgrade. So three commits later I had Wordpress and plugins all updated, with commit notes for each update. (I could have done this before the repo init, but why not do it under version control?)

Step: Add a Procfile and composer.json file

For Heroku compatibility, it's advisable to add a Procfile and a composer.json and composer.lock file, to indicate to heroku what PHP version to prefer, that you prefer Apache over Nginx, etc. You will want these in version control.

web: vendor/bin/heroku-php-apache2

  "require" : {
    "php": "^5.6.0"
  "require-dev": {
    "heroku/heroku-buildpack-php": "*"

composer.lock is generated from the composer.json with a command:
composer update --ignore-platform-reqs

Step: Push to Heroku

All set? Then here goes:
git push heroku master
And I visit my website. And it's a Wordpress error that it can't make the database connection. That's to be expected: my wp-config.php has the old credentials and I still need to upload the database content. But that's definitely Wordpress making the error, so a fine start.

Step: Database Configuration

First step was to scrub my database credentials from the wp-config.php file. Yeah, dummy move to forget to do that, but the credentials are wrong for Heroku so are useless, and my local MySQL is going away in an hour anyway. But yes... don't do what I did. ;)

When I scrubbed the database credentials, I replaced them with $_ENV variables like this:
define('DB_NAME', $_ENV['DATABASE_BASE']);
define('DB_USER', $_ENV['DATABASE_USER']);
define('DB_HOST', $_ENV['DATABASE_HOST']);
Add, commit, push. Site is still dead but it's ready for this next trick.

Run heroku config and it dumps the app's configuration variables back to me. I tease apart the database URL string, into my set of 4 environment variables for the 4 $_ENV items above.
My app/dyno reboots and... the site's up!

Step: Database Data

A simple mysqldump was all it took to take a backup of my database, then loading it was one more command.

mysqldump -h localhost -u olduser -p olddbname > private/dbdump.sql
mysql -h herokuhost -u herokuuser -p herokudbname < private/dbdump.sql

It doesn't get as lot easier than this.

And now the site is up! My data, on a new database on a new Heroku server. Shiny.

Step: Custom Domain

My site is and not Heroku calls this a custom domain. There are two steps in setting up the Heroku app to work properly with a custom domain.

  • I hit up Heroku's dashboard and the Settings for my site, and added two domains for it: and This allows it to respond to these alternate hostnames, should they point to this app.
  • I went to my domain registrar's domain control panel and set up a CNAME record, so that is equivalent to This took a little bit to propagate, but was done about the time I finished my cup of coffee.

And that really was it. Well, almost. More on this tomorrow.

No comments:

Post a Comment