This tutorial will show you how to install and configure a private git server in Ubuntu 20.04. As you know for github ,all contents hosting there are public which means everyone have the access .But for some scenarios , we want our data to be private , that’s why this post comes , here we will cover set up a git server using ssh protocol , http protocol and git protocol.


Running a Git server is fairly straightforward. First, you choose which protocols you want your server to support, 4 distinct protocols can be used to transfer git data: Local, HTTP, Secure Shell (SSH) and Git.

  • Local protocol

    The name tells everything , shared access is generally more difficult to set up and reach from multiple locations than basic network access, so this tutorial won’t cover this one’

  • Http Protocol

    HTTP protocol is very popular since it’s simpler for the user and smarter about how it communicates, one example is many people git cloning a git hub repository using https link address

  • Ssh protocol

    A common transport protocol for Git when self-hosting is over SSH. This is because SSH access to servers is already set up in most places. SSH is also an authenticated network protocol and, because it’s ubiquitous, it’s generally easy to set up and use.

  • Git protocol

    This is a special daemon that comes packaged with Git; it listens on a dedicated port (9418) that provides a service similar to the SSH protocol but with absolutely no authentication,so normally for git read access.


  • sudo or root access : for creating user account , installing packages
  • a Ubuntu server , we use hostname gitserver as example in this tutorial
  • a linux client, we use hostname client as example

Set up git server using ssh protocol

In this example, we’ll use the authorized_keys method for authenticating your users.

1.create new user account git and a .ssh directory for it

$ sudo adduser git
$ su git
$ cd
$ mkdir .ssh && chmod 700 .ssh
$ touch .ssh/authorized_keys && chmod 600 .ssh/authorized_keys

2.set up an empty repository

running git init with the --bare option, which initializes the repository without a working directory

$ sudo mkdir /srv/git
$ sudo chown git:git /srv/git
$ su git
$ cd /srv/git
$ mkdir project.git
$ cd project.git
$ git init --bare
Initialized empty Git repository in /srv/git/project.git/

3. setup ssh authorized_keys

On client side , using command ssh-keygen -t rsa to generate ssh key pairs. You can ignore this step if you already had an authorized keys

ssh-keygen -t rsa

For simplicity ,you can leave all as default .

Then upload the ssh public key from client side to git server

cat ~/.ssh/ | ssh git@gitserver "cat >> /home/git/.ssh/authorized_keys"

4.Push the first version of your project to git server

$ cd project01
$ git init
$ git add .
$ git commit -m 'Initial commit'
$ git remote add origin git@gitserver:/srv/git/project.git
$ git push origin master

Below is the output of example.

j@ubuntu2004:~/gitproject$ git remote add origin git@gitserver:/srv/git/project.git
j@ubuntu2004:~/gitproject$ git push origin master
Enumerating objects: 44, done.
Counting objects: 100% (44/44), done.
Delta compression using up to 2 threads
Compressing objects: 100% (43/43), done.
Writing objects: 100% (44/44), 31.44 KiB | 699.00 KiB/s, done.
Total 44 (delta 1), reused 0 (delta 0)
To gitserver:/srv/git/project.git
 * [new branch]      master -> master

5. (Optional) Add more users

Now you have push some data into gitserver , others can git clone it down and push changes back.

Just get the ssh pub key of others , then append it to /home/git/.ssh/authorized_keys

cat | ssh git@gitserver "cat >> /home/git/.ssh/authorized_keys"

6.(Optional) disable shell login for user account git

You should note that currently all these users can also log into the server and get a shell as the git user. If you want to restrict that, run below command on git server.

sudo chsh git -s $(which git-shell)

Set up a private git server using git protocol

Now let’s set up a daemon serving repositories using the “Git” protocol. This is a common choice for fast, unauthenticated access to your Git data. Remember that since this is not an authenticated service, anything you serve over this protocol is public within its network.

1.First ,let’s test it out , run below commands on gitserver to start git daemon

$ touch /srv/git/git-daemon-export-ok
$ git daemon --reuseaddr --base-path=/srv/git/ /srv/git/

2.Now try git clone on client side

git02@ubuntu2004:~$ git clone git://gitserver/project.git
Cloning into 'project'...
remote: Enumerating objects: 44, done.
remote: Counting objects: 100% (44/44), done.
remote: Compressing objects: 100% (43/43), done.
remote: Total 44 (delta 1), reused 0 (delta 0)
Receiving objects: 100% (44/44), 31.44 KiB | 870.00 KiB/s, done.
Resolving deltas: 100% (1/1), done.

3.It works , so let’s enable it in systemd , create file /etc/systemd/system/git-daemon.service and put below contents in.

sudo touch /etc/systemd/system/git-daemon.service
Description=Start Git Daemon

ExecStart=/usr/bin/git daemon --reuseaddr --base-path=/srv/git/ /srv/git/





Now we can use systemctl enable git-daemon to automatically start the service on boot, and can start and stop the service with, respectively, systemctl start git-daemon and systemctl stop git-daemon.

Set up a private git server using http protocol

Now we have authenticated access through SSH and unauthenticated access through git://, but there is also a protocol that can do both at the same time. Setting up Smart HTTP is basically just enabling a CGI script that is provided with Git called git-http-backend on the server. This CGI will read the path and headers sent by a git fetch or git push to an HTTP URL and determine if the client can communicate over HTTP.

1.Install Apache2 and apache utils

sudo apt-get install apache2 apache2-utils
sudo a2enmod cgi alias env

These 2 commands will install apache2 and also enables the mod_cgi, mod_alias, and mod_env modules, which are all needed for this to work properly.

2.Give www-data access to /srv/git

sudo chgrp -R www-data /srv/git

Because the Apache instance running the CGI script will be running as user www-data

3. Apache2 virtual host set up

cd /etc/apache2/sites-available
sudo cp 000-default.conf

Then let’s add some things to the Apache configuration to run the git-http-backend as the handler for anything coming into the /git path of your web server.

SetEnv GIT_PROJECT_ROOT /srv/git
ScriptAlias /git/ /usr/lib/git-core/git-http-backend/

Finally you’ll want to tell Apache to allow requests to git-http-backend and make writes be authenticated somehow.

<Files "git-http-backend">
    AuthType Basic
    AuthName "Git Access"
    AuthUserFile /srv/git/.htpasswd
    Require expr !(%{QUERY_STRING} -strmatch '*service=git-receive-pack*' || %{REQUEST_URI} =~ m#/git-receive-pack$#)
    Require valid-user

The final contents of look like below:

<VirtualHost *:80>
	ServerAdmin webmaster@localhost
	DocumentRoot /srv/git
	ErrorLog ${APACHE_LOG_DIR}/error.log
	CustomLog ${APACHE_LOG_DIR}/access.log combined
	SetEnv GIT_PROJECT_ROOT /srv/git
	ScriptAlias /git/ /usr/lib/git-core/git-http-backend/
<Files "git-http-backend">
    AuthType Basic
    AuthName "Git Access"
    AuthUserFile /srv/git/.htpasswd
    Require valid-user

Create a test user testuser01.

sudo htpasswd -c /srv/git/.htpasswd user01

4. Enable http for /srv/git and reload apache

sudo a2ensite
sudo a2dissite 000-default.conf
sudo systemctl reload apache2

5.Test from client side

git02@ubuntu2004:~$ git clone
Cloning into 'project'...
remote: Enumerating objects: 44, done.
remote: Counting objects: 100% (44/44), done.
remote: Compressing objects: 100% (43/43), done.
remote: Total 44 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (44/44), 31.42 KiB | 1.85 MiB/s, done.

Do some modifications and push the updates using the credential of new created user user01

git02@ubuntu2004:~/project/go04$ git push origin master
Username for '': user01
Password for '': 
Everything up-to-date


Now we have showed you how to set up a private git server using either ssh protocol , git protocol, http protocol in Ubuntu 12.04.

If anything not clear for you , please leave a comment.