Creating Your Own Git Server

栏目: IT技术 · 发布时间: 4年前

内容简介:Ever considered setting up and running your very own git server? It’s actually quite easy! In this post, I’ll outline the steps I took to set upmy own so that you can give it a try yourself. But first, why might you even want to go through the trouble of s

Ever considered setting up and running your very own git server? It’s actually quite easy! In this post, I’ll outline the steps I took to set upmy own so that you can give it a try yourself. But first, why might you even want to go through the trouble of setting up your own server?

After all, there are a wide array of excellent and free to use choices out there, such as Github, Gitlab, and the up-and-coming sourcehut .

One reason is ownership: in today’s world of corporate surveillance, rampant privacy violations, and data breaches, there is something to be said of truly owning your own data. Both git and the web itself were designed and built on principles of decentralization and distribution. Standing up your own server is one way to tap into that heritage.

It’s also just plain fun, at least if you’re into that sort of thing. You get to build something useful and put your name on it. It’s something you control. You get to decide how it works, how it looks, who can access it, and what exists on it.

Setting up a git server is actually relatively straight-forward. Almost all of the heavy lifting is done by git itself, but I will also introduce a few supplementary tools to handle things like access control and HTTP access.

Preparing your server

You can run your git server on something as simple as a Raspberry Pi or a Digital Ocean droplet. It’s not very demanding, so you don’t need much horsepower.

First, create a git user on your server. This user’s home directory will act as the base location for all of your repositories. I chose /var/lib/git as the home directory, but /home/git or /srv/git are other common choices.

# useradd -r -d /var/lib/git git

Make sure to set the password for the new user:

# passwd git

And make sure you can SSH to the git user on your server:

$ ssh git@yourserver.com

Gitolite

Next, install the excellent gitolite tool. Gitolite makes managing your server much easier and allows you to do things like user management, access control, triggers, hooks, and more. Copy your SSH public key into your git user’s home directory and then clone gitolite into the git user’s home directory.

From your home computer (i.e. not your server):

$ scp ~/.ssh/id_rsa.pub git@yourserver:yourname.pub

From your server:

$ su - git
$ git clone https://github.com/sitaramc/gitolite
$ mkdir -p ~/bin
$ gitolite/install -ln ~/bin
$ gitolite setup -pk yourname.pub

Now from your home computer, test your gitolite installation:

$ git ls-remote git@server:gitolite-admin

You should get something like:

9dd8aab60bac5e54ccf887a87b4f3d35c96b05e4    HEAD
9dd8aab60bac5e54ccf887a87b4f3d35c96b05e4    refs/heads/master

The gitolite-admin repo is where all of the gitolite configuration takes place. You can clone this to your home computer and push your changes back to your server and gitolite will automatically re-configure itself. This is also how you add new SSH keys (either for yourself or for other users).

Gitolite also interfaces quite nicely with git-daemon and gitweb . Be sure to check out the thorough documentation on gitolite’s website .

git daemon

Git includes a daemon subcommand that will listen for incoming connections and serve data over the git:// protocol. This allows you to clone repos from your server using

$ git clone git://yourserver/repo.git

The git:// protocol is the fastest and simplest option for read-only access, and it’s trivial to set up. Assuming your git user’s home directory is /var/lib/git , simply create the following systemd service file (e.g. at /etc/systemd/system/git-daemon.service ):

[Unit]
Description=Start Git Daemon

[Service]
ExecStart=/usr/bin/git daemon --reuseaddr --base-path=/var/lib/git/repositories /var/lib/git/repositories
Restart=always
RestartSec=500ms
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=git-daemon
User=git
Group=git

[Install]
WantedBy=multi-user.target

Then simply run systemctl enable --now git-daemon . Make sure port 9418 is open on your firewall.

If you don’t use systemd, you can probably find alternative init scripts for your particular init system in your package manager. Debian, for example, has git-daemon-sysvinit and git-daemon-run if you use SysV or runit, respectively.

The git daemon only serves repositories that have a file called git-daemon-export-ok in their directory root. This allows you to control which repositories you want to be publicly accessible. Gitolite will automatically create this file for you for any repos that are readable by the special daemon user.

Gitweb and HTTP

The most difficult part of setting up a git server is the web frontend and HTTP access. The git documentation has a section on Smart HTTP which is a good starting point, but it still took me quite a while to get everything working. Part of the reason I had some difficulty was because I insisted on running the webserver in a Docker container (so that I can version control the configuration).

By default, your git installation includes the git-http-backend script which allows you to clone over HTTP. If you also want to host a web frontend, then you have to create some rules for your webserver so that it knows when to serve the web page and when to direct traffic to the git-http-backend script.

Here is an example Apache configuration file:

ServerName yourserver.com

DocumentRoot /usr/share/gitweb
<Directory "/usr/share/gitweb">
    DirectoryIndex gitweb.cgi
    Options ExecCGI FollowSymLinks SymLinksIfOwnerMatch
    AddHandler cgi-script cgi
    Require all granted
    SetEnv GITWEB_CONFIG /etc/gitweb.conf
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} !^/([^/]+/(HEAD|info|objects|git-(upload|receive)-pack).*)$
    RewriteRule ^.* /gitweb.cgi/$0?js=1 [L,QSA,PT]
</Directory>

ScriptAliasMatch \
    "(?x)^/([^./]+)(\.git)?/(HEAD | \
                info/refs | \
                objects/info/[^/]+ | \
                git-(upload|receive)-pack)$" \
    /usr/libexec/git-core/git-http-backend/$1/$3

<Files "git-http-backend">
    SetEnv GIT_PROJECT_ROOT /var/lib/git/repositories
    Require all granted
</Files>

The above configuration allows repos to be cloned with or without the .git extension, but since gitolite creates all repositories with the .git suffix you’ll have to create non-suffixed symlinks to those directories.

Create and modify the /etc/gitweb.conf file to configure Gitweb.

I run Apache behind a reverse proxy that handles all of the TLS encryption, so the configuration above doesn’t deal with any of that. Setting up TLS for a webserver is out of scope for this guide and if that’s not something you care to do, you can always omit the HTTP/S portion of your server and simply serve via git:// and SSH. Like I said, this part is the most complex and will likely take more time than the other steps. The above snippet should be a good starting point though.

Unfortunately, even after getting the web server configured, I had another problem. The default Gitweb web page is a bit… utilitarian, to phrase it mildly.

Creating Your Own Git Server

Creating Your Own Git Server

Gitweb uses a Perl CGI script to generate the HTML, which means unless you want to manually modify that script your basically stuck with the HTML that Gitweb gives you.

Fortunately, CSS is quite powerful these days and there is a lot you can do with it. With only 6.25 KB of CSS I was able to transform the drab, default Gitweb interface into what you see today atgit.gpanders.com. You may think it still looks drab, but I’m fairly proud of how it turned out.

Gitolite tips and tricks

Here are some of the gitolite tricks I’ve set up on my server that you may find useful.

Mirroring to Github

I still mirror most of my repositories to Github, as that’s still the best place for discoverability and compatibility with other programs.

This is easy to set up in gitolite. In your gitolite.conf file, add the following to configure the repos you want to mirror to Github:

@github = repo1 repo2

repo @github
    config remote.github.url = git@github.com:gpanders/%GL_REPO.git
    config remote.github.mirror = true
    option hook.post-receive.mirror = mirror

Update your gitolite.rc file to allow the remote.* config options to be set:

GIT_CONFIG_KEYS             =>  'remote\..*\.(url|mirror)',

Now create the following script at hooks/repo-specific/mirror in your local code path :

#!/bin/sh
git push --quiet --mirror --force github

You’ll also need to create an SSH key for your git user on your server and upload the public key to Github to allow your server to push to Github:

$ ssh yourserver.com
$ su - git
$ ssh-keygen -t rsa -b 2048 -C 'Git user'
$ # Paste the contents of ~/.ssh/id_rsa.pub to https://github.com/settings/ssh/new

Clone repos without .git suffix

Github and other popular hosting sites allow you to interact with remote git repos with or without the .git suffix, e.g.

git clone https://github.com/gpanders/dotfiles.git

and

git clone https://github.com/gpanders/dotfiles

are the same. Gitolite always uses the .git suffix on repositories, but you can simply create non-suffixed symlinks that will allow you to clone repositories with or without the .git extension:

$ cd /var/lib/git/repositories
$ ln -s dotfiles.git dotfiles

You can do this manually quite easily, but you can also create a gitolite trigger to automatically create these symlinks everytime a new repo is created.

Create a trigger at triggers/post-compile/create-symlinks in your local code path with the following contents:

#!/bin/sh

# For projects that gitweb has access to, create symlinks in the 'repositories'
# directory without the .git suffix pointing to the real repos

symlink() {
    repo="$1"
    [ -L "$repo" ] && rm "$repo"
    if gitolite access -q "$repo" gitweb R any || gitolite git-config -q -r "$repo" gitweb\\.; then
        ln -s "$repo".git "$repo"
    fi
}

cd "$GL_REPO_BASE" || exit 1
if [ "$1" = "POST_CREATE" ] && [ -n "$2" ]; then
    # just one to be done
    symlink "$2"
else
    # all of them
    gitolite list-phy-repos | while IFS= read -r repo; do
        symlink "$repo"
    done
fi

In the above script, only repositories which are publicly acessible on Gitweb have a symlink created, since I only really care about the .git extension on the web interface (e.g. I want to use git.gpanders.com/dotfiles instead of git.gpanders.com/dotfiles.git). If you want this to apply to all repos, simply remove the gitolite access check.

You’ll also need a second trigger at triggers/post-compile/update-gitweb-access-list . This trigger is supplied by gitolite by default, so creating a new trigger just overrides the default one. The only change we need to make to the default trigger is to exclude the .git suffix from the list of repositories that gitolite makes available to Gitweb.

Copy the default trigger to triggers/post-compile/update-gitweb-access-list in your local code path and modify line 28 to

echo "$repo" >> $tmpfile

Generate a README

Github and other sites automatically convert your README file (if it exists) from Markdown, reStructured Text, etc. into HTML when you visit the web page. We can do this too with gitolite!

If the file README.html exists in the root of your repository, Gitweb will display it on the project’s summary page (example). We can create a hook to automatically create this file from the plain text README file in the repo. Create a hook at hooks/repo-specific/readme in your local code directory with the following contents:

#!/bin/sh

if ! command -v pandoc >/dev/null 2>/dev/null; then
        exit 0
fi

tmpdir=$(mktemp -d)
git --work-tree="$tmpdir" checkout --force

for file in README README.md README.rst README.txt; do
        if [ -f "$tmpdir"/"$file" ]; then
                pandoc -o README.html "$tmpdir"/"$file"
                break
        fi
done

rm -rf "$tmpdir"

Now in your gitolite.conf file add

repo @all
    option hook.post-receive.readme = readme

Obviously this requires that pandoc be installed on your git server.

Publish a Hugo site

This is the hook I use to publish this blog. I use Hugo to “compile” my site and I push it to Github where it’s hosted on Github Pages. My publish hook is located at hooks/repo-specific/publish :

#!/bin/sh

set -e

if ! command -v hugo >/dev/null 2>&1; then
        echo "hugo not found" >&2
        exit 1
fi

if [ -z "$GIT_DIR" ]; then
        echo "GIT_DIR not set" >&2
        exit 1
fi

TMPDIR=$(mktemp -d)
git --work-tree="$TMPDIR" checkout --force --recurse-submodules
git clone --quiet git@github.com:gpanders/gpanders.github.io "$TMPDIR"/public

echo "Building site..."
(cd "$TMPDIR" && hugo --quiet --cleanDestinationDir --destination public)

(
        cd "$TMPDIR"/public
        export GIT_DIR=.git
        if ! git diff-index --quiet HEAD --; then
                echo "Publishing site..."
                git add .
                git commit --quiet -m "Rebuilding site $(date)"
                git push --quiet origin master
                echo "Done!"
        fi
)

rm -rf "$TMPDIR"

and in my gitolite.conf I simply use:

repo blog
    option hook.post-receive.publish = publish

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Docker开发指南

Docker开发指南

[英] Adrian Mouat / 黄彦邦 / 人民邮电出版社 / 2017-4 / 79.00元

Docker容器轻量和可移植的特性尤其适用于动态和分布式的环境,它的兴起给软件开发流程带来了一场革命。本书对Docker进行了全面讲解,包括开发、生产以至维护的整个软件生命周期,并对其中可能出现的一些问题进行了探讨,如软件版本差异、开发环境与生产环境的差异、系统安全问题,等等。一起来看看 《Docker开发指南》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

SHA 加密
SHA 加密

SHA 加密工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具