香港服务器部署CentOS Stream 9:从系统初始化到网站上线怎么做?
香港服务器部署 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 权限:

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 配置替换为以下版本:

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 权威服务、解析链路、本地解析器 |
connect | TCP 建连完成时间 | 路由、丢包、防火墙、服务监听 |
tls | TLS 握手完成时间 | 证书链、握手往返、协议配置 |
ttfb | 收到首字节的时间 | PHP、数据库、应用逻辑、服务器负载 |
total | 完整响应结束时间 | 页面体积、静态文件、带宽和缓存 |
size_download | 下载数据量 | 是否返回了异常大页面或压缩未生效 |
例如,connect 明显偏高,优先看路径和丢包;ttfb 偏高但基础 RTT 正常,通常应检查 PHP-FPM、数据库查询和应用日志;ttfb 正常而 total 很高,则应检查页面体积、静态资源数量、压缩和缓存。
4. 以低风险配置改善跨区域访问
建议按照以下顺序处理:
- 确认 A、AAAA 记录没有指向错误地址。
- 确认 80、443 端口可以从目标网络访问。
- 启用 HTTPS keepalive 和 HTTP/2,减少页面包含多个资源时的连接开销。
- 对 CSS、JavaScript、字体和图片设置合理缓存。
- 对文本内容启用 gzip,不压缩已经压缩过的 JPEG、PNG、WebP 和 ZIP。
- 减少首屏需要加载的资源数量,避免将大文件放入首屏 HTML。
- 检查 PHP-FPM 等待队列、数据库慢查询和应用错误日志。
- 如果多个目标访问网络的静态资源延迟明显,再评估内容分发服务;启用后要重新验证缓存规则、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. 应用发布后需要快速回退
如果当前版本通过软链接发布,先查看历史版本:

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 切换前后的记录;
- 证书路径和续期方式;
- 本次上线使用的命令、时间和验证结果。