恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Laravel项目部署:从Windows 10到Gitee再到服务器的完整链路
首页
资讯中心
/
Laravel项目部署:从Windows 10到Gitee再到服务器的完整链路
Laravel项目部署:从Windows 10到Gitee再到服务器的完整链路
发布时间:2026/10/10 19:41:18
做 Laravel 项目最尴尬的一个时刻就是本地php artisan serve跑得好好的给同事演示也没问题结果一到部署就卡住。代码在 Windows 10 上写好怎么弄到服务器上用 U 盘拷贝用压缩包上传再解压这些办法也不是不行但一旦项目要更新你就得重复上传整个文件夹时间一长谁也受不了。更专业的做法是让 Gitee 当中间人本地把代码推送到 Gitee服务器再从 Gitee 拉取代码并完成部署。这篇文章就围绕这条链路把 Windows 10 开发环境、Laravel 框架、Gitee 仓库、服务器部署这四件事串起来讲清楚适合项目已经在本地跑通、但第一次面对“上线”这个动作的开发者。这个流程远没有想象的复杂。本质上就三步本地和 Gitee 建立信任关系把代码推上去服务器和 Gitee 也建立信任关系把代码拉下来最后在服务器上补齐依赖、配置环境并让网站跑起来。真正容易出问题的是第一遍走流程时那些不起眼的细节。比如分支名对不上、.env被提交进仓库、服务器上storage目录权限不对、Nginx 伪静态没配导致路由 404。我会把每一步的操作命令、配置文件和踩坑点都写出来你跟着走一遍基本能避开 90% 的部署问题。1. 项目拆解从 Windows 10 到服务器Laravel 项目的完整交付链路1.1 为什么用“本地推送、服务器拉取”这套链路很多第一次接触部署的人会问为什么不能直接在服务器上开发或者为什么不用 FTP 上传代码答案很简单——这两条路对 Laravel 这种框架项目来说都不可持续。直接在服务器上开发等于放弃本地开发环境的各种便利。你在 Windows 10 上装了 IDE、调试工具、浏览器扩展这些在服务器上统统没有。而且服务器通常是 Linux 系统你还要额外熟悉一套环境效率很低。用 FTP 上传则更危险因为 Laravel 项目里有大量文件手动上传很容易漏文件、传错目录。更重要的是FTP 无法保留版本历史——你改坏了代码想回滚到上一个能跑的版本FTP 做不到。而“本地推送 → Gitee 中转 → 服务器拉取”这套链路本质上是把 Git 的版本管理能力延伸到了部署环节。本地提交一次Gitee 上就多一个历史版本。服务器拉取一次线上代码就对应一个明确的提交记录。出了问题git log一看就知道线上跑的是哪个版本git checkout就能回到上一个稳定版。这套流程对单人开发有效对团队协作更是刚需——Gitee 上的代码仓库可以接入成员管理、代码审查、Issue 跟踪这些是 FTP 和 U 盘拷贝给不了的东西。1.2 链路中三个角色各自要做的事这条链路里一共有三个角色开发机、Gitee 仓库、服务器。很多人对部署的理解是“把文件放到服务器上”其实更准确的说法是“让三个角色之间形成一套标准流程”。角色扮演方核心任务开发机Windows 10编写 Laravel 代码、本地调试、提交代码并推送到远程仓库远程仓库Gitee托管代码、保存版本历史、作为开发机与服务器之间的中转分发点服务器Linux Nginx PHP-FPM MySQL拉取代码、安装依赖、配置环境变量、对外提供 Web 服务有一点要特别说明Laravel 项目部署比静态网页或普通 PHP 项目更繁琐原因在于它有三个典型特征。第一它依赖 Composer 管理外部包代码仓库里通常不包含vendor目录服务器拉下来之后必须先安装依赖第二它依赖环境变量配置数据库、缓存、应用密钥等信息.env文件不能直接放进 Git 仓库服务器上需要单独创建第三它的入口文件在public目录下Web 服务器的根目录必须指向public还要配好伪静态规则才能支持 Laravel 的路由系统。把这三点理解了后面的部署操作就有清晰的目标了。2. 本地准备Windows 10 下的 Git 安装、SSH 密钥与 Gitee 连接2.1 安装 Git 并配置全局参数Windows 10 上第一步是安装 Git。直接去 Git 官网下载 Windows 版本的安装包安装时一路默认即可。有几个选项可以留意一下默认编辑器建议保留 Vim 或者改成 Notepad不影响后面操作PATH 环境变量选择 “Git from the command line and also from 3rd-party software” 那一项换行符转换建议选 “Checkout as-is, commit as-is”这个选择能减少一部分换行符问题后面我会专门讲 CRLF 的坑。安装完 Git 之后打开 Git Bash先配置身份信息。这一步很重要因为 Git 的每一次提交都会把这两个信息写进提交记录里。如果不配置提交时会报错或者生成一串占位信息到后面看历史记录时非常难受。git config --global user.name 你的名字 git config --global user.email 你的邮箱example.com强烈建议这里的邮箱和你在 Gitee 注册时用的邮箱保持一致。这样你推送到 Gitee 的提交记录能直接关联到你的 Gitee 账号团队协作时能看清谁提交了什么。配置完成后可以用git config --list检查一下确认两个参数都写进去了。2.2 生成 SSH 密钥并把公钥加到 GiteeWindows 10 下连接 Gitee 有两种协议可选HTTPS 和 SSH。HTTPS 每次推送都要输账号密码虽然 Git 可以缓存凭证但换机器、换用户时经常会遇到凭证冲突。SSH 则是一次配置永久免密并且安全性更高——它通过公钥和私钥配对的方式验证你的身份私钥保存在本地公钥放在 Gitee。生成 SSH 密钥的命令是在 Git Bash 里执行ssh-keygen -t rsa -b 4096 -C 你的邮箱example.com执行后会出现提示让你选择保存路径直接回车用默认路径即可。默认路径是C:\Users\你的用户名\.ssh\id_rsa.pub其中id_rsa是私钥id_rsa.pub是公钥。再次强调私钥绝对不能泄露、不能上传到任何地方公钥可以分发到 Gitee 等平台。接着查看公钥内容cat ~/.ssh/id_rsa.pub输出结果是一长串以ssh-rsa开头、以你的邮箱结尾的字符串。复制它然后打开 Gitee 网站登录后进入 设置 → 安全设置 → SSH 公钥把复制的内容粘贴进去起一个容易辨识的标题比如“Windows10-dev”保存即可。2.3 验证连接与常见失败处理配置好公钥后在 Git Bash 里执行下面的命令验证是否连通ssh -T gitgitee.com第一次执行时系统会提示无法确认 host 身份问你是否继续连接输入yes回车。如果配置正确会看到类似这样的输出Hi 你的用户名! Youve successfully authenticated, but GITEE.COM does not provide shell access.这句提示的意思是认证成功但 Gitee 不提供 shell 登录能力这很正常说明 SSH 密钥已经生效。我遇到过不少次Permission denied (publickey)的情况排查顺序一般是检查公钥是否完整复制到了 Gitee检查本机 SSH key 是否存在ls -la ~/.ssh确认你当前用的账号和 Gitee 上添加公钥的账号是同一个。还有一种容易被忽略的情况如果你之前用 HTTPS 方式克隆过仓库Git 会优先尝试 HTTPS 认证这时需要检查仓库的 remote 地址是不是gitgitee.com开头的 SSH 格式。3. 推送实战创建 Gitee 仓库、配置 .gitignore 并完成首次提交3.1 创建 Gitee 仓库时的几个关键选择SSH 配置好之后下一步是去 Gitee 上创建一个空仓库。进入 Gitee 首页点“新建仓库”会看到几个需要填的选项。仓库名称最好和项目名一致比如laravel-blog方便识别。路径会自动生成一般不用改。“是否开源”这个选项要慎重开源仓库是所有人都能看到的私有仓库只有你和被你添加的成员能访问。如果你的项目里含业务敏感信息或者暂时不想公开就选“私有”。下面有个初始化仓库的选项里面包含是否自动生成 README 文件。我个人建议先不要勾选自动生成 README也不要在 Gitee 上勾选添加 .gitignore 模板。理由很简单——如果你在 Gitee 上初始化了仓库本地第一次推送时就会出现“两边各自有独立提交历史”的冲突。后面对新手来说处理起来很麻烦还要先 pull 再 push。先创建空仓库本地直接推是最顺滑的路径。还要留意一个设置Gitee 创建仓库时可以选“分支模型”默认是master还是main不同版本界面可能不一样记住你选的这个分支名。后面本地仓库初始化的时候要把本地分支名改成和远程一致否则推送时会提示分支不匹配。3.2 Laravel 项目的 .gitignore哪些文件绝对不能进仓库Laravel 项目创建时根目录下已经自带了一份.gitignore文件。这份文件的作用是告诉 Git某些目录和文件不要纳入版本控制。你可千万别觉得没必要这是 Laravel 项目部署中几乎最重要的防线。至少要确认下面这些内容在.gitignore里/vendorComposer 安装的依赖包每个环境都可以单独执行composer install生成不需要、也不应该进仓库node_modules同理前端依赖由npm install或yarn生成.env环境变量文件包含数据库密码、APP_KEY 等敏感信息绝不能进仓库/storage/*.key存储目录下的密钥文件storage/logs/*.log日志文件.idea、.vscodeIDE 的本地配置不同开发者配置不同不该提交.phpunit.result.cache测试缓存如果你发现vendor已经被提交进了仓库不要慌用下面的命令把它从 Git 管理中移除但保留本地文件git rm -r --cached vendor git commit -m chore: remove vendor directory from version control这里特别强调.env的问题。我在现实中见过不止一次因为.env被误提交导致数据库密码、邮箱密码泄露甚至 APP_KEY 被公开后攻击者可以利用 Laravel 的加密机制反序列化执行恶意代码。既然项目默认的.gitignore已经把你保护好了就不要再自己去把.env手动git add进去。3.3 首次推送到远程仓库完整命令流代码准备就绪后开始首次推送。打开 Git Bash进入你的 Laravel 项目根目录依次执行# 初始化本地仓库 git init # 统一分支名假设远程仓库分支模型是 main git branch -M main # 把所有文件加入暂存区 git add . # 提交 git commit -m feat: 初始化 Laravel 项目 # 关联远程仓库换成你自己的仓库地址 git remote add origin gitgitee.com:你的用户名/你的仓库名.git # 推送并建立上游跟踪 git push -u origin main关于git branch -M main这一步多解释一句。不同版本的 Git 默认分支名不一样有的是master有的是main如果不统一推送时 Git 会提示fatal: The current branch master has no upstream branch或者远程拒绝推送。先加这个参数保证本地分支和远程仓库分支一致后面就不纠结了。推送成功后打开 Gitee 仓库页面就能看到代码了。-u参数的含义是“建立上游跟踪”意思是把本地main分支和远程main分支关联起来之后你再执行git push或git pull就不用再带仓库地址和分支名了。如果第一次推送就被拒绝rejected大概率是远程仓库里已经有提交记录了。解决思路很简单如果你确认远程仓库是空的或不该有的可以把远程仓库清掉重建如果远程仓库里确实有你需要的内容比如同事推过代码那就先拉取再合并git pull --rebase origin main git push -u origin main4. 服务器部署从 Gitee 拉取代码到 Nginx 站点上线4.1 服务器环境准备LNMP 还是宝塔面板代码推送到 Gitee 之后主角切换到服务器。服务器操作系统一般用 Linux常见的有 Ubuntu、Debian、CentOS。以 Ubuntu 22.04 为例Laravel 10 要求 PHP 版本不低于 8.1这里我装 PHP 8.2 比较稳妥。服务器环境的搭建有两条路线手动搭建 LNMPLinux Nginx MySQL PHP或者用宝塔面板这类可视化工具。两者各有优劣。宝塔面板对新手极度友好图形界面上点一点就能装好 Nginx、PHP、MySQL还能创建站点、管理 SSL 证书。我自己的建议是着急上线、不想折腾环境的用宝塔想理解部署原理、以后好排查问题的手动搭建。不管用哪条路线最终服务器上要有的核心软件是固定的NginxWeb 服务器负责接收 HTTP 请求、转发给 PHP 处理PHP 8.x PHP-FPMPHP 解释器和进程管理器MySQL / MariaDB数据库ComposerPHP 依赖管理工具Git用于从 Gitee 拉取代码Ubuntu 上手动安装这些软件包的命令大概是这样sudo apt update sudo apt install -y nginx sudo apt install -y php8.2-fpm php8.2-cli php8.2-mysql php8.2-mbstring php8.2-xml php8.2-curl php8.2-zip php8.2-bcmath php8.2-gd sudo apt install -y composer sudo apt install -y git注意 PHP 扩展我写了一个列表这些是 Laravel 正常运行必需的。漏装php8.2-mbstring会导致使用字符串处理时报错漏装php8.2-xml会导致一些依赖包安装失败漏装php8.2-zip会直接影响composer install的执行。安装完成后用php -v验证版本用php -m列出已加载的扩展。4.2 在服务器上生成 SSH 密钥并从 Gitee 拉取代码服务器上的代码来源有两种方式SSH 方式和 HTTPS 方式。HTTPS 方式最简单克隆无需额外配置但之后每次git pull都可能要求输入账号密码或 Token。SSH 方式需要做一次密钥配置但配好之后一劳永逸。服务器上生成 SSH 密钥ssh-keygen -t rsa -b 4096 -C deployexample.com生成后查看公钥cat ~/.ssh/id_rsa.pub把输出的公钥添加到 Gitee。这里有一个细节不建议把服务器公钥加在“个人 SSH 公钥”列表里更好的做法是使用 Gitee 的“部署公钥”功能。部署公钥可以绑定到指定仓库而且可以只给只读权限这样即使服务器被入侵也只是能拉取这个仓库的代码不能往别的仓库推送东西风险可控。配置完成后把代码克隆到服务器。我习惯统一放在/var/www目录下sudo mkdir -p /var/www cd /var/www sudo git clone gitgitee.com:你的用户名/你的仓库名.git克隆完成后你会看到/var/www/你的仓库名这个目录。这里要立刻处理目录权限问题。PHP-FPM 默认以www-data用户运行如果项目目录的属主是 rootPHP 就没有权限写日志、写缓存。我通常的做法是把项目目录的属主改成www-datasudo chown -R www-data:www-data /var/www/你的仓库名这一步看起来不起眼但如果不做后面 Laravel 报“Permission denied”会让你排查很久。4.3 安装依赖与环境配置composer install、.env 与 key:generate代码拉下来之后第一件要做的事就是安装 PHP 依赖。因为 Laravel 项目的vendor目录默认不进 Git 仓库服务器上执行cd /var/www/你的仓库名 sudo -u www-data composer install --no-dev --optimize-autoloader这是手动搭建环境时比较推荐的顺序。--no-dev表示不安装开发环境依赖线上环境用不到phpunit、barryvdh/laravel-debugbar之类的包装上去只会拖慢应用、增加被攻击面。--optimize-autoloader会生成优化过的自动加载映射让 Laravel 加载类更快一点。接下来创建环境变量文件。Laravel 默认提供.env.example作为模板直接复制sudo -u www-data cp .env.example .env然后编辑.env把关键配置改成线上环境对应的值APP_NAME你的应用名 APP_ENVproduction APP_DEBUGfalse APP_URLhttps://你的域名 DB_CONNECTIONmysql DB_HOST127.0.0.1 DB_PORT3306 DB_DATABASE你的数据库名 DB_USERNAME你的数据库用户 DB_PASSWORD你的数据库密码这里有一个新手很容易忽略的点.env修改完之后必须执行sudo -u www-data php artisan key:generate这个命令会生成一个随机的 32 位字符串写入.env的APP_KEY字段。Laravel 用它做加密解密、session 签名、cookie 加密。如果APP_KEY为空页面会直接报错No application encryption key has been specified。在本地用php artisan serve时 Laravel 会自动处理但到服务器上手动部署这一步必须自己执行。如果项目有数据库迁移可以顺便跑一下sudo -u www-data php artisan migrate --force--force参数是在生产环境跳过确认提示因为这里不带APP_ENVproduction的话migrate 会停下来问“你确定要在生产环境执行吗”。还要建一个软链接让public/storage能访问到storage/app/public目录sudo -u www-data php artisan storage:link如果你用了 Laravel 的Storage磁盘功能上传过文件这一步一定要做不然前端访问上传图片会 404。关于权限我再补一条硬性要求sudo chmod -R 775 storage bootstrap/cachestorage目录要写日志、编译 Blade 模板、存 session 和缓存bootstrap/cache要存配置文件缓存。如果这两个目录不可写页面会白屏或报 500。4.4 Nginx 站点配置根目录、伪静态与 PHP-FPMLaravel 项目跑起来需要 Nginx 把请求交给 PHP-FPM 处理。Nginx 的站点配置文件一般放在/etc/nginx/sites-available/下然后在/etc/nginx/sites-enabled/里建软链接启用。创建一个站点配置比如/etc/nginx/sites-available/laravelserver { listen 80; server_name your-domain.com; root /var/www/你的仓库名/public; index index.php; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php8.2-fpm.sock; } location ~ /\.(?!well-known).* { deny all; } }逐个说明几个关键配置。root指向的是/var/www/你的仓库名/public而不是项目根目录。因为 Laravel 的入口文件是public/index.php所有 HTTP 请求都必须经过这个入口处理。如果把 root 指到项目根目录用户访问时会把.env、storage等敏感目录直接暴露出来非常危险。try_files $uri $uri/ /index.php?$query_string;是 Laravel 路由的伪静态规则。它的逻辑是先尝试把请求作为真实文件返回找不到再当作目录处理还找不到就全部交给index.php由 Laravel 的路由系统解析。没有这一行你访问/about这种路由时会直接 404因为服务器上根本没有about这个文件。location ~ \.php$这一段把以.php结尾的请求交给 PHP-FPM 处理。这里fastcgi_pass用的是 Unix socket具体路径要看你的 PHP 版本Ubuntu 上 PHP 8.2 对应/run/php/php8.2-fpm.sock。如果你用的不是 Ubuntu 或者 PHP 版本不同用php -v或systemctl status php8.2-fpm查一下路径。配置文件写好之后测试语法再重载sudo nginx -t sudo systemctl reload nginx到这里如果域名 DNS 解析已经指向服务器打开浏览器访问你的域名Laravel 网站应该就能正常显示了。5. 上线优化部署后的缓存刷新与日常更新流程5.1 上线前的几个必要设置网站能打开只是第一步上线前还要做几个优化设置否则后面的维护会比较折腾。Laravel 提供了一组缓存命令把配置、路由、视图编译成缓存文件提高整体响应速度sudo -u www-data php artisan config:cache sudo -u www-data php artisan route:cache sudo -u www-data php artisan view:cacheconfig:cache会把所有配置文件合并成一个缓存文件Laravel 加载配置时就不需要逐个读取.env和config目录了。route:cache同样会把路由表打包生产环境能明显降低路由匹配耗时。需要提醒的是执行了config:cache之后你再修改.env文件配置不会立即生效。此时要执行php artisan config:clear才能重新读取环境变量。这个特性很多新人不知道容易在改完数据库密码后得到一个“数据库连接错误”的 500 页面。再把.env里的APP_ENVproduction和APP_DEBUGfalse确认一遍。APP_DEBUGtrue时一旦发生异常Laravel 会把堆栈信息、环境变量、数据库连接信息打印在页面上。这在本地开发是神器在生产环境就是定时炸弹——任何一个报错页面都会把你的服务器底细暴露给访问者。如果条件允许建议顺手把 Nginx 的 80 端口重定向到 443HTTPS。证书可以用 Let’s Encrypt 免费申请配置好后在.env里把APP_URL改成https://开头同时再执行一次php artisan config:cache刷新配置。HTTPS 对加密 Cookie、登录状态保护都很重要这个不能省。5.2 日常更新流程拉取、装依赖、刷新缓存服务器上的 Laravel 项目上线之后你还会持续提交代码。日常发布更新的标准流程也应该形成固定套路。本地开发机上正常提交并推送git add . git commit -m feat: 增加某功能 git push origin main服务器上拉取最新代码并部署cd /var/www/你的仓库名 sudo -u www-data git pull origin main sudo -u www-data composer install --no-dev --optimize-autoloader sudo -u www-data php artisan migrate --force sudo -u www-data php artisan config:clear sudo -u www-data php artisan route:clear sudo -u www-data php artisan view:clear sudo -u www-data php artisan config:cache sudo -u www-data php artisan route:cache sudo -u www-data php artisan view:cache如果你没有修改数据库结构migrate可以不执行如果你更新的代码没有新增配置项config:clear和后面的config:cache也可以跳过。但我的习惯是每次都执行一套完整的部署命令因为有些第三方扩展在安装时会向config目录发布配置文件不刷新缓存会导致新配置不生效。注意到我用sudo -u www-data执行所有命令而不是直接用 root 或普通用户。原因前面提过PHP-FPM 以www-data用户运行用它执行这些命令生成的文件属主就是www-dataPHP 才有权限读写。如果用 root 执行composer install生成的vendor属主是 rootPHP 访问不到页面照样报错。这里说一句实在话更新时最怕的不是代码写错而是更新流程不固定。每次更新都靠“手动拖文件”或者“只传改过的那几个文件”迟早会漏掉东西。把所有发布动作固定成上面这一串命令做成一个脚本或写成笔记每次照做线上出问题就能快速定位是哪一步出了问题。6. 常见问题排查本地推送、服务器拉取与部署的坑6.1 本地到 Gitee 的典型问题推送时报Permission denied (publickey)这个提示说明 Git 没有找到有效的 SSH 密钥或者 Gitee 不认可你的公钥。检查顺序是本地~/.ssh/id_rsa.pub是否存在Gitee 后台是否添加了正确的公钥执行ssh -T gitgitee.com看报什么错。如果提示Host key verification failed是因为服务器指纹未确认重连并输入yes即可。报failed to push some refs远程仓库有本地没有的提交记录。最常见的原因就是你在创建 Gitee 仓库时勾选了自动生成 README 或 .gitignore。解决方法是先拉取合并再推送git pull --rebase origin main git push -u origin main--rebase会把本地的提交“接”到远程提交的后面保持线性历史比直接默认合并更干净。推送时出现LF will be replaced by CRLF警告这是 Windows 和 Linux 换行符差异导致的。Windows 用CRLF回车换行Linux 用LF换行。Git 默认在 Windows 上会把LF转成CRLF这个警告大多数情况下无影响。但如果项目里有 Bash 脚本被转换后上传到 Linux 服务器执行会报$\r: command not found这种错误。解决方式是在项目根目录加一个.gitattributes文件* textauto eollf *.sh text eollf这样 Git 会把文本文件统一按LF提交服务器拉取后就不会有\r的干扰。6.2 服务器上的典型问题composer install报内存不足服务器内存太小或者 PHP 的memory_limit太小Composer 在解析依赖时会报Allowed memory size exhausted。临时解决方式sudo -u www-data COMPOSER_MEMORY_LIMIT-1 composer install --no-dev --optimize-autoloader-1表示不限制内存。但如果项目依赖很重建议还是给服务器加内存或者开启 Swap否则 composer 装一半崩了后面全是麻烦。git pull时提示要输入密码说明服务器上这个仓库是用 HTTPS 协议克隆的。改成 SSH 方式先在服务器上生成 SSH 密钥并添加到 Gitee然后sudo -u www-data git remote set-url origin gitgitee.com:你的用户名/你的仓库名.git sudo -u www-data git pull origin main改一次之后后续 pull 就不用输密码了。页面报 500但storage/logs/laravel.log里没有内容有一种情况很隐蔽storage目录权限是www-data但你执行php artisan命令时用的用户是 root导致storage/logs/laravel.log的属主被 root 占用PHP 写不进去日志文件里自然啥也没有。排查时先看文件属主ls -la /var/www/你的仓库名/storage/logs/ sudo chown -R www-data:www-data /var/www/你的仓库名/storage sudo -u www-data php artisan config:clear6.3 部署后页面异常的排查速查表我把部署后最常见的几种异常现象整理成一张表你可以对照排查现象可能原因排查方向首页直接显示 500 或白屏storage 不可写、vendor 缺失、.env 未配置查看storage/logs/laravel.log确认目录权限子路由全部 404首页正常Nginx 没有配伪静态检查try_files配置reload Nginx页面能打开但样式和图片全丢未执行storage:link或站点根目录不对确认 public 目录配置执行php artisan storage:link提示No application encryption keyAPP_KEY为空执行php artisan key:generate数据库连接失败.env中数据库配置错误或账号权限不足核对 DB_HOST、DB_DATABASE、DB_USERNAME、DB_PASSWORD修改.env后配置不生效之前执行过config:cache执行php artisan config:clear再刷新访问.env文件直接下载Nginx root 根目录配错确保 root 指向public目录而不是项目根目录排查 Laravel 页面异常的通用套路是看日志sudo -u www-data tail -f /var/www/你的仓库名/storage/logs/laravel.log日志里通常直接写着异常原因比如某个扩展缺失、某个类找不到、数据库连接失败等。我处理部署问题时90% 的答案都在这一个文件里。剩下的 10%才是需要去检查 Nginx 配置、PHP-FPM 状态和系统权限。最后再分享一个我自己的习惯每次在大改之前先给当前能跑的配置做个备份。Nginx 配置在改之前复制成xxx.conf.bak.env在改之前也先备份一份。这套习惯让我在维护多个 Laravel 项目时少踩了很多坑——版本回滚容易配置回滚有时候反而急得人直冒汗。部署这件事第一步走通之后后面就是重复和优化但第一步走稳了整条链路就顺了。