新手快速部署Dujiao-Next《新版独角数卡》
在开始之前,先花 2 分钟了解 Dujiao-Next 的整体架构,搞清楚每个部分是干什么的,后面的操作就不会懵了。
Dujiao-Next 由 3 个独立部分 组成:
| 名称 | 类型 | 说明 |
|---|---|---|
| API | Go 编译的二进制程序 | 后端核心,处理所有业务逻辑,监听 8080 端口 |
| User | Vue 静态页面 | 用户看到的购买前台,放在 user/dist 目录 |
| Admin | Vue 静态页面 | 商家管理后台,放在 admin/dist 目录 |
用户浏览器
│
▼
Nginx(宝塔管理)
│
├─── shop.example.com(用户前台)
│ │
│ ├── 普通页面请求 → 直接返回 user/dist 静态文件
│ └── /api/ 请求 → 转发给 API 后端 :8080
│
└─── admin.example.com(管理后台)
│
├── 普通页面请求 → 直接返回 admin/dist 静态文件
└── /api/ 请求 → 转发给 API 后端 :8080
API 后端(Go 程序,Supervisor 托管,监听 8080 端口)
│
├── SQLite 数据库(本地文件,存储所有数据)
└── Redis(缓存 + 任务队列)
前台和后台都是"空壳"静态页面,真正干活的是 API 后端。Nginx 负责把页面里发出的
/api/请求转发给后端,后端处理完再把结果返回给浏览器。
| 项目 | 最低要求 |
|---|---|
| 操作系统 | Ubuntu 20.04 / 22.04(推荐) |
| 内存 | 1GB 以上 |
| 硬盘 | 10GB 以上 |
| 面板 | 宝塔面板(aaPanel) |
一个域名,并解析好两个子域名,例如:
shop.example.com → 用户前台admin.example.com → 后台管理域名已经解析到你服务器的 IP
登录宝塔面板 → 软件商店 → 逐一安装:
⚠️ 不要用宝塔的 PM2 管理器,PM2 是专门为 Node.js 项目设计的,而 dujiao-next 是 Go 编译的二进制程序,用 PM2 会报错。请使用 Supervisor 代替。
Dujiao-Next 分三个部分:
| 名称 | 说明 | 下载地址 |
|---|---|---|
| API | 后端核心程序 | https://github.com/dujiao-next/dujiao-next/releases |
| User | 用户前台页面 | https://github.com/dujiao-next/user/releases |
| Admin | 后台管理页面 | https://github.com/dujiao-next/admin/releases |
⚠️ 三个包的版本号必须一致,比如都选
v1.0.0
打开宝塔面板 → 终端(或者用 Xshell、FinalShell 等工具 SSH 连接服务器),执行:
mkdir -p /www/wwwroot/dujiao-next/{api,user,admin}
cd /www/wwwroot/dujiao-next
# 下载 API(把 v1.0.0 换成你要用的版本号)
wget -O api.tar.gz https://github.com/dujiao-next/dujiao-next/releases/download/v1.0.0/dujiao-next_v1.0.0_Linux_x86_64.tar.gz
tar -xzf api.tar.gz -C api
# 下载 User 前台
wget -O user.zip https://github.com/dujiao-next/user/releases/download/v1.0.0/dujiao-next-user-v1.0.0.zip
unzip -o user.zip -d user
# 下载 Admin 后台
wget -O admin.zip https://github.com/dujiao-next/admin/releases/download/v1.0.0/dujiao-next-admin-v1.0.0.zip
unzip -o admin.zip -d admin
💡 如果 GitHub 下载太慢,可以先在电脑上下载好,再通过宝塔面板的文件管理上传到服务器对应目录。
cd /www/wwwroot/dujiao-next/api
cp config.yml.example config.yml
mkdir -p /www/wwwroot/dujiao-next/api/db
cd /www/wwwroot/dujiao-next/api
sed -i "s/your-secret-key-plokij-in-production-please/$(openssl rand -hex 32)/" config.yml
sed -i "s/user-secret-key-plokij-in-production-please/$(openssl rand -hex 32)/" config.yml
执行完这两条命令,配置文件里的默认密钥就自动替换成随机强密钥了。
chmod +x /www/wwwroot/dujiao-next/api/dujiao-next
cd /www/wwwroot/dujiao-next/api
./dujiao-next 2>&1
看到下面这些内容说明启动成功:
asynq: Starting processing
asynq: Send signal TSTP to stop processing new tasks
asynq: Send signal TERM or INT to terminate the process
确认没报错后,按 Ctrl + C 停掉,准备交给 PM2 托管。
💡 为什么用 Supervisor 而不是 PM2?
宝塔的 PM2 是专门为 Node.js 设计的,dujiao-next 是 Go 编译的二进制程序,直接用 PM2 会报兼容错误。Supervisor 没有这个限制,可以托管任何类型的程序。
宝塔面板 → 软件商店 → 搜索 Supervisor → 安装
安装完成后,宝塔左侧菜单会出现 Supervisor 入口。
宝塔面板 → Supervisor → 添加守护进程,填写以下信息:
| 字段 | 填写内容 |
|---|---|
| 名称 | dujiao-next-api |
| 启动用户 | root |
| 运行目录 | /www/wwwroot/dujiao-next/api |
| 启动命令 | /www/wwwroot/dujiao-next/api/dujiao-next |
| 进程数量 | 1 |

填好后点击 「确定」,状态变为 「运行中」 即成功。
如果宝塔里找不到 Supervisor,可以手动安装并配置:
# 安装 Supervisor
apt-get install -y supervisor
# 创建配置文件
cat > /etc/supervisor/conf.d/dujiao-next.conf << 'EOF'
[program:dujiao-next-api]
command=/www/wwwroot/dujiao-next/api/dujiao-next
directory=/www/wwwroot/dujiao-next/api
autostart=true
autorestart=true
startsecs=3
stdout_logfile=/www/wwwroot/dujiao-next/api/logs/supervisor.log
stderr_logfile=/www/wwwroot/dujiao-next/api/logs/supervisor_err.log
user=root
EOF
# 重载配置并启动
supervisorctl reread
supervisorctl update
supervisorctl start dujiao-next-api
curl http://127.0.0.1:8080/api/ping
有内容返回(不报错)就说明后端正常了。
宝塔面板 → 网站 → 添加站点:
| 字段 | 填写内容 |
|---|---|
| 域名 | shop.example.com |
| 根目录 | /www/wwwroot/dujiao-next/user/dist |
| PHP版本 | 纯静态(选"不使用") |
同上,再添加一个站点:
| 字段 | 填写内容 |
|---|---|
| 域名 | admin.example.com |
| 根目录 | /www/wwwroot/dujiao-next/admin/dist |
| PHP版本 | 纯静态(选"不使用") |
两个站点都要申请:
宝塔面板 → 网站 → 点击对应站点的**「设置」** → SSL → Let's Encrypt → 申请免费证书 → 开启强制 HTTPS
这一步是让前台和后台页面能正确请求到后端 API。两个站点都需要配置,且每个站点需要添加多条反向代理规则。
宝塔面板 → 网站 → 点击 shop.example.com 的**「设置」** → 反向代理 → 添加反向代理
需要依次添加 4 条规则:
第 1 条 — API 接口
| 字段 | 填写内容 |
|---|---|
| 代理名称 | api |
| 代理目录 | /api/ |
| 目标 URL | http://127.0.0.1:8080/api/ |
| 发送域名 | $host |
参考以下截图设置:

第 2 条 — 上传文件
| 字段 | 填写内容 |
|---|---|
| 代理名称 | uploads |
| 代理目录 | /uploads/ |
| 目标 URL | http://127.0.0.1:8080/uploads/ |
| 发送域名 | $host |
第 3 条 — 网站地图(SEO 用)
| 字段 | 填写内容 |
|---|---|
| 代理名称 | sitemap |
| 代理目录 | /sitemap.xml |
| 目标 URL | http://127.0.0.1:8080/sitemap.xml |
| 发送域名 | $host |
第 4 条 — 爬虫协议(SEO 用)
| 字段 | 填写内容 |
|---|---|
| 代理名称 | robots |
| 代理目录 | /robots.txt |
| 目标 URL | http://127.0.0.1:8080/robots.txt |
| 发送域名 | $host |
💡 每条规则的「启用缓存」保持关闭,「高级功能」不需要动。
添加完成后,还需要开启 SPA 路由支持,否则刷新页面会报 404:
宝塔面板 → 该站点**「设置」** → URL 重写 → 填入以下内容并保存:
location / {
try_files $uri $uri/ /index.html;
}
同上,进入 admin.example.com 的**「设置」** → 反向代理,添加 2 条规则:
第 1 条 — API 接口
| 字段 | 填写内容 |
|---|---|
| 代理名称 | api |
| 代理目录 | /api/ |
| 目标 URL | http://127.0.0.1:8080/api/ |
| 发送域名 | $host |
第 2 条 — 上传文件
| 字段 | 填写内容 |
|---|---|
| 代理名称 | uploads |
| 代理目录 | /uploads/ |
| 目标 URL | http://127.0.0.1:8080/uploads/ |
| 发送域名 | $host |
同样需要开启 SPA 路由支持:
宝塔面板 → 该站点**「设置」** → URL 重写 → 填入以下内容并保存:
location / {
try_files $uri $uri/ /index.html;
}
全部保存后,Nginx 会自动重载,配置立即生效。
打开浏览器,访问 https://admin.example.com
默认账号密码:
| 项目 | 内容 |
|---|---|
| 用户名 | admin |
| 密码 | admin123 |
⚠️ 登录后第一件事:马上修改密码!默认密码是公开的,不改会有安全风险。
admin123,再填写新密码(两次)密码要求:8位以上,包含大写字母、小写字母和数字,例如 MyShop2024。
如果还想修改用户名,可以在终端执行命令:
# 进入 API 目录
cd /www/wwwroot/dujiao-next/api
# 修改用户名(把 newusername 换成你想要的用户名)
./dujiao-next admin update-username --old admin --new newusername
💡 用户名修改后,下次登录需要用新用户名,旧用户名将无法使用。
原因: API 后端没有运行。
解决:
# 查看 API 是否在运行
supervisorctl status
# 如果没有,重新启动
supervisorctl start dujiao-next-api
检查两个地方:
# 1. 看日志
tail -20 /www/wwwroot/dujiao-next/api/logs/app.log
# 2. 确认 db 目录存在
ls /www/wwwroot/dujiao-next/api/db/
# 如果不存在,创建它
mkdir -p /www/wwwroot/dujiao-next/api/db
最常见的原因是:
db/ 目录不存在 → 执行上面的 mkdir 创建sed 命令替换密钥检查站点根目录是否设置正确:
/www/wwwroot/dujiao-next/user/dist/www/wwwroot/dujiao-next/admin/dist注意是 dist 子目录,不是 user 或 admin 目录本身。
Nginx 缺少 SPA 路由支持,检查配置文件里是否有:
location / {
try_files $uri $uri/ /index.html;
}
supervisorctl status
tail -f /www/wwwroot/dujiao-next/api/logs/supervisor.log
supervisorctl restart dujiao-next-api
supervisorctl stop dujiao-next-api
cp /www/wwwroot/dujiao-next/api/db/dujiao.db /root/dujiao_backup_$(date +%Y%m%d).db
建议在宝塔面板 → 计划任务 里设置每天自动备份这条命令。
部署完成后,对照下面逐项确认:
db/ 目录已创建config.yml 里 JWT 密钥已替换为随机强密钥./dujiao-next 手动运行没有报错curl http://127.0.0.1:8080/api/ping 有响应user/distadmin/dist/api/ 反向代理适合对安全性有要求的用户。把前端页面和后端 API 分别放在两台服务器上,即使前端服务器遭受 DDoS 攻击被打挂,后端数据库也完全不受影响。
互联网(外网)
│
▼
┌──────────────────────────┐
│ 服务器 A(前端服务器) │ ← 暴露在公网,承受攻击流量
│ - Nginx │
│ - user/dist 用户前台 │
│ - admin/dist 管理后台 │
│ 开放端口:80、443 │
└────────────┬─────────────┘
│ 内网 IP 访问后端 API
▼
┌──────────────────────────┐
│ 服务器 B(后端服务器) │ ← 不对外网暴露,只接受内网请求
│ - API(Go 程序 :8080) │
│ - Redis │
│ - 数据库(SQLite/PG) │
│ 开放端口:仅内网 8080 │
└──────────────────────────┘
按照本教程第二章到第四章操作,把 API 跑起来。
完成后修改 API 监听地址,让它接受来自内网的请求(默认已是 0.0.0.0 不需要改),记下服务器 B 的内网 IP,例如 192.168.1.10。
然后在服务器 B 的防火墙里,只允许服务器 A 的内网 IP 访问 8080 端口:
# 只允许服务器 A(192.168.1.5)访问 8080,拒绝其他所有来源
ufw allow from 192.168.1.5 to any port 8080
ufw deny 8080
💡 内网 IP 在宝塔面板首页或者云服务商控制台可以查到。两台服务器需要在同一个 VPC(私有网络)内才有内网 IP,阿里云、腾讯云、AWS 等都支持。
按照本教程第五章,在服务器 A 上创建两个网站(user/dist 和 admin/dist),申请 SSL 证书。
配置反向代理时,目标 URL 改为服务器 B 的内网 IP,不再是 127.0.0.1:
| 字段 | 单服务器填法 | 双服务器填法 |
|---|---|---|
| 目标 URL(API) | http://127.0.0.1:8080/api/ |
http://192.168.1.10:8080/api/ |
| 目标 URL(uploads) | http://127.0.0.1:8080/uploads/ |
http://192.168.1.10:8080/uploads/ |
其余配置(代理目录、SPA 重写规则)完全一样,按第六章操作即可。
在服务器 A 上测试能否访问到服务器 B 的 API:
curl http://192.168.1.10:8080/api/ping
有返回内容说明内网连通正常,前端页面就能正常请求到后端了。
| 操作 | 说明 |
|---|---|
| 服务器 B 不绑定公网域名 | 后端不需要域名,只通过内网 IP 通信 |
| 服务器 B 关闭 80/443 端口 | 防火墙只开放 22(SSH)和 8080(仅内网) |
| 服务器 A 不安装数据库 | 前端服务器上不存任何数据 |
| 定期备份服务器 B 的数据库 | 数据都在 B 上,B 才是最需要保护的 |
| 两台服务器都开启 SSH 密钥登录 | 禁用密码登录,防止暴力破解 |
例如:服务器 A 在香港,服务器 B 在新加坡。不在同一机房就没有内网 IP,两台机器只能通过公网通信,直接暴露 8080 端口风险很高。下面提供三种解决方案,任选其一。
| 方案 | 难度 | 安全性 | 推荐程度 |
|---|---|---|---|
| 方案一:WireGuard 虚拟内网 | ⭐⭐⭐ | ★★★★★ | ✅ 最推荐 |
| 方案二:Cloudflare Tunnel | ⭐⭐ | ★★★★★ | ✅ 免费易用 |
| 方案三:Nginx 反代 + HTTPS + IP 白名单 | ⭐⭐ | ★★★★ | ✅ 备选 |
WireGuard 是一个轻量级 VPN 工具,可以把两台不同机房的服务器虚拟成同一个内网,配置完之后和同机房使用方式完全一样,延迟极低。
# 安装
apt install -y wireguard
# 生成密钥对
wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey
# 查看并记录公钥(后面要填到 A 的配置里)
cat /etc/wireguard/publickey
创建配置文件:
cat > /etc/wireguard/wg0.conf << 'EOF'
[Interface]
PrivateKey = 这里填服务器B的私钥(cat /etc/wireguard/privatekey)
Address = 10.0.0.2/24
ListenPort = 51820
[Peer]
PublicKey = 这里填服务器A的公钥(下一步生成后填回来)
AllowedIPs = 10.0.0.1/32
EOF
apt install -y wireguard
wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey
cat /etc/wireguard/publickey
创建配置文件:
cat > /etc/wireguard/wg0.conf << 'EOF'
[Interface]
PrivateKey = 这里填服务器A的私钥
Address = 10.0.0.1/24
[Peer]
PublicKey = 这里填服务器B的公钥
Endpoint = 服务器B的公网IP:51820
AllowedIPs = 10.0.0.2/32
PersistentKeepalive = 25
EOF
两台服务器都执行:
# 启动
wg-quick up wg0
# 设置开机自启
systemctl enable wg-quick@wg0
在服务器 A 上执行:
ping 10.0.0.2
能 ping 通说明虚拟内网建立成功。
和同机房完全一样,服务器 A 的反向代理目标 URL 改为 WireGuard 的虚拟内网 IP:
http://10.0.0.2:8080/api/
http://10.0.0.2:8080/uploads/
服务器 B 的防火墙只允许 WireGuard 网段访问 8080:
ufw allow from 10.0.0.0/24 to any port 8080
ufw deny 8080
Cloudflare Tunnel 可以把服务器 B 的 API 安全地暴露给服务器 A,服务器 B 不需要开放任何公网端口,流量通过 Cloudflare 加密传输。
# 下载安装
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
dpkg -i cloudflared-linux-amd64.deb
# 登录 Cloudflare(会输出一个链接,用浏览器打开授权)
cloudflared tunnel login
# 创建隧道(名字随意)
cloudflared tunnel create dujiao-api
# 查看隧道 ID(记下来)
cloudflared tunnel list
创建配置文件(把 隧道ID 换成上面查到的):
cat > ~/.cloudflared/config.yml << 'EOF'
tunnel: 隧道ID
credentials-file: /root/.cloudflared/隧道ID.json
ingress:
- service: http://127.0.0.1:8080
EOF
绑定一个二级域名(例如 api-internal.example.com):
cloudflared tunnel route dns dujiao-api api-internal.example.com
启动隧道:
cloudflared service install
systemctl start cloudflared
目标 URL 改为 Cloudflare 隧道域名:
https://api-internal.example.com/api/
https://api-internal.example.com/uploads/
⚠️
api-internal.example.com这个域名不要对外公开,只用于两台服务器之间通信。可以在 Cloudflare DNS 里把它设置为仅代理(橙色云朵),不要直接解析到公网 IP。
如果不想折腾 WireGuard 和 Cloudflare,可以在服务器 B 上用 Nginx 把 API 包一层 HTTPS,再用 IP 白名单只允许服务器 A 访问。
在宝塔面板创建一个站点,例如 api-internal.example.com,申请 SSL 证书,然后在 Nginx 配置中加入:
server {
listen 443 ssl;
server_name api-internal.example.com;
# SSL 证书(宝塔申请)
ssl_certificate ...;
ssl_certificate_key ...;
# IP 白名单:只允许服务器 A 的公网 IP 访问
allow 服务器A的公网IP;
deny all;
location / {
proxy_pass http://127.0.0.1:8080;
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;
}
}
目标 URL 改为:
https://api-internal.example.com/api/
https://api-internal.example.com/uploads/
⚠️ 服务器 A 的公网 IP 要固定,如果 IP 会变(部分云服务器重启后 IP 会变),这个方案就不适用,建议改用方案一或方案二。
| 方案一 WireGuard | 方案二 Cloudflare Tunnel | 方案三 Nginx+IP白名单 | |
|---|---|---|---|
| 配置难度 | 中 | 简单 | 简单 |
| 费用 | 免费 | 免费 | 免费 |
| 安全性 | 极高 | 极高 | 高 |
| 延迟 | 极低 | 中(经过CF节点) | 低 |
| 服务器B需要开放端口 | 仅 51820(UDP) | 无需开放任何端口 | 443 |
| 适合场景 | 追求性能 | 追求简单 | 临时方案 |
教程基于 Dujiao-Next v1.0.0 编写,官方文档:https://dujiao-next.com