789 lines
19 KiB
Markdown
789 lines
19 KiB
Markdown
# 星遇社交平台:宝塔非 Docker 生产环境搭建说明
|
||
|
||
本文适用于在宝塔 Linux 面板中,以原生进程方式部署本项目,不使用 Docker。
|
||
|
||
部署后的结构如下:
|
||
|
||
```text
|
||
app.example.com
|
||
-> 宝塔 Nginx
|
||
-> uni-app H5 静态文件
|
||
|
||
admin.example.com
|
||
-> 宝塔 Nginx
|
||
-> Vben Admin 静态文件
|
||
-> /admin/v1/* 反向代理到 127.0.0.1:18888
|
||
|
||
api.example.com
|
||
-> 宝塔 Nginx
|
||
-> HTTP API、上传文件及 WebSocket
|
||
-> 反向代理到 127.0.0.1:18888
|
||
|
||
127.0.0.1:18888
|
||
-> Go 后端 systemd 服务
|
||
-> 宝塔 MySQL
|
||
```
|
||
|
||
> 为什么使用 `18888`:宝塔面板常使用 `8888`,原生部署时后端不能再占用同一个宿主机端口。后端只监听 `127.0.0.1`,不向公网开放。
|
||
|
||
## 1. 部署前准备
|
||
|
||
### 1.1 推荐配置
|
||
|
||
- Ubuntu 24.04 或 Debian 12
|
||
- 最低 2 核 4 GB,建议 4 核 8 GB
|
||
- 50 GB 以上磁盘
|
||
- 宝塔 Linux 面板
|
||
- Nginx 1.24 或更高版本
|
||
- MySQL 8.0/8.4
|
||
- Go 1.27
|
||
- Node.js 22.18 或更高版本(推荐 Node.js 22 LTS)
|
||
- pnpm 10.33.4
|
||
|
||
项目后端的 `go.mod` 要求 Go 1.27;管理端要求 Node.js `^22.18.0 || ^24.0.0` 和 pnpm 10 或更高版本。不要使用宝塔中较旧的 Node.js 18/20 构建管理端。
|
||
|
||
### 1.2 域名
|
||
|
||
准备三个域名并添加 A 记录:
|
||
|
||
```text
|
||
app.example.com -> 服务器公网 IP
|
||
admin.example.com -> 服务器公网 IP
|
||
api.example.com -> 服务器公网 IP
|
||
```
|
||
|
||
云服务器安全组和宝塔防火墙只需要放行:
|
||
|
||
```text
|
||
22 SSH
|
||
80 HTTP/证书验证
|
||
443 HTTPS/WSS
|
||
```
|
||
|
||
不要向公网开放 MySQL `3306` 和后端 `18888`。
|
||
|
||
### 1.3 规划目录
|
||
|
||
```text
|
||
/www/wwwroot/xingyu-source/ 项目源代码
|
||
/www/wwwroot/xingyu-app/ uni-app H5 发布目录
|
||
/www/wwwroot/xingyu-admin/ 管理端发布目录
|
||
/www/wwwroot/xingyu-api-empty/ API 域名空站点目录
|
||
/www/wwwroot/xingyu-data/uploads/ 本地文件存储目录
|
||
/www/server/xingyu-im/ 后端二进制和迁移脚本
|
||
/etc/xingyu-im.env 后端生产环境变量
|
||
```
|
||
|
||
## 2. 在宝塔安装基础环境
|
||
|
||
在“软件商店”安装:
|
||
|
||
1. Nginx。
|
||
2. MySQL 8.0 或 8.4。
|
||
3. Node 版本管理器。
|
||
|
||
不需要安装 PHP、PM2、Docker、Redis。Go 后端由 systemd 守护,两个前端都是静态文件。
|
||
|
||
进入:
|
||
|
||
```text
|
||
网站 -> Node 项目 -> Node 版本管理器
|
||
```
|
||
|
||
安装 Node.js 22.18 以上版本,并设为“命令行版本”。然后在宝塔终端验证:
|
||
|
||
```bash
|
||
node --version
|
||
npm --version
|
||
npm install --global pnpm@10.33.4
|
||
pnpm --version
|
||
```
|
||
|
||
Node.js 必须满足项目声明的版本要求,建议使用当前 Node.js 22 LTS。
|
||
|
||
## 3. 安装 Go 1.27
|
||
|
||
先检查:
|
||
|
||
```bash
|
||
go version
|
||
uname -m
|
||
```
|
||
|
||
如果已经是 Go 1.27,可跳过本节。以下命令适用于 `x86_64` 服务器:
|
||
|
||
```bash
|
||
cd /tmp
|
||
curl -fLO https://go.dev/dl/go1.27.0.linux-amd64.tar.gz
|
||
echo '675c26c449cbb18fc24b74650de1eabbae6e16f64326fd85a283fb3b58280685 go1.27.0.linux-amd64.tar.gz' | sha256sum -c -
|
||
install -d /opt/go1.27.0
|
||
tar -C /opt/go1.27.0 --strip-components=1 -xzf go1.27.0.linux-amd64.tar.gz
|
||
ln -s /opt/go1.27.0/bin/go /usr/local/bin/go
|
||
ln -s /opt/go1.27.0/bin/gofmt /usr/local/bin/gofmt
|
||
go version
|
||
```
|
||
|
||
如果 `/usr/local/bin/go` 已存在,不要直接覆盖;先确认现有 Go 的安装方式和用途。ARM64 服务器应从 Go 官方下载页选择 `linux-arm64` 文件并校验对应 SHA256。
|
||
|
||
## 4. 上传源代码
|
||
|
||
在宝塔“文件”中将项目上传并解压为:
|
||
|
||
```text
|
||
/www/wwwroot/xingyu-source/
|
||
├── admin/
|
||
├── backend/
|
||
├── mobile/
|
||
├── deploy/
|
||
└── README.md
|
||
```
|
||
|
||
确认不是下面这种双层目录:
|
||
|
||
```text
|
||
/www/wwwroot/xingyu-source/im/backend/
|
||
```
|
||
|
||
创建运行目录:
|
||
|
||
```bash
|
||
install -d -o www -g www -m 0755 /www/wwwroot/xingyu-app
|
||
install -d -o www -g www -m 0755 /www/wwwroot/xingyu-admin
|
||
install -d -o www -g www -m 0755 /www/wwwroot/xingyu-api-empty
|
||
install -d -o www -g www -m 0750 /www/wwwroot/xingyu-data/uploads
|
||
install -d -o root -g root -m 0755 /www/server/xingyu-im
|
||
```
|
||
|
||
## 5. 创建 MySQL 数据库
|
||
|
||
进入宝塔“数据库”,创建:
|
||
|
||
```text
|
||
数据库名:im
|
||
用户名:xingyu_app
|
||
密码:使用 openssl rand -hex 32 生成
|
||
字符集:utf8mb4
|
||
访问权限:本地服务器
|
||
```
|
||
|
||
不要让后端使用 MySQL `root` 账号。生产配置会主动拒绝 `root` DSN。
|
||
|
||
生成数据库密码:
|
||
|
||
```bash
|
||
openssl rand -hex 32
|
||
```
|
||
|
||
数据库密码建议使用十六进制随机字符串,避免 `@`、`:` 等字符破坏 MySQL DSN 格式。
|
||
|
||
## 6. 执行数据库迁移
|
||
|
||
本项目包含 `001` 到 `026` 的顺序迁移。非 Docker 环境可以创建下面的迁移脚本:
|
||
|
||
```bash
|
||
nano /www/server/xingyu-im/migrate.sh
|
||
```
|
||
|
||
脚本内容:
|
||
|
||
```bash
|
||
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
|
||
mysql_cli=/www/server/mysql/bin/mysql
|
||
database_host=127.0.0.1
|
||
database_name=im
|
||
database_user=xingyu_app
|
||
migration_dir=/www/wwwroot/xingyu-source/backend/migrations
|
||
|
||
if [ ! -x "$mysql_cli" ]; then
|
||
mysql_cli="$(command -v mysql)"
|
||
fi
|
||
|
||
if [ -z "${MYSQL_PWD:-}" ]; then
|
||
echo '请先通过 MYSQL_PWD 环境变量提供数据库密码' >&2
|
||
exit 1
|
||
fi
|
||
|
||
mysql_args=(
|
||
--host="$database_host"
|
||
--user="$database_user"
|
||
--database="$database_name"
|
||
--default-character-set=utf8mb4
|
||
--batch
|
||
--skip-column-names
|
||
)
|
||
|
||
"$mysql_cli" "${mysql_args[@]}" --execute "
|
||
CREATE TABLE IF NOT EXISTS schema_migrations (
|
||
version VARCHAR(255) NOT NULL PRIMARY KEY,
|
||
checksum CHAR(64) NOT NULL,
|
||
applied_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||
"
|
||
|
||
for migration_file in "$migration_dir"/*.sql; do
|
||
migration_name="$(basename "$migration_file")"
|
||
migration_checksum="$(sha256sum "$migration_file" | awk '{print $1}')"
|
||
stored_checksum="$("$mysql_cli" "${mysql_args[@]}" --execute "SELECT checksum FROM schema_migrations WHERE version='${migration_name}'" || true)"
|
||
|
||
if [ -n "$stored_checksum" ]; then
|
||
if [ "$stored_checksum" != "$migration_checksum" ]; then
|
||
echo "迁移校验和不一致:$migration_name" >&2
|
||
exit 1
|
||
fi
|
||
echo "已执行:$migration_name"
|
||
continue
|
||
fi
|
||
|
||
echo "正在执行:$migration_name"
|
||
"$mysql_cli" "${mysql_args[@]}" < "$migration_file"
|
||
"$mysql_cli" "${mysql_args[@]}" --execute "INSERT INTO schema_migrations(version, checksum) VALUES('${migration_name}', '${migration_checksum}')"
|
||
done
|
||
```
|
||
|
||
设置权限并执行:
|
||
|
||
```bash
|
||
chmod 0750 /www/server/xingyu-im/migrate.sh
|
||
export MYSQL_PWD='替换为数据库密码'
|
||
/www/server/xingyu-im/migrate.sh
|
||
unset MYSQL_PWD
|
||
```
|
||
|
||
正常情况下会依次显示 `001_users.sql` 到 `026_report_operations.sql`。已经登记过且校验和一致的迁移会跳过。
|
||
|
||
不要修改已经在生产数据库执行过的迁移文件;后续数据库变更应该新增编号更大的迁移。
|
||
|
||
## 7. 构建 uni-app H5
|
||
|
||
客户端 API 域名和 WSS 域名会在构建时写入产物。必须使用正式域名构建:
|
||
|
||
```bash
|
||
cd /www/wwwroot/xingyu-source/mobile
|
||
corepack enable
|
||
pnpm install --frozen-lockfile
|
||
VITE_API_ORIGIN=https://api.example.com \
|
||
VITE_WS_ORIGIN=wss://api.example.com \
|
||
VITE_APP_VERSION=1.0.0 \
|
||
pnpm build:h5
|
||
```
|
||
|
||
发布静态文件:
|
||
|
||
```bash
|
||
rsync -a --delete \
|
||
/www/wwwroot/xingyu-source/mobile/dist/build/h5/ \
|
||
/www/wwwroot/xingyu-app/
|
||
chown -R www:www /www/wwwroot/xingyu-app
|
||
```
|
||
|
||
`rsync --delete` 只会清理 `/www/wwwroot/xingyu-app/` 中上一版本遗留的静态文件,不会操作源代码和用户上传目录。
|
||
|
||
域名修改后必须重新构建 H5,单纯修改 Nginx 不会更新已经写入 JavaScript 的 API/WSS 地址。
|
||
|
||
## 8. 构建 Vben 管理端
|
||
|
||
管理端生产配置使用同域名 `/admin/v1`,由宝塔 Nginx 转发到后端。
|
||
|
||
管理端 build 接口地址位于 `admin/.env.production`。如需使用独立 API 域名,编辑:
|
||
|
||
```bash
|
||
nano /www/wwwroot/xingyu-source/admin/.env.production
|
||
```
|
||
|
||
然后将接口地址设为:
|
||
|
||
```dotenv
|
||
VITE_GLOB_API_URL=https://api.example.com/admin/v1
|
||
```
|
||
|
||
保持同域名反向代理时无需修改,默认值就是 `/admin/v1`。开发接口地址位于 `admin/.env.development`,不会影响生产构建。
|
||
|
||
先将 `admin/apps/web-ele/.env` 中的下面一项改为独立随机值:
|
||
|
||
```dotenv
|
||
VITE_APP_STORE_SECURE_KEY=替换为独立随机字符串
|
||
```
|
||
|
||
该值可以使用 `openssl rand -hex 32` 生成。它会进入前端产物,不能替代服务端密钥,但不应继续使用示例值。
|
||
|
||
执行构建:
|
||
|
||
```bash
|
||
cd /www/wwwroot/xingyu-source/admin
|
||
pnpm install --frozen-lockfile
|
||
NODE_OPTIONS=--max-old-space-size=4096 pnpm --filter @vben/web-ele build
|
||
```
|
||
|
||
发布静态文件:
|
||
|
||
```bash
|
||
rsync -a --delete \
|
||
/www/wwwroot/xingyu-source/admin/apps/web-ele/dist/ \
|
||
/www/wwwroot/xingyu-admin/
|
||
chown -R www:www /www/wwwroot/xingyu-admin
|
||
```
|
||
|
||
## 9. 构建和安装 Go 后端
|
||
|
||
先运行测试:
|
||
|
||
```bash
|
||
cd /www/wwwroot/xingyu-source/backend
|
||
go mod download
|
||
go test ./...
|
||
```
|
||
|
||
测试通过后构建静态二进制:
|
||
|
||
```bash
|
||
CGO_ENABLED=0 go build \
|
||
-trimpath \
|
||
-ldflags='-s -w' \
|
||
-o /tmp/xingyu-api \
|
||
./cmd/server
|
||
|
||
install -o root -g root -m 0755 \
|
||
/tmp/xingyu-api \
|
||
/www/server/xingyu-im/xingyu-api
|
||
```
|
||
|
||
生产运行不依赖 Go、Node.js 或 pnpm;它们只在构建和更新时使用。
|
||
|
||
## 10. 配置后端生产环境变量
|
||
|
||
生成三组不同的密钥:
|
||
|
||
```bash
|
||
openssl rand -hex 48
|
||
openssl rand -hex 48
|
||
openssl rand -hex 32
|
||
```
|
||
|
||
前两个分别用于 JWT 和平台配置加密,第三个可作为初始管理员密码随机部分。`IM_CONFIG_ENCRYPTION_KEY` 上线后必须永久、安全保存,不能随意更换。
|
||
|
||
创建配置文件:
|
||
|
||
```bash
|
||
nano /etc/xingyu-im.env
|
||
```
|
||
|
||
内容如下:
|
||
|
||
```dotenv
|
||
IM_ENV=production
|
||
IM_HOST=127.0.0.1
|
||
IM_PORT=18888
|
||
|
||
IM_DB_DSN=xingyu_app:替换为数据库密码@tcp(127.0.0.1:3306)/im?charset=utf8mb4&parseTime=True&loc=Local
|
||
IM_JWT_SECRET=替换为至少32字节的独立随机密钥
|
||
IM_CONFIG_ENCRYPTION_KEY=替换为另一个至少32字节的独立随机密钥
|
||
|
||
IM_ALLOWED_ORIGINS=https://app.example.com,https://admin.example.com
|
||
IM_SEED_DEMO=false
|
||
IM_MEDIA_DIR=/www/wwwroot/xingyu-data/uploads
|
||
|
||
IM_BOOTSTRAP_ADMIN_USERNAME=admin
|
||
IM_BOOTSTRAP_ADMIN_PASSWORD=替换为至少12位且包含大小写字母数字和特殊字符的密码
|
||
IM_BOOTSTRAP_ADMIN_REAL_NAME=平台管理员
|
||
|
||
TZ=Asia/Shanghai
|
||
```
|
||
|
||
保护配置文件:
|
||
|
||
```bash
|
||
chown root:root /etc/xingyu-im.env
|
||
chmod 0600 /etc/xingyu-im.env
|
||
```
|
||
|
||
生产环境要求:
|
||
|
||
- JWT 密钥至少 32 字节。
|
||
- 配置加密密钥至少 32 字节。
|
||
- CORS 来源必须是明确的 HTTPS 地址,不能使用 `*`。
|
||
- 数据库账号不能是 `root`。
|
||
- 初始管理员密码至少 12 位,且包含大小写字母、数字和特殊字符。
|
||
- 禁止开启演示数据。
|
||
|
||
## 11. 创建 systemd 服务
|
||
|
||
创建:
|
||
|
||
```bash
|
||
nano /etc/systemd/system/xingyu-im.service
|
||
```
|
||
|
||
内容如下:
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=Xingyu Social Platform API
|
||
Wants=network-online.target
|
||
After=network-online.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
User=www
|
||
Group=www
|
||
WorkingDirectory=/www/server/xingyu-im
|
||
EnvironmentFile=/etc/xingyu-im.env
|
||
ExecStart=/www/server/xingyu-im/xingyu-api
|
||
Restart=always
|
||
RestartSec=3
|
||
TimeoutStopSec=30
|
||
LimitNOFILE=65535
|
||
UMask=0027
|
||
NoNewPrivileges=true
|
||
PrivateTmp=true
|
||
PrivateDevices=true
|
||
ProtectHome=true
|
||
ProtectSystem=strict
|
||
ReadWritePaths=/www/wwwroot/xingyu-data/uploads
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
启动服务:
|
||
|
||
```bash
|
||
systemctl daemon-reload
|
||
systemctl enable --now xingyu-im
|
||
systemctl status xingyu-im --no-pager
|
||
```
|
||
|
||
查看日志:
|
||
|
||
```bash
|
||
journalctl -u xingyu-im -n 200 --no-pager
|
||
journalctl -u xingyu-im -f
|
||
```
|
||
|
||
本机验证:
|
||
|
||
```bash
|
||
curl -fsS http://127.0.0.1:18888/healthz
|
||
ss -lntp | grep 18888
|
||
```
|
||
|
||
应该只能看到 `127.0.0.1:18888`,不能看到 `0.0.0.0:18888`。
|
||
|
||
首次启动成功并登录管理端修改密码后,可以清空 `/etc/xingyu-im.env` 中的:
|
||
|
||
```dotenv
|
||
IM_BOOTSTRAP_ADMIN_PASSWORD=
|
||
```
|
||
|
||
然后执行:
|
||
|
||
```bash
|
||
systemctl restart xingyu-im
|
||
```
|
||
|
||
## 12. 在宝塔创建三个网站
|
||
|
||
### 12.1 H5 网站
|
||
|
||
进入“网站”,新增 HTML 静态网站:
|
||
|
||
```text
|
||
域名:app.example.com
|
||
根目录:/www/wwwroot/xingyu-app
|
||
PHP:纯静态
|
||
```
|
||
|
||
在站点 Nginx 配置的 `server` 内确保包含:
|
||
|
||
```nginx
|
||
location = /index.html {
|
||
add_header Cache-Control "no-store";
|
||
}
|
||
|
||
location / {
|
||
try_files $uri $uri/ /index.html;
|
||
}
|
||
|
||
location ~* \.(?:js|css|png|jpg|jpeg|gif|webp|svg|ico|woff2?)$ {
|
||
expires 7d;
|
||
add_header Cache-Control "public, immutable";
|
||
try_files $uri =404;
|
||
}
|
||
```
|
||
|
||
### 12.2 管理端网站
|
||
|
||
新增 HTML 静态网站:
|
||
|
||
```text
|
||
域名:admin.example.com
|
||
根目录:/www/wwwroot/xingyu-admin
|
||
PHP:纯静态
|
||
```
|
||
|
||
在该站点 `server` 内加入或替换相应 `location`:
|
||
|
||
```nginx
|
||
location ^~ /admin/v1/ {
|
||
proxy_pass http://127.0.0.1:18888;
|
||
proxy_http_version 1.1;
|
||
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 10s;
|
||
proxy_read_timeout 60s;
|
||
}
|
||
|
||
location = /_app.config.js {
|
||
expires -1;
|
||
add_header Cache-Control "no-store, no-cache, must-revalidate";
|
||
try_files $uri =404;
|
||
}
|
||
|
||
location = /index.html {
|
||
add_header Cache-Control "no-store";
|
||
}
|
||
|
||
location / {
|
||
try_files $uri $uri/ /index.html;
|
||
}
|
||
|
||
location ~* \.(?:js|css|png|jpg|jpeg|gif|webp|svg|ico|woff2?)$ {
|
||
expires 7d;
|
||
add_header Cache-Control "public, immutable";
|
||
try_files $uri =404;
|
||
}
|
||
```
|
||
|
||
`/_app.config.js` 保存管理端运行时接口地址,必须禁止浏览器和 CDN 缓存;否则修改接口域名后客户端可能继续请求旧地址。
|
||
|
||
### 12.3 API 和 WebSocket 网站
|
||
|
||
新增网站:
|
||
|
||
```text
|
||
域名:api.example.com
|
||
根目录:/www/wwwroot/xingyu-api-empty
|
||
PHP:纯静态
|
||
```
|
||
|
||
在该站点 `server` 内加入:
|
||
|
||
```nginx
|
||
client_max_body_size 16m;
|
||
|
||
location ^~ /ws {
|
||
proxy_pass http://127.0.0.1:18888;
|
||
proxy_http_version 1.1;
|
||
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_read_timeout 70s;
|
||
proxy_send_timeout 70s;
|
||
proxy_buffering off;
|
||
}
|
||
|
||
location / {
|
||
proxy_pass http://127.0.0.1:18888;
|
||
proxy_http_version 1.1;
|
||
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 10s;
|
||
proxy_read_timeout 60s;
|
||
}
|
||
```
|
||
|
||
保存配置前点击宝塔的配置检查,或在终端执行:
|
||
|
||
```bash
|
||
nginx -t
|
||
```
|
||
|
||
检查成功后重载:
|
||
|
||
```bash
|
||
/etc/init.d/nginx reload
|
||
```
|
||
|
||
不要在宝塔中再为 API 域名创建另一条普通“反向代理”,避免宝塔生成的 `location /` 与上面的 WebSocket 配置冲突。
|
||
|
||
## 13. 配置 HTTPS
|
||
|
||
依次打开三个网站:
|
||
|
||
```text
|
||
网站设置 -> SSL -> Let's Encrypt
|
||
```
|
||
|
||
分别申请证书并开启强制 HTTPS。宝塔负责证书文件和自动续签。
|
||
|
||
证书完成后验证:
|
||
|
||
```bash
|
||
curl -fsS https://api.example.com/healthz
|
||
```
|
||
|
||
客户端必须使用:
|
||
|
||
```text
|
||
https://api.example.com
|
||
wss://api.example.com/ws
|
||
```
|
||
|
||
不能在生产页面中连接 `http://` 或 `ws://`,否则浏览器会拦截混合内容,消息传输也没有 TLS 保护。
|
||
|
||
## 14. 上线验收
|
||
|
||
### 14.1 服务状态
|
||
|
||
```bash
|
||
systemctl is-active xingyu-im
|
||
curl -fsS http://127.0.0.1:18888/healthz
|
||
curl -fsS https://api.example.com/healthz
|
||
```
|
||
|
||
### 14.2 页面
|
||
|
||
- `https://app.example.com`
|
||
- `https://admin.example.com`
|
||
- `https://api.example.com/healthz`
|
||
|
||
### 14.3 核心功能
|
||
|
||
至少完成以下测试:
|
||
|
||
1. 用户注册、密码登录、验证码登录和找回密码。
|
||
2. H5 图片上传、头像修改和动态发布。
|
||
3. WebSocket 连接、消息发送、接收、历史消息和未读数。
|
||
4. 管理端登录与管理员密码修改。
|
||
5. 管理端用户、会员、订单、认证、违规、动态和消息记录查询。
|
||
6. 短信厂商配置保存、切换和发送测试。
|
||
7. 文件存储厂商配置保存、切换和上传测试。
|
||
8. 第三方登录授权、回调和账号绑定。
|
||
9. 支付下单、异步通知、订单状态和退款流程。
|
||
|
||
生产环境不能继续使用 debug 短信或 sandbox 支付。第三方厂商的回调地址必须填写正式 HTTPS 域名。
|
||
|
||
## 15. 日常更新流程
|
||
|
||
每次发布前先备份数据库、上传目录和 `/etc/xingyu-im.env`。
|
||
|
||
推荐顺序:
|
||
|
||
```bash
|
||
export MYSQL_PWD='替换为数据库密码'
|
||
/www/server/xingyu-im/migrate.sh
|
||
unset MYSQL_PWD
|
||
|
||
cd /www/wwwroot/xingyu-source/backend
|
||
go test ./...
|
||
CGO_ENABLED=0 go build -trimpath -ldflags='-s -w' -o /tmp/xingyu-api ./cmd/server
|
||
install -o root -g root -m 0755 /tmp/xingyu-api /www/server/xingyu-im/xingyu-api
|
||
systemctl restart xingyu-im
|
||
systemctl status xingyu-im --no-pager
|
||
```
|
||
|
||
然后按第 7、8 节重新构建并发布两个前端。
|
||
|
||
如后端启动失败,立即查看:
|
||
|
||
```bash
|
||
journalctl -u xingyu-im -n 200 --no-pager
|
||
```
|
||
|
||
不要在未确认数据库迁移兼容性的情况下直接覆盖生产版本。
|
||
|
||
## 16. 备份要求
|
||
|
||
至少备份:
|
||
|
||
```text
|
||
MySQL 数据库 im
|
||
/www/wwwroot/xingyu-data/uploads
|
||
/etc/xingyu-im.env
|
||
/www/server/xingyu-im/xingyu-api
|
||
宝塔三个站点的 Nginx 配置和 SSL 证书
|
||
```
|
||
|
||
建议:
|
||
|
||
- MySQL 每天备份,保留 7~30 天。
|
||
- 上传目录每天增量备份。
|
||
- 备份复制到另一台服务器或对象存储,不能只留在本机。
|
||
- 定期执行恢复演练,而不是只检查“备份任务成功”。
|
||
- `/etc/xingyu-im.env` 包含敏感密钥,备份文件必须加密并限制访问。
|
||
|
||
## 17. 常见故障
|
||
|
||
### 后端启动失败
|
||
|
||
```bash
|
||
systemctl status xingyu-im --no-pager
|
||
journalctl -u xingyu-im -n 200 --no-pager
|
||
```
|
||
|
||
常见原因:数据库未迁移、密钥不足 32 字节、管理员密码强度不足、使用 root DSN、CORS 使用 HTTP 或 `*`。
|
||
|
||
### 管理端接口返回 404
|
||
|
||
检查管理端站点是否存在 `/admin/v1/` 反向代理,以及 `proxy_pass` 是否为:
|
||
|
||
```nginx
|
||
proxy_pass http://127.0.0.1:18888;
|
||
```
|
||
|
||
### H5 仍然连接本机地址
|
||
|
||
说明 H5 构建时没有设置生产变量。按第 7 节重新构建,不能只修改 Nginx。
|
||
|
||
### WebSocket 连接失败
|
||
|
||
检查:
|
||
|
||
- API 域名证书是否有效。
|
||
- H5 是否使用 `wss://api.example.com`。
|
||
- `/ws` 是否设置 Upgrade/Connection 请求头。
|
||
- `/etc/xingyu-im.env` 是否允许 H5 域名来源。
|
||
- 服务器时间是否准确。
|
||
|
||
### 上传失败
|
||
|
||
检查:
|
||
|
||
```bash
|
||
ls -ld /www/wwwroot/xingyu-data/uploads
|
||
sudo -u www test -w /www/wwwroot/xingyu-data/uploads
|
||
```
|
||
|
||
同时确认 API 站点配置了:
|
||
|
||
```nginx
|
||
client_max_body_size 16m;
|
||
```
|
||
|
||
### Node 构建内存不足
|
||
|
||
管理端构建建议至少提供 4 GB 可用内存。可以设置:
|
||
|
||
```bash
|
||
NODE_OPTIONS=--max-old-space-size=4096 pnpm --filter @vben/web-ele build
|
||
```
|
||
|
||
如果仍然被系统杀死,应增加内存或临时交换空间,不要不断重试导致服务器失去响应。
|
||
|
||
## 18. 官方资料
|
||
|
||
- [宝塔安装基础环境](https://docs.bt.cn/getting-started/install-basic-environment)
|
||
- [宝塔安装 Web 服务器](https://docs.bt.cn/user-guide/site/install-webserver)
|
||
- [宝塔网站 SSL 配置](https://docs.bt.cn/user-guide/site/php/site-config/ssl)
|
||
- [Go 官方下载](https://go.dev/dl/)
|
||
- [Node.js 22 官方下载](https://nodejs.org/en/download/archive/v22)
|
||
- [pnpm 官方安装说明](https://pnpm.io/installation)
|