📝 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-shell is missing, ensure Git is installed (sudo apt install -y git). You can verify with which 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: If gitpi.local doesn’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