本文记录了私网 Go 开发所需的所有相关服务,包括版本管理,模块代理,持续集成。
涉及服务如下:
- Gogs
- goproxy
- Jenkins
系统配置:
- CentOS 7
版本管理
目的
搭建版本管理系统(VCS)的目的:一方面是为私有项目提供版本管理,一方面是托管修改过的开源项目。
选型
私网环境开发,项目源码可以托管于任何版本管理系统,但是 Go 对 Git 的支持更好,优先考虑搭建 Git 服务作为版本管理。
Go 要求版本管理系统实现 go-get
接口。我们选择了 Gogs 。它是由 Go 语言编写的开源 Git 服务,搭建十分便捷 。
部署
详见 官方搭建指南 ,以下仅作记录。
如果使用 MySQL ,要求版本不低于 5.7 。参考这篇 安装 MySQL 8.0
新建数据库
名称: gogs
编码: utf8mb4
数据库中通过以下脚本新建数据库:
CREATE DATABASE gogs CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
下载最新二进制程序包
下载官网提供的二进制文件。
wget https://cdn.gogs.io/0.11.91/gogs_0.11.91_linux_amd64.tar.gz
解压运行
tar xf gogs_0.11.91_linux_amd64.tar.gz
cd gogs
./gogs web
按照提示进行配置
配置前确保 Git 已安装
安装 Git
sudo yum -y install git
浏览器访问当前主机的 3000 端口,开始配置。
有几个配置项需要注意:
-
域名:建议填域名,不然引用地址会很奇怪,即使没有真实域名也可以再客户端上做个 host 映射。例如:
go.private.dev
。 -
HTTP 端口号:可以使用任意未占用的端口号,之后通过 nginx 映射到 80 端口。
-
应用 URL:必须启用 HTTPS,例如:
https://go.private.dev
。之后反向代理配置好 HTTPS 即可。 -
禁止用户注册:建议勾选,之后统一由管理员分配账号。
配置守护进程
修改 ./scripts/systemd/gogs.service
[Unit]
Description=Gogs
After=syslog.target
After=network.target
After=mysqld.service
[Service]
LimitMEMLOCK=infinity
LimitNOFILE=65535
Type=simple
User=root
Group=root
WorkingDirectory=/home/shank/gogs
ExecStart=/home/shank/gogs/gogs web
Restart=always
Environment=USER=shank HOME=/home/shank
ProtectSystem=full
PrivateDevices=yes
PrivateTmp=yes
NoNewPrivileges=true
[Install]
WantedBy=multi-user.target
注意修改为实际的用户目录
复制到系统目录
sudo cp ./scripts/systemd/gogs.service /usr/lib/systemd/system/
启用守护进程
sudo systemctl enable gogs
sudo systemctl start gogs
模块代理
目的
Go 1.11 之后推荐使用 go mod
作为依赖管理,使用 go mod
可以通过配置模块代理服务加快依赖包的下载。这类代理服务通过环境变量 GOPROXY
进行指定,只要实现了模块代理协议(Module proxy protocol)的服务都称为模块代理服务。
因为公有网络的不确定性(比如开源作者删除了代码仓库或者网络被防火墙劫持),可以考虑自己维护一个代理服务,方便私网内构建时拉取常用第三方代码依赖。
选型
目前有许多开源项目实现了 goproxy 服务,我们选择了社区活跃且版本稳定的 goproxyio/goproxy。
源码构建及部署
Go 版本不低于 1.11
配置 Go 1.13.3 编译环境
wget https://dl.google.com/go/go1.13.3.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.13.3.linux-amd64.tar.gz
echo 'export PATH=$PATH:/usr/local/go/bin' >> $HOME/.profile
source $HOME/.profile
安装 make
sudo yum -y install make
下载一份稳定版版本的源码
wget https://github.com/goproxyio/goproxy/archive/v2.0.1.tar.gz
v2.0.0 版本有 BUG 。 我遇到如下问题
go get golang.org/x/tools/cmd/present: no matching versions for query "upgrade"
。 故此处已更新。
解压 & 编译
tar xf v2.0.1.tar.gz
cd goproxy-2.0.1
make
如果你使用的是 go 1.13 以下版本, make 可能因网络问题耗时严重,你需要设置环境变量 GOPROXY 加速构建,例如:
export GOPROXY=https://goproxy.io
。因为 go 1.13 指定了默认的 GOPROXY 可以不需要另外配置。
添加二进制文件到系统目录
sudo cp ./bin/goproxy /usr/local/bin
配置守护进程
修改 ./scripts/goproxy.service
[Unit]
Description=goproxy service
Documentation=https://goproxy.io
After=network-online.target
[Service]
User=root
Group=root
LimitNOFILE=65536
Environment=PATH=/usr/bin:/usr/local/go/bin
Environmnet=GO111MODULE=on
ExecStart=/usr/local/bin/goproxy -listen=0.0.0.0:8081 -proxy=https://goproxy.io -exclude=go.private.dev
KillMode=control-group
SuccessExitStatus=2
Restart=always
[Install]
WantedBy=multi-user.target
Alias=goproxy.service
参数说明
-listen
:服务监听地址。-proxy
:上游代理模块,不配置则直接请求目的地址。-exclude
:不走代理的域名,私网域名公网无法访问应直接请求。
复制到系统目录
sudo cp ./scripts/goproxy.service /usr/lib/systemd/system/
启用守护进程
sudo systemctl enable goproxy
sudo systemctl start goproxy
持续集成(可选)
目的
开发者将代码提交到版本管理系统,之后的编译构建,自动化测试,打包,发布,部署等都是固定流程,应该由持续集成系统去完成。
使用持续集成,可以降低重复繁琐操作的出错率。
选型
有许多在线的持续集成服务,由于我们是私网部署,我们选择了 Jenkins ,它是由 Java 语言编写的开源 CI&CD 服务,搭建十分便捷 。
部署
详见 官方搭建指南 ,以下仅作记录。
安装 Java 1.8 运行环境
sudo yum -y install java-1.8.0-openjdk-devel
启用 Jenkins 存储库
curl --silent --location http://pkg.jenkins-ci.org/redhat-stable/jenkins.repo | sudo tee /etc/yum.repos.d/jenkins.repo
sudo rpm --import https://jenkins-ci.org/redhat/jenkins-ci.org.key
安装 Jenkins
sudo yum -y install jenkins
启用守护程序
sudo systemctl start jenkins
sudo systemctl enable jenkins
按照提示进行配置
浏览器访问当前主机的 8080 端口,开始配置。
安装建议的插件,按需求以后添加插件。
反向代理
这里我们选用使用最广泛的 NGINX 作为反向代理服务。
鉴于篇幅,仅介绍对于 Gogs 的反向代理。
安装 NGINX
sudo yum install -y nginx
HTTPS 证书
获取证书的途径有很多,可以购买商业证书,或者申请免费证书,私网环境为了简单,我就选择自签证书。
使用 openssl 自签证书可以 参考这篇
也可以用 Gogs 可执行程序提供的子命令:
./gogs cert -ca=true -duration=8760h0m0s -host=go.private.dev
会在执行目录下得到两个文件: cert.pem
和 key.pem
。
Gogs 配置
找到 Gogs 的配置文件 gogs/custom/conf/app.ini
,确保 ROOT_URL
为 https 协议,比如: https://go.private.dev
。其他的配置都不用改。
NGINX 配置
先把 /etc/nginx/nginx.conf
中的默认 server
配置删除,你也可以把它注释掉,如下所示:
#server {
# listen 80 default_server;
# listen [::]:80 default_server;
# server_name _;
# root /usr/share/nginx/html;
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
# location / {
# }
# error_page 404 /404.html;
# location = /40x.html {
# }
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
#}
新建配置文件 /etc/nginx/conf.d/default.conf
,填入如下内容:
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name go.private.dev;
ssl_certificate "/home/shank/gogs/keys/cert.pem";
ssl_certificate_key "/home/shank/gogs/keys/key.pem";
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://127.0.0.1:3000$request_uri;
}
}
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name go.private.dev;
return 301 https://$host$request_uri;
}
验证配置
nginx -t
启用守护程序
sudo systemctl start nginx
sudo systemctl enable nginx
可能遇到的问题
- 无法外部访问服务:检查 CentOS 的防火墙策略,放行特定端口。安全性要求不高甚至可以关闭防火墙。
- 私网仓库通过模块代理 go get 失败:
...exec: "git": executable file not found in $PATH...
: 确保git
已安装。... reading https://sum.golang.org/lookup/... 410 Gone
: 本地添加环境变量GOSUMDB=off
- NGINX 启动失败:
...SSL: error:0200100D:system library:fopen:Permission denied...
: 对证书文件无访问权限,这是 SELinux 的强制模式导致的。解决办法就是restorecon -v -R /path/to/keys
。...[emerg] bind() to 0.0.0.0:XXXX failed...
: 也可能表现为 NGINX 反代的端口返回 502 错误,这也是 SELinux 的坑。使用 semanage 添加 HTTP 端口即可,详见参考资料。
- 各种 ssl 验证出错的问题: 使用自签证书,要在所有客户端的系统上都信任自签的证书。