ASP.NET Core Linux部署失败主因是Windows专属依赖;需用--os linux编译验证、正确配置systemd工作目录与权限、Kestrel绑定*地址、Nginx用127.0.0.1代理、certbot续期后转PFX并reload服务。

ASP.NET Core 应用在 Linux 上跑不起来?先确认是否用了 Windows-only 依赖
绝大多数部署失败不是因为“不会部署”,而是应用本身偷偷依赖了 Windows API 或 .NET Framework 组件。比如 System.Drawing.Common 在非 Windows 系统上默认禁用图像处理,Microsoft.Win32.Registry 直接抛 PlatformNotSupportedException。
实操建议:
- 本地开发时,在
dotnet build后加--os linux --arch x64模拟目标环境编译,提前暴露平台敏感代码 - 检查
.csproj中是否显式引用了<packagereference include="Microsoft.AspNetCore.App" version="..."></packagereference>—— 这个包在 Linux 上必须通过 SDK 安装,不能靠 NuGet 单独拉 - 运行前执行
dotnet publish -c Release -r linux-x64 --self-contained false,注意--self-contained false表示依赖系统已安装的 .NET Runtime,更轻量也更易排查版本冲突
systemd 服务启动后立即退出?多半是工作目录或权限没设对
systemd 启动 ASP.NET Core 应用时最常见症状:服务状态显示 active (exited),日志里只有 Process exited with code 0,但 HTTP 根本没监听。根本原因是 WorkingDirectory 路径不存在、不可读,或 ExecStart 指向的可执行文件没有执行权限。
实操建议:
- 服务文件(如
/etc/systemd/system/myapp.service)中必须显式设置WorkingDirectory=/var/www/myapp,不能省略 -
ExecStart必须指向publish输出目录下的实际可执行文件,例如/var/www/myapp/myapp(.NET 6+ SDK 发布后生成的无扩展名可执行文件),而不是dotnet myapp.dll - 确保运行用户(如
www-data)对/var/www/myapp有读+执行权限,尤其要chmod +x /var/www/myapp/myapp - 调试时临时加
Environment=DOTNET_ENVIRONMENT=Development和StandardOutput=journal,再用journalctl -u myapp -f实时看输出
反向代理配置 Nginx 报 502 Bad Gateway?检查 Kestrel 是否真在监听 localhost:5000
Nginx 返回 502 不代表它配错了,大概率是 Kestrel 根本没起来,或者监听地址不对。默认情况下,ASP.NET Core 只监听 http://localhost:5000,而 Nginx 是从外部访问,需要确认 Kestrel 是否允许外部连接。
实操建议:
- 在
Program.cs中显式调用webBuilder.UseUrls("http://localhost:5000;http://*:5000")(.NET 5+ 改为builder.WebHost.UseUrls(...)),否则*绑定不会生效 - 检查
appsettings.Production.json里Kestrel:Endpoints:Http:Url是否设为"http://*:5000",避免被配置覆盖 - Nginx 的
proxy_pass必须写成http://127.0.0.1:5000,不要用localhost—— 某些 DNS 配置下localhost解析慢或失败,导致超时 - 手动测试:
curl -v http://127.0.0.1:5000看能否通,不通就别配 Nginx
HTTPS 证书自动续期失败?certbot 与 Kestrel 的协作边界要划清
certbot 不能直接给 Kestrel 提供证书文件,它只负责申请和更新 PEM 格式证书(fullchain.pem + privkey.pem)。Kestrel 需要的是 PFX(.p12)格式,且必须带密码 —— 这一步必须手动或脚本转换。
实操建议:
- 不要在
Program.cs里硬编码证书路径,改用环境变量传入:builder.Configuration["Kestrel:Certificates:Default:Path"],然后由 systemd 注入Environment=Kestrel__Certificates__Default__Path=/etc/letsencrypt/live/example.com/fullchain.pfx - 每次 certbot 续期后,用命令转格式:
openssl pkcs12 -export -out /etc/ssl/private/example.com.pfx -inkey /etc/letsencrypt/live/example.com/privkey.pem -in /etc/letsencrypt/live/example.com/fullchain.pem -password pass:your-pfx-password - 续期脚本末尾记得
systemctl reload myapp.service,而不是 restart —— reload 会触发 Kestrel 重新加载证书而不中断连接
Operation not permitted —— 它可能来自 SELinux 策略、systemd 的 NoNewPrivileges=true 限制、甚至 Docker 容器里没开 NET_BIND_SERVICE capability。遇到这种报错,先查 journalctl -xe,再看 ausearch -m avc -ts recent(如果启用了 SELinux)。


















