Laravel部署后storage和bootstrap/cache目录必须可写,否则导致500错误、日志失败、缓存生成失败、队列无法运行;需将目录属组设为web服务器用户(如www-data),权限设为775并启用g+s继承组写权限,同时处理SELinux或systemd等额外限制。

Laravel 部署后 storage 和 bootstrap/cache 目录必须可写,否则日志写不进、缓存生成失败、队列无法运行——这不是可选项,是运行前提。
为什么 storage 目录权限不对会导致 500 错误
Laravel 在运行时会往 storage/logs 写日志、storage/framework 存 session/cache/views、storage/app 存上传文件。PHP 进程(比如 nginx 用户或 www-data)没写权限,就会报 file_put_contents(...): failed to open stream: Permission denied,页面直接 500。
- 常见错误现象:
production.ERROR: file_put_contents(/var/www/myapp/storage/logs/laravel.log): failed to open stream: Permission denied - 不是所有环境都一样:本地开发用
php artisan serve是当前用户跑的,但生产环境是 web server 用户(如www-data、nginx或apache)在跑 - 不能简单
chmod -R 777 storage:不安全,且部分系统(如启用了 SELinux 的 CentOS)还会拦截
正确的权限设置步骤(Linux + Nginx/Apache)
核心思路:让 web server 用户对 storage 和 bootstrap/cache 拥有组写权限,而不是全开 777。
- 确认 web server 用户名:
ps aux | grep nginx或ps aux | grep apache,通常为www-data(Ubuntu/Debian)或nginx(CentOS/RHEL) - 把项目目录归给该用户和组:
sudo chown -R $USER:www-data /var/www/myapp - 设好目录权限:
sudo chmod -R 775 storage bootstrap/cache - 确保新文件继承组权限(关键!):
sudo chmod g+s storage bootstrap/cache—— 否则子目录新建后组权限丢失 - 如果用 Supervisor 跑队列,也要确保
supervisor进程用户和 web server 用户一致,否则队列 worker 写不了storage
SELinux 或 systemd 环境下的额外限制
CentOS/RHEL 默认开启 SELinux,即使 chmod 正确,也会因上下文标签拒绝写入。
- 检查是否被阻止:
sudo ausearch -m avc -ts recent | grep storage - 临时放行(调试用):
sudo setsebool -P httpd_can_network_connect 1 && sudo setsebool -P httpd_read_user_content 1 - 更稳妥做法:
sudo semanage fcontext -a -t httpd_sys_rw_content_t "/var/www/myapp/storage(/.*)?",然后sudo restorecon -Rv /var/www/myapp/storage - systemd 启动的 PHP-FPM 如果用
PrivateTmp=true,也可能导致storage路径不可见——需关掉或改用 socket 模式
最常被忽略的一点:部署脚本里如果用了 git pull 或 rsync,新拉下来的 storage 目录权限会重置,必须在部署流程末尾重新执行 chown 和 chmod g+s。不然上线后第一波请求就崩。


















