How to migrate your blog from Drupal to Ghost
I have been trying to migrate my blog from Drupal 6 for almost a year now but kept putting it off for one reason or another.
With Drupal 6 announcing end of support in Feb 2016, it was high time to migrate the blog. Also, the mixed content issue on the blog coupled along with running old Drupal 6 base with security vulnerabilities and archaic theme – all acted as catalysts. Did I mention that I have been running this blog on Drupal 6 since 2008? Thank you, partner! :)
You might be wondering why did I choose Ghost? I am thinking of writing a blog post on that. Buckle up. We're getting started. So how do you migrate your content from Drupal? And that too quickly. After doing research for a few hours, I came up with an action plan:
- Export content from Drupal blog based on the content type
- Export the media files from Drupal
- Import media files into Ghost
- Update media file source in the exported content
- Convert the exported content into Ghost compatible format
- Import content into Ghost
Armed with the action plan. Now it's the time for execution!
1. Export content from Drupal 6 blog
When I checked Ghost's migration documentation, I saw support for all the popular blogging platforms including WordPress, Jekyll, Blogger, GitHub readme, Tumblr, and even Medium. Alas! Drupal was missing.
Fortunately, I came across a Ghost migration module for Drupal 7 - https://github.com/luiselizondo/drupal-to-ghost. The next bit was easy. Convert the Drupal 7 module to be compatible with Drupal 6.
Here you go: https://github.com/darklrd/drupal-to-ghost. This module is compatible with Drupal 6.
Download and install the module and then go to Export content to Ghost page under Site Configuration.
Select the content type and vocabulary to be exported. Only one type of node can be exported at a time. Click on Create File
and download the file. Leave this file for now. We will come back to it later.
2. Export the media files from Drupal
This bit is easy. Download the files
folder from sites/default/files
to your local system.
Next rename the files
to content/images
(yes, images
folder inside the content
directory!) and compress this to content.zip
.
3. Import media files into Ghost
Ghost can use this zip to upload images. Go to your Ghost admin panel and navigate to /ghost/settings/labs/
.
Upload this zip file using the Import content
option.
Now all the images inside the files
folder of the Drupal 6 would be available at /content/images/
inside Ghost. Next let's move on to the exported content file, export_1587285008.json
, from Step 1.
4. Update the media file source in exported content
If we replace all the occurrences of /site/default/files/
with /content/images/
within our export file then Ghost would be able to render images and other media files correctly within the blog.
Open the export file in your favorite editor and do find and replace all operation.
5. Convert the exported content file into Ghost format
Ghost uses a format called Mobiledoc to store and represent the data internally. We need to install Ghost's migrate tool to convert HTML fields to Mobiledoc fields within our content file. This will make the content compatible with Ghost and then it can be imported.
- Requires Node.js v10 installed locally
npm install @tryghost/migrate -g
- install the migration toolmigrate json html /path/to/your/export.json
- this will convert the HTML fields in your JSON file- The tool will output a path to a converted JSON file named
ghost-import.json
. - Run
npm uninstall @tryghost/migrate -g
to cleanup
6. Import content into Ghost
The final step is to import the blog posts into the Ghost using our processed import file named ghost-import.json
.
Before we do that, one small change in the import file. Open the file in any editor and update the version
property to the Ghost version you're using like 3.13.3
.
Head over to the Ghost panel and navigate to /ghosts/settings/labs
. Upload the above file and voila! You should see all your posts under /ghosts/posts/
.
Just repeat the same process for different content types and we're done!