From 4ddc0c0c382c0e12c5d7a900eaa739660c80ed77 Mon Sep 17 00:00:00 2001 From: Charles Date: Sat, 25 Jul 2020 16:57:08 +0200 Subject: Added git server article draft --- blog/git_server.html | 135 ++++++++++++++++++++++++++++++++++++++ blog_src/git_server.md | 174 +++++++++++++++++++++++++++++++++++++++++++++++++ generate-blog | 6 +- index.html | 2 +- 4 files changed, 313 insertions(+), 4 deletions(-) create mode 100644 blog/git_server.html create mode 100644 blog_src/git_server.md diff --git a/blog/git_server.html b/blog/git_server.html new file mode 100644 index 0000000..49a9566 --- /dev/null +++ b/blog/git_server.html @@ -0,0 +1,135 @@ + + + + + cacharle + + + + + + +
+ +

How to make your own git server/website

+

Server setup

+

We’re going to create a git user and group, will be used for accessing our git repositories without needing to be root.

+
useradd -m git
+mkdir /srv/git
+chown git:git /srv/git
+

The repositories will be stored as bare, this mean that we will only store the .git folder to save space.

+
+

To create a bare repo: git init --bare

+
+
+

To clone a repo as bare: git clone bare <location>

+
+

You can either add a password for the git user or put your ssh public key in /home/git/.ssh/authentication_keys and disable password authentication for ssh.

+

You can now clone from your server with git clone git@<hostname>:/srv/git/<reponame>

+

Better server interaction with git-shell

+

Permit the git user to have a regular shell can be a security issue, we would like that to restrict him to a few action, like creating/deleting a repository, importing a repository, listing the repo currently stored

+

Make the git-shell a valid shell echo $(which git-shell) >> /etc/shells

+

Change the shell of the git user chsh -s $(which git-shell) git

+

If you try to ssh as the git user, you will be greeted with something along the line of:

+
fatal: Interactive git shell is not enabled.
+hint: ~/git-shell-commands should exist and have read and execute access.
+Connection to <host> closed.
+

As suggested by the hint we have to create the directory /home/git/git-shell-commands and put the commands (executable) that the git user is allowed to execute in.

+

Here is a script to create a repo:

+
#!/bin/sh
+[ $# -ne 1 ] && echo "Usage: $0 name" && exit 1
+repo_path="/srv/git/$1.git"
+[ -d "$repo_path" ] && echo "$0: Error: $repo_path already exist" && exit 2
+mkdir "$repo_path"
+git -C "$repo_path" init --bare
+

Put it under git-shell-commands/create and make it executable then try to ssh as the git user once again.

+

You should have a prompt like git>, you can call the create command with a repo name as the first argument and it should create a new repository for you.

+

Allow anyone to clone with git-daemon

+

The git daemon will allow annone to clone your repos with something like git clone git://<host>/<repo>

+

git daemon --reuseaddr --base-path=/srv/git/ /srv/git/ and that’s it

+

You should make it a service in your service supervisor, example with systemctl:

+
[Unit]
+Description=Start Git Daemon
+[Service]
+ExecStart=/usr/bin/git daemon --reuseaddr --base-path=/srv/git/ /srv/git/
+Restart=always
+RestartSec=500ms
+StandardOutput=syslog
+StandardError=syslog
+SyslogIdentifier=git-daemon
+User=git
+Group=git
+[Install]
+WantedBy=multi-user.target
+

Put it in /etc/systemctl/system/git-daemon.service and run systemctl enable git-daemon then systemctl start git-daemon.

+

Public/private repo

+

You may want to introduce a distiction of which repo is public and which is private

+

A simple way to do this is by creating a public directory in /srv/git which will contain symbolic link to the repo in /srv/git

+
/srv/git
+|- foo.git
+|- bar.git
+|- qux.git
+|- public
+    |- foo.git -> /srv/git/foo.git
+    |- bar.git -> /srv/git/bar.git
+

You can change the git daemon to only serve the public repositories git daemon --reuseaddr --base-path=/srv/git/public /srv/git/public

+

Generate a static website

+

Here we will create a site that look’s like this with nginx, stagit and a few scripts.

+

If you don’t like the minimalistic appearence of the site, here is a list of alternative.

+

Install nginx (on Debian based distro): apt install nginx

+

Create a basic configuration file for your site:

+
server {
+    root /var/www/git;
+    index index.html index.htm;
+
+    server_name git.<hostname> www.git.<hostname>;
+
+    location / {
+        try_files $uri $uri/ =404;
+    }
+}
+

It’s a convention to put it in a git. subdomain. systemctl enable nginx && systemctl start nginx

+

Install stagit:

+
git clone git://git.codemadness.org/stagit
+cd stagit
+make
+make install
+

To generate a static page for a repo stagit /path/to/repo. To generate an index for multiple repositories stagit-index repo1 repo2 repo3 > index.html

+

Here is a script to generate a site for all repo in /srv/git/public

+
#!/bin/sh
+
+repos=$(find /srv/git/public/ -type l)
+current=$(pwd)
+
+for repo in $repos; do
+    repo_name=$(basename "$repo" | sed 's/\.git//')
+    repo_static_path="/var/www/git/$repo_name"
+    mkdir -p "$repo_static_path"
+    cd "$repo_static_path" || exit 1
+    echo "git://cacharle.xyz/$repo_name" > "$repo/url"
+    stagit "$repo"
+    ln -sf "$repo_static_path/log.html" "$repo_static_path/index.html"
+    echo "Generated $repo_static_path"
+done
+
+echo "Creating index"
+stagit-index $repos > /var/www/git/index.html
+
+cd "$current" || exit 1
+chown -R git:git /srv/git
+

There is more smart ways to handle this to rebuild the webpages each time someone pushes to the repo with git hooks.

+

Sources

+ +
+ +