Here are my requirements for a Ghost blogging platform backend:
- Cheap – ideally under $5 / month
- Ability to setup multiple blogs if I later want to add a new blog hosted on a different domain: so blog1.domainA.com + and blog2.domainB.com, without increasing cost.
- Easy to manage and backup
Non-requirements:
- High traffic
- Avoiding CLI or some server management (would be nice, but does that exist for < $5 month?)
And here is the tech stack:
- AWS Lightsail instance running Ubuntu 18
- SQLite
- Nginx
- Node.js
- Ghost Node.js module(s)
SQLite was chosen over MySQL since this is one less “moving part” and slightly easier to manage. See this blog post for the rationale.
Launch a Lightsail instance
Lightsail seems like a good value since you can get a decent sized instance and a static IP for $5.
Login to the AWS console and create a Lightsail instance with the following specs:
- Blueprint: OS Only Ubuntu 18.04 LTS
- SSH key: upload your
~/.ssh/id_rsa.pub
(maybe make a copy and rename it with a better name to easily find it in the AWS console later) - Instance Plan: $5/mo with 1GB or RAM, 1 vCPU, 40 GB SSD and 2 TB of transfer. Ghost recommends at least 1 GB of RAM, so it’s probably better to use this instance size or greater.
- Identify your instance: rabbit (or whatever you wanna call it!)
You should see the following:
Create a static ip
Go to the Lightsail Networking section, and choose “Attach static ip”. Associate the static ip with the lightsail instance, and make a note of it as you will need in the next step.
Add DNS A record
Go to your DNS register where you registered your blog domain name (eg, Namecheap), and add a new A record as follows:
- Use “blog” for the host if you want the blog named “blog.yourdomain.com”, but you could also name it something else.
- Use the public static ip address created in the previous step.
Install Ghost dependencies
ssh in via ssh ubuntu@<your ligthsail instance ip>
Update the apt package list:
1
|
|
Install nginx:
1 2 |
|
Install nodejs:
Add the NodeSource APT repository for Node 12, then install nodejs
1 2 |
|
Install Ghost-CLI
1
|
|
Create ghost blog
Create a directory to hold the blog:
1 2 3 4 |
|
Install Ghost:
1
|
|
If you get an error about the node.js version being out of date, see the “Error installing ghost due to node.js being out of date” section below.
Here is how I answered the setup questions, but you can customize to your needs:
- Enter your blog URL: http://blog1.domainA.com
- Do you wish to setup Nginx?: Yes
- Do you wish to setup SSL?: No
- Do you wish to setup Systemd?: Yes
- Do you want to start Ghost?: Yes
I decided to setup SSL in a separate step rather than initially, but the more secure approach would be to use https instead, eg https://blog1.domainA.com for the blog URL and answer Yes to the setup SSL question, which will trigger SSL setup initially.
If you do setup SSL, you will need to open port 443 in the Lightsail console, otherwise it won’t work. See the “Setup SSL” section below for instructions.
Create Ghost admin user
This part is a little scary, (and ghosts are scary), but Ghost basically puts your blog unprotected to the world without an admin user. The first person that stumbles across it gets to become the admin user. You want that to be you!
Quickly go to http://blog1.domainA.com and create the Ghost admin user.
Configure blog2 and map it’s DNS
Go to your DNS register where you registered your blog domain name (eg, Namecheap), and add a new A record as follows:
- Use “blog” for the host if you want the blog named “blog.domainB.com”, but you could also name it something else.
- Use the public static ip address from the Lightsail AWS console.
1 2 3 4 |
|
Install Ghost:
1
|
|
Use the same steps above, except for the blog URL use: http://blog.domainB.com
Congrats!
You now have two separate Ghost blogging sites setup on a single $5 / mo AWS Lightsail instance.
Appendix
Error installing ghost due to node.js being out of date
If you see this error:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
Fix option #1 – specify an older version of ghost
Find an older version of ghost that is compatible with the node.js you have installed, then specify that version of ghost when installing it:
1
|
|
How do you find that version? I happened to have another blog folder that I had previously installed, so I just used that. Maybe on the ghost website they have a compatibility chart.
The downside of this approach is that you won’t have the latest and greatest version of ghost, including security updates. The upside though is that you won’t break any existing ghost blogs on the same machine by upgrading node.js.
Fix option #2 – upgrade to a later node.js and retry
In the error above, it mentions that ghost requires node.js 14.17.0 or above.
The downside is that this could potentially break other existing ghost blogs on the same machine that are not compatible with the later version of node.js. Using containers to isolate dependencies would be beneficial here.
Upgrade to that version of node.js based on these instructions:
1 2 |
|
Run node -v
to verify that you’re running a recent enough version:
1 2 |
|
Update the ghost cli version:
1
|
|
Retry the ghost install command:
1
|
|
and this time it should not complain about the node.js version.
Setup SSL
During installation, you can answer “Yes” to setup SSL, and it will ask you for your email and use letsencrypt to generate a certificate for you. See this page for more details.
But you must also open port 443 in your Lightsail firewall, otherwise it won’t work.
Auto-renew SSL cert every 90 days
Lets Encrypt certificates expire after 90 days. To avoid downtime on your site, you should auto-renew the certificates. See this blog post for details.
I tried to follow the blog post, and ran ghost setup ssl-renew
in my blog folder, but after switching to root with sudo su
, I noticed this existing cron entry:
1 2 |
|
So it looks like it is already setup to renew the certs every day.