为基于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报错,且证书发行者又是比较常见的发行者的情况,多半是证书文件有问题。

 

用CentOS 7和Docker搭建Gitlab环境

先安装好CentOS 7 操作系统

操作之前,先开启ssh,以方便后续操作:
service sshd start
chkconfig sshd on

第一步,系统升级到最新:
yum -y update

第二步,安装docker:
老版本是:yum -y install docker

从Docker官方镜像安装新版本:
https://docs.docker.com/engine/installation/linux/centos/

然后注册自动启动并立即启动:
chkconfig docker on
service docker start

第三步,由于众所周知的原因(Fork the G.F.W.),国内访问Docker Hub常常很慢甚至访问不了,因此可以改用阿里云的Docker Registry(根据服务器选择合适的加速器,阿里云、腾讯都有):

# 系统要求 CentOS 7 以上,Docker 1.9 以上。

sudo cp -n /lib/systemd/system/docker.service /etc/systemd/system/docker.service sudo sed -i “s|ExecStart=/usr/bin/docker daemon|ExecStart=/usr/bin/docker daemon –registry-mirror=https://XXXXX.mirror.aliyuncs.com|g” /etc/systemd/system/docker.service sudo systemctl daemon-reload sudo service docker restart

其中的https://XXXXX.mirror.aliyuncs.com 即是阿里云Docker镜像访问加速器地址。需要自己去申请一下,免费的,路径:管理控制台-容器服务-指南-镜像管理-加速器。

第四步,运行Gitlab-ce Docker镜像:

docker run –detach \
–hostname gitlab.iconben.com \
–publish 443:443 –publish 80:80 –publish 22:22 \
–name gitlab \
–restart always \
–volume /srv/gitlab/config:/etc/gitlab \
–volume /srv/gitlab/logs:/var/log/gitlab \
–volume /srv/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce:latest

以上是用指定参数来运行官方的gitlab(社区版本)的容器。要注意的是,可能在CentOS上默认SELinux是开启的,如果是这样的话,以上命令运行会权限不足,容器运行不成功,此时应该运行如下命令:

docker run --detach \
    --hostname gitlab.iconben.com \
    --publish 443:443 --publish 80:80 --publish 22:22 \
    --name gitlab \
    --restart always \
    --volume /srv/gitlab/config:/etc/gitlab:Z \
    --volume /srv/gitlab/logs:/var/log/gitlab:Z \
    --volume /srv/gitlab/data:/var/opt/gitlab:Z \
    gitlab/gitlab-ce:latest

以上的端口映射,如果本机80端口已经被Apache或者Nginx占用,则需要改到另外端口。22端口也是,可能与sshd冲突,一样可以修改。修改方式有三种:

1,Container生成之前,也就是在执行以上命令行之前,修改命令行参数,如:

docker run –detach \
–hostname gitlab.iconben.com \
–publish 443:443 –publish 880:80 –publish 822:22 \
–name gitlab \
–restart always \
–volume /srv/gitlab/config:/etc/gitlab \
–volume /srv/gitlab/logs:/var/log/gitlab \
–volume /srv/gitlab/data:/var/opt/gitlab \
gitlab/gitlab-ce:latest

2,如果Container已经生成,这时候可以 docker rm gitlab删除该容器,然后用改过端口的命令行重新生成;

3,如果不想删除重建Container,可以停止docker,然后修改Container的配置文件:

docker stop container
service docker stop
vi /var/lib/docker/%container_id%/hostconfig.yml

在这个文件里面可以修改端口映射,改完再启动。
**注意:一定要停用整个service,改完配置文件,再启动service才生效。否则service还开着的时候,配置修改了也不会生效,还会被自动改回去。

第五步,配置与使用Gitlab

以上步骤操作得当的话,这时候浏览器里面输入网址,就应该已经能访问到gitlab了。初始会要求设置新密码。然后就可以做各种新建用户、新建项目、设置权限等操作了。

有些配置如external url要修改的话,需要改gitlab的配置文件。这时候可以停用gitlab,然后修改,方式有两种:

1,由于存储是加载的外部卷,可以根据之前启动Docker的时候指定的存储卷位置,直接在Host中修改对应文件,如前面例子中的参数:–volume /srv/gitlab/config:/etc/gitlab \,说明在docker内的/etc/gitlab文件夹,在宿主机上实际是放在/srv/gitlab/config位置的。

2,就是通过 docker exec gitlab /usr/bin/bash 来进入docker命令行操作,譬如 vi /etc/gitlab/gitlab.rb来修改gitlab配置文件。

3,追加还有一种方式,就是删除容器(不删除配置和数据),然后用新的参数重新运行创建容器的命令,因为OMNIBUS 的Gitlab容器镜像支持通过命令行直接传递配置进去,这些配置会存储在Docker的容器配置里面,并且会在启动容器后自动覆盖容器内文件系统中所保存的Gitlab配置,具体可以参见OMNIBUS关于Gitlab镜像使用说明的官方文档。

 

CentOS+Apache环境下安装gitlab

环境:CentOS 6.8,  Apache 2.22.15

先根据官方教程,安装omnibus版本的安装包。官方源速度太慢,镜像选择了清华tuna。安装过程一路顺利。

关键是配置,gitlab默认内嵌nginx服务器,如果要使用Apache的话,需要禁用掉先,否则开机会报80端口冲突(话说这两天服务器被我重启了三四次。。。,之前170天左右稳定运行没动过)。

设置workhouse tcp连接,本机 127.0.0.1 端口8181

具体参考:

http://docs.gitlab.com/omnibus/settings/nginx.html#using-a-non-bundled-web-server

https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/settings/nginx.md#using-a-non-bundled-web-server

看文档,SELinux环境下需要做一些配置,本次安装因为本机SELinux已经禁用,因此没有遇到。

参考:https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache#selinux-modifications

根据使用的gitlab版本及本机apache版本,选择一个合适的配置文件,本机参考了:

https://gitlab.com/gitlab-org/gitlab-recipes/blob/master/web-server/apache/gitlab-omnibus-apache22.conf

启动服务器,报503错误,查httpd的日志,发现Apache没有与127.0.0.1:8181连上。

 

 

如果要配置HTTPS访问,则配置文件参考:

https://gitlab.com/gitlab-org/gitlab-recipes/blob/8-1-stable/web-server/apache/gitlab-omnibus-ssl-apache22.conf

配置编辑完成后重启httpd,结果报错:

Invalid command ‘SSLCompression’, perhaps misspelled or defined by a module not included in the server

查了一下,是因为Apache版本太低(2.22.15)的原因,起码需要2.22.24。针对低版本的临时解决方案如下:

修改 /etc/sysconfig/httpd文件,添加如下语句:

export OPENSSL_NO_DEFAULT_ZLIB=1

参考:https://gitlab.com/gitlab-org/gitlab-recipes/tree/master/web-server/apache#other-httpd-security-considerations

然后重启结果还是不行。—暂时没解决,谋求升级系统。

参考:

http://serverfault.com/questions/455450/how-to-disable-sslcompression-on-apache-httpd-2-2-15-defense-against-crime-bea

http://serverfault.com/questions/508520/how-to-disable-ssl-tls-compression-in-apache-2-2-16