开发者文档
从批量部署客户端到把设备状态接进你现有的运维系统,都在这里。接口与自托管配置都会随版本更新。
快速上手
第一次连接只需要三步,不需要记 IP 和端口,也不需要配置路由器。
- 在被控电脑上安装客户端并登录,设备会自动出现在列表里;
- 在主控端(电脑、手机或浏览器)打开客户端,点一下目标设备发起连接;
- 被控端确认后即可开始操作,可勾选「记住此设备」避免每次都确认。
# 在服务器上安装并注册为被控端
curl -fsSL https://get.ggremote.com/agent | sh
ggremote-agent register \
--token gr_agent_**************** \
--name "prod-db-01" \
--tags "env=prod,role=db" \
--unattended # 允许无人值守访问(会提示设置独立密码)
# 确认状态
ggremote-agent status
# → {"device_id":"dev_8f31c7","status":"online","peers":0}
关于无人值守:启用后即使无人坐在被控机前也能连入。 这是运维场景的必需能力,但请在后台同时配置好设备分组授权,避免权限过宽。
CLI 批量部署
无界面版(Agent)适合批量下发。下面是一个 Ansible 片段,用于给一批服务器注册为被控端。
- hosts: db_servers
become: true
vars:
ggremote_token: "{{ vault_ggremote_token }}"
tasks:
- name: 安装 ggremote agent
ansible.builtin.shell: curl -fsSL https://get.ggremote.com/agent | sh
args:
creates: /usr/local/bin/ggremote-agent
- name: 注册为被控端
ansible.builtin.command:
cmd: >
ggremote-agent register
--token {{ ggremote_token }}
--name {{ inventory_hostname }}
--tags "env=prod,role=db"
--unattended --password-stdin
args:
stdin: "{{ vault_unattended_password }}"
register: reg
changed_when: "'already registered' not in reg.stdout"
自托管部署
自托管部署会替换掉我们的中继与信令服务,客户端仍然照常使用,只是连接的服务器换成了你自己的地址。 自托管版本仅企业版提供,需要授权文件。
# 1. 拉取部署文件
curl -fsSL https://get.ggremote.com/selfhost | sh
# 2. 配置域名、证书与授权
cat > .env <<'EOF'
GGREMOTE_DOMAIN=remote.your-company.com
GGREMOTE_LETSENCRYPT_EMAIL=ops@your-company.com
GGREMOTE_LICENSE=eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9...
GGREMOTE_TURN_SECRET=$(openssl rand -hex 32)
EOF
# 3. 启动
docker compose up -d
# 4. 验证
curl https://remote.your-company.com/healthz
# → {"status":"ok","version":"3.4.1","peers":0,"relay_region":"internal"}
客户端切换到自托管地址
在客户端「设置 → 服务器」中填入自托管地址即可。支持同时保留公共节点作为备用通道,主节点不可达时自动回退。
# Windows: %ProgramData%\ggremote\config.json
# macOS: /Library/Application Support/ggremote/config.json
# Linux: /etc/ggremote/config.json
{
"server": "remote.your-company.com",
"port": 443,
"fallback_public": true,
"telemetry": false
}
| 规模 | 并发会话 | 建议配置 | 带宽 |
|---|---|---|---|
| 小规模 | ≤ 50 | 2 核 4 GB | 50 Mbps |
| 中等规模 | ≤ 500 | 4 核 8 GB | 500 Mbps |
| 大规模 | > 500 | 8 核 16 GB + 多节点 | 1 Gbps |
带宽说明:直连成功的会话不占用服务器带宽—— 画面在两端之间直接传输。服务器带宽主要消耗在无法直连时的中继转发上,实际占用通常远低于并发数 × 单会话码率。
身份认证
开放 API 使用 API Key 认证。可在「后台 → 开发者 → API 密钥」中创建,并按最小权限申请 scope。
| 请求头 | 是否必填 | 说明 |
|---|---|---|
| Authorization | 是 | 格式为 Bearer <api_key> |
| X-GGR-Org | 否 | 多组织账号下指定操作的组织;缺省为默认组织 |
| Idempotency-Key | 否 | 写操作幂等键,避免重复下发命令 |
API 参考
接口根地址为 https://api.ggremote.com/v1(自托管时替换为你的域名)。
| 方法 | 路径 | 说明 |
|---|---|---|
| GET | /v1/devices | 查询设备列表,支持按标签、在线状态筛选 |
| GET | /v1/devices/{id} | 查询单台设备详情与实时连接质量 |
| POST | /v1/devices/{id}/session | 创建一次会话令牌,供客户端 SDK 发起连接 |
| POST | /v1/devices/{id}/wake | 发送 Wake-on-LAN 唤醒离线设备 |
| POST | /v1/devices/{id}/revoke | 吊销设备授权,立即断开并禁止重连 |
| GET | /v1/sessions | 查询历史会话记录(含发起人、时长、录像 ID) |
| GET | /v1/audit-logs | 查询审计日志,支持时间范围与操作类型筛选 |
| POST | /v1/groups/{id}/members | 把成员加入设备分组,赋予对应连接权限 |
| DELETE | /v1/webhooks/{id} | 取消一个 Webhook 订阅 |
调用示例
import requests
BASE = "https://api.ggremote.com/v1"
HEADERS = {"Authorization": "Bearer gr_live_****************"}
# 1. 找出所有生产环境的在线设备
devices = requests.get(
f"{BASE}/devices",
headers=HEADERS,
params={"tags": "env=prod", "status": "online"},
timeout=10,
).json()
for d in devices["data"]:
print(d["id"], d["name"], d["last_seen"], d["quality"]["latency_ms"])
# 2. 为某台设备创建会话令牌(客户端用这个令牌发起连接)
session = requests.post(
f"{BASE}/devices/dev_8f31c7/session",
headers={**HEADERS, "Idempotency-Key": "req-20260911-001"},
json={"mode": "control", "record": True, "ttl_seconds": 300},
timeout=10,
).json()
print(session["data"]["token"]) # 供客户端 SDK 使用
print(session["data"]["recording_id"]) # 本次会话的录像 ID
Webhook
订阅事件后,平台会在事件发生时向你的回调地址推送 JSON。所有推送带 HMAC-SHA256 签名,务必校验。
| 事件名 | 触发时机 | 典型用途 |
|---|---|---|
| device.online | 设备上线或离线恢复 | 更新 CMDB 中的设备状态 |
| device.offline | 设备掉线超过 60 秒 | 触发告警或自动排查工单 |
| session.started | 有人发起了远程连接 | 高风险设备实时通知主管 |
| session.ended | 会话结束 | 写入审计系统,附录像 ID |
| file.transferred | 文件传输完成 | 记录数据外带路径 |
| policy.changed | 权限或策略被修改 | 同步到自建 SIEM |
import hmac, hashlib
def verify(raw_body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)
# Flask 示例:必须用原始 body,不能先 json.loads 再序列化
@app.post("/ggremote/webhook")
def hook():
if not verify(request.get_data(), request.headers["X-GGR-Signature"], SECRET):
return "", 401
event = request.json
if event["type"] == "session.started":
notify_security_team(event["data"]) # 含发起人、目标设备、来源 IP
return "", 204
重试策略:推送失败按 1s / 10s / 1min / 10min / 1h 间隔重试 5 次。 请保证回调接口幂等——同一条事件可能被投递多次。超过 5 次仍失败会触发告警并记录在后台。
错误码
所有错误遵循 HTTP 状态码 + 业务错误码 双层语义。请按业务错误码分支处理。
| 错误码 | HTTP | 含义 | 处理建议 |
|---|---|---|---|
| InvalidApiKey | 401 | 密钥无效或已被撤销 | 检查密钥是否正确、是否已被轮换 |
| DeviceRevoked | 403 | 设备授权已被吊销 | 需在被控端重新人工确认后才能连入 |
| DeviceOffline | 409 | 目标设备不在线 | 可先调用 /wake 唤醒,或等待其上线 |
| ConcurrentLimit | 429 | 并发会话数已达套餐上限 | 结束空闲会话,或升级套餐 |
| ApprovalRequired | 428 | 该设备需要审批才能连接 | 提示发起人走审批流程 |
| RateLimited | 429 | 请求频率超限 | 指数退避重试;或申请提高限额 |
| InternalError | 500 | 服务端异常 | 携带 request_id 提交工单 |
{
"request_id": "req_3a91bd0c72",
"error": {
"code": "ApprovalRequired",
"message": "设备 prod-db-01 已启用连接审批,需主管批准",
"retryable": false,
"details": { "approval_id": "apr_71c3f9", "policy": "high-risk-devices" }
}
}
限额与支持
API 调用频率按套餐分层。自托管部署不限频率。
| 套餐 | 读接口 | 写接口 | Webhook 频次 |
|---|---|---|---|
| 个人版 | 30 次 / 分钟 | 10 次 / 分钟 | 5 次 / 秒 |
| 团队版 | 300 次 / 分钟 | 100 次 / 分钟 | 50 次 / 秒 |
| 企业版 / 自托管 | 不限 | 不限 | 不限 |
技术支持:对接过程中遇到问题,把 request_id 和请求示例发到 dev@ggremote.com, 工程团队会在 1 个工作日内回复。企业版客户可使用专属技术对接群,并可索取安全白皮书。