Setting up Raspberry Pi as a git server
Tags: git, raspberrypi, server
Published: 2019-06-06 19:12:23

---
title: Setting up Raspberry Pi as a git server
published: true
description: 
tags: git, raspberry-pi, 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](https://docs.gitea.io/en-us/install-from-binary/)**

**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](https://www.cyberciti.biz/faq/debian-ubuntu-centos-rhel-install-apcups/), [apcupsd docs](http://www.apcupsd.org/manual/manual.html))**

{% twitter 1136092621149880320 %}

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](https://www.noip.com/free) 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=192.168.0.28
#static ip6_address=fd51:42f8:caae:d92e::ff/64
static routers=192.168.0.1
static domain_name_servers=192.168.0.1
```

## 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](https://kb.netgear.com/24289/How-do-I-set-up-port-forwarding-on-my-Nighthawk-router)

## 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](https://www.noip.com/) 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
NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
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:
[https://devtidbits.com/2013/03/21/using-usb-external-hard-disk-flash-drives-with-to-your-raspberry-pi/](https://devtidbits.com/2013/03/21/using-usb-external-hard-disk-flash-drives-with-to-your-raspberry-pi/)

## 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 https://github.com/yourAccount/YourRepo.git
```

## 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 "your_email@example.com"
```
Add SSH Key [https://help.github.com/en/articles/adding-a-new-ssh-key-to-your-github-account](https://help.github.com/en/articles/adding-a-new-ssh-key-to-your-github-account)
```
git clone git@github.com:kodaman2/RigInfo.git
```

## 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:
    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:
    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:**
[https://stackoverflow.com/questions/1764380/how-to-push-to-a-non-bare-git-repository](https://stackoverflow.com/questions/1764380/how-to-push-to-a-non-bare-git-repository)

[This options](https://github.com/git/git/blob/v2.3.0/Documentation/config.txt#L2155)  was added  [in Git 2.3](https://github.com/blog/1957-git-2-3-has-been-released), 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.
To https://github.com/kodaman2/Data_Preserve.git
   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
```

## Issues
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.

## Conclusion
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.