You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS+Nginx部署后静态资源404问题的排查与解决

问题解决:NestJS静态资源在Nginx反向代理下返回404

核心问题分析

本地/构建模式下静态资源可正常访问,部署到EC2+Nginx+PM2后仅静态资源404,说明问题出在Nginx配置转发逻辑、服务器目录权限或NestJS构建后路径匹配这三个环节。


解决方案

1. 修正Nginx配置(优先推荐)

Nginx的location块不能嵌套,且需确保静态资源请求要么直接由Nginx处理(性能更优),要么正确转发给NestJS。

选项A:让Nginx直接提供静态资源(推荐)

直接让Nginx读取服务器上的静态文件,无需经过NestJS,减少请求链路:

server {
    server_name domain.tld;
    
    include /etc/nginx/default.d/*.conf;

    # 处理静态资源请求
    location /uploads/ {
        # 替换为EC2上你的项目storage目录实际路径,比如/home/ubuntu/Project/storage
        root /path/to/Project/storage;
        # 文件不存在时 fallback 到NestJS(可选)
        try_files $uri $uri/ @nestjs;
    }

    # 其他请求转发给NestJS
    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_cache_bypass $http_upgrade;
    }

    # 备用规则:静态文件不存在时转发给NestJS
    location @nestjs {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    listen 443 ssl http2; # managed by Certbot
    ssl_certificate /certpath/domain.tld/fullchain.pem; # managed by Certbot
    ssl_certificate_key /certpath/domain.tld/privkey.pem; # managed by Certbot
}

server {
    if ($host = domain.tld) {
        return 301 https://$host$request_uri;
    } # managed by Certbot

    server_name domain.tld;
    listen 80;
    return 404; # managed by Certbot
}

选项B:确保静态资源请求转发到NestJS

如果需要NestJS处理静态资源逻辑(比如权限校验),添加独立的location块转发请求:

server {
    server_name domain.tld;
    
    include /etc/nginx/default.d/*.conf;

    # 单独转发静态资源请求到NestJS
    location /uploads/ {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://127.0.0.1:3000;
    }

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_cache_bypass $http_upgrade;
    }

    listen 443 ssl http2; # managed by Certbot
    ssl_certificate /certpath/domain.tld/fullchain.pem;
    ssl_certificate_key /certpath/domain.tld/privkey.pem;
}

2. 修复服务器目录权限

EC2上的storage目录权限可能限制了PM2进程读取文件:

# 进入项目根目录
cd /path/to/Project
# 将目录权限设置为当前部署用户(比如ubuntu)
sudo chown -R $USER:$USER storage
# 设置可读可执行权限
sudo chmod -R 755 storage

3. 验证NestJS构建后路径配置

确认构建后的ServeStaticModule路径是否正确,可临时添加日志验证:

// 在AppModule中添加
import { join } from 'path';
console.log('静态资源根路径:', join(__dirname, '..', '..', 'storage'));

查看PM2日志确认路径是否为EC2上实际的storage目录:

pm2 logs your-app-name

如果路径错误,调整join参数(比如构建后dist目录结构变化,可能需要改为join(__dirname, '..', 'storage'))。


验证操作

  1. 重新加载Nginx配置:
sudo nginx -s reload
  1. 重启PM2应用:
pm2 restart your-app-name
  1. 访问静态资源URL,检查是否返回200状态码。

内容的提问来源于stack exchange,提问作者Md. A. Apu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 22:52:28