GitLab + Container Registry 安装及反向代理配置
本文介绍了我在局域网内 ubuntu 虚拟机上安装 GitLab ,并配置外网 https+ssh 访问的过程。主要使用公网机器的 nginx 配置 letsencrypt 的 ssl 证书,并且反向代理到 frp 的 http 端口;通过 frp 进行内网穿透,反向代理到内网虚拟机上运行的 GitLab。同样的方式启用了 GitLab 自带的 Container Registry。
思路
因为 GitLab 内存占用非常高,官方推荐内存 4G 缓存 4G 起步,我的个人实验小鸡内存小跑不起来,一直报 502 错误,所以我只好安装到家里的个人机器上,利用 frp 做内网穿透;通过公网主机的 nginx 处理 https 协议,同时将请求反向代理到 frp。安装过程比较麻烦,不过最后的效果不错,速度很理想。
GitLab 安装
CE or EE?
CE(Community Edition)是社区版,开源,MIT授权, EE(Enterprise Edition)是企业版。EE 版核心和 CE 版一样,另外包含一些收费的功能,没提供授权的话,可以和 CE 版一样运行。
后续可以从 CE 版升级到 EE 版。版本说明见:Community Edition or Enterprise Edition
我选择了 CE 版,给钱是不可能给钱的。
准备
- 一外网主机,运行 frps、nginx
- 一本地虚拟机, ubuntu 18.04 系统,内存4G(另配置了 4G 交换分区(swap))、虚拟磁盘 20G 固态,运行 frpc
安装
采用软件包的方式安装,照着官方文档就可以了: Omnibus package installation。
默认是 EE 版的安装说明,CE 版需要在链接上加上 ?version=ce
。CE 版主要安装步骤如下:
sudo apt-get install -y curl openssh-server ca-certificates
sudo apt-get install -y postfix # 用来发邮件,由于采用 smtp 发信,这步跳过
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
sudo EXTERNAL_URL="http://gitlab.example.com" apt-get install gitlab-ce
其中 EXTERNAL_URL
是外部访问地址,配置成自己的 GitLab 外网地址,安装完成后先测试下能否正常运行,后续会改成 https
的。可以改本地电脑的 hosts ,将 EXTERNAL_URL
里的域名临时解析到虚拟机的 ip 地址,然后在浏览器里访问 EXTERNAL_URL
,进去后按照提示设置 root
账号的密码。
https 配置 + 反向代理接力 + 内网穿透
为方便测试,可以将本地电脑的 hosts 先改回来,将 GitLab 所用的域名解析到外网主机 ip。
外网主机准备
-
安装 nginx、certbot(用于获取 lentsencrypt 证书)
sudo apt-get update sudo apt-get install nginx sudo apt-get install software-properties-common sudo add-apt-repository ppa:certbot/certbot sudo apt-get update sudo apt-get install python-certbot-nginx
-
获取 letsencrypt ssl 证书。运行
sudo certbot certonly
,按提示操作即可,生成的证书保存在/etc/letsencrypt/live/
对应的域名目录下。 -
frp 安装。外网主机需要运行 frp 服务端(frps),方法不赘述。
-
nginx 配置。直接上配置:
/etc/nginx/conf.d/frp.conf
:## frp upstream frp { server localhost:8080 fail_timeout=0; }
/etc/nginx/sites-enabled/gitlab.conf
:## http server { listen 80; server_name gitlab.example.com; return 301 https://$server_name$request_uri; } ## https server { listen 443 ssl; server_name gitlab.example.com; server_tokens off; root /dev/null; ## Increase this if you want to upload larger attachments client_max_body_size 20m; ## SSL ssl on; ssl_certificate /etc/letsencrypt/live/gitlab.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/gitlab.example.com/privkey.pem; ## Individual nginx logs for this vhost error_log /var/log/nginx/gitlab_ssl_error.log; location / { ## If you use https make sure you disable gzip compression ## to be safe against BREACH attack. gzip off; proxy_read_timeout 300; proxy_connect_timeout 300; proxy_redirect off; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Frame-Options SAMEORIGIN; proxy_pass http://frp; } }
其中 8080
是 frps 配置里的 vhost_http_port
,http 请求通过 301 跳转到 https,https 请求用 nginx 反向代理到 frp,此时防卫 GitLab https 地址会出现 frp 的错误提示:
GitLab 虚拟机改动
-
GitLab 配置修改。参考 Supporting proxied SSL ,修改虚拟机里的
/etc/gitlab/gitlab.rb
,有 3 处改动:## GitLab URL ##! URL on which GitLab will be reachable. ##! For more details on configuring external_url see: ##! https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-the-external-url-for-gitlab external_url 'https://gitlab.example.com' ... ##! **Override only if you use a reverse proxy** ##! Docs: https://docs.gitlab.com/omnibus/settings/nginx.html#setting-the-nginx-listen-port nginx['listen_port'] = 80 ##! **Override only if your reverse proxy internally communicates over HTTP** ##! Docs: https://docs.gitlab.com/omnibus/settings/nginx.html#supporting-proxied-ssl nginx['listen_https'] = false
external_url
改为https
,nginx['listen_port']
改为80
,nginx['listen_https']
改为false
,更新配置重新启动 GitLab:sudo gitlab-ctl reconfigure sudo gitlab-ctl restart
此时的 GitLab 暂时无法访问到,需要通过反向代理。
-
frpc 配置。虚拟机的
frpc.ini
添加 gitlab 配置段:... [gitlab] type = http local_port = 80 custom_domains = gitlab.example.com ...
此时 nginx -> frps/frpc -> GitLab 的通道就完全打通了,可以通过 https 地址访问到 GitLab。
ssh 穿透
为了简化操作,并且保持 GitLab 使用 ssh 协议操作代码库时地址的简洁,GitLab 虚拟机的 ssh 端口保持默认的 22
不变,外网主机的 ssh 端口换成别的(通过修改 /etc/ssh/sshd_config
内的 Port
字段),再通过 frp 将外网的 ssh 请求转到内网。虚拟机的 frpc 配置增加 ssh 部分:
[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 22
这样 ssh gitlab.example.com
时访问的即是 GitLab 虚拟机,访问外网主机时需要加端口号。
启用 Container Registry
项目的一些发布操作可能会用到 Container Registry,需要启用 GitLab 自带的 Container Registry 。Registry 的设置方法与前面设置 GitLab 时类似,也是 nginx->frp->gitlab 一路反向代理过来。
再次生成 https 证书
再次运行sudo certbot certonly
,这次使用 registry 的域名。
配置修改
-
虚拟机
/etc/gitlab/gitlab.rb
:... ################################################################################ ## Container Registry settings ##! Docs: https://docs.gitlab.com/ce/administration/container_registry.html ################################################################################ registry_external_url 'https://registry.example.com' ... ################################################################################ ## Registry NGINX ################################################################################ # All the settings defined in the "GitLab NGINX" section are also available in this "Registry NGINX" section # You just have to change the key "nginx['some_settings']" with "registry_nginx['some_settings']" # Below you can find settings that are exclusive to "Registry NGINX" registry_nginx['enable'] = true registry_nginx['listen_port'] = 5001 registry_nginx['listen_https'] = false registry_nginx['proxy_set_headers'] = { "Host" => "$http_host", "X-Real-IP" => "$remote_addr", "X-Forwarded-For" => "$proxy_add_x_forwarded_for", "X-Forwarded-Proto" => "https", "X-Forwarded-Ssl" => "on" } ...
registry_external_url
一步到位设置成 https 地址,registry_nginx['enable']
设置为 true
,增加 registry_nginx['listen_port']
设置为 5001
(设置为 5000 时访问出错),增加 registry_nginx['listen_https']
设置为 false
,取消注释 registry_nginx['proxy_set_headers']
。
-
虚拟机
frpc.ini
,增加 registry 部分:... [gitlab_registry] type = http local_port = 5001 custom_domains = registry.example.com ...
-
外网主机 nginx 添加 registry 配置
/etc/nginx/sites-enabled/gitlab_registry.conf
:server { listen 80; server_name registry.example.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl; server_name registry.example.com; server_tokens off; root /dev/null; ## Increase this if you want to upload larger attachments client_max_body_size 20m; ## SSL ssl on; ssl_certificate /etc/letsencrypt/live/registry.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/registry.example.com/privkey.pem; ## Individual nginx logs for this vhost error_log /var/log/nginx/gitlab_registry_ssl_error.log; location / { ## If you use https make sure you disable gzip compression ## to be safe against BREACH attack. gzip off; proxy_read_timeout 300; proxy_connect_timeout 300; proxy_redirect off; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Frame-Options SAMEORIGIN; proxy_pass http://frp; } }
注意此处的 proxy_pass
复用了上面 GitLab 使用的 frp 反向代理地址,因为 custom_domains
不同,frp 可以正确处理 2 个不同域名的请求。
访问 registry
浏览器直接访问 https://registry.example.com/v2
,会出现 {"errors":[{"code":"UNAUTHORIZED","message":"authentication required","detail":null}]}
,表明 registry 启用成功了,此时查看 GitLab 里的项目,会看到有 Registry
标签页:
sudo docker login registry.example.com
尝试用户名密码登陆,因为虚拟机的 registry 是通过 http 访问的,不支持 http basic auth,会出现:Error response from daemon: Get https://registry.codegeass.cc/v2/: unauthorized: HTTP Basic: Access denied
。
参考GitLab Container Registry#using-with-private-projects,我们用 Token 的方式,docker login registry.example.com -u <your_username> -p <your_access_token>
:
➜ ~ sudo docker login registry.example.com
Username: qqjt
Password:
WARNING! Your password will be stored unencrypted in /home/tt/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
密码换成了 Personal Access Token 就可以成功登陆,Personal Access Token可以在 GitLab 个人设置(/profile/personal_access_tokens
)的 Access Tokens
处生成。
至此配置就完成了。
GitLab 常用命令
gitlab-ctl start|stop|restart|status # 控制服务启动/停止
gitlab-ctl tail # 查看实时日志
gitlab-ctl reconfigure # 更新配置
问题与解决
- docker push 命令出现
413 Request Entity Too Large
的问题,可以调大前文中 nginx 配置里的client_max_body_size
参数。
后续思考
frp 同时支持 https 协议的代理,不知道能否利用一下。