# 呆鸟修仙项目迁移指南
本指南帮助您将项目从 coze.site 平台迁移到自己的服务器(如阿里云、腾讯云)。
## 目录
- [迁移前准备](#迁移前准备)
- [服务器环境配置](#服务器环境配置)
- [数据库迁移](#数据库迁移)
- [项目部署](#项目部署)
- [域名与SSL配置](#域名与ssl配置)
- [支付接入准备](#支付接入准备)
- [监控与维护](#监控与维护)
---
## 迁移前准备
### 1. 服务器要求
**推荐配置:**
- CPU:2核及以上
- 内存:4GB及以上
- 硬盘:40GB SSD及以上
- 带宽:3Mbps及以上(根据用户量调整)
- 操作系统:Ubuntu 20.04 / 22.04 LTS 或 CentOS 7/8
**必需软件:**
- Node.js 18.x 或 20.x
- PostgreSQL 14 或更高版本
- Nginx(作为反向代理)
- PM2(进程管理)
- Git
- pnpm(包管理器)
### 2. 域名准备
- 购买域名(如:dainiaoxiuxian.com)
- 准备备案(如需要接入微信支付)
- 准备DNS服务商
### 3. 第三方服务账号
#### 必需服务:
- **PostgreSQL 数据库**(云数据库或自建)
- **对象存储(S3兼容)**:阿里云OSS、腾讯云COS或AWS S3
- **天气API**:和风天气(推荐)或 wttr.in
#### 支付服务(可选):
- **Stripe**:适合国际用户
- **微信支付**:适合国内用户(需要企业资质)
- **支付宝**:适合国内用户(需要企业资质)
---
## 服务器环境配置
### 步骤1:基础环境安装
```bash
# 更新系统
sudo apt update && sudo apt upgrade -y
# 安装基础工具
sudo apt install -y curl wget git vim build-essential
# 安装 Node.js 20.x
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs
# 验证安装
node -v # 应显示 v20.x.x
npm -v # 应显示 10.x.x
# 安装 pnpm
npm install -g pnpm
# 验证安装
pnpm -v
```
### 步骤2:安装 PostgreSQL
```bash
# 安装 PostgreSQL
sudo apt install -y postgresql postgresql-contrib
# 启动服务
sudo systemctl start postgresql
sudo systemctl enable postgresql
# 切换到 postgres 用户
sudo -u postgres psql
# 在 psql 中执行:
CREATE USER dainiao WITH PASSWORD 'your_strong_password';
CREATE DATABASE dainiao OWNER dainiao;
GRANT ALL PRIVILEGES ON DATABASE dainiao TO dainiao;
\q
# 修改 PostgreSQL 认证方式
sudo vim /etc/postgresql/14/main/pg_hba.conf
# 找到 IPv4 local connections 部分,修改为:
# host all all 127.0.0.1/32 md5
# 重启 PostgreSQL
sudo systemctl restart postgresql
```
### 步骤3:安装 PM2
```bash
npm install -g pm2
# 验证安装
pm2 -v
```
### 步骤4:安装 Nginx
```bash
sudo apt install -y nginx
# 启动服务
sudo systemctl start nginx
sudo systemctl enable nginx
# 验证安装
curl localhost # 应显示 Nginx 欢迎页面
```
---
## 数据库迁移
### 方案1:从 coze.site 导出数据(推荐)
```bash
# 1. 在 coze.site 服务器上导出数据
pg_dump -h your_host -U your_user -d your_database > dump.sql
# 2. 将 dump.sql 传输到新服务器
scp dump.sql user@your-server:/tmp/
# 3. 在新服务器上导入数据
psql -U dainiao -d dainiao < /tmp/dump.sql
```
### 方案2:重新初始化数据库
```bash
# 1. 克隆项目到服务器
git clone <your-repo-url> /var/www/dainiao
cd /var/www/dainiao
# 2. 安装依赖
pnpm install
# 3. 配置环境变量
cp .env.example .env
vim .env
```
#### 环境变量配置(.env)
```env
# 数据库配置
DATABASE_URL="postgresql://dainiao:your_password@localhost:5432/dainiao"
# 对象存储配置(以阿里云OSS为例)
S3_ENDPOINT="https://oss-cn-hangzhou.aliyuncs.com"
S3_ACCESS_KEY_ID="your_access_key"
S3_SECRET_ACCESS_KEY="your_secret_key"
S3_BUCKET="your-bucket-name"
S3_REGION="oss-cn-hangzhou"
# 天气API配置(和风天气)
QWEATHER_API_KEY="your_qweather_key"
# 端口配置
PORT=3000
NODE_ENV=production
# JWT密钥(自行生成随机字符串)
JWT_SECRET="your_jwt_secret_here"
# 管理员信息(用于初始化)
ADMIN_USERNAME="李邦华"
ADMIN_PASSWORD="admin123"
ADMIN_INVITE_CODE="LIBANGHUA"
```
```bash
# 4. 运行数据库迁移
pnpm drizzle-kit push
# 5. 初始化数据
curl -X POST http://localhost:3000/api/admin/init-libanghua-v2
```
---
## 项目部署
### 步骤1:部署项目代码
```bash
# 1. 克隆项目(或上传代码)
cd /var/www
git clone <your-repo-url> dainiao
cd dainiao
# 2. 安装依赖
pnpm install
# 3. 构建项目
pnpm build
```
### 步骤2:使用 PM2 启动服务
创建 PM2 配置文件 `ecosystem.config.js`:
```javascript
module.exports = {
apps: [{
name: 'dainiao',
script: 'node_modules/next/dist/bin/next',
args: 'start',
cwd: '/var/www/dainiao',
instances: 2,
exec_mode: 'cluster',
env: {
NODE_ENV: 'production',
PORT: 3000
},
error_file: '/var/log/dainiao/error.log',
out_file: '/var/log/dainiao/out.log',
log_date_format: 'YYYY-MM-DD HH:mm:ss Z',
merge_logs: true,
autorestart: true,
max_restarts: 10,
min_uptime: '10s',
max_memory_restart: '1G'
}]
};
```
启动服务:
```bash
# 创建日志目录
sudo mkdir -p /var/log/dainiao
sudo chown -R $USER:$USER /var/log/dainiao
# 启动服务
pm2 start ecosystem.config.js
# 查看服务状态
pm2 status
pm2 logs dainiao
# 设置开机自启
pm2 startup
pm2 save
```
### 步骤3:配置 Nginx 反向代理
创建 Nginx 配置文件 `/etc/nginx/sites-available/dainiao`:
```nginx
upstream dainiao_backend {
server 127.0.0.1:3000;
keepalive 64;
}
# HTTP 重定向到 HTTPS
server {
listen 80;
listen [::]:80;
server_name dainiaoxiuxian.com www.dainiaoxiuxian.com;
# Let's Encrypt 验证路径
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$server_name$request_uri;
}
}
# HTTPS 配置
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name dainiaoxiuxian.com www.dainiaoxiuxian.com;
# SSL 证书配置(稍后配置)
ssl_certificate /etc/letsencrypt/live/dainiaoxiuxian.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dainiaoxiuxian.com/privkey.pem;
# SSL 安全配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# 日志
access_log /var/log/nginx/dainiao_access.log;
error_log /var/log/nginx/dainiao_error.log;
# 客户端最大上传大小
client_max_body_size 10M;
# 代理到 Next.js
location / {
proxy_pass http://dainiao_backend;
proxy_http_version 1.1;
# WebSocket 支持
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
# 代理头
proxy_set_header Host $host;
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;
# 超时设置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# 缓存设置
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}
# 静态资源缓存
location /_next/static {
proxy_pass http://dainiao_backend;
proxy_cache_valid 200 365d;
add_header Cache-Control "public, immutable";
}
location /static {
proxy_pass http://dainiao_backend;
proxy_cache_valid 200 365d;
add_header Cache-Control "public, immutable";
}
}
```
启用配置:
```bash
# 创建软链接
sudo ln -s /etc/nginx/sites-available/dainiao /etc/nginx/sites-enabled/
# 测试配置
sudo nginx -t
# 重启 Nginx
sudo systemctl restart nginx
```
---
## 域名与SSL配置
### 步骤1:DNS解析
在您的域名DNS管理中添加记录:
```
类型 主机记录 记录值
A @ 您的服务器公网IP
A www 您的服务器公网IP
```
### 步骤2:配置SSL证书(使用 Let's Encrypt)
```bash
# 安装 Certbot
sudo apt install -y certbot python3-certbot-nginx
# 获取证书(自动配置 Nginx)
sudo certbot --nginx -d dainiaoxiuxian.com -d www.dainiaoxiuxian.com
# 按提示输入邮箱,同意条款,选择是否重定向到 HTTPS
# 设置自动续期
sudo certbot renew --dry-run
# 添加 cron 任务
sudo crontab -e
# 添加以下行(每天凌晨2点检查续期)
0 2 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"
```
### 步骤3:防火墙配置
```bash
# 启用 UFW
sudo ufw enable
# 允许必要端口
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
# 查看状态
sudo ufw status
```
---
## 支付接入准备
### 选项1:Stripe(推荐,适合国际用户)
#### 优势:
- 无需企业资质,个人账号即可申请
- 支持全球支付
- API 简单易用
- 不需要域名备案
#### 申请流程:
1. 访问 [Stripe](https://stripe.com) 注册账号
2. 完成个人验证(护照/身份证)
3. 添加银行账户(用于提现)
4. 获取 API Keys(Publishable Key 和 Secret Key)
#### 集成步骤:
1. 安装 Stripe SDK:
```bash
pnpm add stripe
```
2. 创建支付 API `src/app/api/payment/stripe/create-checkout-session/route.ts`:
```typescript
import { NextRequest, NextResponse } from "next/server";
import Stripe from "stripe";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: "2024-12-18.acacia",
});
export async function POST(request: NextRequest) {
try {
const body = await request.json();
const { membershipType } = body;
// 定义价格
const prices = {
monthly: "price_xxx", // 月度会员价格ID
quarterly: "price_xxx", // 季度会员价格ID
annual: "price_xxx", // 年度会员价格ID
};
const priceId = prices[membershipType as keyof typeof prices];
if (!priceId) {
return NextResponse.json({ error: "无效的会员类型" }, { status: 400 });
}
// 创建 Checkout Session
const session = await stripe.checkout.sessions.create({
mode: "subscription",
payment_method_types: ["card"],
line_items: [
{
price: priceId,
quantity: 1,
},
],
success_url: `${process.env.NEXT_PUBLIC_BASE_URL}/payment/success?session_id={CHECKOUT_SESSION_ID}`,
cancel_url: `${process.env.NEXT_PUBLIC_BASE_URL}/payment/cancel`,
metadata: {
userId: body.userId,
membershipType: membershipType,
},
});
return NextResponse.json({ url: session.url });
} catch (error) {
console.error("创建支付会话失败:", error);
return NextResponse.json(
{ error: "创建支付会话失败" },
{ status: 500 }
);
}
}
```
3. 创建 Webhook API `src/app/api/payment/stripe/webhook/route.ts`:
```typescript
import { NextRequest, NextResponse } from "next/server";
import Stripe from "stripe";
import { getDb } from "coze-coding-dev-sdk";
import { sql } from "drizzle-orm";
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: "2024-12-18.acacia",
});
export async function POST(request: NextRequest) {
const body = await request.text();
const signature = request.headers.get("stripe-signature")!;
try {
const event = stripe.webhooks.constructEvent(
body,
signature,
process.env.STRIPE_WEBHOOK_SECRET!
);
if (event.type === "checkout.session.completed") {
const session = event.data.object as Stripe.Checkout.Session;
const userId = session.metadata?.userId;
const membershipType = session.metadata?.membershipType;
// 更新用户权限
const db = await getDb();
const dailyLimits = {
monthly: 10,
quarterly: 20,
annual: 50,
};
await db.execute(
sql`UPDATE user_permissions
SET sign_max_daily = ${dailyLimits[membershipType as keyof typeof dailyLimits] || 3},
membership_type = ${membershipType},
updated_at = NOW()
WHERE user_id = ${userId}`
);
}
return NextResponse.json({ received: true });
} catch (error) {
console.error("Webhook 处理失败:", error);
return NextResponse.json({ error: "Webhook 处理失败" }, { status: 400 });
}
}
```
4. 在 Stripe Dashboard 配置 Webhook:
- URL: `https://dainiaoxiuxian.com/api/payment/stripe/webhook`
- 事件: `checkout.session.completed`
- 获取 Webhook Secret 并添加到环境变量
### 选项2:微信支付(适合国内用户)
#### 前置条件:
- 企业营业执照
- 域名备案(ICP)
- 企业银行账户
#### 申请流程:
1. 访问 [微信支付商户平台](https://pay.weixin.qq.com)
2. 注册商户账号
3. 提交企业资质审核
4. 审核通过后获取 API 证书和密钥
#### 注意事项:
- 开发流程复杂,需要对接微信支付 SDK
- 需要配置回调地址(必须是 HTTPS)
- 建议使用第三方支付服务商(如 Ping++)简化集成
### 选项3:支付宝(适合国内用户)
#### 前置条件:
- 企业营业执照
- 域名备案(ICP)
- 企业银行账户
#### 申请流程:
1. 访问 [支付宝开放平台](https://open.alipay.com)
2. 创建应用并提交审核
3. 签约支付产品
4. 获取 APPID 和密钥
#### 集成步骤:
1. 安装支付宝 SDK:`pnpm add alipay-sdk`
2. 创建支付订单 API
3. 配置异步通知回调
4. 处理支付结果
---
## 监控与维护
### 1. 日志管理
```bash
# PM2 日志
pm2 logs dainiao --lines 100
# Nginx 日志
sudo tail -f /var/log/nginx/dainiao_access.log
sudo tail -f /var/log/nginx/dainiao_error.log
# 应用日志
tail -f /var/log/dainiao/out.log
tail -f /var/log/dainiao/error.log
```
### 2. 自动备份脚本
创建 `/home/scripts/backup.sh`:
```bash
#!/bin/bash
# 配置
BACKUP_DIR="/backup/dainiao"
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="dainiao"
DB_USER="dainiao"
RETENTION_DAYS=7
# 创建备份目录
mkdir -p $BACKUP_DIR
# 备份数据库
pg_dump -U $DB_USER -h localhost $DB_NAME > $BACKUP_DIR/db_$DATE.sql
# 备份上传文件(如果有本地存储)
tar -czf $BACKUP_DIR/uploads_$DATE.tar.gz /var/www/dainiao/public/uploads
# 压缩数据库备份
gzip $BACKUP_DIR/db_$DATE.sql
# 删除旧备份(保留最近7天)
find $BACKUP_DIR -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete
find $BACKUP_DIR -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete
echo "备份完成: $DATE"
```
设置定时任务:
```bash
chmod +x /home/scripts/backup.sh
# 每天凌晨3点执行备份
sudo crontab -e
# 添加:
0 3 * * * /home/scripts/backup.sh >> /var/log/backup.log 2>&1
```
### 3. 监控服务
#### 方案1:使用 PM2 Plus(推荐)
```bash
pm2 link <your_public_key> <your_secret_key>
```
#### 方案2:使用监控工具(如 UptimeRobot)
- 免费监控服务可用性
- 配置邮件/短信告警
### 4. 性能优化
#### Nginx 缓存配置:
```nginx
# 在 http 块中添加
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=dainiao_cache:10m max_size=1g inactive=60m use_temp_path=off;
# 在 server 块中添加
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
proxy_pass http://dainiao_backend;
proxy_cache dainiao_cache;
proxy_cache_valid 200 30d;
proxy_cache_use_stale error timeout invalid_header updating;
add_header X-Cache-Status $upstream_cache_status;
}
```
#### 数据库优化:
```sql
-- 创建索引
CREATE INDEX idx_users_invite_code ON users(invite_code);
CREATE INDEX idx_game_records_user_id ON game_records(user_id);
CREATE INDEX idx_daily_signs_user_id ON daily_signs(user_id);
```
### 5. 安全加固
```bash
# 禁止 root 远程登录
sudo vim /etc/ssh/sshd_config
# 修改:PermitRootLogin no
# 修改 SSH 端口
# Port 2222
# 重启 SSH
sudo systemctl restart sshd
# 安装 fail2ban 防止暴力破解
sudo apt install -y fail2ban
sudo systemctl enable fail2ban
sudo systemctl start fail2ban
# 定期更新系统
sudo apt update && sudo apt upgrade -y
```
---
## 迁移检查清单
### 部署前:
- [ ] 服务器已购买并配置完成
- [ ] 域名已购买并解析
- [ ] SSL 证书已申请
- [ ] 数据库已创建
- [ ] 对象存储已配置
- [ ] 环境变量已配置
### 部署后:
- [ ] 项目代码已部署
- [ ] PM2 服务正常运行
- [ ] Nginx 配置正确
- [ ] HTTPS 访问正常
- [ ] 数据库连接正常
- [ ] 用户注册/登录功能正常
- [ ] 游戏功能正常
- [ ] 日签功能正常
- [ ] 备份脚本已配置
- [ ] 监控已配置
### 支付接入(可选):
- [ ] 支付账号已申请
- [ ] API Keys 已配置
- [ ] Webhook 已配置
- [ ] 支付流程测试通过
- [ ] 退款流程已配置
---
## 常见问题
### Q1: PM2 启动失败怎么办?
```bash
# 查看详细错误
pm2 logs dainiao --err
# 检查端口占用
sudo lsof -i :3000
# 检查环境变量
pm2 env dainiao
```
### Q2: Nginx 502 错误?
```bash
# 检查后端服务状态
pm2 status
# 检查 Nginx 配置
sudo nginx -t
# 重启服务
pm2 restart dainiao
sudo systemctl restart nginx
```
### Q3: 数据库连接失败?
```bash
# 检查数据库服务
sudo systemctl status postgresql
# 测试连接
psql -U dainiao -d dainiao -h localhost
# 检查防火墙
sudo ufw status
```
### Q4: 如何升级项目?
```bash
cd /var/www/dainiao
git pull
pnpm install
pnpm build
pm2 restart dainiao
```
### Q5: 如何查看数据库大小?
```sql
SELECT pg_size_pretty(pg_database_size('dainiao'));
```
---
## 技术支持
如遇到问题,请提供以下信息:
1. 服务器配置(CPU、内存、操作系统)
2. 错误日志(PM2、Nginx、数据库)
3. 操作步骤
4. 预期结果和实际结果
---
## 附录:完整部署脚本
如需一键部署脚本,请联系技术团队获取定制化部署方案。
---
**祝您迁移顺利!**

