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.
- Enter
sudo raspi-config
in a terminal window - Select
Interfacing Options
- Navigate to and select
SSH
- Choose
Yes
- Select
Ok
- 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
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
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/
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
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
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.
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.
Top comments (6)
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 thegit
user directory, set upsshd_config
and off you go. Just usegit 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 containinggit 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 :)
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!
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 git.ghosh.pro. Cheers!
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:
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. π΅
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.
Will definitely give that a try, looks like that is a full front end, right?