BLOG
Nginx站点配置中容易忽略的细节
Nginx 配置要保护源码目录,同时保证前台路由能正常转发。
先分清要保护什么、要放行什么
Nginx 站点配置里,最容易出问题的不是某个指令写错,而是对“哪些路径必须挡、哪些路径必须放”没有形成清晰边界。PHP 项目通常只应该把 public 目录暴露给外部访问,app、database、storage、tools 这些目录一旦被直接请求,就可能泄露源码、配置甚至备份文件。
但只做拦截还不够。前台路由依赖入口文件转发,如果规则顺序不对,拦截规则可能把正常请求也挡掉,或者伪静态失效,页面直接返回 404。配置的核心不是写一堆 location,而是让每条规则都回答一个问题:这个请求到底该交给谁处理。
配置前先确认三件事
动手改配置之前,先确认现有资料、最终用途和不能改动的部分。比如站点是否已有 HTTPS 证书、是否使用了反向代理、PHP 版本对应的 fastcgi 配置是哪种写法、是否有定时任务需要访问特定路径。这些信息决定了 location 规则怎么组织,也决定了改完以后要检查什么。
把工作拆成几个可以单独检查的步骤。每完成一项就能看到结果,而不是到最后才发现方向不对。通常按这个顺序处理:
- 先禁止访问敏感目录。
- 再让静态资源直接返回。
- 最后把不存在的路径统一交给入口文件。
这个顺序本身就是一个检查逻辑:拦截规则在最前面,静态资源规则次之,兜底转发放在最后。如果顺序颠倒,比如把 location / 的转发规则写在前面,后面的敏感目录拦截可能根本不会生效。
location 规则怎么组织才不容易出错
Nginx 的 location 匹配有优先级,不是按书写顺序从上到下执行。精确匹配(=)优先于前缀匹配(^~),前缀匹配优先于正则匹配(~ 或 ~*),最后才是普通前缀匹配。很多人在这里出错,是因为写了多个 location 但没意识到它们之间的优先级关系。
一个常见的做法是,用 location ^~ 拦截敏感目录,确保这些路径不会被后面的正则规则接管:
```nginx
location ^~ /app/ { deny all; }
location ^~ /database/ { deny all; }
location ^~ /storage/ { deny all; }
location ^~ /tools/ { deny all; }
```
deny all 直接返回 403,比 return 404 更明确——404 会让人误以为路径不存在,而 403 明确表示“资源存在但不允许访问”。
静态资源单独处理。图片、CSS、JavaScript 文件不需要经过 PHP 解析,直接让 Nginx 返回文件即可,既减轻 PHP 进程负担,也避免这些请求落入转发规则:
```nginx
location ~* \.(jpg|jpeg|png|gif|css|js|ico|svg|woff2?)$ {
expires 30d;
access_log off;
}
```
最后是前台路由的兜底转发。对于 ThinkPHP、Laravel 这类框架,通常需要把所有不存在的路径交给 index.php 处理:
```nginx
location / {
try_files $uri $uri/ /index.php?s=$uri&$args;
}
```
try_files 的含义是:先尝试按请求的 URI 找真实文件,找不到就找目录,再找不到就转发给 index.php。这样伪静态规则由框架内部解析,Nginx 层不需要写死每个路由。
验证配置不能只看页面能不能打开
配置改完,先执行 nginx -t 检查语法,确认无误后 nginx -s reload 重载。但语法正确不代表行为正确,必须逐项验证:
- 直接访问
https://你的域名/app/,应该返回 403。 - 访问
https://你的域名/storage/logs/,同样应该被拒绝。 - 访问一个不存在的伪静态路径,应该正常返回页面而不是 404。
- 访问真实的静态资源文件,应该直接返回文件内容,响应头里能看到 Nginx 而不是 PHP 的处理痕迹。
换一个使用环境重新查看也很重要。页面要检查电脑和手机,服务器设置要检查日志和备份。只盯着浏览器看页面是否正常,很容易漏掉错误日志里反复出现的 403 或 500。
容易忽略的地方
只关注网站能打开,忽略错误日志、备份和磁盘空间,是运维里最常见的盲区。站点能访问不代表配置健康,错误日志里可能已经堆满了扫描器对敏感路径的探测记录,磁盘空间可能因为日志文件过大而告警。
把后台、上传目录和私有资源暴露给搜索引擎抓取,是另一个容易被忽略的问题。robots.txt 只能约束遵守协议的搜索引擎,不能阻止恶意抓取。上传目录如果允许 PHP 执行,攻击者上传一个脚本文件就可能直接拿下站点。这类目录应该单独配置为不解析 PHP:
```nginx
location ^~ /uploads/ {
location ~ \.php$ { deny all; }
}
```
没有记录变更和登录行为,后期排查问题缺少依据。改了什么配置、什么时候改的、为什么改,这些信息如果不记录,等出问题的时候只能靠回忆。每次修改配置前先备份原文件,修改后记录变更内容,这是成本最低的恢复手段。
遇到异常时应先保留现场和记录,再逐项排除。不要在原因不明时连续修改多个地方——改得越多,越难判断到底是哪一步导致了问题。先看错误日志,确认是权限问题、路径问题还是转发问题,再针对性地修改。
上线前后的检查边界
上线前检查环境、备份、日志、HTTPS、权限和性能。上线后同样要观察一段时间,确认没有异常请求和错误日志。恢复边界要提前想清楚:配置备份放在哪里、怎么回滚、回滚后是否需要重新加载 PHP 进程。
后续可以加入安全响应头和访问日志分析。能公开的设置、过程和结果,补进对应文章,方便下次维护时直接参考。
评论
登录后可发表评论。