Migrating WordPress from Pagely

Pagely is an expensive and robust solution for WordPress hosting. With the right caching setup wordpress can be performant, so let’s slap it in a docker container behind nginx.

To get off of Pagely, the most critical thing you’ll need to do with your exported backups is to make sure to either remove or rename or remove the mu-plugins folder.

  1. Rename or delete mu-plugins/ from the folder export.
  2. Import the database and wp-content directories.

What’s easier than physically moving your wp-content directory is using the Updraft Plus plugin to create a backup of your wordpress install.

Redirect Hell

Setting the siteurl and home settings in the database shoots me into redirect hell.

 

Setting as localhost instead of localhost/blog yields a somewhat more functional site, but all the links are broken and nothing tends to work. I must need PHP 5. (This was definitely not the solution)

So it all works after disbabling the pagely plugins but this reverse proxying to a docker container from a subfolder thing, wordpress really doesn’t appear to like it very much. Everything worked for a second but now it doesnt again, just stuck in a 301 redirect loop to itself. The wp-admin functions fine as long as you remember to add the trailing slash on the URL.

Endless redirect loops later, we’re still stuck in a redirect loop.

Hopefully you won’t need to spend that much time dickerin with it.

wp-config.php

define('FORCE_SSL_ADMIN', true);

define('WP_HOME', 'http://example.com/newblog/');
define('WP_SITEURL', 'http://example/newblog/');

$_SERVER['REQUEST_URI'] = '/newblog' . $_SERVER['REQUEST_URI'];

This $_SERVER['REQUEST_URI'] line was the most helpful fix I came across. I had previously been using $_SERVER['REQUEST_URI'] = str_replace("/wp-admin/", "/blog/wp-admin/", $_SERVER['REQUEST_URI']); as recommended by several resources in place for the wp-admin but rewriting the whole URI with $_SERVER['REQUEST_URI'] = '/newblog' . $_SERVER['REQUEST_URI']; stopped redirect hell.

/etc/nginx/sites-enabled/default

We’ll add a section for nginx to proxy to the wordpress container.

    location /newblog/ {
        access_log off;
        auth_basic off;

        rewrite /newblog/wp-admin$ $scheme://$host$uri/ permanent; # This line redirects /newblog/wp-admin to /newblog/wp-admin/ which is nice to have. 

        proxy_set_header  Host               $host;
        proxy_set_header  X-Real-IP          $remote_addr;
        proxy_set_header  X-Forwarded-For    $proxy_add_x_forwarded_for;
        proxy_set_header  X-Forwarded-Proto  $http_x_forwarded_proto;

        proxy_http_version 1.1;
        proxy_buffering off;
        proxy_read_timeout    90;
        proxy_connect_timeout 90;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Proxy "";

        proxy_redirect    off;
        proxy_pass        http://wordpress/;
    }

.htaccess

The .htaccess file that wordpress creates will attempt to make the RewriteBase and RewriteRule include the newblog/ part of the URL, which we don’t want, and will cause a redirect loop.

# BEGIN WordPress

RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

# END WordPress

The deploy

So it all works after destroying and rebuilding containers. What are the steps to do it live?

  1. ✅ Install Updraft Plus and create a backup, stuff it in dropbox.
  2. ✅ Deploy the containers, on the /newblog/ URL.
  3. ✅ Run our install script via wp_cli:
#!/bin/bash

docker-compose run wp_cli core install --url='http://example.com/newblog/' --title=temp --admin_user=temp --admin_email=youremail@example.com --admin_password="password"
docker-compose run wp_cli plugin install updraftplus --activate
  1. ✅ Connect dropbox in the updraft plus plugin. Click rescan remote storage, select the backup to install, and restore that backup.
  2. ✅ Reset the siteurl and home options in the wp_options table.
mysql -uroot -psecret -h 0.0.0.0 wp_database -e 'update wp_options set option_value = "http://example.com/newblog" where option_name = "siteurl" or option_name = "home"'
  1. 💣 Make sure it all works!
  2. ✅ Remove the old nginx redirect for the /blog url and replace it with the /newblog directive. Update the wp-config.php and the database to remove the references to /newblog.
  3. ✅ Shut down pagely. Keep your money.

HTTPS Support.

We didn’t test SSL support locally before deployment, and it’s easy to bang your head against the wall chasing down a fix for a problem that’s the result of something else.

Turns out that Jeff’s Application Load Balancers handle SSL termination and thus pass http_x_forwarded_proto. We set that right in the nginx config and suddenly there is no more redirect hell, and everything’s running on https.

The line in the nginx config proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto; must use x_forwarded_proto instead of $scheme since we’re behind an ALB on AWS. This is only needed if you’re using nginx behind an application load balancer on aws, otherwise using $scheme should allegedly work.


Resources

github ↗ a5hleyrich/wordpress-nginx
docs.j7k6.org ↗ Basically looks to be exactly what we are looking for, but not quite.
stackoverflow ↗ nginx subpath to redirect to wordpress docker container

serverfault ↗ hosting a wordpress blog using nginx as a sub directory
stackoverflow ↗ wordpress nginx proxy and subdirectory wp login php redirects to domain

stackexchange ↗ wordpress wp admin https redirect loop

stackexchange ↗ https leads to sorry you are not allowed to access this page
stackexchange ↗ setting server https on prevents access to wp-admin

codex.wordpress.org ↗ administration over ssl

serverfault ↗ x forward proto custom header

Beats

WordPress Plugins You Should Be Using in 2017

5 minute read

The WordPress ecosystem has matured quite a bit since the last time I spent much time with it around 2011-2012. The paid themes and premium plugins specifically are light years ahead of where we were 5 years ago. A light weight website is easy to set up with WordPress, cheap to host, and you really have a lot more control over it than what you get with a Squarespace or Wix site.

Here’s my go-to plugin protocol for any generic WordPress install that you actually care about:

1. Akismet Anti-Spam

The obligatory spam blocker for WordPress. Created by Automattic, the same company behind WordPress, Akismet is offered at a “Pay whatever you want” rate. This could be anywhere from zero dollars up to more than zero dollars. It’s up to you.

2. Child Theme Configurator

If you’re planning on doing any sort of theme editing on top of a custom theme that you’ve chosen, save yourself a lot of time and headache by installing Child Theme Configurator and creating a child theme before you just go start hacking away at your chosen theme.

Creating a child theme will allow you to keep updating the parent theme, [hopefully] without loosing any of the changes that you made. With the vibrancy of the WordPress ecosystem that’s alive now adays, and assuming you’ve chosen a theme that is actively being worked on count on theme updates being released on a fairly regular basis – at least once a month.

If you edit a theme and you haven’t created a child theme, installing updates to the theme will stomp all over your changes and it won’t be fun.

3. Free & Simple Contact Form Plugin – Pirateforms

There are a lot of free plugins to create forms, I like Pirateforms mostly because it’s compatible with my theme choice. It uses wordpress shortcodes so you can drop a form in on any page you want.

The thing I do like about Pirateforms is that the content of the forms is stored in the WordPress Admin for easy processing, in addition to sending the form content via email.

4. Jetpack by WordPress.com

The ubiquitous Kitchen Sink of the WordPress world – Constantly being pushed to upgrade by Automattic is not my favorite part about this plugin.

Jetpack lets you write your posts in markdown which is reason enough on its own to use. Note: _markdown support is not spectacular even when using Jetpack, but at least it’s there_ to some extent

Other features that are included for better or worse are Portfolios & Testimonials (which many themes will leverage), showing Related posts, adding sharing buttons to posts, generating sitemaps, and improved loading of images by scaling them down to size where it can.

5. Simple 301 Redirects

“Cool URIs Don’t Change”, but your thinking & information architecture sure will. It’s worth pointing out that while 301 redirects are in most cases the best way to redirect, this type of redirect is permanent, so don’t go throwing them around willy-nilly. You’ll also be pulling your hair out if you create one of these and try and update it quickly, because most web browsers will cache the Permanent Redirect and simply deliver you to where the new page was set up at – ignoring any changes you may have made after establishing the Permanent Redirect.

If you want even more control over URI management, check out Permalink Manager Lite which has a lot more features that you may or may not be interested in.

6. Updraft Plus

This is by far the most impressive plug in I’ve found for wordpress. Automatically schedule backups of your content, database, plugins, themes and send it to whatever cloud storage service is your favorite, such as Drop Box or Google Drive, Amazon S3, FTP, or even to Microsoft 👀

The paid version of Updraft plus gives you even more control over backup schedules and they have some impressive services that they offer at the paid tier to allow you to manage multiple WordPress installs – upgrading and backing them up from a single control panel. If you need to manage several WordPress installs this seems like a great way to go (although I can’t say I’m using this feature – the free version is enough for my purposes).