| code | ||
| Readme.md | ||
Braids: Intro to Git workshop
This repo contains technical notes from the preparation for the Braids: Intro to git we gave at Het Nieuwe Instituut on Januari 15 2026 on invitation of The Hmm and NNAD as part of the workshop series "How to Archive Better: Preserving Practices".
The slides for the workshop live in their own repo at: https://git.hackersanddesigners.nl/hrk/Braid-slides and are viewable at https://braids.hackersanddesigners.nl/slides/
We’ve set up a Forgejo instance (you're probably reading this there) on a Raspberry Pi, accessible over the web via Tinc. During the workshop, user account registration was temporarily open. After a short introduction to the basics of Git, participants were invited to clone the workshop repository, create a personal branch (for example braids/), make a few small edits to the starter HTML page, commit their changes, and push the branch back to Forgejo. A webhook on the same machine published each pushed branch to a shared gallery site, so everyone could immediately view each other’s pages in the browser and iterate with additional commits.
The Forgejo repository is configured with a push webhook that calls a small deployment script on the Raspberry Pi. When a branch is pushed, the webhook triggers the script to fetch the latest updates from Forgejo, export the contents of each participant branch, and write them to the web server directory under a per-branch path. It also regenerates the gallery index page so new or updated branches appear immediately. This provides a near real-time “publish on push” loop during the workshop. The main branch was protect to commits in the Forgejo repo settings.
This involved:
Installing Forgejo
Mostly based on https://pimylifeup.com/raspberry-pi-forgejo/ with some modification because we're storing the repos on an external SSD
I am going to pretend i did this in the right order. We first setup the SSD, so we can configure the proper paths rightaway.
Set up the SSD.
Create mount directory:
sudo mkdir /media/ssd
Test mount.
sudo mount /dev/sda1 /media/ssd
If it works add it to fstab
To get uuid
lsblk -f
Edit /etc/fstab and add:
UUID=<uuid> /media/ssd ext4 defaults,no-fail 0 2
No-fail so the raspi boot even if the disk unplugged.
Then install Forgejo
Following: https://pimylifeup.com/raspberry-pi-forgejo/
Install docker with:
curl -sSL https://get.docker.com | sh
Create user (in current user group)
sudo usermod -aG docker $USER
Logout
logout
Check if the group exist
groups
test:
docker run hello-world
Docker should now be set up.
Create a directory for the installation:
sudo mkdir -p /opt/stacks/forgejo
cd /opt/stacks/forgejo
nano compose.yaml
services:
server:
image: codeberg.org/forgejo/forgejo:7
container_name: forgejo
environment:
- USER_UID=1000
- USER_GID=1000
- FORGEJO__database__DB_TYPE=postgres
- FORGEJO__database__HOST=db:5432
- FORGEJO__database__NAME=forgejo
- FORGEJO__database__USER=forgejo
- FORGEJO__database__PASSWD=<db_password>
- FORGEJO__WEBHOOK__ALLOWED_HOST_LIST=private,loopback
restart: always
networks:
- forgejo
volumes:
- /media/ssd/forgejo:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "3000:3000"
- "222:22"
depends_on:
- db
db:
image: postgres:14
restart: always
environment:
- POSTGRES_USER=forgejo
- POSTGRES_PASSWORD=<db_password>
- POSTGRES_DB=forgejo
networks:
- forgejo
volumes:
- ./postgres:/var/lib/postgresql/data
networks:
forgejo:
external: false
docker compose up -d
It should now be accessible at :3000
Now we have to set up tinc proxying, but in this case it was already setup for another service. So only nginx config on the tinc edge node and creating a certificate.
sudo certbot --nginx -d git.hackersanddesigners.nl
And configure nginx in /etc/nginx/sites-available/forgejo.conf:
Set the newly created domain in the Forgejo config with:
nano /media/ssd/forgejo/gitea/conf/app.ini
And change the domains:
ROOT_URL = https://git.hackersanddesigners.nl
DOMAIN = git.hackersanddesigners.nl
And restart the service
docker compose restart
We shoudl now have a running instance of Forgejo
Setting up a webhook
Setting up the webhook took a bit of time because it is somewhat confusing what IP to use to get from the Docker container to the host. But that is probably my inexperience with Docker.
Setup web hooks like this: https://www.shawenyao.com/Voice-Controlled-Raspberry-Pi/
sudo apt install webhook
configure
sudo nano /etc/webhook.conf
[
{
"id": "git-pull-site",
"execute-command": "/usr/local/bin/deploy-git-site.sh",
"command-working-directory": "/var/www/html/",
"pass-arguments-to-command": []
}
]
Create the shell script
sudo nano /usr/local/bin/deploy-git-site.sh
#!/usr/bin/env bash
set -euo pipefail
cd /var/www/html/testsite
git pull --ff-only
Make it executable
sudo chmod +x /usr/local/bin/deploy-braids.py
Edit the web hook:
sudo systemctl edit webhook
Add:
[Service]
ExecStart=
ExecStart=/usr/bin/webhook -hooks /etc/webhook.conf -ip 0.0.0.0 -port 9010 -verbose
sudo systemctl daemon-reload
sudo systemctl enable --now webhook
sudo systemctl restart webhook
Check for errors:
sudo systemctl status webhook --no-pager
Allow the webhook to connect to localhost, add to compose.yaml
- FORGEJO__WEBHOOK__ALLOWED_HOST_LIST=private,loopback
We have to call the webhook on the IP of the docker host. Get it with:
ip -4 addr show docker0
Gave:
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
(if i understand correctly 172.17.0.1 is kinda standard, but i did not know that)
Now add the webhook to the repo with that IP: url: http://172.17.0.1:9010/hooks/git-pull-site
Deploying the sites
The script called by the webhook is a python script that was cobbled together from a bunch of resources:
- https://stackoverflow.com/questions/31261600/how-to-archive-a-remote-git-repository-programmatically-using-python
- https://git-scm.com/docs/git-archive
- https://www.funkycloudmedina.com/2018/10/deploy-a-hugo-website-from-github-to-s3-using-github-webhooks-api-gateway-and-lambda/
- https://www.aicodesnippet.com/python/quality-and-best-practices/basic-git-operations-in-python-using-subprocess.html
- https://forgejo.org/docs/next/contributor/static-pages/
You can find the script in this repo under /code/deploy-braids.py