DEV Community

Fernando B πŸš€
Fernando B πŸš€

Posted on • Updated on

Setting up Raspberry Pi as a git server

Update 1 June, 6th: I have installed gitea to test it out as well, as per comments. It is awesome! Their docs are pretty good to get you started, if you'd like a front end. If you don't continue on with the article. Gitea Docs

Update 2 June, 8th: I setup my UPS APC 600va with my pi, installed apcupsd utility, edit conf file, and use data port to usb. This way the pi will do a proper shutdown in the event of power loss, and/or surges. Make sure you set is as a service on boot. guide here, apcupsd docs)

I've noticed this tweet a few days ago, and sparked some interest in how to setup raspberry pi as a git server. This way if Github takes a crap or whatever you still have a full working git project in another place. Github CEO responded that the repo was restored, I don't think he would reply to me if I lost a repo lol but nevertheless github team was all over it and I give them props.

I always have pi's and arduinos or microcontrollers available at home so might as well put my pi for some real work. I do have a handful of repo's that I've put some good work so having another full backup would be nice.

Strap on you are in for a full ride, it took me a few hours but that's because I had some minor issues here and there so in this guide I hope that you'll be up and running a lot more quicker than me. Feel free to replace vim with nano : )

Note: I am no linux nor git expert, so let me know if I did any mistakes.

Things you will need

  • Raspberry Pi 3
  • USB thumbdrive if you want data on a thumbdrive rather than Pi SD card
  • A No-IP Account if you have ISP dynamic IP
  • Just a little bit of technical know how

Overview of the Guide

  • SSH Enable
  • Static IP
  • SSH Port Change (Optional)
  • Router Port Forwarding
  • DNS server (Optional)
  • USB Mount (Optional)
  • Clone repository or init new repo
  • Give git directory pi:pi permissions
  • Add receive.denyCurrentBranch updateInstead
  • Add pushurl to origin
  • Test your setup, and have some coffee after all this hard work!

Enable SSH

By default SSH is disabled, once you enabled default port is 22.

  1. Enter sudo raspi-config in a terminal window
  2. Select Interfacing Options
  3. Navigate to and select SSH
  4. Choose Yes
  5. Select Ok
  6. Choose Finish

Static IP

A static IP is needed to be able to configure port forwarding. Replace with your own pi address ip on terminal run ifconfig

 sudo vim /etc/dhcpcd.conf
# Example static IP configuration
interface eth0
static ip_address=
#static ip6_address=fd51:42f8:caae:d92e::ff/64
static routers=
static domain_name_servers=

SSH Port (Optional)

Changing the port is not needed but is recommended if you have another machine on your network you SSH into.

sudo vim  /etc/ssh/sshd_config

After changing the port

sudo service ssh restart

Router Port Forwarding

This is something you might need to google to get clear instructions for your router. Could also download your router manual. Go to a browser enter your router IP, credentials, advanced settings, and look for port forwarding. We need a TCP service, give it a name, your pi IP, and port. Make sure you can SSH into it locally, before you attempt to try remote SSH.

Here's an example for the Nighthawk

DNS Setup (Optional)

Most ISP change your router IP, mine is every couple of weeks or so. And so to be able to push changes to a repo on the pi you need a static address since you can't rely on your changing router ip. Sign up for an account at NoIP and go through the steps.

Once you have your dns address, take that into your router. If your router doesn't have the ability for a dns address then download one of the utilities from NoIP which can update your router IP but be aware that utility will need to be running on a machine on your network.

Also for me I couldn't use my custom dns address from work, so I still had to use my router IP.

USB Drive Mount

In case you want to save your git repositories on a thumbdrive or hdd you'll need to mount it first. Otherwise skip this part.

lsblk or sudo fdisk -l will show disk devices. Mine is sda on partition sda1 as shown below. Note that lsblk will also show the mountpoint if is already mounted.

pi@raspberrypi:~$ lsblk
sda           8:0    1   15G  0 disk
└─sda1        8:1    1   15G  0 part /media/usbstick
mmcblk0     179:0    0 14.9G  0 disk
β”œβ”€mmcblk0p1 179:1    0  1.6G  0 part
β”œβ”€mmcblk0p2 179:2    0    1K  0 part
β”œβ”€mmcblk0p5 179:5    0   32M  0 part /media/pi/SETTINGS
β”œβ”€mmcblk0p6 179:6    0   69M  0 part /boot
└─mmcblk0p7 179:7    0 13.2G  0 part /

To mount the usb:

sudo mount /dev/sda1 /mount/path

Lastly check whether is mounted by running lsblk or cat /proc/mounts

Formating: WARNING: Ensure you are on the correct drive. Unplug, and plug your drive and check brand, and size with cat /var/log/messages | tail -n 50

In case you want to format your USB follow the below steps:

  • sudo fdisk /dev/sda1
    • m, for help
    • q, for exit
    • d, to delete partitions, repeat if there are more i.e. sda2, sda3, etc...
    • n, to create new partitions, I did p, and hit enter 4 times.
    • w, to finish

Resources for USB:

Clone a repo

My thumbdrive git directory is /media/usbstick/git/ I would assume most people are good with git on this site, but I'll try to give all steps.

git clone

Cloning Private Repo

Generate SSH Key, when done just cat to it, and paste on github:

cd ~/.ssh
ls id_*
ssh-keygen -t rsa -C ""

Add SSH Key

git clone

Directory permissions

Your folder might need permissions for pi user.

sudo chown -R pi:pi /your/git/folder

Add receive.denyCurrentBranch updateInstead

You can skip this step if you'd like to see the error below on your machine or if you know another way to make remote push work:

receive.denyCurrentBranch updateInstead

git config --local receive.denyCurrentBranch updateInstead

If you don't configure it this way, you'll get the below error.

Total 3 (delta 2), reused 0 (delta 0)
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: is denied, because it will make the index and work tree inconsistent
remote: with what you pushed, and will require 'git reset --hard' to match
remote: the work tree to HEAD.
remote: You can set 'receive.denyCurrentBranch' configuration variable to
remote: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: its current branch; however, this is not recommended unless you
remote: arranged to update its work tree to match what you pushed in some
remote: other way.
remote: To squelch this message and still keep the default behaviour, set
remote: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To ssh://yourip:yourport/media/usbstick/git/Data_Preserve/.git
 ! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'ssh://pi@yourip:yourport/media/usbstick/git/Data_Preserve/.git'

Resources on this configuration:

This options was added in Git 2.3, and it makes the server update its working tree if it is clean.

Add pushurl to origin

git remote set-url --add --push origin ssh://pi@yourIp:yourPort/media/usbstick/git/yourRepo/.git

You can also go into .git folder and do it on the config file, change path as needed, pi is the user so change if needed:
pushurl = ssh://pi@yourIp:yourPort/media/usbstick/git/yourRepo/.git

You can also add another remote if you'd like, is up to you but this works by pushing to both github, and the pi with one command.

Test your setup

Hopefully you have made it through, and you can push your changes to your pi by now.

On your remote computer, make a small change, and commit, then push. You will need to enter your pi password, and I hope is not the default if it is please change it:

C:\Users\MyAccount\IdeaProjects\Data_Preserve>git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 290 bytes | 290.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
   e1e6f2b..3434e4d  master -> master
pi@myRouterIP's password:
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 290 bytes | 290.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To ssh://myRouterIP:myPort/media/usbstick/git/Data_Preserve/.git
   e1e6f2b..3434e4d  master -> master

SSH into your pi, and do the usual to make sure your pi repo is up to date:

git status
git log


There are way too many issues you can get based on your experience with unix based systems, routers, and git but if you get an error someone should be able to help you here or on google. Nevertheless here are some issues that you might likely hit along the way.

If you can't SSH into your pi from remote, you most likely have not configured the port forwarding correctly or have firewall issues. If you get the password prompt then you know you are at least connecting to your pi.

If git push stops after total, then is most likely a folder read/write persmission issue, make sure your user is listed for the git directory you can check this by doing ls -la if you see your username for each file, then this is most likely not an issue unless you have the wrong user on the push url rule, the users must match.


I am quite happy with this setup, I don't have to do much to keep adding repos, all is needed for the next one is to clone it, add the receive.denyCurrentBranch updateInstead rule, and add the set url on my remote setup.

What do you think? Will you give it a try?
Any questions concerns, let me know.

Top comments (6)

sudipto profile image
Sudipto Ghosh

I use Gitea myself and definitely recommend it or even a self-hosted GitLab CE setup over this 'hack'. I mean you could just do git init --bare in a directory (reponame) under the git user directory, set up sshd_config and off you go. Just use git remote add origin git@ip.or.domain:reponame.git on your local machine. If you wish to keep the GitHub 'mirror' updated, set up an access token and a post-receive hook containing git push --mirror --quiet https://ghusername:accesstoken@github.con/ghusername/reponame.git.

All of this can be done with a few clicks on the Gitea/GitLab UI. Good post by the way :)

thefern profile image
Fernando B πŸš€ • Edited

Glad you liked it. Tbh I didn't even know gitea existed until I posted this comment and Julian brought it to my attention.

Yes there are always tons of ways to do something, I am no expert on git but I need to get more familiar with --mirror for sure since I haven't used it before.

Btw I just got done installing gitea, and it's looking good!

Thread Thread
sudipto profile image
Sudipto Ghosh • Edited

It's just the Blade templating engine, so you can customise it a lot. Clone the go-gitea/gitea repo from GitHub and look for the templates folder and move it to the custom folder in the Gitea's installation directory. My setup is at Cheers!

downey profile image
Tim Downey

Thanks for this post! Definitely a good use case for those unused Pis some of us have lying around! Just wanna double down on how important I think this piece you touched on is:

USB thumbdrive if you want data on a thumbdrive rather than Pi SD card

As a person who likes to play around with Raspberry Pis a lot, you will definitely want to use an external HDD if you care about your data at all (and in the case of git I imagine you do). πŸ˜›

SD cards just aren't designed for the kind of file access patterns of an OS.

If you do plan on using an SD card to get started, though, disabling swap is a must. Otherwise with the Pi's low amount of RAM your OS will be swapping memory to disk a lot and this will thrash the SD card. 😡

thefern profile image
Fernando B πŸš€

Yes SD cards are super duper slow when it comes to R/W. Definitely will need a drive for this task.

Thanks for the disabling swap suggestion, will keep that in mind.

thefern profile image
Fernando B πŸš€

Will definitely give that a try, looks like that is a full front end, right?