处理git clone命令的非标准SSH端口连接使用git clone命令clone项目时，如果repository的SSH端口不是标准22端口时（例如，SSH tunnel模式，等等），可以使用如下命令：git clone ssh://git@hostname:port/.../xxx.git 举例如下：git clone ssh://git@11.22.33.44:2201/mango/test.git
背景默认Gitea是以容器的形式运行的，并默认不使用Gitea内部的ssh服务而是使用转发宿主机ssh端口的方式，一般会将222端口绑定到容器的22端口上。问题安装完并新建仓库后，无法使用 git clone git@host:user/repo.git 的方式拉取仓库。http方式一般不会出问题。原因由于公开出来的端口不是默认的22而是222所以需要配置客户端的.ssh/config 文件，配置以下内容Host some-name HostName your-gitea-host User git # 这里我使用了非常用的key，这不是必须的 IdentityFile /c/Users/tuoxi/.ssh/id_ecdsa_gitea IdentitiesOnly yes # 主要是这里一定要设置为222 Port 222在gitea的个人设置中添加你的公钥。注意，正确的添加位置如下。添加到每一个仓库设置里的key是没用的，另外下图画圈右侧的“密钥”那个也是不对的，那些都是用来做其他用途的。（Action）测试上述设置了以后应该就可以用ssh拉取仓库了，比如git clone git@your-gitea-host:mango/test.git或者直接省略git这个用户名直接使用指定的Host（注意不需要是HostName）git clone some-name:mango/test.git要注意的是host名（your-gitea-host处）需要和config中设置的一致才会使用config的222端口的设置，所以如果不是真实的域名而是修改hosts来映射的局域网的“假”域名或主机名，也要保证两边一致。$ git clone git@your-gitea-host:mango/test.git Cloning into 'test'... remote: Enumerating objects: 3, done. remote: Counting objects: 100% (3/3), done. remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 Receiving objects: 100% (3/3), 218 bytes | 218.00 KiB/s, done.
本文将说明如何在 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 服务，并且不需要过多的定制化配置，那么完全可以不必使用这些设置。[scode type="red"]--enable=receive-pack：启用 push 支持。git-daemon 默认情况下是不支持 push 操作的。git-daemon 主要用于提供一个轻量级的、只读的访问方式，使得用户可以通过 Git 协议克隆和拉取（fetch）公开的仓库。然而，git-daemon 确实提供了一个 --enable=receive-pack 选项，这个选项可以启用 push 支持。但要注意，这是一个不安全的操作，因为这将允许任何人对您的仓库进行修改。这种设置通常不推荐用于生产环境。如果你需要在团队中共享仓库并支持 push 操作，推荐使用 SSH 或 HTTPS 协议，并利用像 GitLab、Gitea 或 GitHub 这样的服务，它们提供了用户权限管理和认证，以确保仓库的安全。[/scode]创建 /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协议对外公开