Using rsync to Deploy Your Jekyll Site

Image of the macOS Dock
No one uploads their stuff via FTP anymore. Or at least they shouldn't.

When you locally build your site with Jekyll, you end up with a finished generated site in the _site folder that you can upload to your web host.

Yes, you could just upload it via FTP, but that’s filthy. Insecure. And to be honest, if FTP is the only thing your web host allows you to use, run. Run fast. You would be better off and cheaper just deploying to GitHub Pages.

But that’s not what we’re doing. Let’s assume you have your host ready and can SSH into it.

Deploying to a VPS

The following script will use rsync to mirror your local folder to your remote server. rsync is quite intelligent in doing so, only transferring the changed portions of your site on subsequent commits.

Make sure to edit the variables above. Note: rsync will in fact wipe the destination folder clean and only leave the mirrored content there so double-check the path.

If your sshuser is unprivileged, make sure that the content in your web root is owned by him, the group can stay at www-data or whichever group your web server belongs to. The script will also leave hidden files and directories alone and not change or delete them, ensuring compatibility with the web root functionality of letsencrypt.

#!/bin/sh
# -----------------------------------------------------------
# commit-vps.sh
# -----------------------------------------------------------

# Variables

localjekyll="/Users/tobyx/websites/tobyx.com/current"
remotewebroot="/var/www/tobyx.com/public_html"
instancehost="yourinstance.example.com"
sshuser="admin"
sshport="22"
sshidentity="~/.ssh/your-private-key.key"

# Execution

cd $localjekyll
# bundle install
bundle exec jekyll build --config=_config.yml,_config_production.yml

echo "rsync to SSH host $instancehost ..."

rsync -vrh -e "ssh -p $sshport -i $sshidentity" --exclude ".*" --delete-after $localjekyll/_site/ $sshuser@$instancehost:$remotewebroot

echo "SSH connection closed. Done. Committed."

Deploying to an AWS EC2 instance

This AWS EC2 deployment script uses my On-demand Opening of SSH Ports on AWS method of opening a SSH port for your specific current IP address, doing the rsync and removing the rule from the security group again. You will need the AWS CLI for this to work.

#!/bin/sh
# -----------------------------------------------------------
# commit-aws.sh
# -----------------------------------------------------------

# Variables

localjekyll="/Users/tobyx/websites/tobyx.com/current"
remotewebroot="/var/www/tobyx.com/public_html"
instancehost="yourinstance.example.com"
sshuser="admin"
sshport="22"
sshidentity="~/.ssh/your-private-key.key"
securitygroup="sg-1234abcd"
region="eu-central-1"

# Execution

cd $localjekyll
# bundle install
bundle exec jekyll build --config=_config.yml,_config_production.yml

ip=`curl -s https://api.ipify.org`

echo "Current IP address: $ip"
echo "Instance Host: $instancehost"
echo "AWS Security Group ID: $securitygroup"
echo "Adding IP $ip to AWS Security Group $securitygroup ..."

aws ec2 authorize-security-group-ingress --protocol tcp --port $sshport --cidr $ip/32 --group-id $securitygroup

echo "rsync to SSH host $instancehost ..."

rsync -vrh -e "ssh -p $sshport -i $sshidentity" --exclude ".*" --delete-after $localjekyll/_site/ $sshuser@$instancehost:$remotewebroot

echo "SSH connection closed. Removing IP $ip from AWS Security Group $securitygroup ..."

aws ec2 revoke-security-group-ingress --protocol tcp --port $sshport --cidr $ip/32 --group-id $securitygroup --region $region

echo "Done. Committed."

Other methods

There’s many other ideas and methods described on the official Jekyll site here: http://jekyllrb.com/docs/deployment-methods/

Feel free to reach out if you have any questions.