Setup a Git Server and Deploy with Git Hooks on Ubuntu 18.04
Tags: git, digitalocean, ubuntu
Published: 2019-07-24 17:52:10

---
title: "Setup a Git Server and Deploy with Git Hooks on Ubuntu 18.04"
published: true
description: "Steps to create a git repository and deploy a git push with server side hooks on Digitalocean ubuntu 18.04 using a non root account."
tags: git, digitalocean, ubuntu  
cover_image: 
canonical_url: https://kags.me.ke/post/digitalocean-setup-git-server-deploy-with-hooks-ubuntu
---

### Introduction 

In this post we look at the process of setting up a Git repository on a DigitalOcean droplet running Ubuntu&nbsp;18.04. After setting up the repository, we create a server side hook to automatically deploy a successful git push to a web server. A non-root user with no `sudo` permissions will be used to create the Git repository. The Git user will also be granted read and write permissions on the website for a successful deployment. After the process of setting up and deploying the repository is complete, we will disable interactive shell for the Git user.

### Prerequisites

In order to follow along in this post, you will require the following:

- A server running on Ubuntu 18.04 or higher
- A user with `sudo` permissions to connect to the server using SSH. We will use this user to setup the Git user.
- An installation of Git on the server
- A directory to deploy the Git repository on a successful git push

### Login to Server Using SSH Keys

Using SSH (**S**ecure **SH**ell) log into your DigitalOcean server. You can SSH the server using either the server IP address or your domain name.

- Using an IP address  

```bash 
   ssh kagundajm@23.45.90.11 -i ~/.ssh/kagundajm-droplet
```

- Using a domain name. You must configure your domain to point to DigitalOcean before you using the domain name.

```bash 
   ssh kagundajm@droplet.com -i ~/.ssh/kagundajm-droplet
```


### Create Git Repository Owner

Create non sudo git user with a disabled password. Logins will only be possible using SSH keys and not passwords. 

  ```bash
  sudo adduser --disabled-password git
  ```

### Create Git Repository Owner

Create non sudo git user with a disabled password. Logins will only be possible using SSH keys and not passwords. 

  ```bash
  sudo adduser --disabled-password git
  ```

### Create File For Authorized SSH Keys

Switch user to the newly create repository owner

```bash
sudo su git
```

Move to home directory of the repository owner

```bash
cd
```

Create directory for SSH key files with read, write and execute for the owner 

```bash 
mkdir ~/.ssh 

chmod 700 ~/.ssh
```

Create authorized keys file with read/write permissions for the owner 

```bash 
touch ~/.ssh/authorized_keys 

chmod 600 ~/.ssh/authorized_keys
```

Create your project repository folder. These steps have to be repeated for all the projects you want to host as repositories.

```bash 
mkdir project.git 

cd project.git

git init --bare
```

`--bare` creates a storage space for your repository or a repository without a working directory.

### Copy User Public SSH Key to Clipboard

From your local computer, copy and add public keys for any users you would like to access the private git server. 

- If using a Mac, run 

  ```bash
  pbcopy < ~/.ssh/kagundajm-droplet.pub
  ``` 
The above command will copy the contents of the public SSH key file to the clipboard. Remember to replace `~/.ssh/kagundajm-droplet.pub` with your user's SSH public key

- You can also open your SSH public key with your text editor, select all the contents of the file and copy the contents to the clipboard


### Append SSH Key to Git Server Authorized Keys

Back on your Git server, open **~/.ssh/authorized_keys** with your favorite text editor.

 ```bash
 vi ~/.ssh/authorized_keys
 ```

 Append the contents of the key file we copied in the previous step at the end of the file.
 
 Save the file and and close the text editor.


### Managing Multiple SSH keys on Your Local Computer

In situations where you have multiple SSH keys on your local computer, then you can specify the configuration file to use on the command line.

```bash 
GIT_SSH_COMMAND='ssh -i ~/.ssh/kagundajm-rsa' git push website
```

Using this approach would require specifying the key every time you are executing a Git push command.

A better alternative would be to create a custom [SSH configuration](https://linux.die.net/man/5/ssh_config) file. Using a configuration file, we will assign an alias name to our remote connection and use this name when accessing these remote computers. This is the approach we will adopt.

Using your preferred Editor, open your custom configuration file

```bash
vim ~/.ssh/config
```

Append the following to the configuration file:

```bash
Host website
    Hostname droplet.com
    User git
    IdentityFile ~/.ssh/kagundajm_droplet_rsa
    IdentitiesOnly yes
```

Note that indentation is not required but is used here to make it easier to read the available options within the file. Also you can assign **Host** any name you prefer; in this instance our **Host** is named **web**.

Save the changes and close the text editor.

By default, the SSH configuration file does not exist. If a new file was created, make sure to grant read/write permissions to the owner no permissions to the group and anyone else (others).

```bash
chmod 600 ~/.ssh/config
```

Now the git user can use SSH connections to ssh into the server, push, pull or even clone from the repository using commands like the following:

```bash
    ssh website

    git clone website:project.git

    git push website
```

### Add Remote Git Repository to Local Git Config

On your local computer, you may be in one of two scenarios. Either you have an existing git repository or you are creating a new repository. In this post, we will be using **website** as the name of our remote directory but you can use any name you prefer.

- if you already have an existing local repository.  

  - add the remote git project directory to the local .git/config.
    
```bash 
    git remote add website website:project.git
```

  - Push the contents of the local repository to the remote one. 
    
```bash
    git push website +master:refs/heads/master
```

`website` is the name of the remote repository we want to add

`master:refs/heads/master` is a [refspec](https://git-scm.com/book/en/v2/Git-Internals-The-Refspec#_refspec) that can be used for fetching. 
    
The format for the refspec is `+<src>:<dest>` with the **+** being optional.


- if it is a new git repository you are setting up, then use run the following commands from the Terminal.

```bash 
      git init

      git add .

      git commit -m 'initial commit'

      git remote add website website:project.git

      git push website master
```

Any future changes you make locally can now be uploaded to the remote repository simply by running 

```bash
git push website
```

### Git Server Side Hook to Deploy to Web Server on Git Push

Git hooks are custom scripts that Git executes when certain actions occur. There are client side and server side hooks. These hooks are stored in **.git/hooks** folder. In automatically updating our web server, we will use&nbsp;**post-receive** server side hook.


Make sure you are using the user you used to create git user

Create your project's folder on the web server 

```bash 
sudo mkdir /var/www/project01
```

Change group ownership of web folder  to **git:www-data**.

```bash 
sudo chown -R git:www-data /var/www/project01
```
    
Grant write permissions on the folder to the new owner and group 

```bash
sudo chmod -R ug+rwx /var/www/project01/
```

Make all new files and subdirectories created within **project01** inherit the folder's group id (www-data) of the directory rather than the group ID of the user who created the file/directory.

```bash
sudo chmod g+s /var/www/project01
```

Now that we have setup the project folder on the web server, switch back to git user  

```bash 
sudo su git
```

Move to root of your git project 

```bash 
cd ~/project.git
```

Create a post-receive hook that will checkout your latest push to the web server 

```bash 
vi hooks/post-receive
```

Update the **hooks/post-receive** file with the following:

```bash
#!/bin/bash

GIT_WORK_TREE=/var/www/projects.droplet.com git checkout -f
```
Save the changes and close the text editor.

Make **hooks/post-receive** file executable 

```bash
chmod +x hooks/post-receive
```

A successful **git push** will now trigger the **post-receive** hook which will copy the latest contents of the repository to your web server.


### Prevent Git Users Interactive Login Into the Server

Using SSH to login to a server also provides an interactive shell access to the remote Git users. To restrict the users to only Git-related activities for managing the repositories, we need to replace the shells assigned to **git-shell** which is a more restrictive shell.

List the available shells to determine whether **git-shell** is already included among the shells.

```bash 
cat /etc/shells
```

If **git-shell** is not listed, find out where it is located. 

```bash
which git-shell
```

Take note of the displayed **git-shell** path

Open  **/etc/shells** with your text Editor

```bash
sudo vim /etc/shells
```

Append the path to **/etc/shells**

Save the changes and close the text editor.

Edit the shell for Git users to `git-shell `

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

Note you can always change back to the default **bash** shell for the Git user by running 

```bash
sudo chsh git -s $(which bash)
```

Now all Git users will only use SSH connections to push and pull Git repositories.


### References

1. [HOWTO setup a private git server on Ubuntu 18.04](https://www.andrewhoog.com/post/howto-setup-a-private-git-server-on-ubuntu-18.04/)
1. [4.4 Git on the Server - Setting Up the Server](https://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server)
1. [A git Primer](https://danielmiessler.com/study/git/)
1. [Using Git to manage a web site](http://toroid.org/git-website-howto)
1. [How To Set Up Automatic Deployment with Git with a VPS](https://www.digitalocean.com/community/tutorials/how-to-set-up-automatic-deployment-with-git-with-a-vps)