上一篇 下一篇 分享链接 返回 返回顶部

香港服务器部署CentOS Stream 9:从系统初始化到网站上线怎么做?

发布人:Minchunlin 发布时间:2026-10-05 08:14 阅读量:1

香港服务器部署 CentOS Stream 9,建议以“可登录、可更新、可回滚、可验证”为主线,先完成系统初始化和安全基线,再安装 Nginx、PHP-FPM、MariaDB,最后绑定域名、配置 HTTPS,并从目标访问网络检查 DNS、路由、连接建立和页面响应时间。下面以 CentOS Stream 9 x86_64、单台香港服务器、IPv4 公网地址、PHP 网站为例,网站目录使用 /var/www/example.com,域名使用 example.com,实际操作时请替换为自己的域名和 IP。

导语配图

这套流程适合常见的 PHP 网站、内容管理系统或自研 PHP 应用。纯静态网站可以跳过 PHP-FPM 和 MariaDB;Node.js、Java 等其他运行环境应保留相同的初始化、端口、防火墙、域名、HTTPS、日志、验证和回滚原则,不要直接套用 PHP 配置。

一、部署前准备与回滚点

1. 明确上线目标

本示例的目标环境如下:

项目示例值或建议
操作系统CentOS Stream 9
Web 服务Nginx
动态运行环境PHP-FPM,版本以仓库实际可用版本为准
数据库MariaDB,仅监听本机
网站目录/var/www/example.com/current/public
公网端口TCP 22、80、443
数据库端口仅本机访问,不对公网开放
域名example.com、www.example.com
上线目标HTTP 自动跳转 HTTPS,PHP 页面可访问,应用可以连接本机数据库

准备以下信息后再操作:

  • 服务器公网 IPv4 地址,以及确认可用的 IPv6 地址;没有经过测试的 IPv6 不要提前添加 AAAA 记录。
  • root 登录方式或云控制台、VNC 等带外管理入口。
  • 一个可使用 SSH 公钥登录的普通管理员账号。
  • 已备案或可管理的域名 DNS 权限。
  • 网站程序包、数据库备份、环境变量和上传目录清单。
  • TLS 证书,或者可以使用 ACME 客户端申请证书。
  • 服务器快照能力。涉及系统更新、SSH、防火墙、Nginx 和数据库变更前,建议先创建快照。

示例域名和密码只能作为格式演示,数据库密码应使用随机长密码,不要直接使用文中的字符串。

2. 创建配置备份目录

首次登录后,先保存主要配置。以下命令适用于刚安装完成或已有网站但准备改造配置的 CentOS Stream 9。配置文件可能因安装状态不同而不存在,因此使用 2>/dev/null 不代表可以跳过后续检查。

export BACKUP_DIR="/root/site-deploy-backup-$(date +%F-%H%M%S)"
mkdir -p "$BACKUP_DIR"

cp -a /etc/ssh "$BACKUP_DIR/" 2>/dev/null || true
cp -a /etc/nginx "$BACKUP_DIR/" 2>/dev/null || true
cp -a /etc/php-fpm.d "$BACKUP_DIR/" 2>/dev/null || true
cp -a /etc/my.cnf.d "$BACKUP_DIR/" 2>/dev/null || true

printf '备份目录:%s\n' "$BACKUP_DIR"

此时还没有安装 MariaDB,不能执行数据库备份。数据库安装并导入数据后,应再执行一次 mariadb-dump。

二、系统初始化与安全基线

1. 更新系统并安装基础工具

先确认系统版本和当前内核:

cat /etc/centos-release
uname -r
hostnamectl

预期可以看到 CentOS Stream 9 信息。确认无误后更新系统:

dnf clean all
dnf makecache
dnf update -y

系统更新可能替换内核或基础库。如果更新后提示需要重启,应在业务尚未上线时执行:

reboot

重连后再次查看版本:

uname -r
dnf history list

安装常用工具、时间同步、SELinux 管理工具和诊断命令:

dnf install -y \
  sudo curl wget rsync tar unzip vim-minimal \
  chrony firewalld policycoreutils-python-utils \
  bind-utils traceroute mtr

启动时间同步和防火墙:

systemctl enable --now chronyd
systemctl enable --now firewalld

timedatectl set-timezone Asia/Hong_Kong
timedatectl status
chronyc tracking

时区只影响日志时间显示,不会降低网络延迟。选择香港时区的主要目的是让服务器日志、发布记录和维护时间更容易对应。

2. 创建普通运维账号

不要长期使用 root 直接进行日常网站维护。创建普通账号并加入 wheel 组:

useradd -m -s /bin/bash deploy
usermod -aG wheel deploy

install -d -m 700 -o deploy -g deploy /home/deploy/.ssh

将维护人员的公钥写入授权文件。下面的内容需要替换为真实公钥:

cat > /home/deploy/.ssh/authorized_keys <<'EOF'
ssh-ed25519 AAAA...替换为实际的SSH公钥... deploy
EOF

chown deploy:deploy /home/deploy/.ssh/authorized_keys
chmod 600 /home/deploy/.ssh/authorized_keys

先新开一个终端,确认可以使用 deploy 登录,并验证 sudo 权限:

二、系统初始化与安全基线 / 2. 创建普通运维账号配图

ssh deploy@服务器公网IP
sudo -v
id

只有新账号登录和 sudo 都成功后,才进行 SSH 加固。

3. 加固 SSH,避免锁死远程登录

创建独立的 SSH 配置片段,便于后续回滚:

cat > /etc/ssh/sshd_config.d/99-site-hardening.conf <<'EOF'
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
EOF

检查语法并重新加载:

sshd -t
systemctl reload sshd

sshd -t 没有输出通常表示语法检查通过。重新加载后,必须用另一个终端再次登录验证:

ssh deploy@服务器公网IP
sudo -v

如果登录失败,不要关闭当前 root 或控制台会话。可以通过服务器控制台删除配置片段并恢复:

rm -f /etc/ssh/sshd_config.d/99-site-hardening.conf
sshd -t
systemctl reload sshd

不要在没有备用控制台的情况下同时修改 SSH 端口、禁用密码和禁止 root 登录。一次只改一项,验证后再进行下一项。

4. 配置防火墙和 SELinux

只开放网站和 SSH 所需端口:

firewall-cmd --permanent --add-service=ssh
firewall-cmd --permanent --add-service=http
firewall-cmd --permanent --add-service=https
firewall-cmd --reload
firewall-cmd --list-all

不要为了远程连接 MariaDB 而开放 3306。后续数据库配置也应只允许本机连接。

确认 SELinux 状态:

getenforce
sestatus

推荐保持 Enforcing。不要使用 setenforce 0 作为长期解决方案。遇到访问拒绝时,应先查看 AVC 日志、文件上下文和实际权限,再针对性调整。

三、安装 Nginx、PHP-FPM 与 MariaDB

1. 安装软件包并核对版本

先查看 PHP 模块和可用版本,避免直接假设某个版本一定存在:

dnf module list php

如果系统显示多个 PHP 流,可以根据网站兼容性选择一个可用流。例如,确认网站支持后再执行类似命令:

dnf module enable -y php:8.2

如果系统已经启用了合适的 PHP 流,则不需要重复执行。安装运行环境:

dnf install -y \
  nginx \
  php-fpm php-cli php-mysqlnd php-gd php-mbstring php-opcache php-xml \
  mariadb-server

查看实际版本和服务状态:

nginx -v
php -v
mariadb --version
systemctl status nginx php-fpm mariadb --no-pager

先启动 MariaDB 和 PHP-FPM,Nginx 配置完成后再启动或重新加载:

systemctl enable --now mariadb
systemctl enable --now php-fpm

2. 初始化 MariaDB

执行安全初始化向导:

mariadb-secure-installation

不同 MariaDB 版本的提问略有差异,通常需要完成以下事项:

  • 设置或确认数据库管理员认证方式;
  • 删除匿名用户;
  • 禁止 root 通过远程连接;
  • 删除测试数据库;
  • 重新加载权限表。

创建网站数据库和专用账号:

mariadb -u root -p

进入 MariaDB 后执行以下 SQL。请把数据库密码替换为随机生成的强密码:

CREATE DATABASE site_db
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_unicode_ci;

CREATE USER 'site_user'@'localhost'
  IDENTIFIED BY '请替换为随机长密码';

GRANT ALL PRIVILEGES ON site_db.* TO 'site_user'@'localhost';

FLUSH PRIVILEGES;
EXIT;

验证专用账号只能按预期访问数据库:

mariadb -u site_user -p -e 'SELECT 1 AS database_ok;' site_db

预期结果中出现 database_ok 和数值 1。数据库配置完成后,保存一份备份:

mkdir -p "$BACKUP_DIR"

mariadb-dump \
  --single-transaction \
  --routines --events \
  -u root -p site_db \
  > "$BACKUP_DIR/site_db.sql"

ls -lh "$BACKUP_DIR/site_db.sql"

如果是新站点,备份文件可能只有少量内容;如果是迁移站点,应确认导出的文件大小和表数量符合预期。

四、准备网站目录与 PHP-FPM 运行池

1. 使用版本目录保存网站文件

直接覆盖线上目录不利于回滚。可以按版本创建发布目录,再让 current 软链接指向当前版本:

mkdir -p /var/www/example.com/releases
mkdir -p /var/www/example.com/shared/uploads

RELEASE_DIR="/var/www/example.com/releases/$(date +%Y%m%d-%H%M%S)"
mkdir -p "$RELEASE_DIR/public"

printf '%s\n' "$RELEASE_DIR"

将网站程序上传或解压到:

/var/www/example.com/releases/时间戳/public

如果只是验证 PHP 环境,可先创建临时页面:

cat > "$RELEASE_DIR/public/index.php" <<'EOF'

设置文件权限。常规网站文件不应对所有用户可写:

chown -R root:nginx "$RELEASE_DIR"
find "$RELEASE_DIR" -type d -exec chmod 755 {} \;
find "$RELEASE_DIR" -type f -exec chmod 644 {} \;

chown -R nginx:nginx /var/www/example.com/shared/uploads
find /var/www/example.com/shared/uploads -type d -exec chmod 750 {} \;
find /var/www/example.com/shared/uploads -type f -exec chmod 640 {} \;

让 Nginx 和 PHP-FPM 使用当前版本:

ln -sfn "$RELEASE_DIR" /var/www/example.com/current
ls -la /var/www/example.com/current

2. 设置 SELinux 文件上下文

网站静态文件使用只读上下文,上传目录使用可写上下文:

semanage fcontext -a -t httpd_sys_content_t \
  '/var/www/example.com(/.*)?'

semanage fcontext -a -t httpd_sys_rw_content_t \
  '/var/www/example.com/shared/uploads(/.*)?'

restorecon -Rv /var/www/example.com

如果命令提示对应规则已经存在,应先查看现有规则:

semanage fcontext -l | grep '/var/www/example.com'

确认规则后再次执行:

restorecon -Rv /var/www/example.com

不要把整个网站目录标记为可写。只有确实需要由应用写入的上传、缓存或临时目录才使用可写上下文。

3. 创建独立 PHP-FPM 池

为网站创建独立 PHP-FPM 运行池,可以减少与其他站点之间的资源和权限混用:

cat > /etc/php-fpm.d/example.conf <<'EOF'
[example]
user = nginx
group = nginx

listen = /run/php-fpm/example.sock
listen.owner = nginx
listen.group = nginx
listen.mode = 0660

pm = ondemand
pm.max_children = 20
pm.process_idle_timeout = 10s
pm.max_requests = 500

request_terminate_timeout = 120s
EOF

pm.max_children = 20 只是示例值。内存较小的服务器应适当降低,PHP 应用较重或并发较高时,应结合实际内存和响应时间调整。不要在没有观察内存使用的情况下盲目增大。

检查 PHP-FPM 配置:

php-fpm -t

预期类似:

NOTICE: configuration file /etc/php-fpm.conf test is successful

重新启动 PHP-FPM:

systemctl restart php-fpm
systemctl is-active php-fpm
ls -l /run/php-fpm/example.sock

如果没有看到 socket,先查看日志:

journalctl -u php-fpm -n 80 --no-pager

五、配置 Nginx 并验证本机访问

1. 创建 HTTP 配置

先不急于强制 HTTPS,使用 HTTP 完成网站和 PHP-FPM 的本机验证:

cat > /etc/nginx/conf.d/example.com.conf <<'EOF'
server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;
    root /var/www/example.com/current/public;
    index index.php index.html;

    client_max_body_size 32m;

    location ^~ /.well-known/acme-challenge/ {
        try_files $uri =404;
    }

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        try_files $fastcgi_script_name =404;

        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $document_root;
        fastcgi_pass unix:/run/php-fpm/example.sock;
        fastcgi_read_timeout 120s;
    }

    location ~ /\. {
        deny all;
    }
}
EOF

这里的 try_files 会先查找真实文件,找不到时再交给 index.php,适合常见的 PHP 路由模式。如果网站本身是纯静态文件,可以将 location / 改成只提供静态文件,并移除 PHP-FPM 配置。

检查并加载 Nginx:

nginx -t
systemctl enable nginx
systemctl reload nginx

如果 nginx -t 报错,不要 reload,先根据行号修复配置。验证本机 HTTP:

curl -i -H 'Host: example.com' http://127.0.0.1/

临时页面应返回类似内容:

HTTP/1.1 200 OK
...
site-ok

确认监听端口:

ss -lntp | grep -E ':(80|443|9000|3306)\b'

PHP-FPM 使用 Unix socket 时,不一定会出现 9000 端口。MariaDB 的 3306 监听地址应重点检查是否为本机地址:

ss -lntp | grep ':3306'

2. 上传正式网站程序

正式发布时,将程序上传到新的 releases 子目录,不要直接覆盖 current:

NEW_RELEASE="/var/www/example.com/releases/20261004-120000"
mkdir -p "$NEW_RELEASE/public"

rsync -a --delete ./local-site/ "$NEW_RELEASE/public/"

chown -R root:nginx "$NEW_RELEASE"
find "$NEW_RELEASE" -type d -exec chmod 755 {} \;
find "$NEW_RELEASE" -type f -exec chmod 644 {} \;

restorecon -Rv "$NEW_RELEASE"

ln -sfn "$NEW_RELEASE" /var/www/example.com/current
nginx -t && systemctl reload nginx

rsync --delete 会删除目标目录中本地不存在的文件,必须确认目标路径是新的发布目录,不能误指向当前线上目录。正式应用的数据库密码、密钥和第三方凭据不要放在 public 目录中,优先使用应用支持的环境变量或网站根目录之外的配置文件。

六、绑定域名并启用 HTTPS

1. 先检查 DNS

在域名管理处创建:

example.com      A       服务器公网IPv4
www              A       服务器公网IPv4

如果服务器已经验证 IPv6 可用,再添加 AAAA 记录。检查解析结果:

dig +short A example.com
dig +short A www.example.com
dig +short AAAA example.com

没有稳定 IPv6 服务时,不要添加 AAAA。部分访问者会优先尝试 IPv6,错误的 AAAA 可能表现为部分地区打不开,而不是所有用户都失败。

解析结果指向正确地址后,在服务器上测试域名到本机的匹配:

curl -i --resolve example.com:80:127.0.0.1 http://example.com/

2. 申请或安装证书

如果使用仓库提供的 Certbot,可以先确认软件包:

dnf info certbot python3-certbot-nginx

仓库可用时安装:

dnf install -y certbot python3-certbot-nginx

使用 Webroot 方式申请证书前,确保域名已经解析到当前服务器,且 TCP 80 端口可以从外部访问:

certbot certonly \
  --webroot \
  -w /var/www/example.com/current/public \
  -d example.com \
  -d www.example.com

如果当前环境不提供上述软件包,也可以使用已经选定的 ACME 客户端或已有证书。关键是确认以下两个文件存在且证书域名匹配:

证书链文件:/etc/letsencrypt/live/example.com/fullchain.pem
私钥文件:/etc/letsencrypt/live/example.com/privkey.pem

私钥应限制为 root 可读:

chown root:root /etc/letsencrypt/live/example.com/privkey.pem
chmod 600 /etc/letsencrypt/live/example.com/privkey.pem

3. 配置 HTTPS 和静态资源缓存

证书准备好后,将 Nginx 配置替换为以下版本:

静态资源读取 /var/www/example.com/current/public,PHP 请求通过 /run/php-fpm/example.sock 交给

server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;
    root /var/www/example.com/current/public;

    location ^~ /.well-known/acme-challenge/ {
        try_files $uri =404;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

    server_name example.com www.example.com;
    root /var/www/example.com/current/public;
    index index.php index.html;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    client_max_body_size 32m;

    gzip on;
    gzip_vary on;
    gzip_comp_level 5;
    gzip_min_length 1024;
    gzip_types
        text/plain
        text/css
        application/javascript
        application/json
        application/xml
        image/svg+xml;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~* \.(css|js|jpg|jpeg|png|gif|svg|webp|ico|woff|woff2)$ {
        try_files $uri =404;
        expires 7d;
        add_header Cache-Control "public, max-age=604800";
    }

    location ~ \.php$ {
        try_files $fastcgi_script_name =404;

        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $document_root;
        fastcgi_pass unix:/run/php-fpm/example.sock;
        fastcgi_read_timeout 120s;
    }

    location ~ /\. {
        deny all;
    }

    add_header X-Content-Type-Options "nosniff" always;
}

静态资源缓存只适合文件名带版本号或内容不经常变化的网站。如果每次发布都使用相同的 app.js、style.css 文件名,缓存时间过长可能导致访客继续使用旧文件。此时应缩短 expires,或者在发布时修改资源版本号。

检查并加载配置:

nginx -t
systemctl reload nginx

从服务器本机检查 HTTPS:

curl -I --resolve example.com:443:127.0.0.1 https://example.com/

检查证书有效期和域名:

openssl s_client \
  -connect example.com:443 \
  -servername example.com /dev/null |
  openssl x509 -noout -subject -issuer -dates

证书自动续期不能只看申请是否成功,还应检查续期任务:

systemctl list-timers --all | grep -Ei 'certbot|acme'

如果使用 Certbot,可在维护窗口执行:

certbot renew --dry-run

七、香港服务器的跨境网络检查与优化

跨境访问慢,不能只看服务器带宽或一次 ping 结果。应分别观察域名解析、TCP 建连、TLS 握手、首字节响应和页面主体传输时间。

1. 使用 ping 判断基础往返时延

在目标访问网络中执行:

ping -4 -c 20 example.com

ping 主要反映 ICMP 的往返时延和丢包情况,适合观察基础网络稳定性,但不能直接证明网页访问速度。部分网络会限制或降低 ICMP 优先级,出现少量丢包时,还需要结合 HTTPS 请求结果判断。

如果服务器和访问网络都启用了 IPv6,可以分别测试:

ping -6 -c 20 example.com

IPv4 和 IPv6 结果差异明显时,优先检查 AAAA 记录和 IPv6 路由;如果 IPv6 不稳定,删除错误的 AAAA 记录通常比修改服务器内核参数更有效。

2. 使用 traceroute 观察路径

针对 HTTPS 端口执行 TCP 路由探测:

traceroute -4 -T -p 443 example.com

也可以使用 MTR 观察一段时间内的路径:

mtr -4 -rwzc 20 --tcp --port 443 example.com

判断时注意以下边界:

  • 中间某一跳显示 *,可能只是该节点不回应探测包,不代表最终网站丢包。
  • 只有从某一跳开始一直到目标地址都出现明显丢包,才更值得关注。
  • traceroute 能帮助识别路径和延迟增加的位置,但不能证明 HTTP 页面加载速度、带宽或应用性能。
  • 同一个香港 IP,从不同运营商、不同地区和不同时间访问,路径可能不同,应该在实际主要访客网络中测试。

3. 使用 curl 拆分网站响应时间

在访问端执行以下命令:

curl -4 -sS -o /dev/null \
  -w 'dns=%{time_namelookup}s connect=%{time_connect}s tls=%{time_appconnect}s ttfb=%{time_starttransfer}s total=%{time_total}s size=%{size_download}bytes\n' \
  https://example.com/

各字段含义如下:

字段主要含义异常时优先检查
dns域名解析耗时DNS 权威服务、解析链路、本地解析器
connectTCP 建连完成时间路由、丢包、防火墙、服务监听
tlsTLS 握手完成时间证书链、握手往返、协议配置
ttfb收到首字节的时间PHP、数据库、应用逻辑、服务器负载
total完整响应结束时间页面体积、静态文件、带宽和缓存
size_download下载数据量是否返回了异常大页面或压缩未生效

例如,connect 明显偏高,优先看路径和丢包;ttfb 偏高但基础 RTT 正常,通常应检查 PHP-FPM、数据库查询和应用日志;ttfb 正常而 total 很高,则应检查页面体积、静态资源数量、压缩和缓存。

4. 以低风险配置改善跨区域访问

建议按照以下顺序处理:

  1. 确认 A、AAAA 记录没有指向错误地址。
  2. 确认 80、443 端口可以从目标网络访问。
  3. 启用 HTTPS keepalive 和 HTTP/2,减少页面包含多个资源时的连接开销。
  4. 对 CSS、JavaScript、字体和图片设置合理缓存。
  5. 对文本内容启用 gzip,不压缩已经压缩过的 JPEG、PNG、WebP 和 ZIP。
  6. 减少首屏需要加载的资源数量,避免将大文件放入首屏 HTML。
  7. 检查 PHP-FPM 等待队列、数据库慢查询和应用错误日志。
  8. 如果多个目标访问网络的静态资源延迟明显,再评估内容分发服务;启用后要重新验证缓存规则、HTTPS 证书和源站回源。

Nginx 的 gzip_comp_level 不宜盲目调到很高。压缩等级提高会消耗更多 CPU,通常中等等级已经能在响应体积和 CPU 使用之间取得平衡。

5. 可选启用 BBR,但先验证内核支持

CentOS Stream 9 的内核是否提供 BBR,应以实际输出为准:

cat /proc/sys/net/ipv4/tcp_available_congestion_control
sysctl net.ipv4.tcp_congestion_control

如果输出中包含 bbr,可以先临时加载模块并测试:

modprobe tcp_bbr
sysctl -w net.ipv4.tcp_congestion_control=bbr
sysctl net.ipv4.tcp_congestion_control

确认没有异常后再持久化:

cat > /etc/modules-load.d/tcp_bbr.conf <<'EOF'
tcp_bbr
EOF

cat > /etc/sysctl.d/99-site-network.conf <<'EOF'
net.ipv4.tcp_congestion_control = bbr
EOF

sysctl --system

这不是所有业务都必须启用的参数,不能把它当作跨境访问速度的保证。启用后应重新观察 curl 的连接时间、响应时间、CPU 和丢包情况。

如需回滚:

rm -f /etc/modules-load.d/tcp_bbr.conf
rm -f /etc/sysctl.d/99-site-network.conf

sysctl -w net.ipv4.tcp_congestion_control=cubic

如果系统不支持 BBR,就保留默认拥塞控制,不要强行加载未知模块。

八、上线验收

1. 服务与端口检查

systemctl is-active nginx
systemctl is-active php-fpm
systemctl is-active mariadb
systemctl is-active firewalld

检查端口:

ss -lntp | grep -E ':(22|80|443|3306)\b'

应看到 SSH、HTTP、HTTPS 正常监听,MariaDB 不应对公网地址开放。

2. 页面、PHP 和数据库检查

检查 HTTP 跳转:

curl -I http://example.com/

预期为 301 或 308,并包含 HTTPS 地址。

检查 HTTPS:

curl -I https://example.com/

预期为 200、301 或应用自身的正常状态码。若是登录页或接口,不要只以 200 作为唯一判断标准,还应检查页面内容和应用日志。

检查 Nginx 和 PHP-FPM 日志:

tail -n 80 /var/log/nginx/error.log
journalctl -u php-fpm -n 80 --no-pager

检查 SELinux 是否有近期拒绝:

ausearch -m AVC -ts recent

如果没有输出,说明近期没有匹配到 AVC 拒绝;如果有输出,应结合访问时间、路径和进程进行判断,不能直接关闭 SELinux。

3. 应用级验收清单

正式切换前至少确认:

  • 首页、登录页、后台或核心接口可以正常打开。
  • PHP-FPM 没有持续积压或频繁重启。
  • 应用能够使用 site_user 连接 site_db。
  • 文件上传仅写入指定的 shared/uploads 目录。
  • 数据库 3306 未暴露到公网。
  • HTTPS 证书域名、有效期和中间证书正常。
  • 静态资源没有因缓存规则加载旧版本。
  • 从主要访问网络分别执行过 ping、traceroute 或 MTR、curl 测试。
  • 已保存网站程序、Nginx、PHP-FPM、数据库和 DNS 变更记录。

九、常见失败处理与回滚

1. SSH 无法登录

先不要反复重启服务器。使用带外控制台登录,检查:

sshd -t
journalctl -u sshd -n 100 --no-pager
ls -la /home/deploy/.ssh

确认授权文件属主和权限:

chown -R deploy:deploy /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keys

若是 SSH 加固导致锁定,删除 /etc/ssh/sshd_config.d/99-site-hardening.conf,执行 sshd -t 后 reload。不要在没有验证新会话前关闭控制台连接。

2. Nginx 返回 502

按由外到内的顺序检查:

systemctl is-active php-fpm
php-fpm -t
ls -l /run/php-fpm/example.sock
tail -n 100 /var/log/nginx/error.log

常见原因包括 PHP-FPM 未启动、socket 路径不一致、socket 权限不正确或 PHP-FPM 配置语法错误。修复后执行:

systemctl restart php-fpm
nginx -t && systemctl reload nginx

如果改动独立 PHP-FPM 池后出现问题,可以恢复备份配置:

cp -a "$BACKUP_DIR/php-fpm.d" /etc/php-fpm.d
php-fpm -t
systemctl restart php-fpm

恢复前应确认备份目录中的配置是本次变更前的版本。

3. Nginx 返回 403 或出现 SELinux 拒绝

检查当前路径、权限和上下文:

namei -l /var/www/example.com/current/public/index.php
ls -lZ /var/www/example.com/current/public/index.php
restorecon -Rv /var/www/example.com

目录需要具备可遍历权限,网站文件需要可读。不要直接把整个目录执行 chmod -R 777。如果上传功能失败,只调整上传目录的属主和 httpd_sys_rw_content_t 上下文。

4. HTTPS 失败或证书不匹配

检查配置和证书文件:

nginx -t
openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -noout -subject -dates

从访问端确认 SNI 对应的证书:

openssl s_client \
  -connect example.com:443 \
  -servername example.com /dev/null |
  openssl x509 -noout -subject -issuer -dates

如果证书申请失败,先检查 DNS、80 端口、防火墙和 /.well-known/acme-challenge/ 路径,不要频繁重复申请,以免触发申请频率限制。

5. 页面打开慢但 ping 正常

依次检查:

curl -sS -o /dev/null \
  -w 'dns=%{time_namelookup}s connect=%{time_connect}s tls=%{time_appconnect}s ttfb=%{time_starttransfer}s total=%{time_total}s\n' \
  https://example.com/
  • ttfb 高:检查 PHP-FPM、数据库慢查询、应用外部请求和服务器 CPU、内存。
  • total 高而 ttfb 正常:检查页面大小、静态资源数量、gzip 和缓存。
  • connect 高:检查目标访问网络到香港服务器的路径、丢包和防火墙。
  • dns 高:检查域名权威解析和访问端 DNS,不要先修改 PHP 或数据库。

6. 应用发布后需要快速回退

如果当前版本通过软链接发布,先查看历史版本:

九、常见失败处理与回滚 / 6. 应用发布后需要快速回退配图

ls -lt /var/www/example.com/releases
readlink -f /var/www/example.com/current

切回上一版本:

ln -sfn /var/www/example.com/releases/上一版本目录 \
  /var/www/example.com/current

restorecon -Rv /var/www/example.com/current
nginx -t && systemctl reload nginx

如果数据库结构也发生变化,仅回退网站文件可能不够。数据库迁移前应先导出备份,恢复时在业务暂停或维护窗口中执行:

mariadb -u root -p site_db < /root/site-deploy-backup-时间/site_db.sql

导入会覆盖或新增数据库对象,执行前必须确认备份文件、目标数据库和恢复范围,不能把生产库恢复命令当作普通测试命令执行。

7. DNS 切换后出现大面积访问异常

先用 dig 核对 A、AAAA 记录:

dig +short A example.com
dig +short AAAA example.com

如果错误来自 AAAA 记录,且服务器 IPv6 未验证,应优先删除或修正 AAAA。若网站迁移前仍保留旧服务器,可以将 A 记录改回旧地址完成回滚。DNS TTL 只影响缓存更新时间,不能保证所有递归解析器立即刷新,因此切换前应降低 TTL,切换完成并确认稳定后再恢复到合理值。

8. 软件更新造成系统异常

记录每次 DNF 事务:

dnf history list
dnf history info ID

对于内核、Nginx、PHP 或数据库等基础组件,不建议直接执行未经确认的 dnf history undo ID,因为它可能连带删除依赖或改变其他软件。优先使用服务器快照恢复;确实需要撤销时,先在维护窗口查看事务详情并保存当前配置。

部署完成后,至少保留以下回滚材料:

  • 系统快照或镜像;
  • /etc/ssh、/etc/nginx、/etc/php-fpm.d 配置备份;
  • 网站上一版本发布目录;
  • 数据库逻辑备份;
  • DNS 切换前后的记录;
  • 证书路径和续期方式;
  • 本次上线使用的命令、时间和验证结果。
目录结构
全文