CentOS 6.8服务器给Apache下的站点配置Let’s Encrypt 证书

我们有几个站点,之前用的wosign的免费SSL证书,最近在Chrome中查看站点,都提示是不安全的站点,应该是wosign的不佳的国际声誉连累的。
于是决定换成Let’s Encrypt证书。方法不难,参看:官方文档

有几个注意点:

如果用自动化的配置certbot-auto的话,它会自动找 /etc/httpd/conf.d 文件夹下面的站点配置文件,但只对配置文件里面仅配置了一个80端口的情况有效,如果您的一个配置文件里面配置了多个80端口的站点,则不能自动识别。另外,如果已经自行配置了ssl站点(443端口的virtualhost)的话,也不会再自动识别为需要配置的站点。

我自动化配置了两个站点,先将原来的的配置文件里面的ssl配置(443端口的virtualhost)注释掉了。然后用certbot-auto,选择了识别出来的这两个站点,然后一切自动运行,提示证书生成,且生成了新的配置文件,文件名 www.example.com-le-ssl.conf。

这时候访问网站,是一片空白,服务器端没有输出任何东西。事实证明,自动生成的这个https站点的配置还是有一些问题的:

1,没有指定DocumentRoot;

2,整个配置文件用了<IfModule mod_ssl.c></IfModule>,但其实本机的环境里面没有包含这样的文件,而mod_ssl确实是启用的,在/etc/httpd/modules/文件夹下可以看到有mod_ssl.so。因此果断注释掉了IfModule的语句(本以为也可改为IfModule nod_ssl.so,但发现不起作用),再次打开,网站成功显示,且证书确实已更新为letsencrypt证书。

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

跨服务器迁移基于Docker的Gitlab

这两天将gitlab从内网迁移到了外网,以便更好的与外部合作伙伴及客户进行协作。

两台服务器都是 CentOS 7.2,Docker上运行的OMNIBUS版本的gitlab容器。迁移的步骤在网上有不少人记录,有的直接拷贝数据文件和配置文件的,有的是通过gitlab的备份命令来将数据备份,再用恢复命令的。由于这个容器版本的数据与配置都在/srv/gitlab文件夹下面,我就采取了第一种方式,步骤大约是这样的:

1,新服务器上安装Docker环境,配置一切,gitlab跑起来,只不过是一个新的站点而已,如何安装可以参考我这篇文章

2,关停旧服务器,然后将配置与数据文件拷贝到新服务器;

3,新服务器关停原容器,将拷贝过来的服务器配置到容器的数据与配置文件夹中去,然后开起来;

4,以上每一步都做到的话,其实就可以了。

但是实际上还是有点曲折,容易遇到坑,迁移的几个要点记录如下:

1,尽量保证新老服务器上的Docker版本一致,这是出于保险起见。不过本人操作过程中其实有不一致的情况,差了前后一个版本(新服务器的高一个版本,正好是操作的这两天出来的,当时没注意到。),没出问题,毕竟gitlab 容器本来就支持通过拉取latest的镜像来构建新版本gitlab,新版本第一次启动的时候会自动对数据进行migration。

2,新服务器上搭建环境的时候,注意看swap分区是否有创建,没有的话,需要创建,参见我这篇文章

3,从旧服务器拷贝文件到新服务器,要注意文件的权限,尤其是owner会变化,导致新服务器跑不起来。原因是gitlab那些数据文件实际上是容器内的postgreSQL、redis等多个组件各自读写的,具有不同的owner。但通过SFTP或者SCP等方式传到新服务器后,owner变成了操作传输动作的账号。这是一个挺大的坑,很多地方都没有明确提到这一点,也没有特别说明如何解决,后来在官方文档里面某一页的末尾处看到提到了一句,笼统的说遇到文件权限问题时候可以运行如下命令:

sudo docker exec gitlab update-permissions
sudo docker restart gitlab

确实执行之后,问题就解决了。

顺便说一下,当时遇到这个文件权限问题的时候,症状是gitlab容器不停的重启,也没法命令行连进去执行命令。通过查看gitlab日志文件夹,发现reconfigure和sshd两个文件夹有日志产出。其中reconfigure文件夹里面的日志,有提到文件操作权限出错的问题。可惜具体报错信息没有记录下来。

升级PHP7.1后微信支付SDK遇到的一个bug

把PHP版本从5.3.3升级到7.1之后(操作系统版本CentOS 6.8, Apache 2.4),Web应用出现微信支付不能确认的问题。

查看日志,发现微信支付回调程序报错:

undefined index : HTTP_RAW_POST_DATA

网上搜索了一下,知道了答案。在我们所引用的微信商户API的支付SDK(v3版本,下载下来的文件名为WxpayAPI_php_v3.zip)中,WxPay.Api.php 的notify方法中有如下赋值调用:

//获取通知的数据
//$xml = $GLOBALS[‘HTTP_RAW_POST_DATA’];

因为这种取值方式在php5.6之后有可能取不到值(在php7之后的版本中已经弃用),故改为下句:
$xml = isset($GLOBALS[‘HTTP_RAW_POST_DATA’]) ? $GLOBALS[‘HTTP_RAW_POST_DATA’] : file_get_contents(“php://input”);

问题得到有效解决。参考如下链接:

https://secure.php.net/manual/zh/reserved.variables.httprawpostdata.php

http://stackoverflow.com/questions/9553168/undefined-variable-http-raw-post-data

同时,网上也有文章指出该SDK的其它一些错误,可参考:

http://www.cnblogs.com/xxoome/p/5705583.html

安装测试osTicket

从github 上clone 了osTicket v1.10 ,在本地Windows 10环境下安装。是Nginx + php-cgi的开发环境。

配置好php站点后在浏览器中打开。结果第一步安装就报错:

core: Unknown or invalid schema signature xxxxxxxx……….

根据网上文章(参考:https://github.com/osTicket/osTicket/issues/511),知道是换行符的问题,重新从github下载了zip文件,覆盖了原来的代码,然后重新开始安装,一切正常。

CentOS6.8 下升级php5.3.3 到php7.1

阿里云的ECS,从centos 6.5 镜像安装的,后来升到了6.8。PHP版本一直太低,PHP 5.3.3,对laravel也不支持,ThinkPHP5也不支持,就想干脆升到PHP 7.1吧。

其实没什么,就是先要启用remi源。然后卸载5.3.3, yum remove php* ,然后安装php71及一堆相关配件。

中间曾经虚惊一场,安装完后重启httpd,发现php文件没有被解析,直接输出了PHP代码。当时估计是php插件没安装全,当时有篇帖子里面有一个安装脚本,于是直接copy过来安装了一遍。然后就好了。

是周日晚上操作的,子夜开始操作,凌晨三点半左右才弄好睡觉。可惜当时没记录下来具体漏掉没安装的是哪个包,现在回忆也想不起来了。

恢复并重新配置SiteServer构建的网站

在亚马逊美国机房的某网站(操作系统 Windows 2008 R2,SQL Server 2008数据库,SiteServer CMS)连不上了,检查发现操作系统自动做了恢复操作,磁盘都回滚到以前的状态了。由于没有做快照,没法恢复到最近的状态。还好手上有早一些的文件和数据库,应该可以勉强恢复一个版本出来。

义工师兄新建了windows实例,复制了文件,恢复了数据库,遇到好几个问题,逐步解决,记录如下:

1,数据库的登录账号,SQL Server数据库必须支持windows认证+sqlServer认证两种形式;且恢复出来的数据库里面的原用户必须删除重建;账号信息应该与web.config里面记录的一致。本次我们还遇到一个比较妖的问题,服务器上装了两个不同版本的数据库引擎,一个对应 127.0.0.1,一个对应 (local),如果程序中配置得不对,就会报错。

2,要保证程序文件都完整,我们遇到缺少文件的情况,后基本补全,补全的过程要注意路径正确,解压缩要注意路径层次正确。

3,网站首页就报500错误,在IIS中查看网站的”模块”设置,发现提示:“不能在此路径中使用此配置节。如果在父级别上锁定了该节,便会出现这种情况。锁定是默认设置的…”,经查,是因为 IIS 7 采用了更安全的 web.config 管理机制,默认情况下会锁住配置项不允许更改,需要运行如下命令行解决:

appcmd unlock config -section:system.webServer/hanlers
appcmd unlock config -section:system.webServer/modules
%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -i

以上运行完毕,首页可以显示内容了。

参见:

http://blog.csdn.net/pianpianboy/article/details/40536891

关于new Date()以及时区的问题

最近发现一个小知识点:

在使用<input type=’date’ id=’time_begin’>的时候,因为是日期型,所以是没有时分秒的。这时候,如果在Javascript里面将该值使用new Date(string)转换为Date类型,会根据你当前所在的时区自动加上时间。如以下代码:

var strTime = $("#timebegin").val();
var time_begin = strTime =='' ? null : new Date(strTime);
alert(time_begin);

举例说,我在上海,input框里面选择了2016年10月17日,这时候new Date出来的值,如果alert出来看,会发现是 2016-10-17 08:00:00 (GMT +8:00)。

要解决这个问题只要在字符串后面加上” 00:00:00″就可以了。注意日期与时间之间要有空格。这时候就不会自动加上时区的偏移量了。代码如下:

var strTime = $("#timebegin").val() + " 00:00:00";
var time_begin = strTime =='' ? null : new Date(strTime);
alert(time_begin);

CentOS7上面安装Nginx

可以运行如下脚本:

安装nginx
echo ‘[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/7/$basearch/
gpgcheck=0
enabled=1’ > /etc/yum.repos.d/nginx.repo
yum -y install nginx
chkconfig nginx on
service nginx start

解释:

第一步,加源;
第二步安装;
第三步,设为开机自动启动;
第四步,现在就启动