RHEL 8 使用总结(二)-Nginx,SSL证书和PHP支持

本文是RHEL8使用总结第二篇, 包括Nginx使用,SSL证书配置和PHP配置。前一篇链接如下:

  1. RHEL 8 使用总结/避坑指南(一) 安装及配置SSH和防火墙

提纲:

0. 前言:为什么使用RHEL 8?
1. 下载、制作启动U盘安装RHEL 8
2. 配置防火墙
3. 配置SSH
4. 安装最新稳定版nginx
5. 配置SSL 安全证书
6. 安装PHP-FPM支持PHP
7. 挂载额外硬盘
8. 配置Samba服务
9. 安装Plex media server

4. 安装最新稳定版nginx

4.1. 查看当前repo里的版本

准备安装Nginx,默认repo里的Nginx版本比较旧,先查看一下repo里的版本, 涉及到如下两个dnf 命令:

# dnf 命令用法 参考 [Package Management with dnf](https://linuxhint.com/centos8_package_management_dnf/)

sudo dnf search nginx

 ==== Name Exactly Matched: nginx ===========
 nginx.x86_64 : A high performance web server and reverse proxy server
 ===== Name & Summary Matched: nginx =========
 # 列出一堆,没什么用,用provides就可以了,看到1.14,是老版本。改用provides

sudo dnf provides nginx

nginx-1:1.14.1-8.module+el8+2505+fe936cef.x86_64 : A high performance web server and reverse proxy server  
# 版本是1.14, 太老了


4.2. 修改repo设置安装最新稳定版nginx

通过上面的操作可以看到版本比较旧,需要手动修改Centos 8的repo设置来安装更新版本。具体做法参考另一篇文章How to install the latest stable Nginx version on CentOS 8?

这里整理记录我的操作如下:

# 1. 修改Repo设置。创建一个新的repo文件,名字可以随便起,这里叫nginx.repo:
sudo nano /etc/yum.repos.d/nginx.repo

# 2. 添加如下内容并保存:
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

# 3. 有的参考网页上还提了个main line的repo,虽然Nginx官方说main line不是beta版,
# 但毕竟最新的可能bug会多些,还是偏向稳定版本,因此不再添加那个repo。
# 保存后就可以直接用这个repo了,不过可以执行如下命令建一下dnf 的cache(参考这个网页[关于Centos 8下使用dnf命令详解]
# (https://linuxhint.com/centos8_package_management_dnf/))
sudo dnf makecache

# 4. 执行安装命令
sudo dnf install nginx # 安装
sudo systemctl enable nginx # 设置为服务,以后开机后会自动启动。首次安装完毕并没有启动,需要手动执行start启动命令
sudo systemctl start nginx # 手动启动nginx

4.3. 查看Nginx版本及详细信息

查看版本信息可以使用-v(简洁), -V(详细)两个参数。加-V后显示的详细信息里包含了很多文件路径信息和编译信息,都是来自config文件。

nginx -v
nginx version: nginx/1...

nginx -V
nginx version: nginx/1...
configure arguments: 
--conf-path=/etc/nginx/nginx.conf  # 重要!它指出了配置文件所在的路径
--error-log-path=/var/log/nginx/error.log # 错误日志所在路径
--http-log-path=/var/log/nginx/access.log  # 访问日志所在路径
--pid-path=/var/run/nginx.pid # 存有Nginx进程的pid的文本文件
...
--with-mail_ssl_module
--with-stream_ssl_preread_module 
--with-cc-opt='-O2 -g ...省略了' 

4.4 操作nginx

参照官方的guide [Beginner’s Guide]:

# 1. nginx启动的两种方法:

sudo nginx  #直接执行nginx的bin文件
sudo systemctl start nginx # 启动nginx服务

# 2. 当nginx运行后,可以通过(-s 消息)的方式来控制nginx
nginx -s reload     #重新加载配置文件, 这个很常用
nginx -s reopen     #重新打开log文件
nginx -s stop       #快速关闭nginx服务
nginx -s quit       #优雅的关闭nginx服务,等待工作进程处理完所有的请求

nginx -t # 测试Nginx 配置是否正确, 这个很常用, 配合 -s reload

# 3. 停止Nginx的方法:
sudo nginx -s stop #直接执行nginx的bin文件 或者
sudo systemctl stop nginx # 停止nginx服务

# 4. 也可以采用Linux 方式发送信号到nginx的master 进程,
# 比如可以采用 kill -s QUIT pid 的方式来执行优雅退出, pid是nginx的master进程的id,可以通过读取/var/run/nginx.pid 文本文件获得,也可以通过ps命令获得:
ps -ax | grep nginx # 或者替换-ax 为 -ef

# 5. Nginx 生成basicauth需要的用户名和密码, 
sudo htpasswd -c path/to/psw/file username, 
# -c表示创建新psw文件,不加-c 则是添加到文件里。例如
sudo htpasswd -c /etc/apache2/.htpasswd user1

5. 配置SSL 安全证书

参考了如下两个链接,它们步骤基本一样:

1. [How To Secure Nginx with Let's Encrypt on CentOS 8]
2. [How to Install Let’s Encrypt(Certbot) on RHEL/CentOS 8 Using 10 Easy Steps

5.1 Install and Enable EPEL Repository

这个repo里包含我们要安装的Certbot,所以要先安装它。这是这个repo的简介:

What is Extra Packages for Enterprise Linux (or EPEL)?Extra Packages for Enterprise Linux (or EPEL) is a Fedora Special Interest Group that creates, maintains, and manages a high quality set of additional packages for Enterprise Linux, including,but not limited to, Red Hat Enterprise Linux (RHEL), CentOS and Scientific Linux (SL), Oracle Linux (OL).

安装方法参见EPEL的[wiki],REHL和Centos略有不同, RHEL需要执行如下三行命令:

# RHEL/CentOS 8:
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm

# on RHEL 8 it is required to also enable the codeready-builder-for-rhel-8-*-rpms repository 
# since EPEL packages may depend on packages from it:

ARCH=$( /bin/arch ) # x86-64 (echo $ARCh)

sudo subscription-manager repos --enable "codeready-builder-for-rhel-8-${ARCH}-rpms"

5.2 安装Certbot

sudo dnf install certbot python3-certbot-nginx

#check version
certbot --version
certbot 1.10.1

5.3 设置防火墙允许https

sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

5.4 配置Nginx使它监听多个domain域名

因为后续Certbot会自动检测本机Nginx上支持监听的所有域名,所以我们在这一步要提前设置好,这里我准备了这6个域名,对应3个server实例:

server {
       listen 80 default_server; 
       server_name zangchuantao.com www.zangchuantao.com;
       ...
       }

server {
       listen 80 ; 
       server_name name1.zangchuantao.com www.name1.zangchuantao.com;
       ...
       }
    
server {
       listen 80 ; 
       server_name name2.zangchuantao.com www.name2.zangchuantao.com;
       ...
       }

同时在域名服务商那里要确保这6个域名都能访问到本机,否则下一步里会Certbot会报错 http challenge失败,无法生成SSL证书。关于子域名的解析,我的服务商只要求添加如下A recode(name -> ip 映射)就可以了 (CNAME是name -> name映射):

A	name1 162.252.245.xx # 本机ip地址
A	www.name1       162.252.245.xx	1 Hour

5.5 获取SSL证书

sudo certbot --nginx  
# 这个会生成SSL证书保存到本地,并自动设置跳转http到https, 此命令会修改conf文件。我用的这个。

sudo certbot certonly --nginx # 这个只生成SSL证书保存到本地,但并不会改变你的nginx配置,需要手动添加

# 执行命令后的一些命令输出, 这一步会做http测试,如果发现有域名没有指向本机,报错并停止运行
Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: zangchuantao.com
2: name1.zangchuantao.com
3: www.name1.zangchuantao.com
4: name2.zangchuantao.com
5: www.name2.zangchuantao.com
6: www.zangchuantao.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):
Cert not yet due for renewal  # 这里直接回车就是表示全选

# 之下就是修改你的nginx 配置
Deploying Certificate to VirtualHost xx.conf
Redirecting all traffic on port 80 to ssl in xx.conf

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
Congratulations! You have successfully enabled https://zangchuantao.com,
https://name1.zangchuantao.com, https://www.name1.zangchuantao.com,
https://name2.zangchuantao.com, https://www.name2.zangchuantao.com, and
https://www.zangchuantao.com
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at: # 成功并各显示位置
 ...
To obtain a new or tweaked   version of this certificate in the future, simply run certbot   again. To non-interactively renew *all* of your certificates, run   "certbot renew"
```

5.6 设置自动更新SSL证书

需要使用crontab加个任务就可以了,60天以后就自动更新了。

sudo crontab -e # 需要sudo来获取root权限执行
0 0,12 * * * python -c 'import random; import time; time.sleep(random.random() * 3600)' && certbot renew --quiet
# 按ESC,然后 :wq 退出保存
# 这个是每天0点和12点后延迟随机数字然后执行,每天两次,我改成了 0 12 ...每天中午吧。

6. 安装PHP-FPM支持PHP

sudo dnf install php php-mysqlnd php-fpm php-opcache php-gd php-xml php-mbstring php-json -y

# 安装完毕后Nginx内多了1个文件夹default.d和2个相关文件:/default.d/php.conf 和 conf.d/conf.d/php-fpm.conf

# /default.d/php.conf content
# pass the PHP scripts to FastCGI server
#
# See conf.d/php-fpm.conf for socket configuration
#
index index.php index.html index.htm;  # 修改为php优先

location ~ \.(php|phar)(/.*)?$ {
    fastcgi_split_path_info ^(.+\.(?:php|phar))(/.*)$;  # index.php?name=tom

    fastcgi_intercept_errors on;
    fastcgi_index  index.php;
    include        fastcgi_params;
    fastcgi_param  SCRIPT_FILENAME  
    $document_root$fastcgi_script_name;
    fastcgi_param  PATH_INFO $fastcgi_path_info;
    fastcgi_pass   php-fpm;
}

# 这个比默认的PHP处理block多了如下两句,可以参考fastcgi_split_path_info文档仔细看一下
fastcgi_split_path_info ^(.+\.(?:php|phar))(/.*)$;  # index.php?
fastcgi_param  PATH_INFO $fastcgi_path_info;

# 修改php-fmp 配置文件
vi /etc/php-fpm.d/www.conf
user = nginx  # 找到并替换成nginx
group = nginx
listen.owner = nginx
listen.group = nginx

注意: php-fpm是作为服务运行的,修改了php的设置后,需要重启它才可以:

sudo systemctl restart php-fpm

几个额外处理:

# 1. 移除Nginx版本信息: 
# 默认会显示版本在header里以及其他错误页面如404。
# 修改nginx.conf
server_tokens off; # Header只显示Nginx,不显示Nginx/1.18
        # more_clear_headers Server; # 需要安装更多模块nginx-extras,这个能彻底移除header里的Nginx

# 2. 移除PHP版本信息:
# 默认在Header里会显示X-Powered-By: php 7.x on Nginx
sudo nano /etc/php.ini
# Find the keyword expose_php and set its value to Off:
$ expose_php = off

# If you're running PHP as FPM, then you'll need to reload PHP-FPM
$ sudo systemctl restart php-fpm