It is amazingly trivial to setup private git hosting with complete access control via public keys on Linux. Moreover, you can then start to customize for whatever you see fit or need.
If you are a bit familiar with Linux and have basic shell knowledge, it will take you just a couple of minutes to setup a fully working private git repository server.
Rolling your own git hosting comes in handy if you’re working on internal projects, want to mirror or backup a publicly hosted repository, or when you simply have concerns about leaving your code on servers outside your own country’s jurisdiction. Besides, you will have full access to git’s powerful ‘hooks’ system and can customize them as you please, including but not limited to, custom continuous integration, build and deployment work flows.
Prerequisites:
The shortlist of requirements reads as follows:
sshd
is configured and running on the target machinesudo
privileges (or root access) on host are availablegit
andgit-shell
commands are installed on target host
Walk through
As trivial as it may sound, but all it takes is to use git-shell
and provide remote access to respective machine and user.
Code examples assume a somewhat recent Linux distribution and should work out of the box on most distributions. If in doubt, check the man pages before executing any of the code examples.
Prepare the host machine
First we’re going to create a new unprivileged account on the remote machine and call it git
. Of course, you can use whatever username you want, the only important part is specifying git-shell
.
sudo useradd -s /bin/git-shell git
Our newly created git account is pretty useless right now, unless we add some commands, which will be the building blocks for any future actions:
GITHOME="/home/git" # change this if you customized above command
sudo mkdir $GITHOME/git-shell-commands
sudo cat > $GITHOME/git-shell-commands/help <<\EOF
#!/bin/sh
if tty -s
then
echo "Run 'help' for help, or 'exit' to leave. Available commands:"
else
echo "Run 'help' for help. Available commands:"
fi
cd "$(dirname "$0")"
for cmd in *
do
case "$cmd" in
help) ;;
*) [ -f "$cmd" ] && [ -x "$cmd" ] && echo "$cmd" ;;
esac
done
EOF
sudo cat > $GITHOME/git-shell-commands/init <<\EOF
#!/bin/sh
echo "Initialize new bare git repository:"
if [ ! "$1" ]; then
echo "Usage: $0 <directory>"
echo ""
elif [ -d "$1.git" ]; then
echo "INFO: directory already exists"
else
echo "Initialization new repo $HOME/$1"
mkdir -p "$HOME/$1.git"
cd "$HOME/$1.git"
git --bare init
echo "DONE."
fi
EOF
sudo cat > $GITHOME/git-shell-commands/list <<\EOF
#!/bin/sh
print_if_bare_repo='
if "$(git --git-dir="$1" rev-parse --is-bare-repository)" = true
then
printf "%s\n" "${1#./}"
fi
'
find -type d -name "*.git" -exec sh -c "$print_if_bare_repo" -- \{} \; -prune 2>/dev/null
EOF
sudo chmod +x $GITHOME/git-shell-commands/*
Now log in as git
and you will be prompted by something like this (try typing help
):
Last login: Fri Feb 21 13:33:02 2014 from [redacted]
Run 'help' for help, or 'exit' to leave. Available commands:
init
list
git>
As you can see, git-shell
will accept any script (or program) located at $HOME/git-shell-commands
. It does not have to be a shell script at all! As long as its readable and executable, it will become available as a command to be executed. If there is a executable called help
it will be recognized as such! I will leave it to your imagination what is possible now …
Apropos readable: Lets change ownership and permissions of all git-shell commands (and the folder git-shell-commands itself), so only a user with administrative rights to the machine is capable of adding, changing, or deleting the scripts. Choose whatever user/group you feel comfortable with. For the sake of simplicity, I use root.
sudo chown root:root /home/git/git-shell-commands -R
sudo chmod u+rwx,g-w,o-r /home/git-shell-commands -R
Enable remote access
Depending on your Linux distribution of choice, you either had to set a password for the git user already, or it has been initialized without any password. In the latter case, set a password like so on the remote host:
$ sudo passwd git
Assuming you and/or your colleagues have public ssh-keys provided, copy them over the remote host, so you can access the git repositories without having to type passwords again. Be sure to change the hostname before copy-n-pasting below snippet!
ssh-copy-id -i /path/to/public.key [email protected]
After entering the git user’s password (one last time), the credentials will be copied over to ~/.ssh/authorized_keys
and you can use respective public keys to connect to the git host, execute all commands available in ~/git-shell-commands; as well as do your usual git work flow remotely.
Its a good idea to revoke the old git user’s password on the remote host now, and also to no longer permit password authentication via ssh at all.
Your first self-hosted git repository
Lets say, you already have a local repository available you want to share on your newly available remote machine:
# create bare repository on the remote
$ ssh [email protected]
$ init my/shiny
# on your local machine
$ git remote add myshiny [email protected]:my/shiny.git
$ git push myshiny
Customization
As outlined before, you can create your own scripts, put them into ~/git-shell-commands
and be merry ever after. Also, every repository you create will have a hooks
folder of which you have full control over. By default there are example files in there you could simply strip of the .sample
suffix. For more information consult your friend the manual page via man githooks
:)
Bonus points
Over time and with many developers it becomes cumbersome to manually manage the ~./ssh/authorized_keys
file. Additionally, it probably will be more and more important to have fine-grained access control for each of the hosted repositories.
In this case, its worthwhile to look into gitosis. Gitosis will make it a lot easier to manage access to your hosted repositories. In order to use gitosis, you will have to have python’s setup-tools installed on the remote machine. If you’ve come this far, it should not be any problem to just follow the steps outlined at http://git-scm.com/book/en/Git-on-the-Server-Gitosis.