April 9, 2017

Blog Migration Notes

My SSL certificate expired at the end of last month. And I lost the private key of my EC2 instance by chance. As I didn't want renew the SSL certificate and my amazon account is running out of credit, I decide to migrate my blog to vultr. I keep a migration notes here, so the migration will be more efficient next time.

  • Step 1: Back up blog data.
    As my blog is backed by Ghost, I exported blog data in its control panel and got a json file.
  • Step 2: Install nodejs and npm on new VPS.
    Install nodejs and npm with the package manager of your distribution. Take Ubuntu for example.
    $ sudo apt-get install nodejs
    $ sudo apt-get install npm
    On some versions of Debian/Ubuntu, nodejs-legacy package is required. It provides necessary symbolic links.
    $ sudo apt-get install nodejs-legacy
  • Step 3: Install Ghost.
    Download Ghost and unzip it.
    $ curl -L https://ghost.org/zip/ghost-latest.zip -o ghost.zip
    $ unzip -uo ghost.zip -d /var/www/ghost
    Now install dependency for Ghost.
    $ cd /var/www/ghost && npm install --production
  • Step 4: Configure Ghost.
    Create config.js.
    $ cd /var/www/ghost && cp config.example.js config.js
    Substitute domain name in production section with your own. If you don't need mail service, leave the mail brackets blank. If you do, Mailgun is recommended.
  • Step 5: Make Ghost run.
    $ npm start --production works fine surely. But if you log out from SSH, ghost will stop running. forever give us a way to run Ghost as a service.
    $ npm install forever -g
    $ NODE_ENV=production forever start index.js
  • Step 6: Obtain a SSL certificate.
    Let's Encrypt provides free SSL certificate. Detailed information can be found at https://letsencrypt.org/.
    Since Let's Encrypt certificate only last for 90 days, I add a line to crontab to auto renew certificate.
    0 6 * * 1 certbot renew
  • Step 7: Reverse proxy with nginx.
    By default, Ghost runs on port 2368. It's not recommend to run Ghost directly on port 80 for security concerns. We should run Ghost with a web server and proxy the access of port 80 to port 2368. I prefer nginx.
    Create a configuration file for ghost and create a symbolic link.
    $ touch /etc/nginx/sites-available/ghost.conf
    $ sudo ln -s /etc/nginx/sites-available/ghost.conf /etc/nginx/sites-enabled/ghost.conf
    Here's my ghost.conf, it contains SSL configuration.
server {
    listen 80;
    server_name shunix.com;

    location / {
        return 301 https://$server_name$request_uri;

server {
    server_name www.shunix.com;
    return 301 $scheme://shunix.com$request_uri;

server {
     listen 443 ssl;
     server_name shunix.com;

     root /var/www/ghost;
     index index.html index.htm;
     client_max_body_size 10G;

     location / {
         proxy_pass http://localhost:2368;
         proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
         proxy_set_header Host $http_host;
         proxy_set_header X-Forwarded-Proto $scheme;
         proxy_buffering off;
     ssl on;
     ssl_certificate /etc/letsencrypt/live/shunix.com/fullchain.pem;
     ssl_certificate_key /etc/letsencrypt/live/shunix.com/privkey.pem;
     ssl_prefer_server_ciphers On;
     ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

  • Step 8: Change A record to point to new IP address.
  • Step 9: Setup account and import data.

Till now, we have complete the migration, the new blog should be online.