Setup a Git Server over SSH

Setting up a Git service running over SSH.

Plan server

Like GitHub, I want to have git url like [email protected]:repos/myrepo.git, so I can clone as:

$ git clone [email protected]:repos/myrepo.git

Create git user

To do this, I need create a user named git on my Linux server:

$ sudo useradd -m git --shell /usr/bin/git-shell

To prevent git user ssh login, use --shell /usr/bin/git-shell set git user shell to git-shell.

git-shell is a login shell for SSH accounts to provide restricted Git access. It permits execution only of server-side Git commands implementing the pull/push functionality, plus custom commands present in a subdirectory named git-shell-commands in the user’s home directory.


You can not set shell to /usr/sbin/nologin or /bin/false, it will cause git clone failure. You may get error like following:

$ git clone [email protected]:repos/myrepo.git
fatal: protocol error: bad line length character: This

Add ssh public key authentication

The ssh public key authentication is more secure than username / password authentication.

ssh server use $HOME/.ssh/authorized_keys to authenticate user.

The authorized_keys file in SSH specifies the SSH keys that can be used for logging into the user account for which the file is configured.

$ cd
$ mkdir .ssh
$ touch authorized_keys
$ chmod 600 authorized_keys

Then add client's ssh public key ($HOME/.ssh/ to authorized_keys

Prepare a bare repo

To host a git repo, it need a bare repository — a Git repository that has no working directory. It roughly equal the .git directory.

Create bare repo by git init

Create a bare empty repo with --bare option:

$ cd $HOME/repos
$ git init --bare myrepo.git
Initialized empty Git repository in /Users/git/repos/myrepo.git/

$ ls -l myrepo.git
total 24
-rw-r--r--   1 git  staff   23 Jul 07 16:55 HEAD
-rw-r--r--   1 git  staff  111 Jul 07 16:55 config
-rw-r--r--   1 git  staff   73 Jul 07 16:55 description
drwxr-xr-x  13 git  staff  416 Jul 07 16:55 hooks
drwxr-xr-x   3 git  staff   96 Jul 07 16:55 info
drwxr-xr-x   4 git  staff  128 Jul 07 16:55 objects
drwxr-xr-x   4 git  staff  128 Jul 07 16:55 refs

Create bare repo by git clone

Create a bare repo from exist repo by clone with --bare:

$ git clone --bare
Cloning into bare repository 'fetch.git'...
remote: Enumerating objects: 2129, done.
remote: Total 2129 (delta 0), reused 0 (delta 0), pack-reused 2129
Receiving objects: 100% (2129/2129), 446.70 KiB | 924.00 KiB/s, done.
Resolving deltas: 100% (1369/1369), done.

$ ls fetch.git
HEAD  config  description  hooks  info  objects  packed-refs  refs

Git clone

After the setup, now can clone it:

$ git clone git clone [email protected]:repos/myrepo.git