Schedule Jekyll posts using cron and rsync
This is a static site generated using Jekyll. It’s also hosted on one of my servers rather then on Git(Lab/Hub).
I deploy it using a rsync
to copy the _site
directory to the server.
I wanted to have the ability to schedule posts. That way I wouldn’t put off publishing for too long.
Requirements
- No future interaction from me
- It’s not critical that the posts are published on the exact date. I can tolerate some delay.
- Minimal tools. I prefer using local scripts with built-in packages rather then external services.
Existing solutions
-
Use some combination of Github actions, Netlify, and TravisCI. I didn’t like this setup because they involved external services and I didn’t want to manage them.
-
Use cron on the server to pull and generate the site I seriously considered this but the server that I’m using is for hosting several static sites and I didn’t want to have to set up rvm and jekyll and gems and think about all of thatm.
Building locally using cron and copying using rsync
So, I put together a simple solution using cron
.
First, in config.yml
the future
flag needs to be false.
future: false
This way jekyll b
will not generate the posts that are dated in the future.
Then I added a task that builds and deploys the site at 8am:
0 8 * * * /bin/bash -l -c 'cd /home/regac/code/ognjen.io/ && jekyll b && ./deploy.sh' >> /home/regac/code/ognjen.io/deploy.log 2>&1
Hiccups
I thought it would be easy but there were two issues.
- I’ve had to add the
/bin/bash -l -c
in order to have access torvm
so that the gemset is available.
I figured this out quickly since running rails tasks in cron requires this as well.
- My
deploy.sh
script usesrsync
with a key that has a passphrase. It turns out that cron has no way to unlock that key.
I ended up having to generate a separate ssh key that’s just for the backup that doesn’t have a passphrase.
ssh-keygen -f ~/.ssh/id_passwordless_rsa -C "Backup"
Then I had to change the deploy.sh
to use that key:
rsync -av -e 'ssh -i /home/regac/.ssh/id_passwordless_rsa' --delete _site/ ognjen.io:/home/regac/ognjen.io/_site
Other solutions
There were also two other possible solutions that didn’t work out.
First was to use sshpass
and switch deploy.sh
to use password based auth.
deploy.sh
looked like this:
rsync -av --delete _site/ ognjen.io:/home/regac/ognjen.io/_site
but with sshpass
:
rsync -ratlzv --rsh="sshpass -f '/home/regac/ognjen.io/.pass' ssh ognjen.io -o StrictHostKeyChecking=no -l regac" --delete _site/ ognjen.io:/home/regac/ognjen.io/`_site
Definitely uglier, but would have been fine. Unfortunately it didn’t work.
The other was to install ssh-cron
. At first I rejected that because I didn’t want to effectively maintain two places for scheduled tasks. Since sshpass
didn’t work out I tried it as well. Ultimately I couldn’t get it to work either.
Because solving this took an annoying amount of time, I have to wonder whether it was worth the time.
Sources
- https://superuser.com/questions/713276/rsync-over-ssh-requesting-password
- http://www.guyrutenberg.com/2014/01/14/restricting-ssh-access-to-rsync/
- https://askubuntu.com/questions/521142/why-is-this-rsync-ssh-cron-job-giving-me-permission-denied-publickey-error
- https://support.cloudways.com/how-to-add-cron-via-ssh/
- https://fbb-git.github.io/ssh-cron/ssh-cron.1.html
- https://www.cyberciti.biz/faq/noninteractive-shell-script-ssh-password-provider/