I was running my Ghost blog on an EC2 instance on the AWS Free Tier. When my free trial has ended last month, I realized that AWS EC2 is unnecessarily expensive for the traffic that I get, so I decided to move my instance to DigitalOcean which is 3 times cheaper and has the same configuration with AWS.

But since I have installed Ghost blog manually, I had to make the migration manually too. It's not really a big deal though. My migration was from AWS to DigitalOcean on a domain from NameCheap but most steps could be used for other services as well.

34.xxx.xxx.xxx -> Old server's IP
178.xxx.xxx.xxx -> New server's IP

  1. SSH into your soon-to-be-old server (in my case it's AWS EC2)
    ssh -i your_ec2_ssh_file ubuntu@34.xxx.xxx.xxx

  2. Copy all your images files under the folder /content/images to a temporary folder in your local drive. Actually you can use scp instead of ssh to do this then you don't even need to ssh. My ghost blog was under var/www/ghost so:
    scp -i your_ec2_ssh_file -r ubuntu@34.xxx.xxx.xxx:/var/www/ghost/content/images ~/tmp/ghostcontent/images

  3. Access to your admin panel 34.xxx.xxx.xxx/ghost and from Labs export all your content into a temp location ~/tmp/ghostcontent/export.json

  4. SSH into your new server (in my case it's DigitalOcean)
    ssh -i your_digitalocean_ssh_file root@178.xxx.xxx.xxx

  5. Now create a new blank Ghost instance following the steps below. Since you already have a self-hosted Ghost blog I assume you know how to create one on nginx.
    https://docs.ghost.org/docs/install

  6. Access to your admin panel 178.xxx.xxx.xxx/ghost. Be quick to do this. Because after installation, anyone can create an admin account for your blog

  7. Create a new admin user with the same name and email that you used in your old blog. If you have other users you need to create them with the same name and emails otherwise post authors may not match.

  8. Go to Labs in admin panel, Delete all content (make sure you're in your newly created blog not the old one) and import the json file that you've exported to ~/tmp/ghostcontent/export.json

  9. Open another terminal (from your local which is not ssh) and copy the images using scp. (In step 5 I've create my blog in /var/www/ghost)
    scp -i your_digitalocean_ssh_file -r ~/tmp/ghostcontent/images root@178.xxx.xxx.xxx:/var/www/ghost/content/images

  10. Copy all code injections from your old server to the new one

  11. If you're using Disqus find the post.hbs file from your template and replace it with the one from the new blog

  12. Stop your EC2 instance and remember to remove your Elastic IP. Otherwise it will cost you.

  13. Create a floating IP (equivalent to Elastic IP in AWS) in DigitalOcean otherwise your IP address will change anytime you reboot your instance. Floating IP is like Elastic IP free to use as long as you've attached it to a Droplet instance. Otherwise it means you're reserving the IP address and it will cost you.

  14. Login to your NameCheap (or GoDaddy or whatever) account and replace the IP address from old to new floating IP you created.

I have chosen to stop my EC2 instance for a week or so before completely deleting it. Just in case something bad happens. I still use AWS and pay for many of its awesome services but EC2 was a bit expensive for what I actually do.