配置 Gitlab Pages Access Control 功能的坑

背景

CWOI Blog 这个概念被提出后,我就想到了通过 Gitlab 来进行协作编辑(因为之前开MC服也是通过这个来收集建议的),后面发现真的是非常适合:

  • 审核文章:Developer 只能推送到其他分支,Maintainer 以上级别可以合并PR,通过PR来完成文章审核。
  • Gitlab CI:直接编译静态博客
  • Gitlab Pages:直接用来托管静态博客
  • Review Apps:在PR界面就可以创建一个预览环境
  • 群组功能:外部人员无法看到文档源码

Pages Access Control 配置

那么如何避免外部人员看到Pages上部署的博客呢?一开始根本没想到官方会提供这一功能,都打算反代的时候加个 Basic Auth,或者后面写一个 OAuth 鉴权的“中间件”了。但是后面发现了 Pages Access Control

这是个什么玩意儿呢?启用这个功能后,可以选择只允许项目成员访问Pages(原理大概就是上面的第二种思路,通过OAuth授权后调用API判断用户是否属于这个项目)。

由于网络原因,各种Pages几乎不可直接访问,而其中可以正常访问的Gitee Pages又不支持此功能,因此只好选择自托管。

坑们来啦。

第一个坑

其实在选择在机房搭一个之前,已经在自己服务器上试过了,但总是提示50x。

查看日志,发现:

level=debug msg=“Fetching access token failed” error=“Post https://git.example.com/oauth/token: dial tcp: lookup git.example.com on [::1]:53: dial udp [::1]:53: connect: cannot assign requested address” host=project.pages.example.com path="/auth?code=[MASKED]"

Google一下发现了这个Issue(Created 2 years ago, still open。。。)

所以是开了 inplace_chroot 才导致的,而我又是采用Docker安装的,按照官方说明,我必须要开启这个flag。这时才注意到下方的小字:

inplace_chroot option might not work with the other features, such as Pages Access Control. The GitLab Pages README has more information about caveats and workarounds.

好了,所以说用 Docker 方式启用这个特性是很难成功的。那么我选择 Omnibus Packages 这个安装方式。

第二个坑

基本配置已经配置完了,而我习惯在服务前套一层 Caddy 来负责反向代理+TLS+各种特性(HTTP/3,HTTP/2…),当时并没有想到官方会有文档告诉我需要对此在Gitlab上额外配置一些东西,因此直接尝试修改external_url为https://开头的,但gitlab-ctl reconfigure后直接无法访问。查看日志发现nginx服务缺少证书(但Caddy是跑在另一台机器上的,通过加密的frp进行穿透,难以将自动获取的证书传回),因此将其改为了http://开头的。Gitlab网页中链接基本都是相对位置,因此也不会出现降级的问题。

殊不知,这把我带入了第三个坑。

第三个坑

启动了 Pages Access Control 特性。一开始由于没有拿到用于内网穿透的服务器及域名权限,因此使用本地ip + http进行测试,结果非常顺畅。

但一旦穿透出去,上了https,就在认证后提示404了,十分迷惑。在后台日志也只是记录了状态码404,即使开启了 Pages 的 Verbose log,也没有更有价值的日志出现。这次,搜遍了Google,也只看到了官方Gitlab Pages的其中一次服务瘫痪,并没有关于 self hosted 的任何信息。

直到我猜测,会不会是https的问题。我将https关闭,果然正常了,打开Pages域名的https,也是正常的。但一旦打开了Gitlab本体域名的https,直接404。

试来试去,最终发现了,当将pages['gitlab_server']选项配置成带https的Gitlab地址时,能正常带https使用。

事后想想,发现可能是由于直接按照其默认的external_url 即使用http的Gitlab地址 去请求api,会收到来自Caddy的308回应,让浏览器切换到https。但假如利用curl这类东西去请求,则不会跟随跳转,而是直接返回,直接挂掉。

总结

要想用 Pages Access Control,你不能使用 Docker。(不知道 Kubernetes 方式能否成功)

要想用 外部 TLS 卸载,你必须按照官网的方法去配,否则容易遇到奇奇怪怪的问题。

自动跳转https有些时候会让你难以分析问题原因。