Wordpress迁移到Ghost博客系统踩坑记录

很早之前就想将博客进行迁移了,到一直都是停留在想法阶段。之所以选择Ghost,因为我是个前端,Ghost毕竟是使用Node.js开发的,于我而言,都有很大的吸引力。

我们知道wordpress是个老牌的博客系统了,十分强大,优缺点我就不在赘述。选择Ghost必定要舍弃许多博客的功能,当然也可以二次开发。比如我现在用的这个博客主题是之前在Wordpress上使用的,迁移必定要再次重构Ghost的主题。像评论那些都得舍弃(第三方如畅言倒不用担心)。

那么我下面就具体谈谈迁移之中遇到的问题,先说说我的需求:

  • 全站HTTP/2.0
  • 使用Ghost系统
  • 自建数据库
  • 数据迁移
  • 主题重构

一、全站HTTP/2.0

支持HTTP/2.0需要你有自己的服务器以及域名证书,那么服务器自不必说,花钱买,域名证书可以到腾讯云、阿里云申请免费的,有效期是一年,到期可续签。

因为我们需要使用反向代理,并且要上HTTP/2.0,那么Nginx就是我们的选择了。安装Nginx网上教程十分多,CentOS可以使用yum直接安装,自动解决依赖的问题,后面的数据库安装将是使用Yum安装。那么我在这里说说Nginx的编译安装:

编译安装(如果命令没有加sudo,就说明我是在root用户下,其他用户下我会说明):

1.0 准备工作

新建安装目录:mkdir /usr/local/nginx
安装依赖:yum -y install make zlib zlib-devel gcc-c++ libtool openssl openssl-devel

1.1 安装 PCRE

/usr/local/src目录下:wget https://ftp.pcre.org/pub/pcre/pcre-8.41.tar.gz && tar -xvf pcre-8.41.tar.gz && cd pcre-8.41 && ./configure && make && make install

查看版本:pcre-config --version

PCRE官网

1.2 安装Nginx

/usr/local/src目录下:wget http://nginx.org/download/nginx-1.12.2.tar.gz && tar -xvf nginx-1.12.2.tar.gz && cd nginx-1.12.2

编译设置时需要注意,因为我们要上HTTP/2.0所以我们需要加上几个参数

/usr/local/src/nginx-1.12.2目录下:./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_v2_module --with-http_ssl_module --with-pcre=/usr/local/src/pcre-8.41

--with-http_v2_module :支持HTTP/2.0的模块
--with-http_ssl_module:支持HTTPS的模块

需要说明的是--with-http_ssl_module可以单独安装,但是安装--with-http_v2_module必须同时安装--with-http_ssl_module,因为HTTP/2.0是建立在443这个端口上的。

配置完成后执行编译
/usr/local/src/nginx-1.12.2目录下:make && make install

安装完成后,查看Nginx版本:
/usr/local/webserver/nginx/sbin/nginx -v

配置环境变量:
vi /etc/profile

将下面代码添加到/etc/profile:

export NGINX_HOME=/usr/local/nginx
export PATH=$PATH:$NGINX_HOME/sbin

刷新环境变量:
source /etc/profile

到这里,我们还需要增加用户组,配置vhost。

1.2 增加www用户组

PS:使用特定的用户组是为了增加安全性,在后面安装Ghost时,会增加一个Ghost用户组。

增加www用户组:groupadd www
增加www用户,并将其设置到www用户组:useradd -g www www

1.3 配置vhost

默认的host文件:/usr/local/nginx/conf/nginx.conf

我们替换成这样:

user www www;
worker_processes 1;
error_log logs/error.log;
pid logs/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
# include /usr/share/nginx/modules/*.conf;

events {
    use epoll;
    worker_connections 1024;
    multi_accept on;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  logs/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             mime.types;
    default_type        application/octet-stream;
    
    fastcgi_connect_timeout 300;
    fastcgi_send_timeout 300;
    fastcgi_read_timeout 300;
    fastcgi_buffer_size 64k;
    fastcgi_buffers 4 64k;
    fastcgi_busy_buffers_size 128k;
    fastcgi_temp_file_write_size 256k;

    gzip on;
    gzip_min_length  1k;
    gzip_buffers     4 16k;
    gzip_http_version 1.1;
    gzip_comp_level 2;
    gzip_types     text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/xml+rss;
    gzip_vary on;
    gzip_proxied   expired no-cache no-store private auth;
    gzip_disable   "MSIE [1-6]\.";

    limit_conn_zone $binary_remote_addr zone=perip:10m;
    limit_conn_zone $server_name zone=perserver:10m;

    #limit_conn_zone $binary_remote_addr zone=perip:10m;
    ##If enable limit_conn_zone,add "limit_conn perip 10;" to server section.

    server_tokens off;
    access_log off;
    
    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /usr/local/nginx/conf/vhost/*.conf;

    server {
        listen       80 default_server;
        listen       [::]:80 default_server;
        server_name  _;
        root         /home/wwwroot/default;

        # Load configuration files for the default server block.
        # include /etc/nginx/default.d/*.conf;

        location / {
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }

上面配置有些是默认设置,有些是我自己添加的,具体含义可能需要自己查询了。

这只是单纯的nginx配置项,每个网站有单独的配置。那么这个博客的配置是怎样的呢?

网站配置路径:/usr/local/nginx/conf/vhsot/zhelin.me.conf

server
    {
        listen 443 http2;
        server_name zhelin.me;
  
        ssl on;
        ssl_certificate   ../cert/zhelin_me.pem;
        ssl_certificate_key  ../cert/zhelin_me.key;
        ssl_session_timeout 5m;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        # 配置赫尔曼密钥
        # ssl_dhparam ../cert/dhparam.pem;
        
        #配置HSTS
	    # add_header Strict-Transport-Security "max-age=31536000";
        ...
        
    }

我们从上面看到,我们需要监听443端口,同时指定HTTP版本。
这里我注释了赫尔曼密码和HSTS,这两个按自己的需求使用,

生成赫尔曼密钥(服务器上):openssl dhparam -out dhparam.pem 2048
// 在 ssh 运行, openssl 生成 2048 位的密钥而不是当作参数写入 nginx.conf 文件。

HSTS作用是啥呢,大致就是告诉浏览器,这个网站在这个时间段以内,都用HTTPS打开,这也是为了安全,因为网站都是能用http打开,并重定向到https的,可是重定向之前都是可以截获修改监听的(也就是HTTPS降级攻击)。HSTS配置还有两个参数:includeSubdomains; preload
includeSubdomains :可选参数,如果指定这个参数,表明这个网站所有子域名也必须通过 HTTPS 协议来访问。
preload :这个就比较骚了,下面需要着重介绍一下。
虽然HSTS可以很好的解决 HTTPS 降级攻击,但是对于HSTS生效前的首次HTTP请求,依然无法避免被劫持(因为首次访问浏览器是不知道用户配置了HSTS的)。浏览器厂商们为了解决这个问题,提出了HSTS Preload List方案:内置一份可以定期更新的列表,对于列表中的域名,即使用户之前没有访问过,也会使用 HTTPS 协议。

目前这个 Preload List 由 Google Chrome 维护,Chrome、Firefox、Safari、IE 11 和 Microsoft Edge 都在使用。如果要想把自己的域名加进这个列表,首先需要满足以下条件:

  • 拥有合法的证书(如果使用 SHA-1 证书,过期时间必须早于 2016 年);
  • 将所有 HTTP 流量重定向到 HTTPS;
  • 输出 HSTS 响应头:1、max-age 不能低于 18 周(10886400 秒);2、必须指定 includeSubdomains 参数;3、必须指定 preload 参数;

即便满足了上述所有条件,也不一定能进入 HSTS Preload List,更多信息可以看这里。通过 Chrome 的 chrome://net-internals/#hsts 工具,可以查询某个网站是否在 Preload List 之中,还可以手动把某个域名加到本机 Preload List。

对于 HSTS 以及 HSTS Preload List,我的建议是只要你不能确保永远提供 HTTPS 服务,就不要启用。因为一旦 HSTS 生效,你再想把网站重定向为 HTTP,之前的老用户会被无限重定向,唯一的办法是换新域名。

   location ~* /.* {
            limit_conn perip 20;
            limit_conn perserver 20;
            proxy_pass  http://127.0.0.1:2368;
            #Proxy Settings
            proxy_redirect     off;
            proxy_set_header   Host             $host;
            proxy_set_header   X-Real-IP        $remote_addr;
            proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            expires 7d;
        }

同时配置反向代理到我们的ghost,着重需要注意的是一定要配置proxy_set_header X-Forwarded-Proto $scheme;,不然会出现重定向次数过多的错误。

还有就是,我这里面使用了:

limit_conn perip 20;
limit_conn perserver 20;

这是防止过高的请求,具体说明可以查阅资料。这样我们的整个HTTP/2.0配置工作就完成了。

二、使用Ghost系统

那么至此,我们就来到的最重要的一步,使用Ghost系统,如果小伙伴英语好,可以直接撸官方文档,官方文档十分详细,按照上面的步骤来基本不会出错,

但是有一个问题就是,官方文档不推荐使用nvm安装Node的,那么很多小伙伴就懵逼了,毕竟nvm真的很好用,我就不想舍弃。

以下是Ghost文档的说明:
NVM can be problematic

那么本篇文章就告诉你怎么使用nvm的同时,安装ghost不出问题,同时在任意用户下使用pm2。

========================== 未完待续 ==========================