9

0x00 前言

        WordPress是世界上最受欢迎的CMS系统,它是基于php和MySQL技术栈的,并且还有很多插件,可扩展性非常强。正好最近有一台空闲的ECS,于是来搭建一个玩玩。本教程是基于LEMP技术栈来搭建的,各个版本如下:

  1. L版本为CentOS7.6版本,
  2. E版本为nginx1.12.2版本
  3. M版本为Distrib 5.5.60-MariaDB
  4. P版本为php7.2

此外,现在全面https已经是趋势了,自然我们也不能落后,所以还会使用Let's Encrypt来生成免费的SSL证书进行配置

0x01 前置条件

  1. 有一个域名,我自己的域名为nomansky.xyz
  2. 一台VPS或者云主机,如果是国内的IP需要备案
  3. 具有sudo权限或root权限的用户,这里我新建一个wordpress用户来运行程序,并且使用下列命令设置为nologin
    a. sudo useradd -s /sbin/nologin wordpress
  4. 使用sudo yum install -y epel-release安装了epel源
  5. 关闭firewalld,我更喜欢用iptables来做安全加固
    a. sudo systemctl stop firewalld
    b. sudo systemctl disable firewalld

0x02 安装nginx

  1. 执行sudo yum install nginx安装nginx
  2. 启动nginx守护进程并设置为开机自启
    a. sudo systemctl start nginx
    b. sudo systemctl enable nginx
  3. 将wordpress用户加入到nginx组usermod -a -G nginx wordpress,同时设置目录权限chmod 770 -R /var/lib/nginx/
  4. 此时访问 http://nomansky.xyz 即可看到如下页面,则说明nginx安装成功了
    nginx页面

0x03 安装Mariadb

        Mariadb作为MySQL的一个开源的分支,已经成为了CentOS用来替换MySQL的默认的数据库,所以我这里也使用Mariadb作为数据库。

  1. 执行sudo yum install mariadb-server -y来安装mariadb
  2. 启动Mariadb并设置为开机自启
    a. sudo systemctl start mariadb
    b. sudo systemctl enable mariadb
  3. 执行sudo mysql_secure_installation来加固Mariadb。你会看到要求设置数据库root密码、移除匿名用户、限制只能通过localhost登陆数据库root用户和移除test数据库,这里推荐全部选Y(YES),如下图所示,默认的数据库root密码为空
    安全加固
  4. 除此之外,还要把mariadb监听的地址改为127.0.0.1:3306
    a. vim /etc/my.cnf.d/server.cnf打开Mariadb的配置文件
    b. 在[mysqld]下面加上bind=127.0.0.1,如下图所示
    listen address.png
    c. 执行systemctl restart mariadb重启数据库
    d. 执行netstat -lntp可以看到已经监听为本地回环地址了

0x04 创建数据库

在安装完mariadb数据库,并对其进行加固后,我们自然需要新建一个数据库来存放数据,这里首先我们用之前设置的root账号密码来登陆数据库mysql -uroot -p,并执行以下几条语句

CREATE DATABASE wordpress CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;  # 创建数据库
GRANT ALL ON wordpress.* TO 'wordpress'@'localhost' IDENTIFIED BY '你的密码'; # 创建用户
FLUSH PRIVILEGES;                                                            # 刷新数据库权限
EXIT;

0x05 安装PHP

CentOS的PHP默认版本为5.4,但是WordPress推荐的版本为7.2,所以我们这里安装php7.2的版本
执行下列命令安装php和所有需要的php扩展

sudo yum install yum-utils
sudo yum install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
sudo yum-config-manager --enable remi-php72
sudo yum install php-cli php-fpm php-mysql php-json php-opcache php-mbstring php-xml php-gd php-curl

我们安装PHP FPM是因为我们是用Nginx作为web server,而Nginx并没有自带这个组件。此外,PHP FPM 默认是以apache用户运行在9000端口,我们把这个用户改为wordpress并且把它从TCP Socket改为Unix Socket,具体怎么修改查看下面的步骤

  1. 打开/etc/php-fpm.d/www.conf,并修改如下地方

    ...
    user = wordpress
    ...
    group = wordpress
    ...
    listen = /run/php-fpm/www.sock
    ...
    listen.owner = wordpress
    listen.group = wordpress
  2. 用命令sudo chown -R root:wordpress /var/lib/php确保目录的所有组权限为wordpress
  3. 重启并开机自启动PHP FPM
    a. sudo systemctl restart php-fpm
    b. sudo systemctl enable php-fpm

0x06 申请免费证书

  1. 作为一个技(qiong)术(bi)宅,自然有免费的证书就肯定用免费的。因此我们可以申请免费的Let's Encrypt证书,这个证书不但免费,而且操作非常简单,虽然每次只有90天的有效期,但可以通过脚本配置crontab定期更新。
    a. mkdir -p /etc/nginx/ssl目录存放证书
    b. openssl genrsa 4096 > account.key进入这个目录,创建一个 RSA 私钥用于 Let's Encrypt 识别你的身份
    c. openssl genrsa 4096 > domain.key创建域名RSA私钥
    d. openssl req -new -sha256 -key domain.key -out domain.csr有了私钥文件,就可以生成 CSR 文件了。生成CSR会要求填入一些东西信息,这里Common Name为你的域名
    clipboard.png
  2. 我们知道,CA 在签发 DV(Domain Validation)证书时,需要验证域名所有权。传统 CA 的验证方式一般是往 admin@yoursite.com 发验证邮件,而 Let's Encrypt 是在你的服务器上生成一个随机验证文件,再通过创建 CSR 时指定的域名访问,如果可以访问则表明你对这个域名有控制权。所以首先创建用于存放验证文件的目录,例如:
    mkdir /home/wordpress/challenges
    然后配置一个HTTP服务,以Nginx为例:

    server {
        server_name www.nomansky.xyz nomansky.xyz;
    
        location ^~ /.well-known/acme-challenge/ {
            alias /home/wordpress/challenges/;
            try_files $uri =404;
        }
    
        location / {
            rewrite ^/(.*)$ https://nomansky.xyz/$1 permanent;
        }
    }

    以上配置表示查找 /home/wordpress/challenges/ 目录下的文件,如果找不到就重定向到 HTTPS 地址。这个验证服务以后更新证书还要用到,要一直保留。

  3. 接下来把acme-tiny保存到ssl目录wget https://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py
  4. 然后指定账户私钥、CSR 以及验证目录,执行脚本python acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir /home/wordpress/challenges/ > ./signed.crt,看到如下图所示,则说明生成成功了
    生成证书.png
  5. 最后还要下载Let's Encrypt 的中间证书,配置HTTPS证书时既不要漏掉中间证书,也不要包含根证书。在 Nginx 配置中,需要把中间证书和网站证书合在一起:

    wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > intermediate.pem
    cat signed.crt intermediate.pem > chained.pem
  6. 为了后续能顺利启用OCSP Stapling,我们再把根证书和中间证书合在一起(此步也可省略)

    wget -O - https://letsencrypt.org/certs/isrgrootx1.pem > root.pem
    cat intermediate.pem root.pem > full_chained.pem
  7. Let's Encrypt签发的证书只有90天有效期,推荐使用脚本定期更新。创建一个renew_cert.sh并通过chmod a+x renew_cert.sh赋予执行权限。文件内容如下:

    #!/bin/bash
    
    cd /etc/nginx/ssl/
    python acme_tiny.py --account-key account.key --csr domain.csr --acme-dir /home/wordpress/challenges/ > signed.crt || exit
    wget -O - https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem > intermediate.pem
    cat signed.crt intermediate.pem > chained.pem
    systemctl restart nginx
  8. 在crontabl中配置定时任务0 0 1 * * /etc/nginx/ssl/renew_cert.sh >/dev/null 2>&1

0x07 下载WordPress并配置Nginx

  1. 将WordPress下载到/home/wordpress/目录下wget https://wordpress.org/latest.tar.gz
  2. tar zxvf latest.tar.gz解压WordPress文件
  3. chown -R wordpress:wordpress wordpress将wordpress目录的所有者改为wordpress用户
  4. 接着,打开vim /etc/nginx/nginx.conf将nginx的运行角色改为wordpress

    ···
    user wordpress;
    worker_processes auto;
    ···
  5. 然后这里我把处于解耦合的目的,把主配置文件nginx.conf里的server配置块注释掉
  6. 新建sudo mkdir /etc/nginx/snippets目录并vim letsencrypt.conf来将以下配置粘贴到里面

    location ^~ /.well-known/acme-challenge/ {
          alias /home/wordpress/challenges/;
          try_files $uri =404;
    }
  7. 接下来新建vim /etc/nginx/conf.d/wordpress.conf配置文件,修改成如下配置

        # Redirect HTTP -> HTTPS
        server {
            listen 80;
            server_name www.nomansky.xyz nomansky.xyz;
    
            include snippets/letsencrypt.conf;
            return 301 https://nomansky.xyz$request_uri;
        }
    
        # Redirect WWW -> NON WWW
        server {
            listen 443 ssl http2;
            server_name www.nomansky.xyz;
    
            ssl_certificate /etc/nginx/ssl/chained.pem;
            ssl_certificate_key /etc/nginx/ssl/domain.key;
    
            return 301 https://nomansky.com$request_uri;
        }
    
        server {
            listen 443 ssl http2;
            server_name nomansky.com;
    
            root /home/wordpress/wordpress;
            index index.php;
    
            # SSL parameters
            ssl_certificate /etc/nginx/ssl/chained.pem;
            ssl_certificate_key /etc/nginx/ssl/domain.key;
    
            # log files
            access_log /home/wordpress/log/nomansky.xyz.access.log;
            error_log /home/wordpress/log/nomansky.xyz.error.log;
    
            location = /favicon.ico {
                log_not_found off;
                access_log off;
            }
            
                        location = /robots.txt {
                allow all;
                log_not_found off;
                access_log off;
            }
    
            location / {
                try_files $uri $uri/ /index.php?$args;
            }
    
            location ~ \.php$ {
                try_files $uri =404;
                fastcgi_pass unix:/run/php-fpm/www.sock;
                fastcgi_index   index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
            }
    
            location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
                expires max;
                log_not_found off;
            }
    
                                                                                                                                                                                        
  8. 创建日志目录mkdir -p /home/wordpress/log,并设置权限chown -R wordpress:wordpress /home/wordpress/log
  9. nginx -t查看是否是否语法检查正常,如正常则nginx -s reload重载nginx
  10. 接下来看到WordPress页面成功打开了,就此大功告成啦

    result.png

References:

How to install WordPress with Nginx on CentOS 7
免费好用的HTTPS证书

N0mansky
167 声望14 粉丝

Done is better than perfect.