Migrating My Ghost Blog from Raspberry Pi to a VPS: A Step Toward Stability

Migrating My Ghost Blog from Raspberry Pi to a VPS: A Step Toward Stability
Photo by Michael Dziedzic / Unsplash

For several weeks, my personal blog was proudly running on a Raspberry Pi 5. It was more than just a functional website — it was a symbol of learning, tinkering, and building something from the ground up. But as the project grew and my ambitions expanded, it became clear that it was time for an upgrade. This post is a detailed account of how I migrated my Ghost blog from the Pi to a dedicated VPS with a static IP, why I made the switch, and what I learned throughout the process.


Why I Started on a Raspberry Pi

From the beginning, I wanted to challenge myself by avoiding “one-click” solutions. Instead of using a prebuilt hosting service, I wanted to understand what really happens under the hood when you host a website. The Raspberry Pi offered the perfect playground: small, silent, low-powered, and running Linux — just like a production server would.

I learned how to:

  • Set up Ghost via CLI
  • Run a reverse proxy with NGINX
  • Use Let’s Encrypt for HTTPS certificates
  • Deal with DNS and dynamic IPs using DuckDNS
  • Configure firewall rules and SSH for remote access
  • Maintain uptime and automate backups

It wasn’t perfect, but it worked. And most importantly, it taught me the fundamentals of server management.


The Downsides of Hosting on a Raspberry Pi

Despite the great learning experience, some limitations became increasingly frustrating:

  • Dynamic IP issues: My ISP assigned me a dynamic IP. Even with DuckDNS and scripts to update the A record, there were still occasional downtimes.
  • Router quirks: Sometimes the router would restart, or port forwarding would stop working correctly — knocking the blog offline until I manually fixed it.
  • Performance ceilings: The Pi handled light traffic well, but it was never meant to be a production-grade server. File I/O and database queries were slower than on SSD-backed infrastructure.
  • Remote access pain: If something went wrong while I was away from home, there was no way to fix it unless I was on the same network.

That’s when I decided to move everything to a virtual private server — a clean, stable solution that gives me full control without the physical constraints of home hardware.


Why I Chose a VPS with a Static IP

One of the core motivations behind this migration was to eliminate downtime caused by my dynamic home IP. The new VPS comes with a static IPv4 address, which means I no longer have to worry about DNS updates or broken port forwarding. It’s always online, fast, and connected directly to the internet backbone.

Other benefits:

  • High availability: The server is located in a data center with reliable power and connectivity.
  • Faster performance: SSD storage and better CPU resources.
  • Easier management: SSH access from anywhere and better tooling support.
  • Security options: System-level firewalls, automated updates, and TLS encryption with Let's Encrypt.

Preparing the VPS Environment

I spun up a fresh instance of Ubuntu 24.04 LTS and ran through a complete setup from scratch. Here's what I did step-by-step:

  1. Initial Security Configuration
    • Updated system packages
    • Set up a firewall (UFW) with only SSH and HTTP/S open
    • Created a dedicated user for managing the Ghost blog
  2. Installed Required Software
    • Node.js v18.20.8, the version officially supported by Ghost
    • MySQL 8, configured a database and user specifically for Ghost
    • NGINX, to handle SSL and proxying requests to Ghost
    • Ghost-CLI, the official tool for managing Ghost instances
  3. Set Up the Domain
    • Updated DNS records (A and AAAA) to point to the new static IP
    • Used Ghost CLI to auto-configure NGINX and request SSL certificates from Let’s Encrypt
  4. Initial Ghost Setup
    • Installed Ghost in /var/www/ghost using ghost install
    • Verified that the blog launched successfully with the default content

Migrating My Blog Content

The real heart of my site — the posts, images, and theme — lived in the content/ directory of my Raspberry Pi. Inside this folder are several key elements:

  • data/ghost.db: The SQLite database containing all blog posts and settings
  • images/: Uploaded media files
  • themes/: Custom theme files, including the one I modified (solo)
  • logs/: Useful for debugging if needed

I shut down the Ghost process on the VPS and securely copied the entire content/ folder from the Pi using scp over SSH.

After the transfer:

  • I replaced the default content folder on the VPS
  • I set ownership to the correct ghost user and group using chown
  • I restarted Ghost using ghost restart

Everything came up immediately. My site — posts, layout, styling, everything — looked just as it had before, now served from a much more robust machine.


Small Adjustments After the Move

After the successful launch, I made a few final tweaks:

  • I edited the theme’s index.hbs to remove the post limit by adjusting the {{#foreach posts limit="6"}} helper to either increase or remove the limit.
  • I verified HTTPS renewal with certbot renew --dry-run.
  • I tested SSH access and backups from multiple locations to ensure remote maintenance would be smooth.

Final Thoughts

This migration taught me a lot more than I initially expected. Hosting on a Raspberry Pi is an empowering experience — you get to see how every layer fits together, from DNS and HTTP to SQL and theming. But a VPS makes sense when you’re ready for more stability, control, and headroom for experimentation.

I now have a production-grade environment that I can build on. Whether I add a secondary Ghost instance, spin up an internal admin panel, or test self-hosted security tools — the VPS gives me that flexibility.

But I’ll never forget how it started — on a tiny board next to my router, blinking away as I learned one command at a time.