换用腾讯云的免费SSL

之前曾用过沃通的免费SSL,结果几个月前备谷歌宣布不再信任该机构。也曾用过starSSL,似乎也有相似问题。

后来曾用Let’s Encrypt,挺好用,但有两个缺点:

1,证书有效期太短,才半年,感觉眼睛一眨就得要去renew了;

2,在复杂配置的centos上面自动化很麻烦,我们站点设置了80端口自动转https,但certbot(Let’s Encrypt客户端)要工作必须先要能访问验证域名,需要放置验证文件能在80端口下访问。这也意味着每次我们renew证书还需要修改站点配置。自动化Renew反正是没用上。

近期正好看到腾讯有免费ssl,就去申请了一下。很方便,验证方式也比较容易。有效期一年,比Let’s Encrypt长。既然自动化不了,暂时就用他家的方案了。

使用JPA的级联更新问题

假设A对象与B对象是一对多的关系,B的集合作为A的属性children而存在。

class A{
……
@OneToMany(mappedBy=”parent”, cascade={CascadeType.ALL})
private Set<B> children;
……
}

使用CascadeType.ALL能够实现级联保存、级联删除。但是级联更新的时候遇到如下问题:

A.children.remove(child1);
A.children.add(child2);

这时候child2确实被添加到数据库了,但child1却并没有被删除。

其实只要加上orphanRemoval=true 就可以了

class A{
……
@OneToMany(mappedBy=”parent”, cascade={CascadeType.ALL},orphanRemoval=true)
private Set<B> children;
……
}

Angularjs项目中文件上传

项目后端为Java,基于Spring Boot框架,前端为AngularJS。

前端有两个主要的组件可以用,一个是ng-file-upload,一个是angular-file-upload。

尝试使用ng-file-upload,却不能成功。主要是因为前端使用了Pace,有一些不兼容问题。报错如下:
Failed to execute ‘setRequestHeader’ on ‘XMLHttpRequest’
具体可以参见:https://github.com/danialfarid/ng-file-upload/issues/98

网上有人尝试解决这个问题,但在我的案例里面不适用,也没花时间多研究解决。

使用angular-file-upload则非常顺利,事实上从文档和示例来说,感觉angular-file-upload更加友好易用一些。

新服务器的Apache Rewrite问题

新装了一台服务器(CentOS 7.3, Apache 2.4.6, PHP 7.1.6),迁移网站应用到上面,网站文件都放在 /var/www/目录下。访问时候发现如下问题:

采用ThinkPHP开发的A应用,可以通过 http://www.a.com/index.php/Home/Abc/def 来访问

但不能通过 http://www.a.com/Home/Abc/def 来访问

也就是访问地址中没法省略掉index.php。一开始把PathInfo 和Rewrite搞混淆了,以为是前者的问题。

后来发现其实这明显是 Rewrite的问题,因为虽然ThinkPHP代码根目录下面默认有.htaccess文件,但服务器的配置有可能禁止站点自行配置。从以上症状来看正是Rewrite规则根本没起作用。

最后找到开关其实在这里:

找到apache配置文件:/etc/httpd/conf/httpd.conf

找到 对应目录的配置处,修改 AllowOverride All:

<Directory “/var/www”>
AllowOverride All
</Directory>

JHipster项目集成Gitlab CI自动测试遇到的错误

使用 JHipster 生成的项目用 gitlab CI 做自动测试、发布。根据jhipster官方文档进行了操作,在项目根目录下生成了.gitlab-ci.yml文件,同时根据 Gitlab 文档,在一台 Windows Server 2008 环境下安装了Runner。安装过程中配置了私有Gitlab地址,runner的token,也配置了Executor为shell。安装好Runner后发现runner已经能够自动去运行了,不过gitlab中看到build遇到了个错误,maven build 报错,具体为执行.gitlab-ci.yml中这一句:export MAVEN_USER_HOME=`pwd`/.maven的时候,报错,输出信息是乱码,状态码是9009。研究后解决了,发现官方文档少了个提示,runner如果跑在windows 平台,且executor选 shell 的话,应在gitlab-runner根目录下的config.toml 中设置 shell=’powershell’,不然会报错。应该是 export MAVEN_USER_HOME=`pwd`/.maven 的时候,取不到 `pwd` 的值的问题。可以参考有人遇到过类似问题:http://www.cnblogs.com/xishuai/p/gitlab-ci.html

解决Gulp构建的AngularJS项目中的footable依赖不能自动注入的问题

项目是基于Angular 1.5,构建工具为Gulp。项目文件结构来源于某前端模板的种子项目,与多数AngularJS 的Gulp版本的种子项目大同小异。Gulp的inject任务中已经有了将项目所依赖包的js、css文件自动添加到index.html中的脚本。

现在某页面需要用到footable,于是添加footable依赖:
bower install –save footable

安装后检查,看起来插件已经存在于项目的bower_components目录下了,并且项目的bower.json文件中,也已经自动添加了对footable的依赖,当前版本是3.1.4。

但是运行gulp serve 或者gulp build,均未能在index.html中看到footable的踪影。

小小了解了一下才知道原因:gulp的依赖注入,是调用了wiredep(项目地址:https://github.com/taptapship/wiredep)
而wiredep的工作原理,是根据项目的bower.json文件中所列的依赖,一一处理这些依赖项,处理的时候,会分析该依赖包本身的bower.json文件,根据该文件中的”main”的值来决定要将哪个文件添加到index.html中去。而footable的bower.json文件中,缺失了这一项。

根据wiredep的官方文档,只要在自己项目的bower.json文件中override就可以了。代码如下:

"overrides": {
  "footable": {
    "main": [
      "compiled/footable.js",
      "compiled/footable.bootstrap.css"
    ]
  }
}

初次使用 JHipster

安装不难,Yarn,Yeoman 等都装上,按官方文档都装好。

然后运行 yo jhipster 来根据向导生成程序。用的是git shell,不知为什么,互动的过程键盘方向键输入异常,而且界面上字符显示还出现了叠加,所以一路回车,大致按照默认值生成了程序。

(此处特别友情提醒,后来经测试查明,jHipster的生成向导在Git Shell下运作不正常,无法进行菜单选择,在Windows Power Shell下显示正常,其它类型的终端暂未测试)

然后,运行yarn start启动前端,界面能正常显示。运行mnvw启动服务器端的时候出现了问题:

1,一开始是解压缩maven压缩文件的报错,网上搜了一下,说把对应的user/.m2/下面的相关文件夹删除,果然好了;

2,然后看报错信息,mysql连不上,应该是向导生成的默认配置跟实际服务器不一致,这个需要修改一下配置,修改src\main\resources\config\application-dev.yml里面的对应节点即可;

3,报zookeeper连不上,下载zookeeper了之后,在本机安装,按照官方文档,新建了zoo.cfg文件,然后运行bin\zkServer.cmd start启动,结果报错:

2017-04-30 20:48:44,016 [myid:] - WARN  [main:QuorumPeerMain@113] - Either no config or no quorum defined in config, running  in standalone mode
2017-04-30 20:48:44,135 [myid:] - ERROR [main:ZooKeeperServerMain@55] - Invalid arguments, exiting abnormally
java.lang.NumberFormatException: For input string: "C:\zookeeper-3.4.10\bin\..\conf\zoo.cfg"
        at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
        at java.lang.Integer.parseInt(Integer.java:580)
        at java.lang.Integer.parseInt(Integer.java:615)
        at org.apache.zookeeper.server.ServerConfig.parse(ServerConfig.java:59)
        at org.apache.zookeeper.server.ZooKeeperServerMain.initializeAndRun(ZooKeeperServerMain.java:84)
        at org.apache.zookeeper.server.ZooKeeperServerMain.main(ZooKeeperServerMain.java:53)
        at org.apache.zookeeper.server.quorum.QuorumPeerMain.initializeAndRun(QuorumPeerMain.java:116)
        at org.apache.zookeeper.server.quorum.QuorumPeerMain.main(QuorumPeerMain.java:78)

花了半小时才搞清楚,原来Windows下,用zkServer.cmd启动服务,不需要加start参数就可以了。。。

然后。。。zookeeper是运行起来了,但是启动jhipster服务器还是报错,如下:

org.springframework.context.ApplicationContextException: Failed to start bean 'outputBindingLifecycle'; nested exception is org.I0Itec.zkclient.exception.ZkNoNodeException: org.apache.zookeeper.KeeperException$NoNodeException: KeeperErrorCode = NoNode for /brokers/ids

夜深了,留下问题暂未解决。

第二天重新创建了程序,在生成向导中先没有选择服务注册和发现,这样避开使用zookeeper的问题。先把jhipster跑起来,以后再慢慢解决连接zookeeper报错的问题。

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