安装Gogs并共享主机22端口

问题

之前团队一直用的Subversion来管理代码的,开发的时候还OK,但是到了上线后,问题就开始出现,往往发布了一个版本后,代码又有一部分提交,同时可能引进一些新的Bug,再发包的时候,又有新的Bug,很不爽。本身SVN的分支管理不好用,我就强烈推荐Git,之前也一直在用,直接在服务器上开SSH端口就OK,但是权限管理又是一个问题啊,又找了一些Git权限管理的东东,但都太理想。后来想是不是有Github一样的东东,后来就发现了Gitlab,但是这货太耗资源,而且搭建起来也不容易,其他人去维护它就很困难。后来一顿放狗搜,找到了一个比较好的替代Gogs,上周末两天基本就在搞这货,使用起来也是很不错的。花时间的部分主要是与主机共享22端口的问题。

现在服务器那边的环境是,服务器位于防火墙后面,防火墙只开了有限供外网使用的端口,所以Gogs必须在某个共用端口的子目录下进行访问,比如domain.com/git/。防火墙8888端口映射到服务器4444端口,然后服务器4444端口再映射到Gogs Container的3000端口。

Docker Gogs安装

其实用Docker来安装Gogs很简单,直接参考官方的文档主OK了。

1
2
3
4
5
6
7
8
9
10
11
12
13
# Pull image from Docker Hub.
$ docker pull gogs/gogs

# Create local directory for volume.
$ mkdir -p /var/gogs

# Use `docker run` for the first time.
$ docker run --name=gogs -p 10022:22 -p 10080:3000 -v /var/gogs:/data gogs/gogs
# 下面是我的配置
$ docker run --name gogs -p 3000:3000 -p 10022:22 --link mysql:db -v /opt/my_gogs:/data -e "PUID=1002" -e "PGID=1002" -d gogs/gogs

# Use `docker start` if you have stopped it.
$ docker start gogs

其中我运行Gogs的时候加了一些东西。将前端端口映射到Host的3000端口,将Container的SSH端口22映射到Host的1022端口,然后将另一个mysql的Container链接到Gogs,这样可以直接访问MySQL,然后就是将Gogs的配置文件和其它工作文件链接到Host的gogs目录下,然后就是设置Gogs Containerm里面git用户的uid和gid。如果不设置uid和gid的话,container默认的是1000,一般情况下都不是我们想要的结果。一般是在Host新建一个git的用户,将container的uid和gid设置成Host上git用户对应的值,比如我的就是1002和1002。

Gogsl配置

Docker Gogs运行起来后,就可以直接浏览器连3000端口进行配置,配置界面很明了,一看就OK。但此时我用的MySQL也是用的Docker,因为之前用了--link mysql:db,表示我有一个container的名称为mysql,映射到gogs的container的名称为db,这样我可以直接用db:3306就可以连上了。在配置界面点确定前,需要在MySQL里新建一个仓,具体代码可以参考官方脚本

等界面配置好后就再对Gogs进行详细的修改,具体可以参考官方文档

app.ini
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
APP_NAME = Gogs
RUN_USER = git
RUN_MODE = prod

[database]
DB_TYPE = mysql
HOST = db:3306
NAME = gogs
USER = root
PASSWD = mysql_password
SSL_MODE = disable
PATH = data/gogs.db

[repository]
ROOT = /data/git/gogs-repositories
FORCE_PRIVATE = true
DISABLE_HTTP_GIT = true

[repository.upload]
ENABLED = false

[server]
DOMAIN = yourdomain.com
HTTP_PORT = 3000
ROOT_URL = http://localhost:3000/git/
DISABLE_SSH = false
SSH_PORT = 22
START_SSH_SERVER = false
OFFLINE_MODE = false

[mailer]
ENABLED = true
DISABLE_HELO = true
HOST = smtp.xxx.com:587
SUBJECT = GIT
FROM = "GIT" <xxx@xxx.com>
USER = xxx@xxx.com
PASSWD = xxx
SKIP_VERIFY = false
USE_PLAIN_TEXT = false

[service]
REGISTER_EMAIL_CONFIRM = true
ENABLE_NOTIFY_MAIL = true
DISABLE_REGISTRATION = true
ENABLE_CAPTCHA = true
REQUIRE_SIGNIN_VIEW = true

[picture]
DISABLE_GRAVATAR = true
ENABLE_FEDERATED_AVATAR = true

[session]
PROVIDER = file

[log]
MODE = file
LEVEL = Info
ROOT_PATH = /app/gogs/log

[security]
INSTALL_LOCK = true
SECRET_KEY = qHtSV2KhCcMA0Xl

[other]
SHOW_FOOTER_BRANDING = false
SHOW_FOOTER_VERSION = false
SHOW_FOOTER_TEMPLATE_LOAD_TIME = false

现在可以在浏览http://localhost:3000/git/来访问页面了。

Nginx反向代理

对于Nginx反向代理官方也给出了具体配置,还包括Apache和Lighttpd。其中Nginx中很重要的一点就是必须**要最后的反斜框[/]**。

1
2
3
4
5
6
location /git/ {
proxy_pass http://localhost:3000/;
}
location = /git {
proxy_pass http://localhost:3000/;
}

官方文档只提到了上面的一条,后面一条是根据我的实情情况加的。我发现登录的时候,点一次登录好长时间没有反应,过段时间后,返回的地址却是domain.com:4444/git/,很无语,不知道为啥跳到4444端口呢。后来发现登录跳转的路径是domain.com/git,没有最后的一个反斜框,Nginx无法知道怎么代理,这块搞了我快一两个小时,一直没有查出来原因。后来加了下面一条就解决了。

与Host共享22端口的问题

刚开始放狗搜了好久,都没有好的解决方案,有的提到sshd_config里面使用ForceCommand,看着比较靠谱,但好像也不成功。后来发现官方文档推荐一篇不错的文章。看守实操了一遍,大致原理是Host和Container用同一个uid的用户(假定为git),这时候连接到Host的git用户再转到container的10022端口,并运行特定的命令来进行git操作。

新建git用户

1
2
3
4
5
6
7
8
9
$ sudo useradd -s /bin/bash -d /opt/my_gogs -m git
$ id git
uid=1002(git) gid=1002(git) groups=1002(git)
$ su - git
$ cd ~
$ ssh-key -t rsa
$ cd ~/.ssh
$ cat id_rsa.pub >> authorized_keys
$ chmod 600 authorized_keys

这里我新建的git用户的uid和gid是1002,与之前运行gogs container需要对应。同时为了安全起见,将authorized_keys前加一些配置。

1
no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty rsa...

字面意思就很好理解了。因为之前Docker运行Gogs时已经设置-v /opt/my_gogs:/data -e "PUID=1002" -e "PGID=1002", 这样在Host和Container的git用户主目录是同一个,uid和gid也一样,这样Host的git用户直接ssh -p 10022 127.0.0.1是可以直接连接到Container的。

配置git用户登录问题

经过上面一步的设置,在外网就可以直接用git用户的密钥进行登录了,但是因为安全设置,没有tty等。然后就是设置像github那样,用户自己在web端导入自己的公钥,就可以用密钥拉取、推送代码。新建/app/gogs/gogs,脚本如下。

1
2
3
4
5
6
7
mkdir -p /app/gogs/
cat >/app/gogs/gogs <<'END'
#!/bin/sh
ssh -p 10022 -o StrictHostKeyChecking=no git@127.0.0.1 \
"SSH_ORIGINAL_COMMAND=\"$SSH_ORIGINAL_COMMAND\" $0 $@"
END
chmod 755 /app/gogs/gogs

对共享22端口不熟悉的话,可以认真看看这篇文件。SSH真是神器。 :) Happy coding…