Git 服务器

出自 ArchWiki

本文概述了如何托管 Git 服务器。更多信息,请参考 Pro Git 书籍中关于 Git 服务器的章节

协议

请参考 Git on the Server - The Protocols 以获取详细描述以及优缺点。

通用

Step by Step Guide on Setting Up git Server 描述了如何在 Arch 上设置不安全的服务器。

默认情况下,git 用户已过期(“Your account has expired; please contact your system administrator”)。使用 chage 移除过期条件,例如如下操作

# chage -E -1 git

SSH

你只需要设置一个 SSH 服务器

你可以进一步保护 SSH 用户账户,仅允许在此用户账户上执行 push 和 pull 命令。这可以通过将默认登录 shell 替换为 git-shell 来完成。详情请参考 Setting Up the Server

当使用 #通用 中的说明创建 git 服务器,并使用本节 (#SSH) 的说明进行保护时,需要在 Arch 上执行以下额外步骤

  1. 更改 home 目录:为了使 ssh 能够读取 /srv/git/.ssh/authorized_keys,需要将 /etc/passwd 中 git 的 home 目录从 / 更改为 /srv/git
  2. 当 home 目录被修正后更改 base path:为了使 git 服务仓库,如果仓库从 git 的 home 目录提供服务,则需要将 git-daemon\@.service 中的 --base-path 更改为 /srv/git

Dumb HTTP

在此上下文中,“Dumb” 意味着只有 WebDAV 参与 pull 和 push 操作。

nginx

按照 nginx 的基本 WebDAV 说明进行操作。通过 WebDAV 推送也需要锁定 (Locking)。这是一个 location 代码块的示例

/etc/nginx/nginx.conf
location /repos/ {
        auth_basic "Authorized Personnel Only!";
        auth_basic_user_file /etc/nginx/htpasswd;
        dav_methods PUT DELETE MKCOL COPY MOVE;
        dav_ext_methods PROPFIND OPTIONS LOCK UNLOCK;
        dav_access user:rw group:rw all:r;
        dav_ext_lock zone=general;
        create_full_put_path on;
        client_body_temp_path /tmp;
    }

注意 dav_ext_lock zone。将指定的 locking zone 添加到你的配置文件的 http section 中

/etc/nginx/nginx.conf
dav_ext_lock_zone zone=general:10m;

现在执行为服务器准备 git 仓库的常用步骤

  • git clone --bare /path/to/myrepo myrepo.git
  • 将 bare repo 复制到服务器
  • 在 bare repo 中运行 git update-server-info
  • 将 repo 的所有者更改为 http:http

你可能已经注意到我添加了 HTTP Basic Authentication,以便至少拥有一些访问控制手段。任何在 htaccess 文件中拥有密码条目的人都可以推送。

现在你可以像往常一样克隆

$ git clone https://www.example.com/repos/myrepo.git
Cloning into 'myrepo'...
$

进行一些更改,添加、提交和推送

$ git push origin main
error: Cannot access URL https://www.example.com/repos/myrepo.git/, return code 22
fatal: git-http-push failed
error: failed to push some refs to 'https://www.example.com/repos/myrepo.git'

糟糕!由于某些原因,PROPFIND 报告 401 Unauthorized,仅此而已。nginx 错误日志中没有任何内容。显然,git 客户端在为所有后续请求传递用户名和密码时遇到了问题。运行 git 凭据缓存没有帮助。到目前为止,唯一有效的解决方案是编辑 ~/.netrc (显然 git 使用 curl 进行 http)

~/.netrc
machine www.example.com
login git
password topsecret
$  > git push origin main
Fetching remote heads...
 refs/
 refs/heads/
 refs/tags/
updating 'refs/heads/main'
 from 03f8860418facfbecedd5e0a81b480131b31bcba
 to   ec5536091e31ebf172a34c6d1ebddfc36e3bd3a6
   sending 3 objects
   done
Updating remote server info
To https://www.example.com/repos/myrepo.git
  0318860..ec55560  main -> main

甚至不要考虑将克隆 URL 指定为 https://username:password@www.example.com/repos/myrepo.git。这对于初始克隆有效,但对于后续推送,你会在错误日志中收到一条错误消息,指出目标 URL 由不同的仓库处理。

Smart HTTP

本文或本节需要扩充。

原因: 有许多支持 CGI 的 Web 服务器。(在 Talk:Git server 中讨论)

git-http-backend(1) 是一个 CGI 程序,允许通过 HTTP(S) 进行高效的克隆、拉取和推送。

Apache

此设置相当简单,因为你只需要安装 Apache HTTP Server,并启用 mod_cgimod_aliasmod_env),当然还有 git

一旦你的基本设置运行起来,将以下内容添加到你的 Apache 配置文件中,该文件通常位于

/etc/httpd/conf/httpd.conf
<Directory "/usr/lib/git-core">
    Require all granted
</Directory>
 
SetEnv GIT_PROJECT_ROOT /srv/git
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git/ /usr/lib/git-core/git-http-backend/

这假设你的 Git 仓库位于 /srv/git,并且你希望通过类似以下方式访问它们:http(s)://your_address.tld/git/your_repo.git

注意: 确保 Apache 可以读取和写入你的仓库。

有关更详细的文档,请访问以下链接

Git

Git 协议未加密或身份验证,并且仅允许读取访问。

Git 守护进程 (git-daemon(1)) 可以使用 git-daemon.socket 启动。

该服务使用 --export-all--base-path 参数来服务放置在 /srv/git/ 中的所有仓库。

访问控制

为了实现细粒度的访问控制,可以使用以下解决方案

  • Gitolite — Git 之上的访问控制层,用 Perl 编写。
https://github.com/sitaramc/gitolite || gitolite
  • Gitosis — 用于托管 Git 仓库的软件,用 Python 编写。
https://github.com/tv42/gitosis || gitosis-gitAUR

请注意,如果你愿意为所有应该访问仓库的人创建 用户账户,并且不需要在 git 对象级别(如分支)进行访问控制,你也可以使用标准 文件权限 进行访问控制。[1]

Web 界面

简单的 Web 应用程序

  • Gitweb — Git 自带的默认 Web 界面
  • cgit — 用纯 C 编写的 git Web 界面。
https://git.zx2c4.com/cgit/ || cgit

高级 Web 应用程序

  • Forgejo — 自托管的轻量级软件 forge。Gitea 的社区管理分支。
https://forgejo.org || forgejo
  • Gitea — 轻松的自托管 Git 服务。它最初是作为 Gogs 的社区管理分支而诞生的,但在 2022 年,它成为 Gitea Limited 所有,并采用商业模式。
https://gitea.io || gitea
  • GitLab — 项目管理和代码托管应用程序,用 Ruby 编写。
https://gitlab.com/gitlab-org/gitlab-ce || gitlab
  • Gogs — 自托管 Git 服务,用 Go 编写。
https://gogs.io || gogsAUR