新手快速搭建独角数卡教程Dujiao-Next《新版独角数卡》
新手快速部署Dujiao-Next《新版独角数卡》
一、准备工作
1.1 服务器要求
| 项目 | 最低要求 |
|---|---|
| 操作系统 | Ubuntu 20.04 / 22.04(推荐) |
| 内存 | 1GB 以上 |
| 硬盘 | 10GB 以上 |
| 面板 | 宝塔面板(aaPanel) |
1.2 需要准备的东西
-
一个域名,并解析好两个子域名,例如:
shop.example.com→ 用户前台admin.example.com→ 后台管理
域名已经解析到你服务器的 IP
1.3 宝塔面板里提前安装好这些软件
登录宝塔面板 → 软件商店 → 逐一安装:
- ✅ Nginx(Web 服务器)
- ✅ Supervisor(让后端程序在后台持续运行)
- ✅ Redis(缓存服务)
二、下载程序包
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
2.1 SSH 登录服务器,创建目录
打开宝塔面板 → 终端(或者用 Xshell、FinalShell 等工具 SSH 连接服务器),执行:
mkdir -p /www/wwwroot/dujiao-next/{api,user,admin}
cd /www/wwwroot/dujiao-next
2.2 下载并解压(把版本号换成最新版)
# 下载 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 下载太慢,可以先在电脑上下载好,再通过宝塔面板的文件管理上传到服务器对应目录。
三、配置后端 API
3.1 复制配置文件
cd /www/wwwroot/dujiao-next/api
cp config.yml.example config.yml
3.2 创建数据库目录(重要,不做会启动失败!)
mkdir -p /www/wwwroot/dujiao-next/api/db
3.3 生成安全密钥(重要,不做会启动失败!)
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
执行完这两条命令,配置文件里的默认密钥就自动替换成随机强密钥了。
3.4 给程序添加执行权限
chmod +x /www/wwwroot/dujiao-next/api/dujiao-next
3.5 先手动试运行,确认没有问题
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 托管后端(让程序一直在后台跑)
💡 为什么用 Supervisor 而不是 PM2?
宝塔的 PM2 是专门为 Node.js 设计的,dujiao-next 是 Go 编译的二进制程序,直接用 PM2 会报兼容错误。Supervisor 没有这个限制,可以托管任何类型的程序。
4.1 安装 Supervisor
宝塔面板 → 软件商店 → 搜索 Supervisor → 安装
安装完成后,宝塔左侧菜单会出现 Supervisor 入口。
4.2 添加守护进程
宝塔面板 → Supervisor → 添加守护进程,填写以下信息:
| 字段 | 填写内容 |
|---|---|
| 名称 | dujiao-next-api |
| 启动用户 | root |
| 运行目录 | /www/wwwroot/dujiao-next/api |
| 启动命令 | /www/wwwroot/dujiao-next/api/dujiao-next |
| 进程数量 | 1 |

填好后点击 「确定」,状态变为 「运行中」 即成功。
4.3 也可以用命令行配置(二选一)
如果宝塔里找不到 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
4.4 验证 API 是否正常运行
curl http://127.0.0.1:8080/api/ping
有内容返回(不报错)就说明后端正常了。
五、在宝塔面板创建网站
5.1 创建用户前台站点
宝塔面板 → 网站 → 添加站点:
| 字段 | 填写内容 |
|---|---|
| 域名 | shop.example.com |
| 根目录 | /www/wwwroot/dujiao-next/user/dist |
| PHP版本 | 纯静态(选"不使用") |
5.2 创建后台管理站点
同上,再添加一个站点:
| 字段 | 填写内容 |
|---|---|
| 域名 | admin.example.com |
| 根目录 | /www/wwwroot/dujiao-next/admin/dist |
| PHP版本 | 纯静态(选"不使用") |
5.3 申请 SSL 证书(开启 HTTPS)
两个站点都要申请:
宝塔面板 → 网站 → 点击对应站点的**「设置」** → SSL → Let's Encrypt → 申请免费证书 → 开启强制 HTTPS
六、配置反向代理
这一步是让前台和后台页面能正确请求到后端 API。两个站点都需要配置,且每个站点需要添加多条反向代理规则。
6.1 配置用户前台(shop.example.com)
宝塔面板 → 网站 → 点击 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;
}
6.2 配置后台管理(admin.example.com)
同上,进入 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 |
⚠️ 登录后第一件事:马上修改密码!默认密码是公开的,不改会有安全风险。
7.1 修改后台登录密码
- 登录后台后,点击页面右上角的头像
- 在下拉菜单中点击**「修改密码」**
- 填写旧密码
admin123,再填写新密码(两次) - 点击**「确认」**保存
密码要求:8位以上,包含大写字母、小写字母和数字,例如 MyShop2024。
7.2 修改后台登录用户名(可选)
如果还想修改用户名,可以在终端执行命令:
# 进入 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
❓ 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创建- JWT 密钥是默认值 → 重新执行第三步的
sed命令替换密钥
❓ 页面打开是空白或 404
检查站点根目录是否设置正确:
- 前台根目录应为:
/www/wwwroot/dujiao-next/user/dist - 后台根目录应为:
/www/wwwroot/dujiao-next/admin/dist
注意是 dist 子目录,不是 user 或 admin 目录本身。
❓ 刷新页面报 404
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
备份数据库(SQLite)
cp /www/wwwroot/dujiao-next/api/db/dujiao.db /root/dujiao_backup_$(date +%Y%m%d).db
建议在宝塔面板 → 计划任务 里设置每天自动备份这条命令。
十、部署检查清单
部署完成后,对照下面逐项确认:
- [ ]
db/目录已创建 - [ ]
config.yml里 JWT 密钥已替换为随机强密钥 - [ ]
./dujiao-next手动运行没有报错 - [ ] Supervisor 中 API 状态为「运行中」
- [ ]
curl http://127.0.0.1:8080/api/ping有响应 - [ ] 前台站点根目录指向
user/dist - [ ] 后台站点根目录指向
admin/dist - [ ] 两个站点均已申请 SSL 证书
- [ ] Nginx 配置了
/api/反向代理 - [ ] 登录后台后已修改默认密码
十一、进阶:前后端分离部署(双服务器方案)
适合对安全性有要求的用户。把前端页面和后端 API 分别放在两台服务器上,即使前端服务器遭受 DDoS 攻击被打挂,后端数据库也完全不受影响。
架构示意
互联网(外网)
│
▼
┌──────────────────────────┐
│ 服务器 A(前端服务器) │ ← 暴露在公网,承受攻击流量
│ - Nginx │
│ - user/dist 用户前台 │
│ - admin/dist 管理后台 │
│ 开放端口:80、443 │
└────────────┬─────────────┘
│ 内网 IP 访问后端 API
▼
┌──────────────────────────┐
│ 服务器 B(后端服务器) │ ← 不对外网暴露,只接受内网请求
│ - API(Go 程序 :8080) │
│ - Redis │
│ - 数据库(SQLite/PG) │
│ 开放端口:仅内网 8080 │
└──────────────────────────┘
部署步骤
服务器 B(后端)先部署
按照本教程第二章到第四章操作,把 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(前端)配置
按照本教程第五章,在服务器 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 虚拟内网(最推荐)
WireGuard 是一个轻量级 VPN 工具,可以把两台不同机房的服务器虚拟成同一个内网,配置完之后和同机房使用方式完全一样,延迟极低。
服务器 B(新加坡,后端)安装 WireGuard
# 安装
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
服务器 A(香港,前端)安装 WireGuard
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
启动 WireGuard
两台服务器都执行:
# 启动
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(最简单,免费)
Cloudflare Tunnel 可以把服务器 B 的 API 安全地暴露给服务器 A,服务器 B 不需要开放任何公网端口,流量通过 Cloudflare 加密传输。
服务器 B(新加坡,后端)安装 cloudflared
# 下载安装
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
服务器 A(香港,前端)配置反向代理
目标 URL 改为 Cloudflare 隧道域名:
https://api-internal.example.com/api/
https://api-internal.example.com/uploads/
⚠️
api-internal.example.com这个域名不要对外公开,只用于两台服务器之间通信。可以在 Cloudflare DNS 里把它设置为仅代理(橙色云朵),不要直接解析到公网 IP。
方案三:Nginx 反代 + HTTPS + IP 白名单(备选)
如果不想折腾 WireGuard 和 Cloudflare,可以在服务器 B 上用 Nginx 把 API 包一层 HTTPS,再用 IP 白名单只允许服务器 A 访问。
服务器 B 配置
在宝塔面板创建一个站点,例如 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;
}
}
服务器 A 配置反向代理
目标 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