Setting Up a Self-Hosted Ghost Blog Instead of Naver Blog

Setting Up a Self-Hosted Ghost Blog Instead of Naver Blog

I had been using Naver Blog for a long time. While it was convenient, there were often delays when it came to inserting ads and receiving revenue. So, as both a learning experience and a solution, I decided to build a Ghost blog on my home server.

Since I had already set up a cloud storage system on my main home server, I considered installing Ghost on the same physical machine. However, adding both GitLab and Ghost posed too much risk, so I opted to use a separate physical server. That “separate server” is just a second-hand computer I bought for 50,000 KRW (~$35), upgraded with a few parts, and connected to the network.

Previously, I had used CentOS, but this time I went with Ubuntu for the entire setup.
Specs:

  • CPU: Intel(R) Core(TM) i5-3470 @ 3.20GHz
  • RAM: DDR3 8GB × 2
  • Motherboard: HARRISON2
  • Disk: SSD 250GB, HDD 500GB (planned to add)

During the initial OS installation, I got stuck for a while because the BIOS boot setting was on "dual." After fixing that, I successfully installed Ubuntu.

Setup steps:

  • Purchased domain and linked A records for subdomains
  • Installed GitLab
  • Disabled some built-in services like Nginx
    • Initially, I intended to use the built-in Nginx, but it didn’t allow me to insert custom server blocks. Since Ghost requires those, I disabled the default Nginx setup.
  • Installed Ghost

Database issues:
I first tried using MariaDB, and everything seemed fine until I accessed the post analytics page — which triggered queries unsupported by MariaDB and caused 400 errors. Ghost officially supports MySQL 8, Ubuntu 20+, and Node.js 20+
(https://ghost.org/docs/faq/node-versions/)

Switching to MySQL community edition solved the issue.
I had existing data, so I backed it up and moved it.
During the MySQL install, I encountered a “FROZEN” error, which I resolved with:

sudo rm /etc/mysql/FROZEN

Then another error appeared:

mysqld: Error on realpath() on '/var/lib/mysql-files' (Error 2 - No such file or directory)

To fix it:

sudo mkdir -p /var/lib/mysql-files
sudo chown mysql:mysql /var/lib/mysql-files
sudo chmod 750 /var/lib/mysql-files

SSL setup:
Used Let's Encrypt Certbot:

apt install certbot python3-certbot-nginx -y
certbot --nginx -d gitlab.example.com -d pages.example.com -d blog.example.com
sudo certbot renew --dry-run

I’ve had issues with auto-renewal in the past, so I plan to monitor this and add a cron job if it fails to run on schedule.

Update Ghost config:
Edit config.production.json to set the url to https.

Change Ghost content directory:
I mounted a 500GB HDD and updated the Ghost config to point to the new content path.
More details: https://blog.secondpage-zone.com/ubuntu-maunteu-seoljeong/
Make sure Ghost has permission to access the directory.

ghost stop
vi /var/www/ghost/config.production.json
# Update contentPath: "/mnt/your-mounted-directory"
ghost start

Next steps:
Now comes the blog customization. Aside from the theme, small tweaks can be done via code injection, offering a lot of flexibility.
Overall, I’m very satisfied with the setup.