本文将说明如何在 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 服务,并且不需要过多的定制化配置,那么完全可以不必使用这些设置。
创建 /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 开放端口:
- 运行以下命令以允许传入的 TCP 流量到达端口 9418:
sudo iptables -A INPUT -p tcp --dport 9418 -j ACCEPT
- 保存 iptables 规则以便在系统重启后生效:
对于基于 Debian 的发行版(例如 Ubuntu):
sudo sh -c 'iptables-save > /etc/iptables/rules.v4'
对于基于 RHEL 的发行版(例如 CentOS 或 Fedora):
sudo sh -c 'iptables-save > /etc/sysconfig/iptables'
使用 firewalld 开放端口:
- 首先,请确保 firewalld 服务已经安装并正在运行。可以通过以下命令检查 firewalld 服务的状态:
sudo systemctl status firewalld
如果 firewalld 服务未安装,请使用包管理器(如 apt 或 yum)安装它。
- 运行以下命令以允许传入的 TCP 流量到达端口 9418:
sudo firewall-cmd --permanent --add-port=9418/tcp
- 重新加载 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
可能遇到的问题及解决方案:
- 问题:启动 git-daemon 服务时报错 "Failed to enable unit: Unit file git-daemon.service does not exist."
解决方案:请确保已在 /etc/systemd/system/ 目录下创建了 git-daemon.service 文件。 - 问题:执行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 查看日志。 - 问题:使用 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 用户组的方法
- 在 /etc/systemd/system/git-daemon.service 文件中将 User 和 Group 行更改为 git:
[Service]
...
User=git
Group=git
- 更改 /var/cache/git 目录的所有权和权限:
sudo chown -R git:git /var/cache/git
sudo chmod -R 755 /var/cache/git
- 将仓库的软链接添加到 /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
可能遇到的问题:
- 如果使用 git 用户和用户组可能导致之前的用户访问仓库受到影响。例如,mango 用户可能无法访问仓库,因为所有权和权限已更改为 git 用户和用户组。
解决方案:
将原始用户添加到 git 用户组,让此用户仍然可以访问仓库。
sudo usermod -a -G git mango
- 更改仓库目录及其子目录的权限,以便允许属于 git 用户组的用户访问。
sudo chmod -R 775 /path/to/your/repository
完成上述更改后,重新加载 systemd 配置并重启 git-daemon 服务。这样,您将能够使用 git 协议访问您的仓库,同时保留原始用户的访问权限。
系列文章
- 自建Git仓库01-在 Linux 服务器上设置 Git 协议支持【当前文章】
- 自建Git仓库02-将普通的Git仓库用http协议对外公开