为基于Docker的Gitlab服务器配置Let’s Encrypt颁发的SSL证书

继之前跨服务器迁移基于Docker的Gitlab之后,这两天又配置了该Gitlab服务器的HTTPS协议,以增加安全性。SSL证书方面,为了一劳永逸,选择Let’s Encrypt解决方案,用CertBot作为ACME的客户端。

服务器是CentOS 7.2 运行着17.03.1版本的Docker,Gitlab容器(基于OMNIBUS的镜像)是9.1.1版本。

文件存储的映射方面,Gitlab的配置及数据,均被映射到了宿主机的/srv/gitlab/文件夹。

首先是要修改Gitlab的external_url,将http://gitlab.example.com 改为 https://gitlab.example.com。具体既可以修改gitlab的配置文件gitlab.rb,也可以删除容器以后,用新的external_url作为命令参数,创建新的容器,此处不详述。

重新运行gitlab以后,暂时是访问不到的,因为需要放置SSL证书。证书位置默认在容器内的/etc/gitlab/ssl/目录,对应的宿主服务器上的地址就是/srv/gitlab/config/ssl/目录。如果这时候放置有效的gitlab.example.com.crt和gitlab.example.com.key文件。就会发现https站点可以访问了。为了访问方便,本机gitlab容器的端口映射之前已经配置成了http是80,https是443。这时候也注意到一件事情:如果访问http站点,会自动307重定向到https站点。

下面配置Letsencrypt证书,这里需要做三件事:

1,安装certbot,配置服务器以便获取证书;
2,安装证书到gitlab容器;
3,自动续期证书以及自动安装证书;

第一件事,参照官方文档安装并配置certbot。按官方推荐,选择webroot插件的方式。这里的要点是,需要在http://gitlab.example.com站点下创建特定的文件夹,以便certbot放置随机生成的文件,来验证你的网站控制权。

这时候,需要先修改gitlab容器的端口映射配置,让出80端口,然后在宿主机上配置nginx服务器(当然也可以是apache或者其他),配置http:/gitlab.example.com站点,并放置用来验证网站控制权的/.well-known目录。当然,考虑到gitab站点的真正内容应该基于https访问,因此可以对http站点的其他内容设置301重定向。

本机的nginx里面该站点的配置如下供参考:

server {
    listen      80;
    server_name gitlab.example.com;

    location ^~ /.well-known/acme-challenge/ {
        default_type "text/plain";
        root    /usr/share/nginx/html;
    }

    location = /.well-known/acme-challenge/ {
        return 404;
    }

    location / {
         return 301 https://gitlab.example.com;
    }
}

第二件事,将/etc/letsencrypt/live/gitlab.example.com 文件夹下的fullchain.pem 和 privkey.pem复制到/srv/gitlab/config/ssl/文件夹下且分别命名为gitlab.example.com.crt 和gitlab.example.com.key;

第三件事,如果需要certbot自动续期ssl,只要在cron里面设置自动执行如下语句:

05 12 * * * certbot renew
10 12 * * * cp -u /etc/letsencrypt/live/gitlab.example.com/fullchain.pem /srv/gitlab/config/ssl/gitlab.example.com.crt
11 12 * * * cp -u /etc/letsencrypt/live/gitlab.example.com/privkey.pem /srv/gitlab/config/ssl/gitlab.example.com.key

这里要注意,certbot生成的文件有三个,经过我测试,拷贝证书文件的时候,如果是将cert.pem拷贝成gitlab.example.com.crt,虽然从浏览器访问该https://gitlab站点没问题,但git 做clone、checkout等操作的时候,却会报错:

SSL certificate problem: unable to get local issuer certificate

经测试,用fullchain.pem文件就可以。
当时碰到这个问题的时候,花了点时间,网上的解决办法多半是关掉Git的SSL校验功能,属于不求甚解。现在看来,这种某个特定网站的SSL报错,且证书发行者又是比较常见的发行者的情况,多半是证书文件有问题。

网站实现HTTPS协议

HTTPS协议的作用和好处就不多说了。

整个过程的步骤,一是要找到一个证书。

二是安装证书,尤其对于一台服务器部署多个虚拟站点的情况。

证书方面,虽然自己也可以制作,但用户访问的时候,会提示需要用户接受该证书,这个很不友好。换成浏览器能接受的CA发行的证书就没有这个问题了。收费的不用说,贵的便宜的都有,一般的主机托管服务商都会有。免费的找到几家公认可以用的,一家是国内的wosign,一家是国外的startcom,应该都好用,免费ssl主要是针对域名进行验证的,申请过程中需要证明对域名的拥有权,可以通过在网站根目录上传特定文件,或者添加特定二级域名来验证。过程中还发现赛门铁克也注册了一个叫freessl.com的网站,里面显示即将推出免费ssl,咱们拭目以待吧。

安装证书一般都有教程,本人是阿里云的ECS服务器,centos6.7 + apache,找到对应教程即可。值得注意的是,阿里云版本的ssl配置文件位置和独立安装的centos的ssl配置文件的位置稍有不一样。

可以参考:https://freessl.wosign.com/aliyun-ssl.html

由于多数免费ssl会有对应的域名限制(譬如wosign上面最多允许一个证书对应5个域名),所以当单台服务器上有超过五个站点都需要启动https的时候,需要再申请另外的ssl。这时候,需要注意ssl配置文件里面的虚拟主机的设置。要考虑用不同的端口来对应不同的证书。