本文将说明如何在 Linux 服务器上使用 git-daemon 设置 Git 协议支持。也就是支持外部通过git://xxx/reponame 的方式进行clone或一些其他操作(比如将一个普通的git仓库镜像到只支持git协议的Gitea中)

安装 git-daemon:

sudo apt-get update
sudo apt-get install git-daemon-run

创建一个新的 systemd 服务文件:

sudo nano /etc/systemd/system/git-daemon.service

将以下内容粘贴到文件中:

[Unit]
Description=Git Daemon

[Service]
ExecStart=/usr/lib/git-core/git-daemon --reuseaddr --base-path=/var/cache/git --export-all --verbose --syslog --enable=receive-pack
Restart=always
RestartSec=500ms
User=mango
Group=mango
Environment=GIT_HTTP_EXPORT_ALL=1
RuntimeDirectory=git-daemon
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target

保存并关闭文件。

ExecStart:可以用命令 sudo find / -name git-daemon 2>/dev/null 来找到可执行文件文件的位置

--base-path:这个是git-daemon进行服务的根目录,可以指定为你自己仓库的实际位置,但一般用这个默认设置 /var/cache/git 比较好,因为你可能不希望你的仓库目录下可能存在其他你不想公开的仓库。这个默认设置的目录需要手动创建(后面的步骤会提到)否则服务启动时会报错。

--User和Group:请改成你创建仓库时使用的用户和用户组。更标准的做法是创建并使用git用户/组,本文最后会介绍方法。由于我之前是使用一般用户 mango 创建的仓库,这里为了避免复杂的权限设置所以直接使用原来的用户。

其他非必须的选项说明:

Restart=always 和 RestartSec=500ms 是用于设置服务的重启策略的。表示当服务退出时,systemd 会自动尝试重新启动服务。这个选项适用于大多数服务,因为我们通常希望服务在退出后能够自动重新启动。当服务因任何原因退出后,systemd 会在 500 毫秒后尝试重新启动服务。这个选项可以避免过于频繁的重启,从而减少对系统资源的占用。这个设置可以在配置文件中使用,也可以在 systemctl 命令中直接使用。

Environment=GIT_HTTP_EXPORT_ALL=1 这个设置用于设置 Git 的环境变量,其中 GIT_HTTP_EXPORT_ALL 是一个常用的环境变量,表示 Git HTTP 服务器应该公开所有的 Git 仓库,这样用户才能通过 HTTP 协议访问这些仓库。对于 git-daemon,这个设置则是告诉它要导出所有的 Git 仓库。

RuntimeDirectory=git-daemon 和 RuntimeDirectoryMode=0755 这两个设置用于创建一个运行时目录,这个目录将被用于存放 git-daemon 的运行时数据。在这个目录下,git-daemon 会创建一个用于存放缓存文件的子目录。这个设置可以帮助您更好地管理 git-daemon 的运行时数据。

其中 RuntimeDirectory=git-daemon 表示我们要创建一个名为 git-daemon 的运行时目录,RuntimeDirectoryMode=0755 则表示这个目录的权限为 0755,即所有用户都可以读取和执行这个目录,但只有目录的拥有者可以写入这个目录。这个设置可以确保 git-daemon 有一个合适的目录用于存放运行时数据,并且只有具有足够权限的用户才能够修改这个目录。

Restart=always、 RestartSec=500ms、Environment=GIT_HTTP_EXPORT_ALL=1、RuntimeDirectory=git-daemon 和 RuntimeDirectoryMode=0755 这几个设置并不是必须的,如果只是简单地想要在服务器上运行一个 git-daemon 服务,并且不需要过多的定制化配置,那么完全可以不必使用这些设置。

--enable=receive-pack:启用 push 支持。git-daemon 默认情况下是不支持 push 操作的。git-daemon 主要用于提供一个轻量级的、只读的访问方式,使得用户可以通过 Git 协议克隆和拉取(fetch)公开的仓库。然而,git-daemon 确实提供了一个 --enable=receive-pack 选项,这个选项可以启用 push 支持。但要注意,这是一个不安全的操作,因为这将允许任何人对您的仓库进行修改。这种设置通常不推荐用于生产环境。如果你需要在团队中共享仓库并支持 push 操作,推荐使用 SSH 或 HTTPS 协议,并利用像 GitLab、Gitea 或 GitHub 这样的服务,它们提供了用户权限管理和认证,以确保仓库的安全。

创建 /var/cache/git 目录:

sudo mkdir /var/cache/git

更改目录的所有者和权限,以便 git-daemon 可以访问它:

sudo chown mango:mango /var/cache/git
sudo chmod 755 /var/cache/git

注意,请使用你自己的用户和组替换 mango:mango 。

将 Git 仓库的软链接添加到 /var/cache/git:

sudo ln -s /path/to/your/repository /var/cache/git/repository_name

更改符号链接的所有者,以便 git-daemon 可以访问它:

sudo chown -h mango:mango /var/cache/git/repository_name

注意,如果您之前为 git-daemon 设置了不同的用户和组,请使用相应的用户和组替换 mango:mango 。

在仓库中添加 git-daemon-export-ok 文件:

touch /path/to/your/repository/git-daemon-export-ok

重新加载 systemd 配置并启动 git-daemon 服务:

sudo systemctl daemon-reload
sudo systemctl start git-daemon
sudo systemctl enable git-daemon

检查 git-daemon 服务的状态:

sudo systemctl status git-daemon

如果一切正常,你会看到 active (running):

$ sudo systemctl status git-daemon

● git-daemon.service - Git Daemon
   Loaded: loaded (/etc/systemd/system/git-daemon.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2023-05-06 11:29:39 CST; 9min ago
 Main PID: 12563 (git-daemon)
    Tasks: 1 (limit: 2161)
   CGroup: /system.slice/git-daemon.service
           └─12563 /usr/lib/git-core/git-daemon --reuseaddr --base-path=/var/cache/git --export-all --verbose --syslog --enable=receive-pack

如果服务无法启动,可以尝试直接运行 git-daemon 命令,看看是否有具体的错误消息:

sudo /usr/lib/git-core/git-daemon --reuseaddr --base-path=/var/cache/git --export-all --verbose --syslog --enable=receive-pack

开放git协议的默认端口9418:

在 Linux 系统上,iptables / firewalld / ufw 是常用的防火墙管理工具。这里提供在这几种防火墙管理工具中分别开放端口的方法。

使用 iptables 开放端口:

  1. 运行以下命令以允许传入的 TCP 流量到达端口 9418:
sudo iptables -A INPUT -p tcp --dport 9418 -j ACCEPT
  1. 保存 iptables 规则以便在系统重启后生效:

对于基于 Debian 的发行版(例如 Ubuntu):

sudo sh -c 'iptables-save > /etc/iptables/rules.v4'

对于基于 RHEL 的发行版(例如 CentOS 或 Fedora):

sudo sh -c 'iptables-save > /etc/sysconfig/iptables'

使用 firewalld 开放端口:

  1. 首先,请确保 firewalld 服务已经安装并正在运行。可以通过以下命令检查 firewalld 服务的状态:
sudo systemctl status firewalld

如果 firewalld 服务未安装,请使用包管理器(如 apt 或 yum)安装它。

  1. 运行以下命令以允许传入的 TCP 流量到达端口 9418:
sudo firewall-cmd --permanent --add-port=9418/tcp
  1. 重新加载 firewalld 配置以应用更改:
sudo firewall-cmd --reload

使用 ufw开放端口:

sudo ufw allow 9418
sudo ufw status

完成

现在你就拥有 git:// 开头的公开仓库了。

注意,git-daemon是不支持权限管理的,并且对互联网上的任何人都是开放的。它只提供读权限,没有写权限。需要更复杂的用户权限管理功能请使用GitLab / Gitea / Gitee / GitHub 。

顺便提一句,GitHub、GitLab 和 Gitea 这些服务并没有直接使用 git-daemon。它们在底层依赖的是 Git 本身,但实现了自己的服务端和权限管理系统,以支持用户权限、认证、写入操作(如 commit、push)等功能。

这些服务通常使用 SSH 和 HTTPS 协议提供访问 Git 仓库的能力,而不是使用 git-daemon 提供的 Git 协议。SSH 和 HTTPS 协议允许实现更复杂的权限和认证机制,从而更好地满足多用户环境和私有仓库的需求。

所以,虽然这些服务在底层使用 Git,但它们并不是在 git-daemon 的基础上扩展而来。它们实现了自己的服务端逻辑和权限管理,以支持更复杂的功能和需求。

git clone git://your-host/repository_name

可能遇到的问题及解决方案:

  1. 问题:启动 git-daemon 服务时报错 "Failed to enable unit: Unit file git-daemon.service does not exist."
    解决方案:请确保已在 /etc/systemd/system/ 目录下创建了 git-daemon.service 文件。
  2. 问题:执行git clone时报错 "fatal: remote error: access denied or repository not exported: /repository_name"
    解决方案:请确保 git-daemon 服务正在运行且没有报告任何错误。使用 sudo systemctl status git-daemon 查看服务状态。此外,检查 git-daemon 服务的日志,查看是否有关于无法访问或导出仓库的错误或警告。使用 sudo journalctl -u git-daemon 查看日志。
  3. 问题:使用 sudo systemctl status git-daemon 查看服务状态时,存在错误信息:'/var/cache/git/repository_name' does not appear to be a git repository 。这表示git-daemon 认为仓库不是一个有效的 Git 仓库。
    解决方案:更改仓库目录及其子目录的所有权和权限,以便 git-daemon 可以访将 /etc/systemd/system/git-daemon.service 文件中的 User 和 Group 行更改为你希望访问仓库的用户,例如 mango 。重新加载 systemd 配置并重启 git-daemon 服务。

补充:使用 git 用户和 git 用户组的方法

  1. 在 /etc/systemd/system/git-daemon.service 文件中将 User 和 Group 行更改为 git:
[Service]
...
User=git
Group=git
  1. 更改 /var/cache/git 目录的所有权和权限:
sudo chown -R git:git /var/cache/git
sudo chmod -R 755 /var/cache/git
  1. 将仓库的软链接添加到 /var/cache/git,并确保仓库目录及其子目录的所有权和权限允许 git 用户访问:
sudo ln -s /path/to/your/repository /var/cache/git/repository_name
sudo chown -R git:git /path/to/your/repository
sudo chmod -R 755 /path/to/your/repository

可能遇到的问题:

  1. 如果使用 git 用户和用户组可能导致之前的用户访问仓库受到影响。例如,mango 用户可能无法访问仓库,因为所有权和权限已更改为 git 用户和用户组。

解决方案:

将原始用户添加到 git 用户组,让此用户仍然可以访问仓库。

sudo usermod -a -G git mango
  1. 更改仓库目录及其子目录的权限,以便允许属于 git 用户组的用户访问。
sudo chmod -R 775 /path/to/your/repository

完成上述更改后,重新加载 systemd 配置并重启 git-daemon 服务。这样,您将能够使用 git 协议访问您的仓库,同时保留原始用户的访问权限。

系列文章

Last modification:October 10, 2023
If you think my article is useful to you, please feel free to appreciate