admin_back_go 是 E:\admin_go 后台系统的 Go 重写后端。它不是玩具 demo,也不是微服务实验;当前定位是 Gin modular monolith:一个 API 进程、一个 Worker 进程、共享 MySQL/Redis 状态,逐步承接原 admin 系统的认证、RBAC、系统管理、AI 管理、支付、通知、队列和实时 WebSocket 能力。
先说清楚:本仓库不负责前端静态文件托管,不负责宝塔证书申请。Go 后端只负责 HTTP API、Worker、队列、定时任务、WebSocket upgrade 和业务运行时。生产域名、SSL、反向代理放在宿主机 Nginx/OpenResty/宝塔里。
本项目遵守 E:\admin_go 的 open-source-first 和 step-by-step 规则:先固定可运行、可验证的后端骨架,再按窄切片迁移旧 PHP admin 业务。
当前后端事实:
HTTP API Gin
进程入口 cmd/admin-api, cmd/admin-worker
数据库 MySQL
缓存/会话/队列 Redis + Asynq
定时任务 gocron/v2 + DB cron_task 注册
实时能力 gorilla/websocket + local/noop/redis publisher
日志 slog stdout + optional lumberjack file log
响应格式 { "code": 0, "data": {}, "msg": "ok" }
API 前缀 /api/admin/v1
健康检查 /health, /ready
P08R 合同切换状态:当前已发布的 Admin Contract Bundle 仍是历史
browser/desktop variant 合同;批准目标是
docs/contracts/admin-browser-auth-contract.md。在 Task 5 发布匹配的新 bundle
前,目标合同尚未部署,前端不得提前猜字段接入。
| 类型 | 选型 |
|---|---|
| Language | Go 1.26.5 |
| HTTP | Gin |
| ORM | GORM + MySQL driver |
| Redis | redis/go-redis |
| Queue | Asynq |
| Scheduler | go-co-op/gocron/v2 |
| WebSocket | gorilla/websocket |
| Logger | log/slog + lumberjack |
| Excel export | excelize |
| Object storage | 腾讯云 COS STS / COS SDK |
| Captcha | go-captcha slide captcha |
入口:cmd/admin-api/main.go
职责:
1. 启动 Gin HTTP server
2. 注册 REST API
3. 注册 WebSocket upgrade 路由
4. 执行登录、RBAC、系统管理、AI 管理等同步请求
5. 持有 realtime session manager
6. 当 REALTIME_PUBLISHER=redis 时订阅 Redis Pub/Sub 并投递到本机 WebSocket session
默认监听:
HTTP_ADDR=:8080
入口:cmd/admin-worker/main.go
职责:
1. 消费 Asynq 队列任务
2. 执行导出任务、通知任务、登录日志任务、支付定时任务、AI run timeout 等后台任务
3. 从 DB 中读取启用的 cron_task,注册到 scheduler
4. 使用 Redis 锁避免多 worker 重复执行同一定时任务
admin_back_go/
cmd/
admin-api/ # HTTP API 进程入口
admin-worker/ # 队列 + 定时任务进程入口
docs/database-ownership.md # 本地 MySQL 所有权和直接 SQL 规则
deploy/
docker-first/ # 后端 Docker-first Compose 部署模板
docs/ # 后端运行时架构说明;总控状态/契约在 ../docs
internal/
architecture/ # 架构边界 guard tests
bootstrap/ # 装配 config/db/redis/router/services/worker
config/ # 环境变量读取和默认值
infra/ # DB/Redis/queue/storage/realtime/AI/payment 等基础设施
jobs/ # 版本化队列任务注册
middleware/ # RequestID/CORS/Auth/Permission/OperationLog
module/ # 业务模块
readiness/ # /ready 依赖检查
server/ # Gin router 和 middleware 顺序
shared/ # enum/dict/response/apperror/validate/i18n/setting
version/ # 版本信息
runtime/ # 本地运行日志/证书等运行时目录
scripts/ # smoke、contract、证书辅助脚本
Dockerfile
go.mod
固定调用链:
route -> handler -> service -> repository -> model
不要为了“看起来规范”硬造空层。没有数据库就没有 repository;没有表就没有 model。
当前已迁移/落地的主要能力包括:
health / ready
登录 / refresh / logout / forgot-password
slide captcha
后台用户 / 个人资料 / 登录日志 / 会话管理
RBAC 权限定义 / 角色 / 菜单按钮权限
操作日志
系统设置
系统日志读取
上传配置 / 上传 token
导出任务
通知中心 / 通知任务
cron task 管理
支付基础任务和回调入口
客户端版本管理(仅当前 pre-P08R 历史运行时;批准目标将退役)
AI provider / agent / chat / conversation / messages / runs / tools / knowledge
WebSocket realtime
Queue monitor
具体状态以这些文件为准,不要靠 README 猜:
../docs/status/current-status.md
../docs/contracts/admin-api-v1.md
../docs/contracts/admin-realtime-v1.md
docs/architecture.md
底层配置 loader 仍支持先读取仓库根 .env、再读取系统环境变量:
_ = config.LoadDotEnv()
cfg, err := config.Load(config.ProcessAPI)
if err != nil {
log.Fatal(err)
}但这是兼容能力,不是当前项目默认入口。后端本地开发统一 Docker-first,正常不要创建仓库根 .env;本地容器运行配置用:
admin_back_go/deploy/docker-first/admin-go.env
生产 / 宝塔 Docker Compose 默认用:
/www/docker/admin-go-backend/admin-go.env
| 变量 | 说明 |
|---|---|
APP_ENV |
local / production 等运行环境 |
HTTP_ADDR |
HTTP 监听地址,Docker 内建议 :8080 |
MYSQL_DSN |
推荐使用的 MySQL DSN |
REDIS_ADDR |
Redis 地址 |
APP_SECRET |
应用唯一根密钥,所有 API/Worker 节点必须一致;代码内部派生 JWT、refresh token pepper、secretbox 等用途 key |
CORS_ALLOW_ORIGINS |
允许访问 API 的前端 origin |
推荐直接配置完整 DSN:
MYSQL_DSN=admin_user:CHANGE_ME@tcp(127.0.0.1:3306)/admin?charset=utf8mb4&parseTime=True&loc=Local
MYSQL_MAX_OPEN_CONNS=20
MYSQL_MAX_IDLE_CONNS=10
MYSQL_CONN_MAX_LIFETIME=1h兼容配置也存在,但不推荐新部署继续依赖:
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=admin
DB_USERNAME=root
DB_PASSWORD=REDIS_ADDR=127.0.0.1:6379
REDIS_PASSWORD=
REDIS_DB=0
REALTIME_REDIS_DB=1
TOKEN_REDIS_DB=2
QUEUE_REDIS_DB=3注意:缓存 Redis、realtime Redis、token Redis、queue Redis 是同一 Redis 实例的 DB 0/1/2/3 逻辑隔离。
Token Redis key prefix token:、session cache TTL 30m、single-session pointer TTL 720h 是代码内置默认,不再通过 Docker-first env 暴露;access/refresh token 有效期仍由 auth_platforms 管理。
QUEUE_ENABLED=true
QUEUE_REDIS_DB=3
QUEUE_CONCURRENCY=10
QUEUE_DEFAULT_QUEUE=default
QUEUE_CRITICAL_WEIGHT=6
QUEUE_DEFAULT_WEIGHT=3
QUEUE_LOW_WEIGHT=1
QUEUE_SHUTDOWN_TIMEOUT=10s
QUEUE_DEFAULT_MAX_RETRY=3
QUEUE_DEFAULT_TIMEOUT=30s如果 QUEUE_ENABLED=true,必须启动 admin-worker,否则导出、通知、部分异步任务只会入队,不会被消费。
REALTIME_ENABLED=true
REALTIME_PUBLISHER=redis
REALTIME_REDIS_DB=1REALTIME_REDIS_DB 选择 WebSocket Pub/Sub 与 AI cancel 使用的逻辑库。REALTIME_ENABLED 只控制 WebSocket/实时事件能力,不控制 DB 1 客户端生命周期。
代码内置:Redis Pub/Sub channel admin_go:realtime:publish、heartbeat interval 25s、send buffer 16。
取值:
REALTIME_PUBLISHER=local # 单 API 进程,本机直接投递
REALTIME_PUBLISHER=noop # 显式丢弃业务推送,不等于关闭 WebSocket
REALTIME_PUBLISHER=redis # 多 API 进程推荐,Redis Pub/Sub fan-out
生产如果未来有多个 admin-api,推荐 redis。
SCHEDULER_ENABLED=trueScheduler timezone、Redis lock prefix 和 lock TTL 是 Go 默认值。业务定时任务的启用和 cron 表达式通过 cron_task 表/定时任务页面管理;SCHEDULER_ENABLED=false 只用于部署、导入数据或排障时临时关闭 scheduler 注册。
多 worker 节点时,Redis 锁会降低重复执行风险。但不要无脑在多套环境里同时指向同一个数据库和同一个 Redis。
规则很简单:手机号验证码固定 123456,不受 .env 控制;邮箱验证码始终走腾讯云 SES,需要先在邮件管理里启用发信配置和审核通过的模板。验证码有效期归各自渠道配置所有:邮箱读取 mail_configs.verify_code_ttl_minutes,短信读取 sms_configs.verify_code_ttl_minutes;Redis namespace auth:verify_code: 由代码内置,不通过 env 配置。生产如果不开放手机号登录,直接在 auth_platforms.login_types 里关闭 phone。
Docker env 保持短配置,不再承载上传运行时策略。COS bucket、SecretId、SecretKey、Region、APPID、write endpoint、access domain 都来自上传配置表;upload token TTL 来自 system_settings.upload.token.ttl_minutes,默认 15 分钟;Tencent STS endpoint/region 是代码内置默认值,不是 Docker env key。注意:上传配置里的 Region 仍然是 COS bucket region。
本地开发:
CORS_ALLOW_ORIGINS=http://localhost:5173,http://127.0.0.1:5173,http://192.168.5.20:5173http://192.168.5.20:5173 是当前局域网真机调试 origin;如需手机访问开发机上的 Go 后端,把 deploy/docker-first/docker-compose.yml 的 ports 行改成 0.0.0.0:8080:8080,并让 CORS_ALLOW_ORIGINS 覆盖该 origin。
生产示例(按你的前端域名替换):
CORS_ALLOW_ORIGINS=https://<frontend-domain>CORS_ALLOW_ORIGINS 是 Docker-first 唯一 CORS env。允许的请求头、暴露响应头、AllowCredentials=true 和预检缓存 12h 都是代码内置默认值;不要把 CORS policy 放进 system_settings。
Windows 日常开发和正式部署采用两条明确分开的路径:
| 场景 | MySQL / Redis | 前端 / API / Worker | 入口 |
|---|---|---|---|
| 本地热更新 | Docker | Windows 宿主机 | admin-dev |
| 正式部署、阶段验收 | Docker | Docker | admin-up |
生产和正式验收始终使用完整 Docker。admin-dev 只是 Windows 开发反馈环,不改变发布架构,也不会在启动时自动执行数据库迁移。
PowerShell 7.x
Node E:\FlyEnv-Data\app\nodejs\v24.18.0(v24.18.0)
npm 11.16.0
Go go1.26.5 windows/amd64
Air v1.66.0(首次使用时安装到 .tmp/tools,绝不全局安装)
Docker MySQL / Redis 以及正式五容器平台
本地运行配置继续只使用已忽略的 deploy/docker-first/admin-go.env。admin-dev 在子进程内存中把 Docker 地址转换为宿主地址,不复制、不打印 MYSQL_DSN、APP_SECRET 或密码:
mysql:3306 -> 127.0.0.1:33306
redis:6379 -> 127.0.0.1:36379
:8080 -> 127.0.0.1:8080
APP_SECRET 仍遵守现有轮换语义:
# 至少 64 个 ASCII 字符;修改会让旧登录态和已加密业务密钥失效
APP_SECRET=本地长随机字符串pwsh -NoProfile -File E:\admin\admin_back_go\scripts\install-admin-shortcuts.ps1
. $PROFILE安装器同时维护 PowerShell 7 和 Windows PowerShell 的用户 Profile,并且只修改自己的标记区块。之后可直接使用:
admin-dev # Docker 保留 MySQL/Redis;宿主启动热更新,就绪后打开浏览器
admin-dev -NoBrowser # 启动热更新,但不自动打开浏览器
admin-up # 构建并启动正式五容器 Docker 平台
admin-status # 查看两个 Compose 项目状态
admin-stop # 停止完整 Docker 平台如果当前终端尚未重新加载 Profile,也可直接运行仓库脚本:
pwsh -NoProfile -File E:\admin\admin_back_go\scripts\admin-dev.ps1
pwsh -NoProfile -File E:\admin\admin_back_go\scripts\docker-platform.ps1 -Action up- 只允许两个现有
master主检出,拒绝 worktree。 - 获取
.tmp/dev/admin-dev.lock.json,阻止admin-up/admin-stop破坏正在运行的开发环境。 - 停止 Docker 中的 frontend/API/worker,只启动并等待 MySQL、Redis healthy。
- 校验固定 Node/npm/Go,按需安装私有 Air;仅在
package-lock.json哈希变化时执行npm ci。 - 在同一终端启动并监管 Vite、API Air、Worker Air,日志分别带
[WEB]、[API]、[WORKER]前缀。 - 等待 Vite、
/health、/ready和稳定 Worker;任一进程失败会清理其他宿主子进程。 - 默认只打开一次
http://localhost:5173;传入-NoBrowser可禁止打开,热重载不会重复打开。 Ctrl+C释放5173/8080和开发锁,但保留 MySQL、Redis 容器及数据卷。
admin-dev 不会杀死未知端口进程;如果 5173 或 8080 已被其他程序占用,它会明确报错并停止。
pwsh -NoProfile -File scripts/tests/admin-dev.tests.ps1
pwsh -NoProfile -File scripts/tests/docker-platform.tests.ps1后端完整验证和 clean-cache 验证继续保留 PowerShell 7 / Windows PowerShell 两套受支持入口:
pwsh -NoProfile -File scripts/verify-backend.ps1
powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts/verify-backend.ps1
pwsh -NoProfile -File scripts/verify-go-clean.ps1
powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts/verify-go-clean.ps1
pwsh -NoProfile -File scripts/verify-go-clean.ps1 -KeepScratch
powershell.exe -NoProfile -ExecutionPolicy Bypass -File scripts/verify-go-clean.ps1 -KeepScratch前端正式质量门禁仍在固定 Node 24 Docker 镜像中执行:
pwsh -NoProfile -File E:\admin\admin_front_ts\scripts\docker-frontend-gate.ps1 -Command 'npm run verify:frontend'完整平台验证必须切回 Docker:
admin-up
admin-status当前个人开发阶段由本机 Docker MySQL 持有唯一业务事实。仓库不包含
database/、seed、migration、baseline 或数据库生命周期命令;Go 运行时只通过
internal/infra/database 连接正在运行的 MySQL。需要变更数据库时,按
docs/database-ownership.md 确认本机 admin 目标后由
work-ai 执行最小 SQL 并读回验证。密码和私有 SQL 导出只能留在仓库外。
Backend deployment and local backend development are Docker-first. deploy/docker-first/docker-compose.yml is the source template and local validation Compose file; production Baota Docker runs from /www/docker/admin-go-backend/docker-compose.yml after copying the template and changing path fields for that working directory. Do not use repository-root .env / .env.example, and do not start admin-api or admin-worker with go run.
MySQL/Redis 可以也推荐用宝塔 Docker 管,但不要写进后端 Compose。生产默认拆成 admin-go-state 和 admin-go-backend 两个项目:状态服务独立保护,后端应用可随代码发布重建。
当前推荐演示部署:
宿主机宝塔 / OpenResty / Nginx 负责域名、HTTPS、反向代理
Docker Compose 只跑 admin-api 和 admin-worker
MySQL / Redis 可以用 Docker,但必须作为独立的 admin-go-state 项目管理
deploy/docker-first/ 直接作为后端 Docker-first 开发入口,保留:
docker-compose.yml
admin-go.env
admin-go.env.example
README.md
runtime/
exports/
docker-compose.yml 固定开发者默认值:源码目录 ../..、运行配置 ./admin-go.env、挂载目录 ./runtime / ./exports、API 端口 127.0.0.1:8080。如果本机 8080 被占用,直接编辑 docker-compose.yml 的 ports 行。
cd E:/admin_go/admin_back_go/deploy/docker-first
New-Item -ItemType Directory -Force -Path runtime/logs, exportscd /path/to/admin_back_go
git pull本地容器业务运行配置在 deploy/docker-first/admin-go.env;生产运行配置在 /www/docker/admin-go-backend/admin-go.env。新环境可从 deploy/docker-first/admin-go.env.example 复制后再改真实值。
编辑:
vim /www/docker/admin-go-backend/admin-go.env最少要改:
APP_ENV=production
HTTP_ADDR=:8080
MYSQL_DSN=admin_user:CHANGE_ME@tcp(mysql.private-or-docker-host:3306)/admin?charset=utf8mb4&parseTime=True&loc=Local
REDIS_ADDR=redis.private-or-docker-host:6379
REDIS_PASSWORD=
# 至少 64 个 ASCII 字符;所有 admin-api/admin-worker 节点必须一致
APP_SECRET=CHANGE_ME_TO_64_PLUS_RANDOM_CHARS
QUEUE_ENABLED=true
REALTIME_ENABLED=true
REALTIME_PUBLISHER=redis
REALTIME_REDIS_DB=1
SCHEDULER_ENABLED=true
CORS_ALLOW_ORIGINS=https://<frontend-domain>如果 MySQL/Redis 在 admin-go-state Docker 项目里,把连接地址改成对应 Docker network、宿主本地端口或内网 IP。别把 MySQL/Redis 裸奔到公网;必须用安全组/防火墙只放行后端机器。
生产 Compose 工作目录必须已经有从 deploy/docker-first/docker-compose.yml 复制并改好路径的 docker-compose.yml,尤其是 build.context=/www/project/admin_back_go、env_file=./admin-go.env 和 ./runtime / ./exports 挂载。
cd /www/docker/admin-go-backend
docker compose up -d --build查看状态:
docker compose ps
docker compose logs -f admin-api
docker compose logs -f admin-worker验证宿主机本地端口:
curl -fsS http://127.0.0.1:8080/health
curl -fsS http://127.0.0.1:8080/ready
curl -fsS http://127.0.0.1:8080/api/admin/v1/auth/login-config更新时分清两个目录:
代码目录:负责 git pull
Compose 目录:负责 docker compose up -d --build
如果后端代码放在推荐目录:
cd /www/project/admin_back_go
git pull
cd /www/docker/admin-go-backend
docker compose up -d --build如果你把后端代码放在宝塔站点目录,也就是当前单体演示常用方式:
cd /www/wwwroot/<api-domain>
git pull
cd /www/docker/admin-go-backend
docker compose up -d --build重点是:生产更新时 git pull 在代码目录执行,docker compose up -d --build 在 Compose 工作目录 /www/docker/admin-go-backend 执行;MySQL/Redis 不写进后端 Compose。
cd /www/docker/admin-go-backend
# 重启
docker compose restart
# 停止
docker compose down
# 重新构建并启动
docker compose up -d --buildDocker 后端项目只跑 admin-api / admin-worker。
MySQL / Redis 即使用 Docker,也属于独立的 admin-go-state 项目。
宝塔 Nginx 负责域名、SSL、反向代理、前端 SPA 伪静态。
后端站点建议:
<api-domain> -> http://127.0.0.1:8080
前端站点建议:
<frontend-domain> -> /www/wwwroot/<frontend-domain> 静态 dist
宝塔路径:
宝塔 -> 网站 -> <api-domain> -> 设置 -> 配置文件
核心反代:
location ^~ / {
proxy_pass http://127.0.0.1:8080;
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_set_header X-Request-Id $request_id;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_connect_timeout 30s;
proxy_send_timeout 3600s;
proxy_read_timeout 3600s;
}如果宝塔已经生成了 location ^~ /,不要再新建第二个 location /;直接改已有块。
前端 Vue/Vite 刷新页面需要:
location / {
try_files $uri $uri/ /index.html;
}这个只解决前端路由刷新 404,不解决 WebSocket 认证。
生产域名分工固定为:前端静态站 <frontend-domain>,Go 后端入口 <api-domain>。WebSocket 是 Go 后端能力,默认也走 <api-domain>:
wss://<api-domain>/api/admin/v1/realtime/ws
所以后端站点 <api-domain> 必须有一条精确 WebSocket 反代,放在普通 API 反代前面:
location = /api/admin/v1/realtime/ws {
proxy_pass http://127.0.0.1:8080;
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 3600s;
proxy_send_timeout 3600s;
}检查并重载 Nginx:
/www/server/nginx/sbin/nginx -t
/www/server/nginx/sbin/nginx -s reload前端项目在:
../admin_front_ts
Admin 的批准目标只有 Browser 客户端:access token 仅保存在内存,refresh
credential 仅存在于 __Secure-admin_refresh HttpOnly Cookie;登录、刷新、退出
都要求精确允许的 Origin。正式字段以 Task 5 生成的 Admin Contract Bundle
为唯一来源,不读取桌面 variant,也不接受 JSON refresh token。
生产环境建议:
VITE_GO_API_BASE_URL=https://<api-domain>
VITE_WEB_SOCKET_URL=wss://<api-domain>/api/admin/v1/realtime/ws
VITE_PLATFORM=admin解释:
普通 REST API 走 `<api-domain>` 后端域名。
WebSocket 也走 `<api-domain>` 后端域名;不要写成 `<frontend-domain>` 静态站域名。
前端和后端都只通过 Docker 镜像交付。统一从后端仓库执行
scripts/docker-platform.ps1 up,由 Compose 构建并启动前端、admin-api 和
admin-worker;不上传或解压 dist,也不使用 GitHub Actions、宿主机 Vite 或
宿主机 Go 进程作为部署路径。
curl -fsS http://127.0.0.1:8080/health
curl -fsS http://127.0.0.1:8080/ready
curl -fsS https://<api-domain>/health
curl -fsS https://<api-domain>/ready/health 只表示进程活着。
/ready 会报告:
database
redis
realtime_redis
token_redis
queue_redis
realtime
未配置或未启用的资源返回 disabled,不算失败;已配置或已启用的资源才做 ping 或配置有效性检查。
Docker stdout:
cd /www/docker/admin-go-backend
docker compose logs -f admin-api
docker compose logs -f admin-worker文件日志:
/www/docker/admin-go-backend/runtime/logs/admin-api.log
/www/docker/admin-go-backend/runtime/logs/admin-worker.log
宝塔 Nginx 日志一般在:
/www/wwwlogs/<api-domain>.log
/www/wwwlogs/<api-domain>.error.log
/www/wwwlogs/<frontend-domain>.log
/www/wwwlogs/<frontend-domain>.error.log
在本机或服务器代码目录执行:
cd E:/admin_go/admin_back_go
powershell -ExecutionPolicy Bypass -File ./scripts/basic-admin-smoke.ps1 -Account <account> -Password <password>
powershell -ExecutionPolicy Bypass -File ./scripts/full-admin-smoke.ps1 -Account <account> -Password <password>如果在 Linux 服务器上跑这些 PowerShell 脚本,需要安装 pwsh;否则可以先用 curl 验证 /health、/ready 和登录配置。
演示环境推荐单机,简单、可控、少踩坑。未来要拆多节点时,至少遵守这些规则:
1. 所有 admin-api / admin-worker 节点必须使用同一套 MySQL/Redis。
2. 所有节点的 APP_SECRET 必须一致,否则 access/refresh token、Redis session cache、AI/upload/payment 已加密 secret 都会失效。
3. 变更 APP_SECRET 前先按 `E:/admin_go/docs/deployment/auth-foundation-v2-reset-runbook.md` 撤销会话、清 Redis token cache,并重新录入业务密钥。
4. REALTIME_PUBLISHER 多 API 节点建议使用 redis。
5. 支付证书、运行时 cert 目录必须部署到需要处理支付的后端节点。
6. SCHEDULER_ENABLED 不要在多套独立环境里同时指向同一库;同一集群内依靠 Redis lock,但仍要监控重复执行。
7. MySQL/Redis 放独立机器时优先走内网 IP,公网必须安全组白名单。
8. 8080 只绑定 127.0.0.1,由 Nginx 对外暴露 80/443。
一个合理的三机/四机演进方向:
A: 前端静态站 + Nginx + admin-api/admin-worker
B: admin-api/admin-worker
C: MySQL + Redis
D: 备用后端或后续对象存储/监控,不要为了“分布式”硬拆
先看 data.checks 哪项失败:
database MySQL DSN、账号、库名、网络、防火墙
redis REDIS_ADDR、密码、网络
realtime_redis REALTIME_REDIS_DB 对应 Redis 必须可用,供 Realtime/AI cancel 使用
queue_redis QUEUE_ENABLED=true 时 Redis 必须可用
token_redis TOKEN_REDIS_DB 对应 Redis 必须可用
realtime REALTIME_ENABLED/REALTIME_PUBLISHER 配置错误
这通常不是后端“白名单”问题,而是 WebSocket 这条链路没带到 cookie。
推荐配置:
VITE_WEB_SOCKET_URL=wss://<api-domain>/api/admin/v1/realtime/ws并确认 <api-domain> 后端站保留精确 WebSocket 反代:
location = /api/admin/v1/realtime/ws { ... proxy_pass http://127.0.0.1:8080; ... }这是前端 SPA 伪静态问题,不是 Go 后端问题。前端站点加:
location / {
try_files $uri $uri/ /index.html;
}检查:
docker compose ps
docker compose logs -f admin-workeradmin-worker 没跑,队列任务就不会消费。
这是当前业务规则,不是配置遗漏:手机号短信未接入,手机号验证码固定 123456,不受 env 控制。邮箱验证码才走腾讯云 SES;生产如果不开放手机号登录,去 auth_platforms.login_types 关闭 phone。
这个项目的 Docker 镜像只包含:
/app/admin-api
/app/admin-worker
/app/runtime
/app/exports
Nginx、SSL、伪静态、反代都在宿主机宝塔里。
../AGENTS.md
../docs/architecture/00-open-source-first.md
../docs/architecture/01-step-by-step-roadmap.md
../docs/architecture/04-go-backend-framework.md
../docs/architecture/05-development-quality-rules.md
../docs/status/current-status.md
../docs/contracts/admin-api-v1.md
../docs/contracts/admin-realtime-v1.md
docs/architecture.md
internal/middleware/README.md
deploy/docker-first/docker-compose.yml
deploy/docker-first/admin-go.env.example
不要提交仓库根 .env。
不要让 8080 裸奔公网;如果为了局域网真机调试绑定 `0.0.0.0`,必须只在受控内网/防火墙白名单下使用。
不要在个人开发阶段新增 `database/`、migration、seed、baseline 或数据库 CLI。
不要在 README 里承诺未实现能力。
不要为了“分布式”增加复杂度;能单机稳定演示,就先单机。