Digital Radio Advanced Application Real-time Link
面向业余无线电和自研数字电台设备的实时通信、设备管理、用户审核和运维管理平台。
DraARL Server 使用 Go 提供 HTTP API、WebSocket 在线收发和 UDP DraARLv1 设备接入服务,前端使用 React + TypeScript + Material UI 提供公共页面、用户控制台和管理员后台。项目已经包含完整的 API 文档、协议文档、使用说明、架构图和数据字典。
| 类型 | 链接 |
|---|---|
| 在线站点 | https://ptt.4l2.cn |
| 在线文档 | https://daofengql.github.io/DraARL-Server/ |
| GitHub 仓库 | Daofengql/DraARL-Server |
| 最新发布 | GitHub Releases |
| 当前版本 | v2.0.1-alpha4(以根目录 VERSION 和 Release 页面为准) |
| 问题反馈 | Issues |
| 构建发布 | Release workflow |
| 文档发布 | Docs Deploy workflow |
| 文档 | 说明 |
|---|---|
| 文档站首页 | 推荐阅读顺序、文档目录、本地预览与自动发布说明 |
| 架构设计 | 系统模块、数据流、部署形态和核心链路 |
| Type 0 节点互联协议 | 中心/边缘拓扑、控制面、数据面与安全边界 |
| UDP 单机转发压力测试 | 大规模设备 fan-out 实测、瓶颈分析和容量建议 |
| 数据字典 | 数据库表、字段、索引和关系说明 |
| 使用与说明文档 | 部署、账号、设备、群组、在线收发、后台、运维等功能说明 |
| 设备接入指南 | 设备绑定、认证、上报、配置同步和 API 快速对接 |
| 固件与 OTA | 固件发布、版本规则、OTA 查询与下载流程 |
| APRS 与位置服务 | APRS 配置、位置上报和地图展示说明 |
| DraARLv1 协议 | UDP 设备协议、报文结构、状态码和认证流程 |
| API 文档 | HTTP API、WebSocket、错误码与完整路由索引 |
- 实时语音与文本通信:支持 UDP DraARLv1 设备、UDP/WebSocket 幽灵 Session、单发多收、来源频道、PTT 控制、Opus 语音、半双工群组通信和频道消息历史。
- 设备接入与管理:支持设备密码、JWT、动态码绑定、设备 SSID、设备型号上报、远程参数配置、设备禁发/禁收、AT 控制和 SA818 频率配置。
- 群组与互联:支持公开/私有群组、成员即时撤销、设备切组、虚拟互联组,以及 Type 0 中心/边缘节点的跨入口路由。
- 账号与审核:支持账号密码、邮箱验证码、Keycloak SSO、JWT/refresh token、注册审核、操作证上传与审核。
- 管理后台:提供用户、设备、群组、中继台、服务器、资源中心、固件发布、站点配置、SMTP、APRS、缓存指标和操作日志管理。
- 通联与记录:支持平台发信记录、个人通联日志、统计趋势、音频存储和管理员侧全局查询。
- 资源与发布:支持本地磁盘、MinIO、R2、COS、OSS 等 S3 兼容存储,提供客户端资源 manifest、设备固件 OTA、存储迁移/审计、前端资源嵌入和多平台 Release。
| 层级 | 技术 |
|---|---|
| 后端 | Go 1.25、Gin、GORM、Gorilla WebSocket |
| 数据 | MySQL/MariaDB、Redis(release 构建必需;development/test 可降级)、local 或 S3 兼容对象存储(可选) |
| 前端 | React 19、TypeScript 5.9、Vite 7、Material UI 7、React Router 7 |
| 通信 | UDP DraARLv1、WebSocket、Opus、APRS |
| 文档 | MkDocs、MkDocs Material |
| 自动化 | GitHub Actions、GitHub Pages |
DraARL-Server/
├── cmd/draarl/ # 服务入口,启动 UDP、HTTP、APRS、缓存和日志等模块
├── internal/
│ ├── aprs/ # APRS 连接、配置和日志
│ ├── accesspoint/ # 中心/边缘公开接入点发现与短期凭证
│ ├── auth/ # refresh token 存储,release 要求 Redis,development/test 可内存降级
│ ├── captcha/ # 图形验证码
│ ├── config/ # YAML 配置、默认值、Origin 校验
│ ├── db/ # 兼容旧逻辑的原生 SQL 数据访问
│ ├── gormdb/ # GORM 模型、仓储和自动迁移
│ ├── ghostsession/ # 幽灵安装实例、在线 Session 与多收路由
│ ├── handler/ # HTTP API 处理器
│ ├── interconnect/ # Type 0 中心/边缘控制面、数据面与恢复
│ ├── middleware/ # 登录、审核、管理员、群组权限和限流中间件
│ ├── protocol/ # DraARLv1 协议编解码和设备字段校验
│ ├── routesync/ # 数据库变更到运行态/边缘投影同步
│ ├── server/ # Gin 路由、WebSocket、前端静态资源服务
│ └── udphub/ # UDP 设备运行态、语音转发、群组互联和通信记录
├── pkg/ # JWT、缓存、存储、WebSocket、加密、GeoIP 等公共包
├── www/ # React 前端项目
├── docs/ # MkDocs 文档站、API 文档、协议文档和图表资源
├── test/ # Python 设备/协议测试工具和 Go 压测命令
├── .github/workflows/ # Release 与文档发布工作流
├── config.yaml.example # 配置模板
├── Makefile # 常用构建、测试和运行命令
└── README.md
- Go 1.25+
- Node.js 20+
- MySQL 5.7+ 或 MariaDB 10.3+
- Redis 6.0+(release 构建必需;development/test 构建不可用时可降级到内存存储)
- local 或 S3 兼容对象存储(可选;用于资源、头像、通信录音和固件)
- Keycloak(可选,用于 SSO)
- Python 3.11+(仅本地预览/构建 MkDocs 文档时需要)
Compose 会构建带嵌入前端的 DraARL 镜像,并自动拉起 MySQL、Redis 和
MinIO。首次启动会在命名卷内生成 config.yaml、JWT 密钥和设备 AES 密钥,
随后初始化数据库与 MinIO bucket:
cp .env.example .env
# 修改 .env 中的数据库、Redis、MinIO 密码和对外地址
docker compose up -d --build
docker compose ps
curl http://127.0.0.1:9000/healthz首次管理员账号和密码可通过 docker compose logs draarl 查看。普通
docker compose down 会保留四个命名卷;不要在没有备份时使用
docker compose down -v。完整说明见部署与配置。
以下步骤用于不采用 Compose 的手动部署。
git clone https://github.com/Daofengql/DraARL-Server.git
cd DraARL-ServerCREATE DATABASE draarl CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;cp config.yaml.example config.yaml至少需要检查以下配置:
Database:MySQL/MariaDB 连接信息。Redis:release 构建的 refresh token、登录失败和注册/验证码保护存储,生产环境必需。Web.Port:后端 HTTP API 和前端静态资源端口。Web.FrontendURL与Web.AllowedOrigins:登录回调、CORS 和 WebSocket Origin 白名单。JWT.Secret:至少 32 字符;不符合要求时程序会自动生成并写回配置。DeviceAuth.AESKey:16、24 或 32 字节;留空时程序会自动生成并写回配置。Storage:选择local、minio、s3、r2、cos或oss;可通过命名 profile 切换和迁移,并可启用 EdgeOne TypeA CDN 下载签名。GhostSessions:设置每账号在线幽灵 Session 数与每 Session 接收频道数上限。MessageAPI:设置频道消息分页、账号/IP 限流和数据库查询并发上限。Interconnect/Edge:仅在启用 Type 0 中心/边缘部署时配置。
go mod download
cd www
npm ci
npm run build
cd ..首次部署到完全没有表的空数据库时,直接启动即可自动初始化表结构:
go run ./cmd/draarl -c config.yaml如果数据库中已经存在任意一张表,程序不会在普通启动时修改结构。表结构变更后需显式执行自动迁移:
go run ./cmd/draarl -c config.yaml -auto-migrate群组自身呼号和设备准入白名单已停用。正常启动会兼容并忽略旧的
public_groups.call_sign、public_groups.allow_callsign_ssid 列;显式执行
-auto-migrate 时会安全删除遗留列。若准入白名单仍有非空配置,迁移会中止并要求先人工确认清理。
后续正常启动:
go run ./cmd/draarl -c config.yaml首次启动会自动创建管理员用户,并在控制台输出初始用户名和密码。登录后请立即修改密码。
后端:
go run ./cmd/draarl -c config.yaml前端:
cd www
npm run devVite 开发服务器默认监听 9001,并把 /api 代理到 http://localhost:9002。如果本地 Web.Port 不是 9002,请同步调整 www/vite.config.ts 中的代理目标,或把本地后端端口设为 9002。
常用开发命令:
go test ./...
go fmt ./...
go vet ./...
cd www
npm run lint
npm run build默认构建不嵌入前端资源,适合 API 服务或本地开发:
go build -o draarl ./cmd/draarl
./draarl -c config.yamlRelease 工作流使用 embed 构建标签,将 www/dist 放入 internal/server/web/dist 后再编译:
cd www
npm ci
npm run build
cd ..
mkdir -p internal/server/web/dist
cp -r www/dist/* internal/server/web/dist/
go build -tags=embed -o draarl ./cmd/draarlWindows PowerShell 可将复制步骤替换为:
New-Item -ItemType Directory -Force internal/server/web/dist
Copy-Item -Recurse -Force www/dist/* internal/server/web/dist/
go build -tags=embed -o draarl.exe ./cmd/draarlmake help
make build
make test
make run注意:当前 Makefile 的 build/run 目标是普通 Go 构建,不会自动执行前端构建,也不会加 -tags=embed。
当前仓库的发布由 GitHub Actions 驱动:
- 推送形如
v*.*.*的 tag。 - Release workflow 构建 Linux、Windows、macOS 的 amd64/arm64 产物并创建 GitHub Release。
- Release 成功后,Docs Deploy workflow 自动构建 MkDocs 并发布到 GitHub Pages。
示例(发布新版本时将变量替换为目标版本;当前仓库版本来自 VERSION):
VERSION=$(tr -d '\r\n' < VERSION)
git tag -a "$VERSION" -m "release: $VERSION"
git push origin "$VERSION"| 类型 | 默认/常用端口 | 说明 |
|---|---|---|
| UDP 设备接入 | 60050 |
DraARLv1 设备接入和语音转发 |
| Type 0 节点控制 | 60100/tcp |
可选的中心/边缘 TLS 控制面;数据面仍复用 UDP 60050 |
| HTTP API / Web | 9000 或本地开发常用 9002 |
Gin API、WebSocket、前端静态资源 |
| Vite 开发服务器 | 9001 |
前端开发预览,代理 /api 到后端 |
| WebSocket | /ws |
浏览器在线收发连接入口 |
| API 前缀 | /api |
HTTP API 统一前缀 |
常用命令:
# 查看版本
./draarl -v
# 打印关键配置
./draarl -c config.yaml -p json
# 重置管理员密码
./draarl -c config.yaml -reset-admin-pass "new-password"
# 执行数据库自动迁移
./draarl -c config.yaml -auto-migrate生产环境建议:
- 固定并备份
config.yaml中的JWT.Secret和DeviceAuth.AESKey。 - 配置真实的
Web.FrontendURL和Web.AllowedOrigins,避免 Release 模式下 Origin 校验失败。 - 使用 Redis 保存 refresh token,避免进程重启导致登录态丢失。
- 根据部署规模选择 local 或私有 S3 兼容存储;生产环境使用预签名读写,不要开放 bucket 匿名访问。
- 从更早版本升级到
v2.0.0-alpha3前先执行备份,并在维护窗口显式运行-auto-migrate;频道消息迁移会回填消息类型、发送者快照和投递群组快照。 - 对外暴露 UDP 服务时,确认防火墙和反向代理的真实 IP 传递策略;中心直连接入使用
System.ProxyProtocol: v2,边缘接入使用Edge.ProxyProtocol: v2。启用后必须限制 UDP 入口只允许受信代理访问。 - 首次上线后立即修改默认管理员密码,并检查注册审核、操作证审核和设备绑定策略。
更多排障内容请阅读 运维与排障。
README 不再维护大段接口清单,避免与实际路由漂移。请以文档站为准:
pip install -r docs/requirements.txt
mkdocs serve访问 http://127.0.0.1:8000 预览文档站。
静态构建:
mkdocs build --strictmaster:主分支和发布来源。dev:开发分支。v*.*.*tag:触发 Release 和后续文档发布。
提交信息建议使用:
feat: 新功能
fix: 修复问题
docs: 文档更新
refactor: 代码重构
test: 测试相关
chore: 构建或工具调整
本项目使用 PolyForm Noncommercial License 1.0.0 授权,并随附 NOTICE 中的 Required Notice: 声明。
- 允许非商业目的下的学习、研究、运行、修改、二次开发和再分发。
- 未经作者明确书面授权,不允许商业使用、收费销售、收费 SaaS、商业托管或商业集成。
- 二次开发、fork、复制、再分发或派生作品必须保留原始仓库地址:
https://github.com/Daofengql/DraARL-Server。 - 中文说明请阅读 LICENSE.zh-CN.md,正式法律文本以英文 LICENSE 为准。