📝 Introduction
This tutorial turns a Raspberry Pi into a local Git server for your home network. You’ll push via SSH using public-key authentication, with a locked-down git account that can’t open a normal shell. It’s fast, private, and great for home labs, family projects, and offline development.
🧰 What you need
- Raspberry Pi (any model with network) running Raspberry Pi OS (Lite is fine).
- MicroSD card + power + Ethernet/Wi-Fi.
- Basic terminal access to the Pi (keyboard/monitor or SSH).
- A computer on the same home network with Git installed.
💻 Prepare the Raspberry Pi
What this does: Updates the Pi, enables SSH, installs Git, and (optionally) makes the Pi discoverable as gitpi.local.
# On the Raspberry Pi
sudo apt update && sudo apt full-upgrade -y
# Ensure SSH is running (remote access)
sudo systemctl enable --now ssh
# Install Git and Avahi for .local hostname discovery (optional but handy)
sudo apt install -y git avahi-daemon
# Give your Pi a friendly hostname (optional)
sudo hostnamectl set-hostname gitpi
# Reboot so hostname & services settle
sudo reboot
After reboot you should be able to reach it as gitpi.local (mDNS) or via its IP (e.g., 192.168.1.50).
👤 Create a dedicated git user
What this does: Creates a service user whose default shell is git-shell. This blocks normal logins while still allowing Git over SSH.
# Create a system-owned home at /srv/git and set git-shell as the login shell
sudo adduser --system --group --disabled-password \
--home /srv/git --shell /usr/bin/git-shell git
# Prepare the repositories folder and permissions
sudo install -d -o git -g git -m 2775 /srv/git/repos
# Create the SSH directory for keys
sudo -u git mkdir -p /srv/git/.ssh
sudo chmod 700 /srv/git/.ssh
sudo -u git touch /srv/git/.ssh/authorized_keys
sudo chmod 600 /srv/git/.ssh/authorized_keys
Note: If/usr/bin/git-shellis missing, ensure Git is installed (sudo apt install -y git). You can verify withwhich git-shell.
🔑 Add your SSH key (client → server)
What this does: Uses a public key to authenticate. No passwords needed. Repeat for each computer/user.
Generate a key on your computer (Linux/macOS/Windows Git Bash)
# Create a modern Ed25519 key (press Enter to accept defaults)
ssh-keygen -t ed25519 -C "yourname@yourdevice"
Copy your public key to the Pi
Linux/macOS:
ssh-copy-id git@gitpi.local
# If mDNS fails, use the Pi's IP: ssh-copy-id git@192.168.1.50
Windows (Git Bash) or if ssh-copy-id is unavailable:
# Append your public key to authorized_keys on the Pi
cat ~/.ssh/id_ed25519.pub | ssh git@gitpi.local \
'cat >> /srv/git/.ssh/authorized_keys'
Test the connection (you should not get a normal shell, because git-shell is restricted):
ssh git@gitpi.local
# You should see a message like "fatal: Interactive shell is disabled."
🗃 Create your first bare repository
What this does: A bare repo stores only Git data (no working files) and is ideal as a central remote.
# On the Raspberry Pi
sudo -u git git init --bare /srv/git/repos/myproject.git
# (Optional) Give it a friendly description
echo "My Home Project" | sudo tee /srv/git/repos/myproject.git/description >/dev/null
🖥️ Use it from your computer
Start a new project and push
mkdir myproject && cd myproject
git init -b main
echo "# My Home Project" > README.md
git add README.md
git commit -m "Initial commit"
# Add the Pi as your origin and push
git remote add origin git@gitpi.local:/srv/git/repos/myproject.git
git push -u origin main
Push an existing project
cd path/to/existing/project
git remote add origin git@gitpi.local:/srv/git/repos/myproject.git
git push -u origin main
Clone on another computer
git clone git@gitpi.local:/srv/git/repos/myproject.git
Tip: Ifgitpi.localdoesn’t resolve, replace it with your Pi’s IP (e.g.,192.168.1.50).
👥 Add more users
Have each user send you their ~/.ssh/id_ed25519.pub key. Append each line to the authorized_keys file:
# On the Raspberry Pi
echo "ssh-ed25519 AAAA... user@laptop" | sudo tee -a /srv/git/.ssh/authorized_keys >/dev/null
Because the git account’s shell is git-shell, they can only run Git commands—no normal shell access.
🔧 Optional improvements (hostname, firewall, backups)
Nice hostname & discovery
# Already set earlier; repeat here for clarity
sudo hostnamectl set-hostname gitpi
# Avahi lets you use gitpi.local on most networks
sudo systemctl enable --now avahi-daemon
Basic firewall (UFW)
sudo apt install -y ufw
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status
Quick on-demand backup of all repos
# Example: tar to an attached drive mounted at /mnt/backup
sudo tar czf /mnt/backup/git-repos-$(date +%F).tar.gz /srv/git/repos
📋 Common tasks (copy & paste)
# Create another bare repo
sudo -u git git init --bare /srv/git/repos/notes.git
# List all repos
ls -1 /srv/git/repos
# Set a remote named 'home' instead of 'origin'
git remote add home git@gitpi.local:/srv/git/repos/myproject.git
# Change remote URL later (e.g., switch to IP)
git remote set-url origin git@192.168.1.50:/srv/git/repos/myproject.git
🛠 Troubleshooting
Permission denied (publickey).
The server didn’t accept your key. Ensure your public key is in /srv/git/.ssh/authorized_keys (one line), file perms are strict (700 for .ssh, 600 for authorized_keys), and you’re connecting as git@....
Host not found.
Use the Pi’s IP instead of gitpi.local, or ensure avahi-daemon is running and your client supports mDNS.
“fatal: not a git repository” when pushing.
Double-check the remote path (it must end with .git) and that the repo exists under /srv/git/repos/.
Interactive shell appears or “git-shell: command not found”.
Make sure Git is installed on the Pi and the git user’s shell is /usr/bin/git-shell (getent passwd git to check).
Push is slow over Wi-Fi.
Use Ethernet for large repos or initial pushes; subsequent pushes are incremental and much smaller.
📚 Resources & further reading
- Git Book (free) — https://git-scm.com/book
- Git on the Server — Protocols & best practices
- Raspberry Pi Documentation — https://www.raspberrypi.com/documentation/