必须将Nginx的root设为public目录,配置try_files $uri $uri/ /index.php?$query_string,用$realpath_root指定SCRIPT_FILENAME,禁止访问.env等敏感文件,并透传HTTPS头及X-Forwarded-Proto。

要让Laravel项目在Nginx上跑起来且不暴露.env文件、不404、不丢GET参数,必须绕过默认配置陷阱——直接把项目根目录设为Nginx的root,等于把config/、app/、.env全扔到公网可下载路径下,而路由失效根本不是代码问题,是Nginx压根没把请求送进public/index.php。
设置正确的Web根目录
打开你的站点配置文件(通常在/etc/nginx/sites-available/your-site),定位到server块内。
将root指令明确指向Laravel项目的public子目录,例如:root /var/www/myapp/public;
【root必须是public目录,绝不能是项目根目录】——否则访问https://yoursite.com/.env会直接下载明文配置,数据库密码、API密钥全部泄露。
若使用符号链接部署(如/var/www/current → /var/www/releases/20260806),确保current/public是真实存在的目录,或在server块开头加disable_symlinks off;,否则Nginx无法解析路径。
启用Laravel路由转发
在server块中添加或确认存在以下location /块:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
这行不是可选项,是Laravel能响应/users、/api/posts这类非物理路径的前提。漏掉它,Nginx对任何不存在的文件或目录直接返回404,根本不会交由PHP处理。
必须用$query_string而非$args——前者保证?page=2&sort=name完整透传,后者在某些Nginx版本中会截断ampersand。
安全加固:阻止敏感文件访问
在server块内添加独立location规则:
location ~ /\.(env|git|htaccess|lock|log)$ {
deny all;
}
这条规则拦截以.env、.git等结尾的请求,防止源码泄露。注意正则末尾的$,避免误杀user_env.php这类合法文件。
正确传递PHP脚本路径
找到处理PHP的location块(通常是location ~ \.php$),检查其中fastcgi_param SCRIPT_FILENAME的值:
✅ 正确写法:fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
❌ 错误写法:fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
【必须用$realpath_root,不能用$document_root】——符号链接部署时,$document_root会拼出错误物理路径,导致PHP-FPM报No input file specified或加载错版本的文件。
同时,在该location块内必须加try_files $uri =404;,防止攻击者构造/fake.php/xxx绕过重写规则,直接执行任意PHP文件。
HTTPS与URL生成一致性
如果你启用了SSL(比如通过Certbot),在server块(listen 443 ssl那一个)里添加:
fastcgi_param HTTPS on;
并确保.env中APP_URL以https://开头,例如:APP_URL=https://myapp.com
这两项缺一不可。否则Laravel的url()、asset()函数会生成HTTP链接,前端混合内容警告或资源加载失败。
若使用Cloudflare等CDN,在server块中还需加:fastcgi_param HTTP_X_FORWARDED_PROTO $scheme;,并在Laravel中启用App\Http\Middleware\TrustProxies中间件。
静态资源404排查
如果CSS、JS返回404但页面能渲染、API正常,大概率是Nginx未正确处理静态文件。
方法一:在location ~* \.(js|css|png|jpg|gif|woff2?|ttf|eot|svg)$块中显式添加:
try_files $uri =404;
expires 1y;
add_header Cache-Control "public, immutable";
方法二:临时验证是否sendfile冲突,加一行sendfile off;,若恢复则说明底层文件权限或路径映射异常。


















