I thought I would settle down with Jekyll + GitHub + Travis CI + Amazon S3 combination for a resilient, fault-tolerant blog. But, it takes so much time to write, then committing the changes to GitHub, waiting the Travis to build the assets, then having it live by serving the page from Amazon S3. At first, it came to me as being geek, hacky, and resistant to failure. By that I mean GitHub won’t go down, I can switch to different CI quite easily, and Amazon S3 also won’t go down.
Every part of the pipeline is configurable and switchable, but having a lot of moving parts makes the maintenance a bit of a hassle. After all, CaspershireNet is just a small blog. Ideally, writing a post shouldn’t be a long workflow, and updating is possible from almost everywhere. When using git
with my previous setup, that makes it harder to write when I don’t my computer with me.
The current setup includes installing nginx
for reverse proxy, Ghost CMS, NodeJS, Let’s Encrypt client for generating certificate for SSL, and setting up backup strategy to AWS S3.
sudo apt-get update; sudo apt-get upgrade
sudo apt-get install nginx vim htop s3cmd letsencrypt
# installing nvm for managing NodeJS installation
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.3/install.sh | bash
hash -r
# when I was installing Ghost v0.8.0, the guide says it work best with NodeJS v4 Argon LTS (v4.2.3 as of now)
nvm install -s v4.2.3
Follow this guide (Ghost Documentation) to install Ghost. Make sure you have more than 512mb RAM. I am using DigitalOcean 512mb plan. To compensate the low RAM, create 1GB swapfile
to prevent OOM from killing the installation. Follow this guide (DigitalOcean) on setting up swapfile
. Also, set up the nginx
reverse proxy. Follow this guide (Ghost for Beginners).
When I was about to get Let’s Encrypt SSL certificate, I referred to CertBot documentation. I had trouble using the webroot
module to generate the certificate. My theory is that since nginx
already reverse proxy-ing Ghost, it couldn’t access the ACME although I had the nginx
to use /var/www
as web root directory. The solution? Use standalone
module, but nginx
must be stopped first.
sudo service nginx stop
sudo letsencrypt certonly --standalone -d caspershire.net -d www.caspershire.net
Then, instruct the nginx
to serve HTTPS, also forcing HSTS. Don’t forget to renew the certificate once every 3 months, because that’s the requirement for using Let’s Encrypt.
ssl_certificate /etc/path/to/certificate.pem;
ssl_certificate_key /etc/path/key.pem;
add_header Strict-Transport-Security "max-age=31536000";
Restart nginx
. If everything is fine, the blog is ready.
Let’s set up the backup with bash
script and cron
. The files intended for backup will be zipped, date-stamped, and sent to an AWS S3 bucket. I started with creating an S3 bucket, named it as ghostbackup
. I am a bit of a security paranoid, so I created an IAM user and then granting it specific inline policies to access ghostbackup
bucket only, so that my other buckets on AWS S3 won’t be accessed. For the sake of brevity, I don’t include the guide for IAM user creation and introduction into policy because it would make this tutorial 3 times longer than it should. Below is the inline policies I am currently using for IAM user that can only have access to ghostbackup
bucket on S3.
{
"Statement": [
{
"Action": [
"s3:ListAllMyBuckets"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::*"
},
{
"Action": [
"s3:ListBucket",
"s3:PutObject",
"s3:PutObjectAcl"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::ghostbackup",
"arn:aws:s3:::ghostbackup/*"
]
}
]
}
There are 3 moving parts of this backup strategy: archiving files with tar
utility and date-stamp it, sending the archive by synchronizing it to AWS S3 with s3cmd
utility, and automate these 2 processes with cron
job. Configure s3cmd
first.
s3cmd --configure -c ghost.cfg
If you run --configure
without -c
argument, by default it will create a configuration file at ~/.s3cfg
. By adding -c ghost.cfg
, a configuration file is specifically created. Then you will be asked for AWS access key and AWS secret key, along with other questions. It will ask you to set up a password for encryption, and also an option to transmit data through HTTPS.
Test your configuration with s3cmd -c ghost.cfg ls
to see that if it is working as intended. This will list all available buckets in your account. Below is the bash
file (I name it as backup.sh
) for archiving Ghost with tar
, and then synchronizing it to ghostbackup
backup with s3cmd
.
#!/bin/bash
tar -czf ghost_backups3/archive-`date '+%y%m%d'`.tar.gz ghost/content ghost/config.js
s3cmd -c ghost.cfg sync --recursive --preserve ~/ghost_backups3/* s3://ghostbackup
Then, set up the cron job. Issue crontab
command, and then add the line below. Everyday at 10 PM, cron
will execute backup.sh
file, the tar
command will archive Ghost, and having it synchronized with s3cmd
to my ghostbackup
S3 bucket.
0 22 * * * /home/clyne/backup.sh
closing words
I had used Ghost before. In fact, CaspershireNet was setup when I first started using Ghost (hence, the name). It makes sense to have CaspershireNet running on Ghost, right?