1.跟着文档走

gitea的安装比较简单,直接使用官方文档中的docker-compose文件即可。如果想实现ssh容器直通,需要对这个docker-compose文件做一定修改。

如果你还没有安装docker,参考本站教程 linux安装docker

gitea的官方文档上有关于docker容器ssh直通的教程,但是写的不够清晰,有些问题我没有搞懂。本文基于我的折腾记录和docker安装的gitea 1.21.4文档

使用 Docker 安装 | Gitea Documentation

image.png

首先是跟着文章里面的步骤做,先创建一个git子用户。wsl中创建子用户的命令参考本站博客,ubuntu下使用adduser命令来添加。

1
sudo adduser git

注意创建的git用户的uid和gid是可能不是1000,可以用id 用户名的方式查看信息

1
2
$ id git
uid=1002(git) gid=1002(git) groups=1002(git)

为了保证权限一致,docker-compose中的环境变量需要对应修改。

1
2
3
environment:
- USER_UID=1001
- USER_GID=1001

还需要新增一个路径映射,在子用户git的家目录下创建一个.ssh目录。

1
- /home/git/.ssh/:/data/git/.ssh

注意:为了避免文件读写权限问题,我建议在创建git子用户后,在该子用户中操作docker-compose和新建gitea的映射文件夹,这样能保证git用户和gitea容器一定能访问到文件夹且具有权限。

在git用户中执行如下命令,出现的提示框全部回车即可。因为git用户是新创建的,必须把用户git加入sudoers文件中才能执行sudo命令,具体可以参考博客中第八点的介绍。

1
sudo -u git ssh-keygen -t rsa -b 4096 -C "Gitea Host Key"

随后执行如下命令,即把/home/git/.ssh/id_rsa.pub写入/home/git/.ssh/authorized_keys文件。执行完毕后请不要再手动修改authorized_keys文件。

1
echo "$(cat /home/git/.ssh/id_rsa.pub)" >> /home/git/.ssh/authorized_keys

还需要创建一个脚本来执行ssh信息转发

1
sudo vim /usr/local/bin/gitea

写入如下内容,可以通过CTRL+SHIFT+V直接粘贴。这里假设你将gitea容器的22端口转发到宿主机的2222端口(如果你的宿主机映射端口不同,可以修改脚本中的端口号)

1
ssh -p 2222 -o StrictHostKeyChecking=no git@127.0.0.1 "SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $0 $@"

写入脚本后,一定要把这个文件添加可执行权限

1
sudo chmod 777 /usr/local/bin/gitea

因为ssh容器直通都是本机处理的操作,所以我们可以在docker-compose中端口映射的时候限制来源IP地址为本地回环地址,这样就能保证只有宿主机中能访问2222端口到gitea中,而2222端口无法直接被外界访问。

1
2
3
ports:
# [...]
- "127.0.0.1:2222:22"

gitea的ssh直通流程

配置完毕ssh直通后,git操作流程如下:

  1. 用户使用git@IP地址访问主机,默认访问22端口;
  2. 主机验证git用户下.ssh/authorized_keyscommand开头的公钥中,发现用户公钥;
  3. 主机执行command指定的脚本,将此次请求的信息转发给gitea容器的ssh端口;
  4. gitea容器执行ssh请求处理;

如果不使用容器直通,你可以选择用https来进行git操作,或者在ssh使用时添加端口号。二者都会比直接使用ssh麻烦一些。

2.安装ssh服务

另外,默认情况下wsl中是没有ssh服务的,你会发现22端口无人使用

1
2
[root:~]# netstat -nltp | grep 22
tcp 0 0 127.0.0.1:2222 0.0.0.0:* LISTEN 2816/docker-proxy

需要安装一下ssh服务

1
2
sudo apt install -y openssh-server
sudo systemctl start sshd

使用如下命令查看服务状态以及是否启用了开机自启

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
[root:~]# systemsystemctl status sshd
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2024-02-07 14:59:06 CST; 9min ago
Docs: man:sshd(8)
man:sshd_config(5)
Main PID: 5202 (sshd)
Tasks: 1 (limit: 9527)
Memory: 1.7M
CGroup: /system.slice/ssh.service
└─5202 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"

Feb 07 14:59:06 wsl-ubuntu systemd[1]: Starting OpenBSD Secure Shell server...
Feb 07 14:59:06 wsl-ubuntu sshd[5202]: Server listening on 0.0.0.0 port 22.
Feb 07 14:59:06 wsl-ubuntu sshd[5202]: Server listening on :: port 22.
Feb 07 14:59:06 wsl-ubuntu systemd[1]: Started OpenBSD Secure Shell server.
[root:~]# sudo systemctl is-enabled sshd
alias
[root:~]# sudo systemctl is-enabled ssh
enabled

此时再看看22端口,就有人干活了,sshd服务启动成功

1
2
3
4
[root:~]# netstat -nltp | grep 22
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 5202/sshd: /usr/sbi
tcp 0 0 127.0.0.1:2222 0.0.0.0:* LISTEN 2816/docker-proxy
tcp6 0 0 :::22 :::* LISTEN 5202/sshd: /usr/sbi

3.web界面添加用户ssh公钥

随后就是和github一样的操作, 在gitea的web页面添加用户的公钥。

【Linux】如何使用 ssh 密钥配置 git

image.png

添加完毕后,检查一下git用户里面的/home/git/.ssh/authorized_keys文件是否有变动,文件应该如下格式,会有一个command=存放了你刚刚在gitea web页面添加的用户公钥。

1
2
3
4
ssh-rsa <Gitea Host Key>

## other keys from users
command="/usr/local/bin/gitea --config=/data/gitea/conf/app.ini serv key-1",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty <user pubkey>

文档中关于这一块的描述不够清楚(我感觉是机翻的问题)

原文:重要提示:来自 git 用户的公钥需要“按原样”添加,而通过 Gitea 网络界面添加的所有其他公钥将以 command="/app [...] 作为前缀。

其实这个说明的意思是,默认情况下的authorized_keys文件中应该只有下面的内容(即“按原样”添加),而gitea web页面添加的其他公钥应该都是以command=" 作为前缀,自动添加到authorized_keys文件之后的。

1
ssh-rsa <Gitea Host Key>

说白了就是,在执行完毕上文提到的将/home/git/.ssh/id_rsa.pub文件的内容写入/home/git/.ssh/authorized_keys的操作后,我们就不要手动修改authorized_keys这个文件了!如果出现问题,再依照文档中的这个提示检查该文件中的公钥格式是否正确。

官网文档中还提到了下面几个注意事项,我们全都不用管!只要你没有修改过配置文件和gitea容器中的环境,这些配置项都是默认情况下就OK了的。

image.png

4.验证是否直通成功

尝试验证ssh是否成功,这里的ip是wsl的本机ip,可以在wsl中通过ifconfig命令查看。

1
ssh -T git@172.26.39.91

如果出现下面的情况,说明22端口没有被成功开放,请检查:

  • 宿主机中的22端口是否已经配置了sshd服务,并正常监听22端口;
  • 在web页面添加的用户公钥是否添加到了/home/git/.ssh/authorized_keys文件中;
  • /usr/local/bin/gitea脚本中的命令无误。
1
2
3
4
5
6
7
PS D:\test-git> git clone git@172.26.39.91:musnows/test-action.git
Cloning into 'test-action'...
ssh: connect to host 172.26.39.91 port 22: Connection refused
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

如果看到了下面的内容,可以说明我们wsl中的的ssh服务已经成功启动了,但是没有成功通过脚本验证git用户。

1
2
3
4
5
6
7
PS D:\test-git> ssh -T git@172.26.39.91
The authenticity of host '172.26.39.91 (172.26.39.91)' can't be established.
ED25519 key fingerprint is SHA256:xRPtWVSIsHrqmP3VaBD+ZR24nE6SWmgjWUYENN0IfB8.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '172.26.39.91' (ED25519) to the list of known hosts.
bash: line 1: /usr/local/bin/gitea: Permission denied

这是因为我们的git用户没有办法执行/usr/local/bin/gitea脚本,还记得吗,这个脚本是通过sudo创建的,默认情况下是一个文本文件,且只有root用户有权限访问

1
2
[root:~]# ll /usr/local/bin/gitea
-rw-r--r-- 1 root root 109 Feb 7 14:47 /usr/local/bin/gitea

解决办法很简单,将其权限改成777即可。

1
2
3
[root:~]# chmod 777 /usr/local/bin/gitea
[root:~]# ll /usr/local/bin/gitea
-rwxrwxrwx 1 root root 109 Feb 7 14:47 /usr/local/bin/gitea*

此时再次测试,发现成功直通gitea容器内ssh!这里会显示你在web页面中添加的ssh密钥的名字user from windows

1
2
3
4
PS D:\test-git> ssh -T git@172.26.39.91
Warning: Permanently added '[127.0.0.1]:2222' (ED25519) to the list of known hosts.
Hi there, musnows! You've successfully authenticated with the key named user from windows, but Gitea does not provide shell access.
If this is unexpected, please log in with password and setup Gitea under another user.

再试试能不能通过ssh克隆仓库,搞定!

1
2
3
4
5
6
7
8
PS D:\test-git> git clone git@172.26.39.91:musnows/test-action.git
Cloning into 'test-action'...
remote: Enumerating objects: 80, done.
remote: Counting objects: 100% (80/80), done.
remote: Compressing objects: 100% (58/58), done.
remote: Total 80 (delta 22), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (80/80), 56.15 KiB | 9.36 MiB/s, done.
Resolving deltas: 100% (22/22), done.

5.docker-compose文件

下面给出本文所用的gitea容器docker-compose文件,只在官方文档所提供的版本上做了少量修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
version: "3"

networks:
gitea:
external: false

services:
server:
image: gitea/gitea:1.21.4
container_name: gitea
environment:
- USER_UID=1001
- USER_GID=1001
restart: always
networks:
- gitea
volumes:
- /home/git/data:/data
- /home/git/.ssh/:/data/git/.ssh
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "30000:3000"
- "127.0.0.1:2222:22"

注意,在初始化gitea的时候不要修改web界面和ssh的监听端口(对应的是容器内的端口),否则上文的ssh直通可能会失败!

The end

如果有疑问,欢迎在评论区交流。

相关参考:如何通过Docker搭建Gitea并配置SSL和SSH直通 - 莫乔多博客