SJ cartoon avatar

Development From Dreamhost to Digital Ocean - WordPress

It’s been a long time coming, but I have FINALLY ported my Wordpress website from Dreamhost to Digital Ocean. This has been on my to-do list for just over a year, but the tipping point has come over this past week or so, and my frustration at a slow wp-admin when writing or editing posts! A problem, no longer…

In this post, I’ll give a primer on what I’ve done to get this port to work, but it’ll mostly be references to other posts, as I first tested everything in Vagrant. Their were a few gotchas when I was picking my real passwords, and with setting up the DNS, but nothing crazy.

Duplicate! Duplicate! Duplicate!

If you haven’t prepared your blog to be exported, now’s the time. You can go the long route and export the databases, themes, and plugins manually… Or you could save yourself a lot of grief and just download the Duplicator plugin, run it, and in 5 minutes you’re ready to re-install.

That’s all for the source environment for a while. Next up is preparing your destination environment.

A drop in the Digital Ocean

I’ve only used Digital Ocean a handful of times, but I’m such a fanboy now. $5/month for a VPS running a 20GB SSD and 512MB of RAM. There are better deals on the internet to be found, but these guys really know how to streamline their process, so you barely need to go to their web portal. That, I love. To do anything on Dreamhost, I end up clicking away at everything, waiting for pages to load, clicking some more… Miserable. There is very little configuration to do with the Droplets, and Digital Ocean has one of the best support/tutorial blogs I’ve ever seen. Whenever I’m trying to figure out how to do something with DNSes, Nginx, or anything web related, I tack ‘Digital Ocean’ into my Google searches, even if I’m not using DO, because odds are they’ll have a good blog about it.

And as a shameless promo, if you use my referral link, you’ll get $10 in credits (e.g. 2 months of a droplet) and if you stick with them and spend money on their services, I’ll get a credit to my account as well:

Anyways, promos aside, spin up a droplet on their website (giant ‘Create’ button). It must be a force of habit, but I always end up using an LTS version of Linux, and in this case, I spun up an Ubuntu 14.04 droplet. I won’t go into detail on the initial configuration of the server, as Digital Ocean has done a really good job of that in these articles.

I will mention that I always attach my SSH key to Digital Ocean, so that I can spin up droplets with it directly and save myself a password email.

Quick summary: * Login as root * Create a new sudo user (with optional SSH key) * Disallow root logins over SSH * Change the SSH port number (security through obfuscation more than anything) * Optionally lock down all password-based SSH access (SSH keys only)

What happens in Vagrant doesn’t stay in Vagrant

As I mentioned, the reason my porting project was so streamlined was because I had practice porting my Dreamhost Wordpress website to a Vagrant localhost, and running on Digital Ocean is about 95% similar. You take a completely blank Linux VM and provision it as desired.

I’ve already written about this process in this article and have the provisioning scripts in BitBucket GitHub ( The only change that needs to be made is to the location of the provisioning directory, which was initially /vagrant/provision and that can be changed to where you put the provisioning scripts (e.g. /home/[user]/provision/).

If you follow the instructions in the section “Installing WordPress on Vagrant – Using Duplicator”, you should be good to go in about 10 minutes with Wordpress running in your droplet (Duplicator has a very simple, very quick, step-by-step installation). When doing this, one fun error I ran into that was difficult to solve was that Duplicator couldn’t connect to my MariaDB instance. What happened was that when I pre-filled my provision script with a random password, I had some illegal characters in there that never caused any errors during installation - because the characters work, until you try to run them from the command line or through PHP. I think it was a pipe, or something… I tried escaping them, putting single or double quotes, no luck. Instead, I just randomized a password with fewer special characters, with a length of like 60 characters :)

One other note to make is that I like to have a special non-sudo user as the owner for each domain I host on a droplet. That way, I can let other people manage sites for me, without going through the pain of managing a multitude of users, and without worrying about security. Part of what I do with this user is to run the following commands after Duplicator finishes:

sudo chown -R $USER:$USER $SITEPATH/*
sudo chown -R $USER:www-data $SITEPATH/html/wp-content

These settings make installing plugins and updating Wordpress a bit harder, but for the added security, in my opinion it’s worth it. To install plugins, change ownership so that www-data has access to more than what’s in wp-content (I give it access to everything), and once the plugin is installed, reverse the ownership to the default.

What’s in a Name… Server

You should now have a fully operational Wordpress installation working from your custom IP address. The last piece of the puzzle is to setup the DNS. Conveniently, Digital Ocean already has a blog about how to do this.

The one tip I’ll give is that you can speed up the DNS setup if you FIRST setup Digital Ocean’s DNS, and then set it up in Dreamhost. I did it the other way around, and kept running into little mistakes, but since every mistake meant refreshing DNS information - it was painful.

In my setup, I also added Cloudflare to the mix, which was yet another set of DNS updates.

Was it worth it?

Short answer, yes! Long answer, yes it was!

I’ve done a very unscientific, apples-to-oranges experiment (shared Dreamhost server vs private Digital Ocean VPS), by shutting off all third party assistance (no Cloudflare, no Wordpress caching tools - I think I made a mistake here and left it on for Dreamhost) and running the Dreamhost site and the Digital Ocean site through a load test, and some performance tests (at 1am on a Sunday, when my site has the least traffic).

Instead of loading my homepage, I picked an article with a good mix of text, pictures, and a couple of comments: /development/wordpress-to-wamp-tutorial-databases/

The results are below for anyone to peruse (as long as the links live), but the executive summary is this: The Digital Ocean site was about 100% faster and had significantly less variability across load (across up to 50 users, DO varied between 2.5-3.5 seconds load time, Dreamhost was between about 4-10 seconds).

Results from LoadImpact

Dreamhost <—> Digital Ocean

Results from Pingdom

Dreamhost <—> Digital Ocean

Results from GTMetrix

I have the full PDFs somewhere, but basically: Dreamhost - Page load time of 5.98 seconds… Digital Ocean - Page load time of 2.86 seconds

Update: By the way

There is one big thing I forgot to mention about this whole setup… It currently has no provisions for mail! Wordpress assumes that your server can use the php mail() function, but I didn’t explicitly enable that. Quick backstory: Dreamhost has horrendous mail support, meaning that most major mail providers have them on a blacklist somewhere. It’s not their fault, but people use Dreamhost’s shared hosting for sending spam a lot. As a result, even my own site’s administrative emails (e.g. someone commented on a blog) would be put into Gmail’s spam.

To get around this, I started using SendGrid and the WP Mail SMTP plugin. Takes a grand total of 10 minutes to set it all up and just works. The free subscription has a tight limit of 400 emails/day, but if your emails can be queued and sent across multiple days, they you’re looking at 12,000 free emails per month (at which point, the next step up is 40k emails/month for $10/month).

If you want to stick to your droplet’s mailing capability, then just add the correct apt package to the provision script (e.g. postfix or exim) and set it up as per this blog or this one.

Feature Photo credit: AnnetteCS / Foter / CC BY-ND