跳到主要内容
  1. 所有文章/

托管简单 Git 服务器的一些尝试

·980 字·约 2 分钟

前言 #

本文是我打算为 stagit 配置一个简单的 Git 服务器作为后端的尝试,如果仅仅在局域网内玩一下是可以的,对于公网上的服务器还不够安全的,最终我并没有使用此方法。

文中仅在局域网测试,未绑定域名,请勿在公网服务器尝试,以免被骇。

设置用户 #

添加一个新用户,仅用于操作 Git 存储库

# 添加用户
sudo adduser git

# 切换用户
su git && cd && pwd
# 会输出
/home/git

# 设置 SSH 公钥目录
mkdir .ssh \
&& chmod 700 .ssh \
&& touch .ssh/authorized_keys \
&& chmod 600 .ssh/authorized_keys

生成或添加自己的 SSH 公钥(生成部分略)

# 比如 https://github.com/torvalds.keys
curl https://github.com/[username].keys -o ssh.keys \
cat ssh.keys >> ~/.ssh/authorized_keys
rm ssh.keys

初始化存储库 #

将每个单独的存储库都放在 git 用户目录下,比如

/home/git/repo1.git	# 远程存储库 1
/home/git/repo2.git	# 远程存储库 2

初始化裸存储库

git init --bare repo1.git

尝试提交 #

假设本地存储库 repo1 已经有一些提交记录

# 格式 ssh://<username>@<hostname>:<ssh-port><repo-path>
# 比如
git remote add origin ssh://git@192.168.1.101:22222/home/git/repo1.git
git push origin master

设置 Git Shell #

Git Shell 是一个为 Git 命令设计的轻量级 shell,它限制文中 git 用户对系统的访问权限,只允许它执行 Git 命令。

# 切换回普通用户
su [your-username]

# 一般情况下应该输出为空
cat /etc/shells | grep git-shell

# 输出 git shell 路径
which git-shell

# 添加一行 git shell 路径
sudo vim /etc/shells

# 设置 git 用户的默认 shell
sudo chsh git -s $(which git-shell)

禁止 SSH 转发 #

现在用户仍然可以通过 SSH 转发来访问任何可达的 Git 服务器,建议禁止 SSH 转发

echo -n "no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty " | cat - ~/.ssh/authorized_keys > temp && mv temp ~/.ssh/authorized_keys

禁用交互式 Shell #

以前我们访问 GitHub 服务器的时候,可以看到用户 Shell 被禁用的提示信息:

ssh -T git@github.com
Hi DejavuMoe! You've successfully authenticated, but GitHub does not provide shell access.

在我们搭建的 Git 服务器上,也可以设置

# 切换到 git 用户
su git

# 创建 git shell 执行命令目录
mkdir $HOME/git-shell-commands

# 设置禁用交互式 Shell 提示
cat > $HOME/git-shell-commands/no-interactive-login << EOF
#!/bin/sh
printf '%s\n' "Hi Dejavu Moe! You've successfully authenticated to your personal git server, "
printf '%s\n' "but we do not provide interactive shell access."
exit 128
EOF

# 赋予可执行权限
chmod +x $HOME/git-shell-commands/no-interactive-login

现在可以测试一下

ssh -T git@192.168.1.101 -p22222

# 输出
Hi Dejavu Moe! You've successfully authenticated to your personal git server,
but we do not provide interactive shell access.

Git Daemon 配置 #

上面通过 SSH 访问的 Git 服务器访问地址类似这样,看起来又长又臭

ssh://git@192.168.1.101:22222/home/git/repo1.git

我们可以使用 Git Daemon 守护进程守护 Git 服务器,现在的访问地址类似这样

这个地址适合在局域网分享 Git 存储库,没有身份认证和鉴权

# git://<hostname>:9418/<repo-name>
git://192.168.1.101:9418/repo1.git

git daemon 在Debian 或 Ubuntu 上是作为 git core 的一部分安装的,用法为:

git daemon [--reuseaddr] [--base-path=<path>] [--export-all] [--verbose] [--enable=<service>] [--max-connections=<n>] [--timeout=<seconds>] [--init-timeout=<seconds>] [--strict-paths] [--user=<user>] [--group=<group>] [--detach] [--pid-file=<file>] [--syslog] [--listen=<address>] [--port=<port>] [<directory>...]

对于每个参数的详细说明可以去问 ChatGPT

创建一个 Systemd 服务

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

示例

[Unit]
Description=Start Git Daemon

[Service]
ExecStart=/usr/bin/git daemon --reuseaddr --base-path=/home/git/ ---max-connections=20 --detach --syslog --listen=0.0.0.0 --listen=::0 --port=9418 /home/git/

Restart=always
RestartSec=500ms

StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=git-daemon

User=git
Group=git

[Install]
WantedBy=multi-user.target

然后

# 重载配置
sudo systemctl daemon-reload

# 开机自启 git daemon
sudo systemctl enable git-daemon

# 启动 git daemon
sudo systemctl start git-daemon

# 查看 git daemon 状态
sudo systemctl status git-daemon

在每个存储库添加一个文件即可让 git daemon 访问,比如

cd /home/git/repo1.git && touch git-daemon-export-ok

上面的 git daemon 命令带上 --export-all 参数运行,就不必在每个存储库里创建 git-daemon-export-ok 了。最户,在服务器上开放 9418/tcp 端口,就可以在其他机器访问了

git clone git://192.168.1.101:9418/repo1.git

参考信息:

Dejavu Moe
作者
Dejavu Moe
Not for success, just for growing.