---
title: "Git Setup Your Own Server"
date: 2021-06-13T12:07:49+02:00
-type: post
+type: article
author: "danix"
excerpt: "I'll show you how to setup your own git server easily"
featured_image: "uploads/2018/07/gitout.jpg"
-tags: ["git", "server", "setup", "howto", "do it yourself", "ssh"]
-categories: ["code", "diy", "linux"]
+tags:
+ - git
+ - server
+ - setup
+ - howto
+ - do it yourself
+ - ssh
+categories:
+ - code
+ - diy
+ - linux
---
Hello everyone,
So I started planning what I wanted my git server to have. Here's a list:
* **Security** - I decided to make it work only under ssh, that way only someone who has the key can clone or access the repository. I also added an unprivileged git user that has only access to very few commands, so even if somebody manages to access through ssh he'll find himrself with only very few options available.
- * **Notifications** - my server already tells me a lot of what happens, so I wanted my git service to do the same. I implemented a mail service that notifies me every time a new repository is added or everytime there's a push to a repository.
- * **Automation** - I wanted to have less steps possible between creation of the project and deployment to production. Now in two steps I can create a repository and clone it to my local computer, and when I'm done I just need to push my modifications and the code is deployed automatically.
+ * {{< strike >}}**Notifications** - my server already tells me a lot of what happens, so I wanted my git service to do the same. I implemented a mail service that notifies me every time a new repository is added or everytime there's a push to a repository.{{< /strike >}}
+ * **Automation** - I wanted to have less steps possible between creation of the project and deployment to production. Now in two steps I can create a repository and clone it to my local computer, and when I'm done I just need to push my modifications and the code is deployed {{< em >}}automatically{{< /em >}}.
* **Visibility** - I haven't yet decided if I want my code to be visible, so I haven't even started thinking about this possibility.
<!--more-->
I've added a new user and group to my server but before doing so I added /usr/bin/git-shell to /etc/shells in order to use it as login shell for my git user.
-```
+{{< highlight bash >}}
echo "/usr/bin/git-shell" >> /etc/shells
groupadd git
mkdir /var/git
useradd -d /var/git -g git -M -s /usr/bin/git-shell
-```
+{{< /highlight >}}
now the user is all set and ready to be used. Next step will be to create the .ssh directory and the authorized_keys file to hold the keys for the developers that have to access the git server. Here's how I did it:
-```
+```bash
mkdir /var/git/.ssh
touch /var/git/.ssh/authorized_keys
chown -R git:git /var/git
Since I have ssh access to the same server for my normal user I used the ~/.ssh/config file on my computer to set a new host that will ease my access routine for the git user as well as my regular user, that's my config (more or less):
-```
+```bash
cat ~/.ssh/config
Host regular_ssh
HostName server.tld
Now that the access for the git user is setup we have one last thing to do before being able to use it. We'll give him only limited commands to use, That way the git user will be even more limited and much more secure. Inside the documentation shipped with git there's a lot of scripts to get you started with this, so we'll copy them inside a special directory called git-shell-commands, like this:
-```
+```bash
cp -R /usr/doc/git-2.14.4/contrib/git-shell-commands /var/git
chown -R git:git /var/git
Now we have 2 commands inside the git-shell-commands directory, list and help, the first will show all projects inside the /var/git directory and the other will show a simple help text and a list of all the commands available. Now to give you an example of how easy it is to add commands to the git-shell I will create a simple command that acts as the clear command, it will clean the screen, to do so, from inside the /var/git directory I did:
-```
+```bash
echo $(which clear) > git-shell-commands/clear
chmod 0755 git-shell-commands/clear
### create
-<pre class="wp-block-code language-bash"><code>#! /bin/bash
+{{< highlight bash "linenos=table" >}}
+#! /bin/bash
# usage: create <PROJECT> - create a git bare repository named PROJECT.git
# this command will setup the repo and send a mail for confirmation.
;;
esac
fi
-fi</code></pre>
+fi
+{{< /highlight >}}
This is the create script, as you can see it's a bit complex because it will do a few things for me:
So after saving this script as create inside the git-shell-commands directory, we'll give it executable permissions and we can move to the delete script.
-<pre class="wp-block-code language-bash"><code># cat create-bare-repo.sh > /var/git/git-shell-commands/create
-# chown git:git -R /var/git/git-shell-commands
-# chmod 0755 /var/git/git-shell-commands/create</code></pre>
+{{< highlight bash >}}
+cat create-bare-repo.sh > /var/git/git-shell-commands/create
+chown git:git -R /var/git/git-shell-commands
+chmod 0755 /var/git/git-shell-commands/create
+{{< /highlight >}}
### delete
Let's see the delete script:
-<pre class="wp-block-code language-bash"><code>#! /bin/bash
+{{< highlight bash "linenos=table" >}}
+#! /bin/bash
# usage: delete <REPOSITORY> - PERMANENTLY delete a repository if existing.
# CAREFUL, this action cannot be undone. This command will ask for confirmation.
echo "\"${PROJECT}.git\" is an empty directory, Skipping. Check with your System Administrator."
exit 177
fi
-fi</code></pre>
+fi
+{{< /highlight >}}
This script is much simpler than the previous one, it'll accept the name of the project as argument on the command line or will ask for it and will only delete it if it is a proper git repository, otherwise it will just exit with an error code.
Since we are here let's modify the help command to make it show a short description of every available command.
-<pre class="wp-block-code language-bash"><code>#!/bin/sh
+{{< highlight bash "linenos=table" >}}
+#!/bin/sh
# usage: help - Lists all the available commands
# help <command> - Detailled explanation of how "command" works
*) [ -f "$cmd" ] && [ -x "$cmd" ] && echo "$cmd" ;;
esac
done
-fi</code></pre>
+fi
+{{< /highlight >}}
The main thing I added is the support for a command line argument, now I'm able to run it by itself and display the usual output with a list of available commands, or followed by a command name to give a brief explanation like this:
-<pre class="wp-block-code language-bash"><code>git> help
+{{< highlight bash >}}
+git> help
Hi git, Run 'help' for help, 'help <command>' for specific help on a command, run 'exit' to exit. Available commands:
clear
create
usage: create - create a git bare repository named PROJECT.git
this command will setup the repo and send a mail for confirmation.
git>
-</code></pre>
+{{< /highlight >}}
Pretty nice isn't it?! Now it's much more user friendly, and to show the description I used awk and cut to parse the comment at the top of every script I have in the `git-shell-commands` directory.
Let's say I had a new idea for a WordPress plugin, I can't wait to start writing, so the setup of the GIT environment should be as fast as possible. That's where my setup will come in handy. Let's open the terminal, I'll go inside my testing directory and from there I'll run:
-<pre class="wp-block-code language-bash"><code>ssh git_ssh 'create awesomePlugin'
+{{< highlight bash >}}ssh git_ssh 'create awesomePlugin'
creating project "awesomePlugin.git"
Initialized empty Git repository in /var/git/awesomePlugin.git/
All done, you can now work on "awesomePlugin.git"
-</code></pre>
+{{< /highlight >}}
The project is created, now I just need to clone it
-<pre class="wp-block-code language-bash"><code>git clone ssh://git_ssh:/var/git/awesomePLugin.git
+{{< highlight bash >}}git clone ssh://git_ssh:/var/git/awesomePLugin.git
Cloning into 'awesomePlugin'...
warning: Looks like you cloned an empty repository.
-</code></pre>
+{{< /highlight >}}
And that's it, I now have a local and a remote copy of my git repository ready to work with.
Inside the deploy.sh script I'll edit those 2 lines:
-<pre class="wp-block-code language-bash"><code># Directory where to deploy files from repository
+{{< highlight bash >}}# Directory where to deploy files from repository
DPTARGET=""
# Branch that is going to be deployed to server
DPBRANCH="master"
-</code></pre>
+{{< /highlight >}}
adding `/var/www/wp-content/plugins/awesomePlugin` as `DPTARGET` and production as `DPBRANCH`.
now on my local system I'll add a new branch and use that before committing my stable code.
-<pre class="wp-block-code language-bash"><code>git checkout -b production
+{{< highlight bash >}}git checkout -b production
Switched to a new branch 'production'
git add .
remote: \==============================
To ssh://git_ssh:/var/git/awesomePlugin.git
* [new branch] production -> production
-</code></pre>
+{{< /highlight >}}
And that's it, now my new plugin is ready to go live as soon as I activate it inside my WordPress admin area.