Git Without Github: Private Repositories

Git Without Github: Private Repositories

This is a tutorial made to help anyone currently on Github’s paid Developer Plan end their subscription and divest from Github in response to their unethical and misogynstic treatment of employees. In this tutorial, I’ll walk you through how to setup the private repositories which you may currently be paying $7/month to Github for.

Ingredients

  • 1 virtual private server (to host the repos)
  • 1 installed package of Git
  • 1 restricted user (to push/pull git repos to/from the server)
  • 1 Git repository

Here’s a diagram to illustrate what the architecture for this private repo is going to look like.

private repository artchitecture

By the end of this, you’ll be able to host a Git repo, push and pull from it yourself from your local computer, and allow others to push and pull from it too from their local computers!

The rest of this article is going to be written assuming you know your way around the Command Line a little and can SSH into a private server.

I did all of this on an Ubuntu server. Some of the commands or paths may differ if you’re using a different distribution of Linux for your server.

Finding Hosting

Since we’re not using Github anymore, you need to find hosting for your repository that allows you SSH access. The best solution I’ve found is paying for a droplet on Digital Ocean for $5/mo. They’re one of the cheapest hosts around and I’ve been using them reliably for over a year.

For other providers, look for anything that gives you SSH access to your server. Go for the cheapest option too - you don’t need a lot of memory or ram or bandwith for this at all.

Misogynistic workplace cultures are the default in tech. I don’t know if Digital Ocean is any better than Github as a company. At the time of this writing they don’t have any visible scandals or whistleblower pieces written about them (which does not mean that misogyny doesn’t occur at a company), so I’m giving them a conditional endorsement for lack of a better option on my part. The best option would be to self-host or buy from a company that’s majority woman and person of color owned/managed.

Installing Git onto the server

Starting from the command line on your local computer, SSH into the hosting server you just set up/paid for.

ssh root@IP-ADDRESS-OF-SERVER

Once you’ve gained access, check to see if you have Git installed already (hey… you never know).

git --version

If something like >> git version 2.7.4 pops up, you’re good! You can skip to the next section. Otherwise, we need to download and install it.

For Ubuntu (or Debian too):

sudo apt-get update
sudo apt-get install git

Let it install and then run git --version afterwards to make sure everything worked.

Making a restricted Git user

The cool thing about Git is that it comes pre-packaged with a program to create a restricted shell for Git-only users to push and pull from your server (but not do anything else). This is handy if you’re hosting a server with other private files which you may not want contributors to see even though you want them to be able to access your git repositories.

First add a user with adduser (I’m going to name mine gittycat)

adduser gittycat

you’ll see a setup screen that looks something like this

Adding user `gittycat' ...
Adding new group `gittycat' (1002) ...
Adding new user `gittycat' (1002) with group `gittycat' ...
Creating home directory `/home/gittycat' ...
Copying files from `/etc/skel' ...
Enter new UNIX password:
Retype new UNIX password:

…make sure to give the user a password and save it in your password manager! The rest of the questions that appear don’t matter.

Now, run the following line to set gittycat’s shell profile…

sudo usermod -s /usr/bin/git-shell gittycat

-s will set the type of shell profile the user has. The git-shell we’re using comes with a number of restrictions on the user and some special git-only commands.

Finally, paste in the following code and run it to restrict SSH access to your server.

cat >/home/gittycat/git-shell-commands/no-interactive-login <<\EOF
#!/bin/sh
printf '%s\n' "Hi $USER! You've successfully authenticated, but I do not"
printf '%s\n' "provide interactive shell access."
exit 128
EOF

and

chmod +x /home/gittycat/git-shell-commands/no-interactive-login

This will create a file called no-interactive-login that will print a message to any user trying to SSH into the server as gitty-cat and then deny them SSH access.

This is what they’ll see:

Hi gittycat! You've successfully authenticated, but I do not
provide interactive shell access.
Connection to xx.xx.xx.xx closed.

Pretty cool, yeah?

I know it’s not really clear how all of this works but there’s a lot of functionality built into Git that people usually don’t get to see.

You also can choose not to restrict SSH access and instead allow them to SSH in and perform a few limited commands. I won’t get into that here, but check out the documentation for some more insight.

Setting up the Git repository

If you’re starting a repo from scratch, you can create one inside your server using git init the way you already do.

However, if you’re trying to transfer an existing repo from your local machine to the server, skip down to the section called “Transferring an Existing Repo”

We’re going to create this one inside of /home/gittycat so create a new directory to store all of the repos called /repos

mkdir /home/gittycat/repos

and create a new project directory called /my_repo

mkdir /home/gittycat/repos/my_repo

assign ownership to the new directory…

sudo chown -R gittycat:gittycat /home/gittycat/repos

and make your way inside…

cd /home/gittycat/repos/my_repo

and create a new Git repo

git init

Making sure that the absolute path is correct is absolutely vital. If you’re ever unsure of the absolute path, run the pwd command inside of the folder. It should print the path so you can copy and paste it!

Transferring an Existing Repo

This section is only for users who want to transfer an existing repo to their server instead of creating a new one.

Make sure you have a repos directory first…

mkdir /home/gittycat/repos

If you still have your private repos in Github, the easiest thing to do would be to clone them into your server here using git clone REPO-URL (or following the Github guide ).

You may need to follow this guide to add an SSH key from your server into your Github account to allow for cloning.

OTHERWISE, IF YOU CAN’T CLONE because you’ve already cancelled your developer account and have deleted your private repos off of Github (good for you! ;)) you can still transfer your files over using SFTP.

SFTP stands for Secure File Transfer Protocol. If you’ve ever used something like Filezilla for Wordpress or whatever, the idea is the same. You’re transferring files from one place (yours) to another (the server) over a secure, direct connection.

First start an SFTP connection to the server…

sftp root@IP-ADDRESS-OF-SERVER

Navigate to the /repos directory in your server (/home/gittycat/repos) and run the put -r command to transfer a folder from your local machine.

put -r FOLDER_NAME_ON_LOCAL_MACHINE

When you do that, the folder will securely transfer from your local computer to the server and be dropped into /repos. Nice!

Some SFTP tips -

With SFTP, you can navigate around BOTH your local machine and the server at the same time.

Commands like ls or pwd can be run FROM the server BACK into your local machine by adding an “l” to it (that’s “l” for “Local!”) like so: lls or lpwd. Keep this in mind and let it help you find the correct path for your put command if you’re not that familiar with SFTP.

…for a more complete guide to SFTP, try typing the help command!

Cloning the new repo locally

Ok! If your repo is in your server’s repos folder, we’re almost there! Exit the shell (with exit) and go back to your local computer’s terminal.

Navigate to where you want to clone it and then figure out the URL of your repo:

For this tutorial, the URL is gittycat@ip-address-of-server:/home/gittycat/repos/my_repo. You can see that it’s made of the username gittycat, the IP address of the server, and the folder path where the repo lives in the server /home/gittycat/repos/my_repo. Cool right?

git clone gittycat@ip-address-of-server:/home/gittycat/repos/my_repo

You’ll be asked to enter your password and then it will create a new directory called my_repo in the same directory where you ran this command!! You did it!!

Pushing and pulling from your private server

Let’s confirm that pushing and pulling work now.

Next, set the remote of this repo to point to the same address used above.

git remote add origin gittycat@ip-address-of-server:/home/gittycat/repos/my_repo

And let’s push a file to it!

Add a file

touch hello.txt

and then commit it

git add .
git commit -m "init commit"

finally

git push origin master

When you SSH into the server as root, visit /home/gittycat/repos/my_repo, you’ll now see a file called hello.txt in there!

Sharing with friends and collaborators.

To share the repo with a friend, simply give them the URL of your the repo gittycat@ip-address-of-server:/home/gittycat/repos/my_repo

and the password for the Git-only user you made. Remember, if anyone tried to login to the server with gittycat they’ll be denied thanks to the configuration we did earlier.

They should follow same steps above involving git clone and git remote add, to begin pushing and pulling from the repo.

Conclusion

Hopefully, this knowledge will help you to get off the developer plan. If you miss having the UI or the other free features that Github has, I strongly enourage you to try Gitlab or BitBucket who give you all of this PLUS private repos for free. Also, as @sidnext2none pointed out, there are some great tools out there for encrypting your git repositories such as ‘encrypted git’ by keybase.io and git-secret. With these tools, you can use a free public Github repo but encrypt all of the public code - effectively making the repo private for anyone without the key.


Categories:
git-without-github   sys-admin-stuff


Because every coding blog needs a comments section.

Please keep comments respectful! Harassment and general arrogance will not be tolerated.