A Private Git server using Raspberry Pi 3

Sometimes you don’t want to share. That’s what this post is all about. Intentionally not sharing code and data. In this project, I wanted a private Git repo that I could access on my network through SSH.

Most Git services allow users to host public projects for free but will charge varying amounts if you’d like to have a private repo, an exception to this being Atlassian’s Bitbucket which will allow a private repo and five users to use it. Even with Atlassian’s free model, however, you’re only allowed 1GB of storage, which is an incredible amount if you’re storing code, but not a whole lot if you end up saving assets. You then have GitLab which also has a free version, but holy hell… look at this page of features. Can you tell what’s going on here? It took me a while to find out how much storage you can have with GitLab, but you need to have LFS enabled, and even then it doesn’t tell you if that applies to all versions. In my case, I need something simple and flexible. So screw it, let’s do a cost analysis. Assume I MUST pay for a private repo:

  1. Raspberry Pi 3: $54.99 (Amazon) + $9.59 SDCard (Amazon) + $1.7874 electrical cost per year
  2. GitLab: $4 per month (1 user)
  3. GitHub: $7 per month (Unlimited collaborators)
  4. BitBucket: $10 per month (I get five users, only needed the one though)

Knowing this, I can do a price analysis. Normally, I’d use Wolfram Alpha, but I’ve been having trouble getting intersections on functions working correctly. From what I understand doing intersections is trivial in MATLAB, but since I’m a FOSS advocate, I figured I’d give SageMath a whirl. After a brief learning curve (I’ve never touched SageMath until just now) I think I got the answers I wanted. So here’s my SageMath Code:

x = var('x')

f1 = 54.99+9.59+(x*1.7874)
f2 = x*(4*12)
f3 = x*(7*12)
f4 = x*(10*12)

p1 = plot(f1, (0,3), color="pink", legend_label='Raspberry Pi3')
p2 = plot(f2, (0,3), color="purple", legend_label='GitLab')
p3 = plot(f3, (0,3), color="blue", legend_label='GitHub')
p4 = plot(f4, (0,3), color="brown", legend_label='BitBucket')

i1=solve(f1==f2,x)
i2=solve(f1==f3,x) 
i3=solve(f1==f4,x) 

print 'Intersection of f1', f1
print 'and f2', f2
print i1[0].rhs().n()
sect1 = i1[0].rhs().n()

print 'Intersection of f1', f1
print 'and f3', f3
print i2[0].rhs().n()
sect2 = i2[0].rhs().n()

print 'Intersection of f1', f1
print 'and f4', f4
print i3[0].rhs().n()
sect3 = i3[0].rhs().n()

pt1 = point((sect1,f2(x=sect1)), color="red")
pt2 = point((sect2,f3(x=sect2)), color="red")
pt3 = point((sect3,f4(x=sect3)), color="red")

t1 = text(sect1.n(digits=3),(sect1,f2(x=sect1) + 10), color="black")
t2 = text(sect2.n(digits=3),(sect2,f3(x=sect2) + 10), color="black")
t3 = text(sect3.n(digits=3),(sect3,f4(x=sect3) + 10), color="black")

g = plot(p1+p2+p3+p4+pt1+pt2+pt3+t1+t2+t3)

save(g,'cost_analysis2.png',axes=true, axes_labels=['Years','Dollars']) 

os.system('display cost_analysis2.png')

This code makes a lot of assumptions.

  • I’m going to pay for a plan regardless of if I’m going to use what I’d be paying for fully.
  • I didn’t already have a Raspberry Pi already just lying around.
  • I’m paying about $.17 per kilowatt hour.
  • The Raspberry Pi 3 consumes 1.2W.
  • I’m never going to have more than one user.
  • No paid for service will change their pricing schedule.
  • For some reason when I made my final calculation for yearly power cost, there are now 30 days in a month making for 360 days in a year.
  • Taxes not considered.

Despite all of this, my code produces a pretty nifty graphic, and it’s close enough to paint a clear picture:

Well, anyway, you get the idea. Running your Git server is where it’s at. It’s considerably cheaper in the long run, and even in the best case you’ll recoup your investment in a year and a half. You don’t receive some of the nice features that a service like GitLab offers, but it seems to be a fair tradeoff. The next step would be finding out HOW much less expensive, but since this was my first plunge into SageMath, I think I’ll save that for another day.

Getting to the Good Stuff, actually building the Git Server

The instructions for flashing a Pi3 is pretty straightforward. After having done it twenty or so times now, I think I’m just going to link to the official documentation lazily. Quite honestly, the official documents have graphics, and videos, and tools… There’s just no way I’m going to do a better job explaining how to install Rasbian to an SD card. Once you get the Pi setup, you’ll want to change your password from the default, plug it into your network, disable overscan (if that’s a thing for you like it is for me), and download ufw. ufw stands for “uncomplicated firewall.” Getting ufw is easy:

sudo apt-get install ufw

There’s a GUI that you can download for ufw, but I didn’t have much luck with it. I eventually had to use the CLI to make changes, and because I only want SSH access, I had to deny pretty much everything. Here are my ufw settings:

sudo ufw default deny
sudo ufw allow ssh
sudo ufw allow from 192.168.0.0/16 to any port 22
sudo ufw enable

Your IP could change depending upon your network configuration. To find what your first octets are (192.168 in my case), you can do:

ifconfig
enp9s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.253  netmask 255.255.255.0  broadcast 192.168.1.255

That inet number is what you’re looking for, and you should change your firewall accordingly. Then you gotta reboot for your firewall changes to take effect.

sudo reboot

Once your Pi comes back up, you’ve got to create a bare repo. On your raspberry pi, depending on where you create your repositories, you could do something like:

git init --bare --shared=group ~/Desktop/your_repo.git

And if you’re going to allow people to check in, you’ve got to give them permissions to do so. If you’re lazy, which is never a good idea, you can open up all permissions on your repo.

sudo chmod 777 ~/Desktop/your_repo.git

Using another computer on your network should now be able to clone the repo you just created. For this, I’m going to assume you’re just cloning it to your desktop.

cd ~/Desktop
git clone ssh://pi@192.168.1.253:/home/pi/Desktop/your_repo.git
Cloning into 'your_repo'...
pi@192.168.1.253's password: 
warning: You appear to have cloned an empty repository.

The ifconfig command you ran earlier will tell you the IP of your raspberry pi. It would also be a good thing to give your Raspberry Pi a static IP. You’ll have to consult your router’s manual for that part of the process, but there’s information here on what you need to do from the Raspberry Pi’s end. Anyway, you’ll want to check something into your new repository.

cd ~/Desktop/your_repo/
echo 123 > README.md
git add .
git commit -m "initial commit"
git push origin master

If your push hangs, that’s most likely because you didn’t set your permissions correctly on your repository directory on your Pi correctly. If you get some errors about usernames or email addresses or something, you’ll need to set your username and email

git config --global user.name "FIRST_NAME LAST_NAME"
git config --global user.email "MY_NAME@example.com"

I love having my Git server. I’m still going to need to figure out a backup plan for it, but honestly, it’s just been nice to be able to quickly work between my laptop and desktop and have version control. Entirely a project worth doing.

Tagged , , ,