
1. 为什么我选择在 CentOS 7 上手工搭建 WordPress把 WordPress 跑起来这件事说简单也简单很多主机面板点几下就能装好说复杂也复杂一旦遇到性能瓶颈、权限报错、伪静态失效面板背后到底发生了什么你完全不知道。我自己的习惯是但凡一个环境要长期维护就一定要从零手工搭一遍把每个组件的配置文件放在哪、日志在哪、出问题先看什么全部摸清楚。这套 CentOS 7 MySQL Nginx PHP 7 的组合虽然现在看起来不算最新但它在大量存量服务器上仍然是主力尤其是那些跑了五六年、上面还挂着好几个站点的老机器。你如果只会用一键脚本碰到老环境基本就抓瞎。这篇内容适合谁看一是刚接触 Linux 运维、想完整走一遍建站流程的新手二是手里有台老服务器、想自己把 WordPress 迁过来或者重新部署的站长三是想搞清楚 Nginx 和 PHP-FPM 之间到底怎么通信、为什么权限老是配不对的开发者。我会把每一步的命令、配置、参数选择理由都写清楚包括我自己踩过的坑。整套流程走下来大概需要 40 分钟到 1 小时取决于你的网络和手速。先说清楚这套架构里每个角色干什么。Nginx 负责接收浏览器请求静态文件图片、CSS、JS它自己直接返回遇到 PHP 文件就转交给 PHP-FPM 处理PHP-FPM 是一个常驻进程池专门执行 PHP 代码WordPress 的所有逻辑都跑在这里MySQL 存数据文章、用户、评论、设置全在里面。三者通过本机的 socket 或者 TCP 端口通信。理解了这个数据流向后面配置的时候你就知道每个参数是在解决哪个环节的问题。提示CentOS 7 的官方维护已经进入尾声很多软件源里的版本偏旧。如果你是在生产环境新部署建议评估更新的系统版本但如果是维护存量机器本文的流程完全适用。2. 部署前的环境准备与基础配置2.1 系统更新与必要工具安装拿到一台干净的 CentOS 7第一件事不是急着装软件而是先把系统更新到最新并且装上一批后面会用到的工具。很多人跳过这步结果装到一半发现没有wget、没有unzip又回头补很影响节奏。yum update -y yum install -y wget vim unzip net-tools epel-releaseepel-release这个源很关键后面装一些扩展包的时候会用到。net-tools提供netstat命令排查端口占用的时候比ss更直观虽然ss更现代但老运维习惯用netstat。更新完之后建议重启一次尤其是内核有更新的时候。重启前确认你没有正在跑的重要任务。2.2 关闭 SELinux 与配置防火墙这一步是新手最容易翻车的地方。SELinux 是 CentOS 的安全增强模块它会限制 Nginx 去访问/var/www目录、限制 PHP 去连数据库。很多教程让你直接关掉我的建议是学习环境直接关生产环境学会配策略。但为了让你先把站跑起来这里先关掉后面我会讲怎么用正确的方式处理。setenforce 0 sed -i s/SELINUXenforcing/SELINUXdisabled/g /etc/selinux/config第一行是临时关闭立即生效第二行是永久关闭重启后生效。两行都要执行只执行第一行的话重启就恢复了。防火墙方面CentOS 7 默认用的是 firewalld。你需要放行 HTTP80、HTTPS443如果你还要用 SSH 远程管理22 端口别关。firewall-cmd --permanent --add-servicehttp firewall-cmd --permanent --add-servicehttps firewall-cmd --permanent --add-servicessh firewall-cmd --reload注意如果你在云服务器上操作放行端口之前先确认云平台的安全组也开了对应端口否则本地防火墙开了也没用。这是两个独立层面的事情我见过太多人只配了一边然后怀疑人生。2.3 创建站点目录与专用用户我不建议用 root 跑网站也不建议用 root 去管理网站文件。正确做法是创建一个专门的用户和用户组让 Nginx 和 PHP-FPM 都以这个身份去读写网站目录。groupadd www useradd -g www -s /sbin/nologin www mkdir -p /var/www/wordpress chown -R www:www /var/www chmod -R 755 /var/www-s /sbin/nologin表示这个用户不能登录系统只能被服务调用安全性更好。目录权限设成 755意思是所有者可读写执行其他人可读可执行。这个权限对网站目录来说够用不要图省事设成 777那等于把门敞开。3. 三大核心组件的安装与配置3.1 MySQL 安装与安全初始化CentOS 7 自带的 MariaDB 其实和 MySQL 兼容度很高但为了标题里说的 MySQL我们装官方社区版。先添加官方源再安装。wget https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm rpm -ivh mysql80-community-release-el7-3.noarch.rpm yum install -y mysql-community-server装完之后启动并设置开机自启systemctl start mysqld systemctl enable mysqldMySQL 8 首次启动会生成一个临时密码藏在日志里用这条命令找出来grep temporary password /var/log/mysqld.log拿到临时密码后登录并修改mysql -uroot -p ALTER USER rootlocalhost IDENTIFIED BY 你的强密码;MySQL 8 默认的密码策略要求大小写字母、数字、特殊字符都有长度至少 8 位。如果你嫌麻烦想降低策略不推荐生产环境这么做可以改validate_password.policy参数。接下来创建 WordPress 专用数据库和用户。这里有个原则不要用 root 去连 WordPress一旦网站被攻破攻击者拿到的就是 root 权限整个数据库服务器都完了。CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER wpuserlocalhost IDENTIFIED BY 另一个强密码; GRANT ALL PRIVILEGES ON wordpress.* TO wpuserlocalhost; FLUSH PRIVILEGES;字符集选utf8mb4而不是utf8因为 MySQL 里的utf8其实是残缺的存不了 emoji 和部分生僻字utf8mb4才是真正的完整 UTF-8。这个坑我在早期项目里踩过用户发个带表情的评论直接报错。3.2 PHP 7 安装与扩展配置CentOS 7 默认源里的 PHP 是 5.4太老了WordPress 新版本已经不支持。我们需要引入第三方源来装 PHP 7.4这个版本稳定且兼容性好。yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm yum install -y yum-utils yum-config-manager --enable remi-php74 yum install -y php php-fpm php-mysql php-gd php-mbstring php-xml php-json php-curl php-zip php-opcache这里装的扩展每一个都有用我逐个说下为什么不能省扩展作用不装的后果php-mysql连接 MySQL 数据库WordPress 直接无法安装php-gd图片处理无法生成缩略图、无法裁剪头像php-mbstring多字节字符串处理中文乱码、截断出错php-xmlXML 解析无法导入导出、部分插件报错php-curlHTTP 请求无法调用外部 API、更新检查失败php-zip压缩包处理无法在线安装插件和主题php-opcache字节码缓存性能下降明显PHP 重复编译装完之后验证版本php -v应该显示 PHP 7.4.x。然后配置 PHP-FPM。编辑/etc/php-fpm.d/www.conf重点改这几项user www group www listen /var/run/php-fpm/www.sock listen.owner www listen.group www listen.mode 0660用 Unix socket 而不是 TCP 端口127.0.0.1:9000通信因为 socket 不走网络协议栈性能更好而且不用担心端口被外部访问。listen.mode设成 0660只有 www 用户和组能读写这个 socket安全。还要调整 PHP 的上传限制WordPress 默认上传限制往往不够用upload_max_filesize 64M post_max_size 64M max_execution_time 300 memory_limit 256M这几个参数在/etc/php.ini里改。max_execution_time调到 300 秒是为了应对导入大文件或者装大插件时的超时。3.3 Nginx 安装与虚拟主机配置Nginx 直接用 EPEL 源装就行yum install -y nginx systemctl start nginx systemctl enable nginx核心是虚拟主机配置。在/etc/nginx/conf.d/下新建wordpress.confserver { listen 80; server_name your-domain.com www.your-domain.com; root /var/www/wordpress; index index.php index.html; access_log /var/log/nginx/wordpress_access.log; error_log /var/log/nginx/wordpress_error.log; location / { try_files $uri $uri/ /index.php?$args; } location ~ \.php$ { fastcgi_pass unix:/var/run/php-fpm/www.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location ~ /\.ht { deny all; } }try_files这行是 WordPress 伪静态的关键。它的逻辑是先找有没有这个具体文件没有就找有没有这个目录还没有就把请求交给index.php处理。这样/2024/01/hello-world/这种固定链接才能正常工作而不是返回 404。location ~ /\.ht是禁止访问.htaccess文件。虽然 Nginx 不用.htaccess但 WordPress 会在根目录生成一个里面可能包含敏感信息禁止外部访问是必要的。配置完检查语法并重载nginx -t systemctl reload nginx4. WordPress 部署实操全流程4.1 下载与文件权限设置到 WordPress 官网下载最新版解压到站点目录cd /tmp wget https://wordpress.org/latest.tar.gz tar -xzf latest.tar.gz cp -r wordpress/* /var/www/wordpress/ chown -R www:www /var/www/wordpress权限设置是重灾区。我的做法是目录 755文件 644wp-config.php单独设成 640。find /var/www/wordpress -type d -exec chmod 755 {} \; find /var/www/wordpress -type f -exec chmod 644 {} \; chmod 640 /var/www/wordpress/wp-config.php为什么wp-config.php要更严因为它里面存着数据库账号密码640 意味着只有所有者和同组用户能读其他用户连读都不行。这是最小权限原则的体现。4.2 配置文件生成与数据库连接复制一份配置模板cp /var/www/wordpress/wp-config-sample.php /var/www/wordpress/wp-config.php vim /var/www/wordpress/wp-config.php填入前面创建的数据库信息define(DB_NAME, wordpress); define(DB_USER, wpuser); define(DB_PASSWORD, 你的数据库密码); define(DB_HOST, localhost); define(DB_CHARSET, utf8mb4); define(DB_COLLATE, );然后去 WordPress 官方密钥生成页面拿一组认证密钥替换掉文件里那一段AUTH_KEY之类的占位符。这一步很多人偷懒不换结果就是所有用默认密钥的站点存在被伪造登录的风险。密钥的作用是给登录 cookie 签名密钥一样签名就能互相伪造。4.3 浏览器安装与固定链接设置浏览器访问你的域名会进入安装向导。填站点标题、管理员用户名、密码、邮箱。这里有个安全建议管理员用户名不要用 admin这是暴力破解最常试的名字换个个性化的。安装完成后进后台设置 - 固定链接选“文章名”或者自定义结构。这一步会触发 Nginx 的try_files规则如果前面配置对了页面就能正常访问如果返回 404说明伪静态没生效回去检查 Nginx 配置。提示改完固定链接后如果文章页打不开先看 Nginx 的 error log大概率是try_files那行写错了或者fastcgi_param少了SCRIPT_FILENAME。5. 常见问题排查与性能调优5.1 典型报错速查表部署过程中最容易遇到的几个问题我整理成表格方便你对照排查现象可能原因排查方向502 Bad GatewayPHP-FPM 没启动或 socket 路径不对systemctl status php-fpm检查 nginx 配置里的 socket 路径403 Forbidden目录权限不对或 index 文件缺失检查index.php是否存在目录权限是否 755无法连接数据库账号密码错或 socket 位置不对用mysql -uwpuser -p手动测试连接上传图片失败目录不可写或 PHP 上传限制太小检查wp-content/uploads权限看 php.ini 限制固定链接 404Nginx 伪静态规则缺失检查try_files配置白屏无报错PHP 内存不足或扩展缺失开WP_DEBUG看 PHP error log5.2 我踩过的几个坑第一个坑是 SELinux。有次我明明权限都设对了Nginx 就是读不了文件日志里报Permission denied。查了半天才发现是 SELinux 在拦。临时用setenforce 0解决但生产环境正确做法是用chcon给目录打上正确的安全上下文标签或者用semanage fcontext配策略。这个我建议你专门花时间学一下别一直靠关 SELinux 混日子。第二个坑是 PHP-FPM 的 socket 权限。Nginx 和 PHP-FPM 如果跑在不同用户下socket 的listen.owner和listen.group必须和 Nginx 的工作用户匹配否则 Nginx 连不上 socket报 502。我一般让两者都用 www 用户省去这个麻烦。第三个坑是 MySQL 8 的认证插件。MySQL 8 默认用caching_sha2_password老版本的 PHP 客户端可能不认。如果连接报认证错误把用户改成mysql_native_passwordALTER USER wpuserlocalhost IDENTIFIED WITH mysql_native_password BY 密码;5.3 性能调优的几个实用参数站跑起来之后如果访问量上来可以调这几个地方。PHP-FPM 的进程池参数在www.conf里pm dynamic pm.max_children 50 pm.start_servers 5 pm.min_spare_servers 5 pm.max_spare_servers 35pm.max_children是最关键的它决定同时能处理多少个 PHP 请求。设太小高并发时请求排队设太大内存被吃光。经验算法是用服务器可用内存除以单个 PHP 进程平均占用内存大概 30-50MB。比如你有 2GB 可用内存除以 40MB大概能开 50 个。Nginx 层面可以开 gzip 压缩和静态文件缓存gzip on; gzip_types text/css application/javascript image/svgxml; gzip_min_length 1000; location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ { expires 30d; add_header Cache-Control public, no-transform; }gzip 能显著减小传输体积静态文件缓存能减少重复请求。这两个是性价比最高的优化几乎不增加复杂度。6. 后续维护与安全加固建议站建好只是开始维护才是长期工作。WordPress 本身、主题、插件都要定期更新但更新前一定先备份。我见过太多人直接点更新结果插件冲突导致整站白屏又没有备份只能重装。备份分两部分数据库和文件。数据库用mysqldumpmysqldump -uwpuser -p wordpress /backup/wordpress_$(date %F).sql文件直接打包wp-content目录就够了因为核心文件可以从官方重新下载但上传的图片、插件、主题配置都在wp-content里。安全方面除了前面说的不用 admin 用户名、不用 root 连数据库还建议装一个安全插件限制登录尝试次数以及定期检查wp-config.php的权限有没有被改回去。另外把 WordPress 后台的登录地址改掉很多安全插件支持能挡掉大量自动化扫描。最后分享一个我自己的习惯每次部署完我会把整个流程的关键命令和配置整理成一个脚本或者笔记下次再部署直接照着走省得重新回忆。这套 CentOS 7 MySQL Nginx PHP 7 的组合虽然老但把每个环节都吃透之后你换到任何新版本上思路都是通的无非是包管理命令和配置路径变一变。真正值钱的不是记住某条命令而是理解每个组件为什么这么配、出问题该往哪个方向查。