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.
- 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.
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.
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.
Once you’ve gained access, check to see if you have Git installed already (hey… you never know).
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
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
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
and create a new project directory called
assign ownership to the new directory…
sudo chown -R gittycat:gittycat /home/gittycat/repos
and make your way inside…
and create a new Git repo
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…
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…
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
Some SFTP tips -
With SFTP, you can navigate around BOTH your local machine and the server at the same time.
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:
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
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
and then commit it
git add . git commit -m "init commit"
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
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.
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.