What actually is Git? For many developers it's synonymous with Github, Gitlab or that internal Bitbucket instance you have to deal with that only half works.

Funnily enough, it's simpler than that. It's a tool to interact with some specific folder structures and file specifications to allow you to version control your files that can live anywhere. Yes, you can have remote repos stored in Dropbox if you really wanted to! You don't need Github, Gitlab, Bitbucket, self-hosted Gitea or any of that. You can keep it simple and that's what I wanted to do.

The Setup

  • Raspberry Pi 3B+

  • my NAS

  • Hetzner VPS

  • https://tangled.org

Simple right?!?

Ok, there's a lot more going on than just chucking all of your code on Github here, but the concepts are simple.

The big picture

A diagram detailing the data-flow from my Raspberry Pi backing up data to my NAS and pushing public git repositories to my VPS git.treybastian.com

I wanted to keep my private repos really private and feel like I have data ownership over my public repositories so they never leave my local network.

My public repositories get pushed to a VPS that hosts a Tangled Knot.

The Raspberry Pi

My Raspberry Pi 3B+ sitting on my desk in a clear case


This is my source of truth for all of my code public and private. It's the main storage for all of my repositories.

The setup is simple! A user account named git that uses
git shell and some git-shell-command scripts that make my life easier and a simple global git hook for my public repositories.

One of my requirements when I set out to start this was that I wanted to make it as easy as possible to setup new repositories that can either be public or private.

I played with a bunch of solutions, but ultimately landed on
ssh git@pi new-repo

What the hell is that command? It's one of my git-shell-commands that gives me an interactive prompt to create a new repo public or private.

#!/bin/bash
# this script allows the creation of new repos over ssh on git server
# public repos will get a knot.conf containing the remote
# private repos will just exist on the server
# USAGE:
# ssh git@<host> new-repo 
# - follow the prompts

echo "oh look you are starting a project you won't finish again."
echo "What is your projects name?"
read PROJECT_NAME
if [[ $PROJECT_NAME!=*.git ]]; then
  PROJECT_NAME="${PROJECT_NAME}.git"
fi
echo "What's the mirror repo remote url?(leave blank if private)"
read REMOTE_URL

git --bare init "${PROJECT_NAME}"

if [[ $REMOTE_URL ]]; then
  touch "${PROJECT_NAME}/knot.conf" 
  echo "${REMOTE_URL}" >> "${PROJECT_NAME}/knot.conf"
fi

echo "git url: ${USER}@${HOSTNAME}:${PROJECT_NAME}"
if [[ $REMOTE_URL ]]; then
  echo "public repo: ${REMOTE_URL}"
fi
#vim: filetype=bash

This script creates the git bare repo. If it's a public repo it creates a knot.conf file that simply contains the remote repository URL so the global post-receive hook can mirror the repository.

The other big requirement was backups. No one wants to lose their code! I toyed around with a few ideas here but ultimately landed on mounting an NFS share and creating cron jobs to do hourly rsync backups and daily gzip of the hourly backups.

# m h  dom mon dow   command
0 * * * * rsync -avH --delete /home/git/*.git /mnt/backup/hourly
30 0 * * * tar -czf /mnt/backup/daily.`date +\%u`.tar.gz /mnt/backup/hourly

The NAS - for backups

My NAS contained in a small cubed PC case

My NAS mainly houses back-ups and Minecraft at the moment, so it was a great candidate for back-ups. I'll probably kick myself down the road for not having some robust 3-2-1 backup solution. However, this feels strong enough.

All of my repos live on my laptop, my PC, the pi and backed up to 2 MIRRORED 6TB hard drives in my NAS. If EVERY one of those fails at the same time, I feel like I deserved it. All of my public repos are further mirrored on a VPS running a
Tangled Knot.

git.treybastian.com (knot.treybastian.com)

A screenshot from cgit on git.treybastian.com taken 6 December 2025 detailing all of the current public repositories I have at the time of the screenshot.

The final piece of the puzzle. Somewhere to host the public code, that no one really cares about, but if someone stumbles upon it they can use it freely, well, license depending. I think everything is MIT though so fairly freely.

Tangled like most open source projects makes it really easy to self host their knot server if you have a little knowledge of Docker, which most people these days who are wanting to self-host do.

I have to be difficult. I don't use Docker on my VPS's I find it a little heavier than I necessarily need. I've run lots of Docker in production and it is helpful when you need it, I just don't need it at the moment.

Lucky the
documentation that I've now linked 3 times in this post has instructions for manual setup. They are super awesome and even include the systemd service config to make it super painless.

https://tangled.org/treybastian.com

But... hey wait a minute, that screenshot shows something else??

Why yes, yes it does. I setup Cgit too because I like it! It's not necessary by any means. Heck even this tangled knot server isn't necessary if you want to use tangled you can use their knot. That's the power of the
atproto ecosystem.

Thank you for reading, writing like this is fairly new to me so I'd appreciate any and all feedback you have for me in the comments.