Appearance
从零开始部署 Nuxt 应用到 Ubuntu 22.04 服务器
适用场景
本文适用于已经完成 Nuxt 项目本地构建,需要部署到生产环境的开发者。
💡 关于构建方式
本文聚焦于部署环节。构建可以在本地完成,也可以通过 CI 完成(如 GitHub Actions、GitLab CI 等)。无论采用哪种构建方式,本文的部署步骤都完全适用。
前言
Nuxt 项目执行 pnpm build 后,会生成 .output 目录,其中包含了可直接运行的服务器代码。本文将详细讲解如何将构建产物部署到 Ubuntu 22.04 服务器,并提供两种 SSL 证书配置方案供你选择。
0. 前置准备
在要部署 Nuxt 项目的远程服务器上,root 账户的家目录下创建一个工作目录,例如 ~/workspace,这样方便我们在终端上传文件时清晰地表述文件上传之后的落地路径。
1. 准备部署文件
在本地项目根目录,构建产物位于 .output 文件夹中。
💡 关于打包目录
为了部署方便,应该只将 .output 目录下的所有文件打包到 deploy.tar.gz 归档文件中,而不是打包 .output 目录本身。因为如果在服务器上解压后得到的是 .output 目录,会导致路径变成 /var/www/myapp/.output,造成目录管理上的歧义且不友好。
bash
# 方式一:进入 .output 目录后打包
cd .output
tar -czf ../deploy.tar.gz .
cd ..
# 方式二:一行命令打包(推荐)
tar -czf deploy.tar.gz -C .output .
# 上传到服务器(替换为你的服务器信息)
scp deploy.tar.gz root@your-server-ip:/root/workspace/2. 服务器环境配置
SSH 连接到 Ubuntu 22.04 服务器:
bash
ssh root@your-server-ip安装 Node.js
推荐使用 Node.js 20 或更高版本:
bash
# 使用 NodeSource 官方源
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs
# 验证安装
node --version # 应显示 v20.x
npm --version安装 PM2 进程管理器
PM2 用于守护 Node.js 进程,支持自动重启和开机自启:
bash
sudo npm install -g pm23. 解压并部署
bash
# 创建应用目录
sudo mkdir -p /var/www/myapp
sudo chown -R $USER:$USER /var/www/myapp
# 解压文件
tar -xzf /root/workspace/deploy.tar.gz -C /var/www/myapp/
# 进入目录
cd /var/www/myapp/
# 查看目录结构(可选)
ls -la
# 输出应包含 server/ 和 public/ 目录4. 检查并安装依赖(可选)
bash
# .output 目录已经包含运行所需文件,通常直接运行即可
# 如果提示缺少依赖,再执行:
npm install --production5. 配置环境变量
bash
# 创建 .env 文件
cat > .env << 'EOF'
NODE_ENV=production
PORT=3000
NUXT_PUBLIC_SITE_URL=https://your-domain.com
# 根据你的项目需要添加其他变量
# DATABASE_URL=...
# API_BASE_URL=...
EOF6. 使用 PM2 启动应用
bash
# 启动应用
pm2 start server/index.mjs \
--name "myapp" \
--node-args="--env-file=.env"
# 保存 PM2 配置(用于开机自启)
pm2 save
# 生成开机自启脚本
pm2 startup
# 执行上面命令输出的命令PM2 常用命令
bash
pm2 status # 查看应用状态
pm2 logs # 查看日志
pm2 restart # 重启应用
pm2 stop # 停止应用
pm2 monit # 监控资源7. 配置 Nginx 反向代理
安装 Nginx
bash
sudo apt-get update
sudo apt-get install -y nginx基础配置
bash
sudo nano /etc/nginx/sites-available/myappnginx
server {
listen 80;
server_name your-domain.com;
access_log /var/log/nginx/myapp-access.log;
error_log /var/log/nginx/myapp-error.log;
# 获取真实 IP 的配置(如果使用 Cloudflare,需要额外配置)
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# 静态资源缓存策略
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf)$ {
proxy_pass http://127.0.0.1:3000;
expires 1y;
add_header Cache-Control "public, immutable";
}
}启用站点
bash
sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx8. 配置防火墙
bash
# 基础端口开放
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS(如果需要)
# 启用防火墙
sudo ufw enable9. 配置 SSL 证书
这里提供两种方案,你可以根据实际情况选择。
方案一:使用 Let's Encrypt(独立部署)
适用场景:服务器独立对外提供服务,不经过 CDN 代理。
安装 Certbot
bash
sudo apt-get install -y certbot python3-certbot-nginx获取并配置证书
bash
# 自动获取证书并配置 Nginx
sudo certbot --nginx -d your-domain.com
# 测试自动续期
sudo certbot renew --dry-run验证证书配置
bash
# 检查证书状态
sudo certbot certificatesLet's Encrypt 证书有效期为 90 天,Certbot 会自动续期。
方案二:使用 Cloudflare 证书(CDN + SSL)
适用场景:域名已在 Cloudflare 托管,希望获得 CDN 加速和 DDoS 防护。
Cloudflare DNS 配置
在 Cloudflare 控制台将 DNS 记录设置为代理模式:
| 类型 | 名称 | 内容 | 代理状态 |
|---|---|---|---|
| A | your-domain.com | 服务器公网 IP | ✅ 已代理(橙色云朵) |
步骤一:生成 Cloudflare Origin CA 证书
- 登录 Cloudflare 控制台,进入 SSL/TLS → Origin Server
- 点击 Create Certificate
- 保持默认设置:
- Private key type: RSA(2048)
- Hostnames: 添加
your-domain.com和*.your-domain.com - Certificate Validity: 15 years(推荐)
- 点击 Create
- 重要:复制弹出的证书内容和私钥内容,分别保存(私钥只显示一次!)
步骤二:在服务器上安装证书
bash
# 创建 SSL 目录
sudo mkdir -p /etc/nginx/ssl
# 保存证书(粘贴 -----BEGIN CERTIFICATE----- 到 -----END CERTIFICATE----- 的内容)
sudo nano /etc/nginx/ssl/your-domain.pem
# 保存私钥(粘贴 -----BEGIN PRIVATE KEY----- 到 -----END PRIVATE KEY----- 的内容)
sudo nano /etc/nginx/ssl/your-domain.key
# 设置权限(重要!)
sudo chmod 600 /etc/nginx/ssl/your-domain.key
sudo chmod 644 /etc/nginx/ssl/your-domain.pem步骤三:配置 Nginx
bash
sudo vim /etc/nginx/sites-available/your-domain注意
如果您当前部署的是一个域名的主站点,可以直接覆盖 /etc/nginx/sites-available/default
nginx
# HTTP 重定向到 HTTPS
server {
listen 80;
server_name your-domain.com;
return 301 https://$server_name$request_uri;
}
# HTTPS 配置(使用 Cloudflare Origin CA 证书)
server {
listen 443 ssl http2;
server_name your-domain.com;
# Cloudflare Origin CA 证书
ssl_certificate /etc/nginx/ssl/your-domain.pem;
ssl_certificate_key /etc/nginx/ssl/your-domain.key;
# SSL 优化配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
access_log /var/log/nginx/your-domain-access.log;
error_log /var/log/nginx/your-domain-error.log;
# Cloudflare IP 地址范围(用于获取真实客户端 IP)
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
real_ip_header CF-Connecting-IP;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
}
# 静态资源缓存策略
location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf)$ {
proxy_pass http://127.0.0.1:3000;
expires 1y;
add_header Cache-Control "public, immutable";
}
}步骤四:启用站点并重启 Nginx
bash
# 启用站点
sudo ln -s /etc/nginx/sites-available/your-domain /etc/nginx/sites-enabled/
# 测试配置语法
sudo nginx -t
# 重启 Nginx
sudo systemctl restart nginx
# 验证 443 端口是否监听
sudo netstat -tlnp | grep :443注意
如果是编辑的 /etc/nginx/sites-available/default 配置文件,则不需要执行 sudo ln -s /etc/nginx/sites-available/your-domain /etc/nginx/sites-enabled/ 上面这个命令!
步骤五:配置 Cloudflare SSL/TLS 模式
回到 Cloudflare 控制台:
- 进入 SSL/TLS → 概述
- 将加密模式设置为 严格 (Full strict)
- 可选:开启 始终使用 HTTPS 和 自动 HTTPS 重写
验证 HTTPS 是否生效
bash
# 测试 HTTPS 访问
curl -I https://your-domain.com
# 应返回 HTTP/2 200方案对比
| 特性 | Let's Encrypt | Cloudflare |
|---|---|---|
| 配置复杂度 | 中等 | 简单 |
| 证书续期 | 自动(需 certbot 服务) | 全自动 |
| CDN 加速 | ❌ | ✅ |
| DDoS 防护 | ❌ | ✅ |
| 服务器资源占用 | 需管理证书文件 | 无额外占用 |
| 全球访问速度 | 取决于服务器位置 | 边缘节点加速 |
| 费用 | 免费 | 免费 |
10. 部署后验证
检查服务状态
bash
# 检查 PM2
pm2 status
# 检查 Nginx
sudo systemctl status nginx
# 检查端口监听
sudo netstat -tlnp | grep -E "(3000|80|443)"访问测试
bash
# 本地测试
curl http://localhost:3000
# 远程测试(在你的本地终端)
curl http://your-server-ip11. 常见问题处理
Sharp 二进制文件兼容性
构建日志中提示包含了 darwin-x64 的 sharp 二进制文件,在 Ubuntu 上可能需要重新构建:
bash
cd /var/www/myapp/.output
npm rebuild sharp字体下载超时
如果服务器在中国大陆,字体下载可能超时。解决方案:
- 使用国内字体 CDN 镜像
- 下载字体到本地,配置为本地资源
大文件构建警告
日志中出现的 chunk size 警告可以通过以下方式优化:
javascript
// nuxt.config.ts
export default defineNuxtConfig({
build: {
chunkSizeWarningLimit: 1000, // 提高限制(单位 kB)
},
// 或使用动态导入优化代码分割
})12. 设置自动部署脚本(可选)
创建 deploy.sh 脚本在本地运行:
bash
#!/bin/bash
# 配置变量
SERVER="root@your-server-ip"
APP_PATH="/var/www/myapp"
PM2_NAME="myapp"
# 构建
echo "📦 Building project..."
pnpm build
# 打包
echo "📁 Packaging build output..."
tar -czf deploy.tar.gz -C .output .
# 上传
echo "📤 Uploading to server..."
scp deploy.tar.gz $SERVER:$APP_PATH/
# 远程部署
echo "🚀 Deploying on server..."
ssh $SERVER "cd $APP_PATH && \
tar -xzf deploy.tar.gz && \
pm2 reload $PM2_NAME && \
rm deploy.tar.gz && \
echo '✅ Deployment complete!'"
# 清理
rm deploy.tar.gz赋予执行权限并使用:
bash
chmod +x deploy.sh
./deploy.sh结语
部署完成后,访问你的域名即可看到网站。建议先用 HTTP 测试一切正常后,再配置 SSL 证书。
如果遇到问题,可以检查以下日志:
bash
# PM2 日志
pm2 logs myapp
# Nginx 日志
sudo tail -f /var/log/nginx/myapp-error.log
# 系统日志
journalctl -u nginx -f总结
- 使用 PM2 管理 Node.js 进程
- 使用 Nginx 作为反向代理
- 独立部署选择 Let's Encrypt
- 使用 CDN 选择 Cloudflare