~2025

Automatically publish a site using Git

I've just rebuild this site using my own static generator. It would be easy to just rely on github pages to automatically publish my site but I don't want to use too much cloud services. Therefore I want to use the same technology tricks github uses but then on my own system.

I'm using Git to host the sources of my site; some markdown files, pictures, stylesheet and html templates. I've created a bare repository in repos/mysite.git of my home directory on my server.

# this is run on the server!!!
git init --bare

I've added this repo as a remote in my site's git repo and forced pushed all data.

# this is run on the system with the site's git repo
git remote add origin arnaud@myserver.sphaero.org:repos/mysite.git
git push --force origin master

You can now push changes like you do to a github hosted repo! Now for the juicy stuff

Run a script on push using Git hooks?

We can run a script on the server when we push to the repo. Inside the repo's directory you'll find the hooks directory containing example scripts. This is how github triggers all kinds of actions when you do things on a repository. We need to run the script post-receive. In this script we need to:

Ok should be easy. I leave that as an excercise because, holy shit, what am I doing. If I continue this path I'm going to waste lots of resources. Didn't I say I'm into Permacomputing nowadays? If I'm not going to rely on wasteful cloud services such as Github for this simple site why stop there? I don't need to mimick what Github is doing? If I would I would be hosting 3 copies of the same repo and waste precious cpu cycles of my home server (router) as it would be regenerating the complete site from scratch including reparsing and converting all images for nothing. If you don't get what I'm saying, the site is only updated. So only new stuff needs to be added. I don't need to create all its previous files from scratch again. I could write a smarter script that only updates what was changed but I think it can be easier still. It would be better if my workstation would be doing all that because it probably already did so while creating the update for the site.

Long story short. We just need to copy new and updated generated files from the machine I'm working on to the server! A simple rsync would be sufficient!

Running rsync on push

When I push to a remote it usually means I'm done with the change. This would be the perfect moment to push the update to the live site.

In the repository where I'm working in you can find the .git/hooks directory. In there we create the following pre-push script.

#!/bin/bash
remote="$1"
url="$2"
rsync -irpt ~/src/my-generated-site/ myserver.sphaero.org:/var/www/mysite/

Make sure it is executable. And run a test. It shouldn't give any errors and should have copied all files.

Now push changes in the repo. It should run the script as well.

[:~/src/sphaero.org] [venv] master(+0/-0)* ± git add site_src/blog/20250101_automatic_site_publishing_with_git.md 
[:~/src/sphaero.org] [venv] master(+0/-0)* ± git commit -a -m "blog about git hooks"
[master 28fee8a] blog about git hooks
 1 file changed, 92 insertions(+)
 create mode 100644 site_src/blog/20250101_automatic_site_publishing_with_git.md
[:~/src/sphaero.org] [venv] master* ± git push origin master 
arnaud@myserver.sphaero.org's password: 
arnaud@myserver.sphaero.org's password: 
<f.st...... index.html
<f+++++++++ blog/20250101_automatic_site_publishing_with_git.html
<f.st...... blog/index.html
<f+++++++++ tags/git.html
Enumerating objects: 8, done.
Counting objects: 100% (8/8), done.
Delta compression using up to 16 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 2.03 KiB | 2.03 MiB/s, done.
Total 5 (delta 2), reused 0 (delta 0), pack-reused 0 (from 0)
To myserver.sphaero.org:repos/sphaero.org.git
   b5cd0ac..28fee8a  master -> master

As you can see I do have to enter the password twice. Once for the git push and once for the rsync! You can overcome this by using key authentication