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 simply upload to your web host.

But instead of using SFTP to do this, we’ll be making it a little fancier. 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.

I have had issues with wrong permissions on files and folders on the destination host, so you might want to adjust permissions at the target location. This requires a newer version of rsync that’s not available on a default installation of macOS.

Simply install a more current version of rsync with:

brew install rsync

The user-installed version should automatically get priority.

The script will attempt to change permissions on files and folders accordingly.

If your sshuser is unprivileged—he definitely shouldn’t be root—, 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 \
  --chmod=Du=rwx,Dg=rx,Do=rx,Fu=rw,Fg=r,Fo=r \
  $localjekyll/_site/ $sshuser@$instancehost:$remotewebroot

echo "SSH connection closed. Done. Committed."

Other methods

Check out other methods of Jekyll deployment.