OpenDWeb · 应用级组网
多设备应用需要的是逻辑网络 —— 类似游戏房间,不是系统级 VPN。
设备在网络间漂移、地址常变;应用真正缺的是一个「房间」——一个属于自己的逻辑网络:凭邀请加入、身份稳定、能直连。OpenDWeb 在应用层组成这样的逻辑网络:Ed25519 EndpointId 承载身份,签名事实名册承载成员,iroh/QUIC 直连优先、自托管 relay 回退——无需把整台机器拖进系统级 VPN。
$npx opendweb server
* opendweb server v0.4.2
> Local: http://localhost:8787
> Network: http://192.168.1.100:8787
gateway 8787 · rendezvous 8787 · relay 3340
三层答案,及其交付面
第 1 层 · 身份
Ed25519 EndpointId
设备移动、地址常变,成员身份不该跟着变。稳定身份与网络地址解耦——z-base-32 展示串,跨地址变化仍是同一节点。
identity
第 2 层 · 名册
签名事实,union-merge 收敛
成员资格可验证,无需中心数据库:Genesis/Grant/Join/Revoke 签名事实内容寻址(BLAKE3),经 union-merge 收敛。
roster
第 2 层 · 成员
受控邀请加入
是房间,就得凭邀请进。issuer-online 单次兑换:challenge-response PoP 加 invite_id CAS 消费——每个令牌恰好兑换一次。
invites
第 3 层 · 会话
iroh 1.1:QUIC 直连 + relay 回退
网络允许时成员就该直连。QUIC 直连带 NAT 穿透,回退到可自托管 relay;两侧门控(先门控后数据),帧级资源上限。
session
载荷
不透明 envelope,双向收发
fabric 不规定你的数据模型。不透明 envelope 双向收发;Automerge 适配器为后续独立 change。
sync
交付 · 自托管
一行命令 server
控制平面自己托管:npx opendweb server 或 docker ghcr.io/jixoai/opendweb —— gateway 8787 + relay 3340。
server
交付 · 插件
Marketplace,厂商中立内核
厂商集成是可选而非内置。任意非 builtin 首 token 自适应派发;缺失插件首用自取。Cloudflare Tunnel 以插件交付。
plugins
交付 · SDK
Node SDK(napi-rs)
把 fabric 内嵌进应用,而不是再起一个 CLI:@jixo/opendweb-client-sdk(darwin-arm64 / win32-x64)。
sdk
快速开始
启动 server,邀请一个 peer,开始聊天
gateway(8787)承载 /healthz、/services.json 与 rendezvous;relay(3340)独立监听。邀请必须在签发者在线期间兑换——兑换期间签发者进程保持运行。
# 1. 启动自托管 server(gateway + relay)—— 顶层 CLI
npx opendweb server
# 也可用 docker: docker run -p 8787:8787 -p 3340:3340 ghcr.io/jixoai/opendweb
# 横幅会列出本机全部 Network 地址——任一地址即客户端唯一配置入口,
# gateway 经 /services.json 自动发现 relay。
# 2. 每台客户端机器:一次性配置(持久化于 ~/.opendweb/config.json)
npx @jixo/opendweb-example config set relay http://192.168.2.13:8787
# 3. 终端 A:初始化并常驻聊天
npx @jixo/opendweb-example init --data ~/.dweb-a
npx @jixo/opendweb-example invite --data ~/.dweb-a --ttl 30m # 复制 token
npx @jixo/opendweb-example chat --data ~/.dweb-a
# 4. 终端 B(另一目录/设备):兑换邀请并聊天
npx @jixo/opendweb-example join --data ~/.dweb-b <token>
npx @jixo/opendweb-example chat --data ~/.dweb-b* opendweb server v0.4.2
> Local: http://localhost:8787
> Network: http://192.168.1.100:8787
NAME PORT STATE
gateway 8787 entry point
rendezvous 8787 merged into gateway
relay 3340 enabled不用 npx 自托管:docker ghcr.io/jixoai/opendweb。反代或隧道后面,设置 DWEB_PUBLIC_GATEWAY_URL / DWEB_PUBLIC_RELAY_URL —— 厂商中立的方案见 README。
软件包
一个 CLI、一个 server 二进制、一个 SDK —— 全部发布
当前发布线:opendweb 0.4.2 · client-sdk / server-binary / example 0.3.2 · ext-cf 1.0.3 · config 0.1.0。server CLI 即 marketplace 宿主;插件与 Node SDK 扩展同一 fabric。
| npm 包 | 角色 |
|---|---|
opendweb | 服务器 CLI —— `npx opendweb server` 启动自托管 gateway + relay;插件 marketplace 宿主 |
@jixo/opendweb-server-binary | CLI 使用的服务端二进制包装;亦暴露可编程的 `startServer()` |
@jixo/opendweb-example | 双进程参考客户端 CLI(`init` / `invite` / `join` / `chat`) |
@jixo/opendweb-client-sdk | 把 fabric 嵌入你自己应用的 Node SDK(napi-rs;darwin-arm64 / win32-x64) |
@jixo/opendweb-config | 本地插件文件的 `definePlugin` helper(runtime 无关:deno / bun / node) |
@jixo/opendweb-ext-cf | Cloudflare Tunnel 插件:API 推 ingress、DNS 路由、端到端验证、可选 cloudflared 共生 spawn |
生态
厂商集成皆为插件;你的应用内嵌 SDK
CLI 内核在结构上保持厂商中立——任意非 builtin 首 token 都派发到 marketplace 插件。Cloudflare Tunnel 插件覆盖无公网 IP 部署;Node SDK 直接内嵌 fabric。
插件 —— Cloudflare Tunnel
opendweb plugin add cf # 安装进当前项目(探测包管理器),锁定 name@version
opendweb cf setup --hostname opendweb.example.com
# API 推 ingress、路由 DNS、
# 写 opendweb.config.toml、端到端自检
opendweb cf plan --hostname opendweb.example.com # 零副作用预览Node SDK —— 应用内嵌 fabric
const { Fabric } = require("@jixo/opendweb-client-sdk");
const relay = { mode: "custom", urls: ["http://192.168.2.13:3340"] };
// 机器 A:创建 fabric(本节点成为 root)并签发邀请
const a = await Fabric.createRoot({ dataDir: "/path/a", relay });
const token = await a.invite(60 * 60_000, null); // dweb1. 前缀令牌
// 机器 B:兑换令牌(签发者须在线)并收发消息
const b = await Fabric.joinWithToken({ dataDir: "/path/b", relay }, token);
await b.connect(a.endpointId);
await a.send(b.endpointId, Buffer.from("ping"));
await a.revoke(b.endpointId); // 撤销(root-only)事件流:peer-connected / peer-disconnected、roster-updated、message、path-changed(direct / relay)、relay-online / relay-offline。完整契约见 GitHub。