尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

把第三方代码装进生产实例:TREK 插件管理要过的 5 道关

把第三方代码装进生产实例:TREK 插件管理要过的 5 道关 把第三方代码装进生产实例TREK 插件管理要过的 5 道关【免费下载链接】TREKA self-hosted travel/trip planner with real-time collaboration, interactive maps, PWA support, SSO, budgets, packing lists, and more.项目地址: https://gitcode.com/GitHub_Trending/nomad22/TREKTREK 的插件系统允许第三方在不改一行 TREK 源码的前提下往自托管实例里装新能力——仪表盘 widget、独立页面、行程页标签、照片/日历/通知渠道集成。自托管管理员的 TREK 插件管理集中在Admin → Plugins面板而把第三方代码引入生产实例实际要过五道关安装关SHA-256 作者签名 manifest 复校验 版本兼容、审查关预安装对话框逐条展示权限与出口主机、启用关显式开关 权限同意拒绝原因带结构化错误码、更新关扩权必须重新同意、换钥必须重信任、审计关哈希链能力审计用户本人可见。本文按运维流程走完这五道关并用平实语言解释每个操作背后为什么这样设计。读完本文你将能在生产实例上安全地跑完一个插件的完整生命周期并清楚每个徽章、每条权限、每个错误码保证什么、不保证什么。开工前谁能进、哪些开关要开核心事实整个面板只接受管理员账户且每个端点还叠加一层插件运行时总开关总开关默认开启但运行时开着不等于任何代码会跑——每个已安装插件都必须逐个手动激活。服务端所有路由挂在api/admin/plugins之下同时套JwtAuthGuard与AdminGuardplugins.controller.ts。普通用户连已安装列表都列不出来。总开关由TREK_PLUGINS_ENABLED控制判定逻辑在 kill-switch.ts取值只要不是false、0、off、no大小写不敏感就算开启且每次调用实时读取——改环境变量重启后立即生效。关闭时install、upload、activate、update、rescan等操作统一返回 503面板会显示关闭横幅已安装插件保留在磁盘上停用状态、无害重新打开即可恢复。environment: - TREK_PLUGINS_ENABLEDfalse与插件管理相关的其余环境变量环境变量作用默认值TREK_PLUGINS_ENABLED插件系统总开关关闭时对应操作一律 503开启TREK_PLUGINS_DEV_LINK开发专用允许从本地构建目录注册插件并热重载仅当值恰为1时生效dev-link.ts关闭TREK_PLUGIN_ALLOW_PRIVATE_EGRESS设为on时允许插件出口访问私网/局域网地址localhost、192.168.x.x等。⚠️ 这会放宽所有已安装插件的私网出口策略只有你信任全部插件时才应开启关闭默认拒绝私网出口TREK_PLUGIN_REGISTRY_URL覆盖 Discover 视图浏览的注册表索引地址可指向自己的 fork/镜像TREK 官方注册表聚合的dist/index.jsonTREK_PLUGIN_MAX_RSS_MB单个插件子进程的硬内存上限RSS不是 V8 堆300 MBplugin-supervisor.ts第一次安装标准路径核心事实注册表安装 SSRF 安全的下载 → SHA-256 校验 → 防 zip-slip/zip-bomb 解压 → manifest 严格复校验 → 原生二进制重扫 → 原子落盘 → 注册为未激活。全程不执行任何插件代码执行是之后独立的一步。流程分三步切到Discover视图 → 点卡片打开审查对话框 → 点Install。Discover 卡片上的每个字段每张卡片展示图标、名称、作者、描述、类型Widget / Page / Integration / Trip page、Reviewed徽章如适用、Signed/Unsigned徽章、最新版本号、累计下载量。两个徽章的含义在「你可以信什么」一节逐一说破安装前不必先读懂它们但要知道它们不说明代码做了什么。安装前必看的审查对话框点卡片后打开的对话框才是决策依据四个必看项What it can access可访问范围——插件请求的权限逐条用平实语言渲染如读取行程、创建与编辑地点。未知权限代码原样显示一个权限都不请求时明确标注无需特殊访问。Connects to连接目标——manifest 声明的全部出口主机等宽字体 chip。Setup配置项——插件将要求填写的设置标注Instance-wide实例级还是Per user用户级、是否Required。Details详情——版本、体积、所需 TREK 版本范围、审查时间、下载量附Source repository、Report an issue、Homepage链接。关键机制这些信息不是作者自己写的介绍文字。服务端会拉取插件在审查提交点的实时 manifest 生成预览ManifestPreviewregistry.service.ts包含权限列表、出口主机、operatorEgress标记、设置字段key/label/inputType/scope/required、许可证、所需 addon 与插件依赖。拉取失败时软降级对话框仍用注册表元数据渲染。版本兼容Install 能装什么兼容性由服务端计算客户端刻意不持有第二套 semver 实现——UI 若与安装闸门意见不一致会出现按钮亮着却 400的假象registry.service.ts。三种结果最新版兼容 → 正常Install。最新版要求更新的 TREK但存在兼容旧版 → 按钮变为Install {version}装那个旧版对话框在琥珀色提示条里解释原因不藏在 tooltip 里。没有任何版本兼容 → 按钮变为Incompatible并禁用。还有一层更硬的校验下载后、解压后安装管线用归档自带的 manifest再查一次版本范围registry.service.ts。注册表索引里的 min/max 只是较弱的预下载过滤比如表达不了4.0.0这种排他上限真正的判定以工件自身声明为准。装完默认关闭的确切语义安装成功时插件状态是已安装但未激活代码在磁盘、注册表有行、权限已登记但子进程不存在不运行任何代码。安装流程做了下载、完整性与签名校验、安全解压、manifest 复验、原生二进制拒绝、原子替换、登记 inactive没做任何权限授予、任何进程派生。插件要连只有你知道地址的服务operatorEgress自托管 Gotify、ntfy 这类服务的主机名在插件发布时不可能写死。声明了operatorEgress的插件审查对话框会额外出现一个「 hosts you add」chip提示安装后由管理员补填主机。安装后在⋯ → Allowed hosts逐个添加在添加至少一个主机前该行显示琥珀色Add allowed hostchip——因为此时它一个主机都到不了不提示会像静默故障。保存后插件会被重启以加载新白名单出口守卫在子进程初始化时安装一次且拒绝二次init运行中插件的白名单永远不能在原进程内热扩容plugin-runtime.service.ts。主机校验与 manifest 声明出口同一套规则不允许裸*、不允许整 TLD 通配、不允许带协议前缀校验正则见 plugin-runtime.service.ts。三条硬边界未声明operatorEgress的插件永远无法被授予主机安装时同意的范围仍是硬边界只有管理员能添加主机普通用户永远不能扩大出口服务若在 TREK 同机或同局域网还需TREK_PLUGIN_ALLOW_PRIVATE_EGRESSon。删除某个主机后插件立即失去该出口并再次重启卸载时这些主机一并删除。两条旁路不走官方渠道装核心事实两条旁路都以未激活状态注册激活时同样要走权限同意来源徽章Sideloaded/Dev-Link是卡片上的诚实标签——它记录代码来源但不会因此多做一道检查、换一种沙箱或加一层限制。上传 .zip旁路加载用工具栏的Upload plugin按钮或直接把.zip拖到面板上。服务端sideload()分两步先解压到 staging 并执行与注册表安装相同的硬防护防 slip/炸弹的安全解压、严格 manifest 校验、拒绝原生二进制仅注册表的 SHA-256/签名校验不适用因为没有注册表条目可依据registry.service.ts通过后再原子替换代码目录plugin-runtime.service.ts。限制与语义上传上限 50 MB与 SDKpack同上限另留 4 KB 归档开销plugins.controller.ts。该行标记SideloadedUploaded manually — not from the registry, unsigned and unreviewed.——手动上传未签名、未经注册表审查。用相同 id 覆盖上传时旧代码先被强制停止并停用再替换且新代码一律登记为 inactive、清除签名密钥与任何更新阻塞记录registry.service.ts——替换后的代码绝不处于未经重新激活仍在运行的状态。链接本地插件dev-link面板出现Link a local plugin路径输入框当且仅当服务端设了TREK_PLUGINS_DEV_LINK1叠加管理员 总开关两道门plugins.controller.ts。它做的事对插件代码目录创建符号链接不复制、校验 manifest、拒绝原生二进制、注册为 inactive然后对构建输出目录起fs.watch重建后防抖 400 ms 自动重新 forkplugin-runtime.service.ts。为什么仅限开发环境dev-link.ts 注释dev-linked 插件的构建产物会在重启之间变化且不走重新同意绕开了安装时的签名/完整性模型且在npm run dev下 OS 权限 jail 是关的。它的数据访问仍走同一套能力 RPC成员校验、无冒充但正因为前两条加载未签名本地代码必须钉在一个显式开关后面——生产实例上这个入口不应出现。另外已正式安装注册表/旁路的插件不会被同 id 的 dev-link 覆盖须先卸载plugin-runtime.service.ts。让它跑起来并养好它核心事实启用是面板行上的Enable plugin开关翻上去 授予已审查的权限 派生隔离子进程翻下来 立即停进程、保留数据。每个状态词是精确的Active子进程在跑、Off已安装未激活、Error启动/运行失败、disabled运行时总开关关闭。启用被拒怎么办原因 → 补救清单预检按最严重到最不严重排序且全程只读任何一项不满足都不会留下半激活状态plugin-runtime.service.ts。每种拒绝都带结构化错误码和对应补救路径ADDON_DISABLED——必需的 addon 未启用 → 在Admin → Addons打开对应 addon重试。DEPENDENCY_MISSING——依赖的插件缺失或版本不在声明范围 → 依赖对话框逐条列出每个条目带Download / Update一键拉取最新兼容版本后自动重试。TREK_VERSION_INCOMPATIBLE——插件声明的 TREK 范围不含当前宿主版本 → 升级 TREK这也是升级后装好的插件突然启用不了的常见原因。TREK_VERSION_UNKNOWN——插件未声明支持的 TREK 范围无法判断兼容 → 联系作者补声明。CONSENT_REQUIRED——更新拓宽了权限见下节→ 同意对话框里选Approve turn on或Keep off for now。DEPENDENCY_CYCLE——插件依赖成环 → 修改 manifest 依赖声明后重装。图标块上的健康圆点同步反映运行时状态绿active、蓝闪starting、红error、琥珀disabled/incompatible、淡色inactive。每行的⋯菜单提供Restart仅活动插件、View error log、Allowed hosts、Source repository与Report an issue仅注册表插件、Delete。级联语义依赖与 addon 如何连坐启用一个插件前先按依赖图算出启动顺序先拉起所有依赖再拉起目标已安装但停用的依赖会被自动级联启用toast 告知哪些被顺带打开plugin-runtime.service.ts。某个必需 addon 被关闭时依赖它的插件自动停用且所有传递依赖它的插件一并停用plugin-runtime.service.ts。停用一个被其他插件依赖的插件会连带停用所有依赖它的插件——插件不能在依赖缺失下继续运行plugin-runtime.service.ts被依赖方先停、依赖方后停。更新权限与出口永不静默扩大有新版本时行上出现Update → v{version}列表上方出现更新计数提示条与Update all批量按钮。服务端update()先把新版本声明的权限与已授予权限做差集plugin-runtime.service.ts无新增权限与出口主机都没有→ 透明重启到新代码有任何新增 → 新代码安装后插件保持关闭差集返回给界面{name} v{version} is asking for rights you havent granted yet. The new version is installed but stays off until you approve it.即新版装好了但不开管理员在对话框里看到Newly requested permissions与New outbound connections后选Approve turn on或Keep off for now。批量更新时这些同意提示排队依次出现一个都不跳过。更新目标的选择同样防坑resolveUpdateTarget取的是当前 TREK 能运行的最新兼容版本而非字面最新版若兼容版本反而比已装版本旧直接以NO_COMPATIBLE_UPDATE拒绝——更新语义下静默降级比不更新更糟plugin-runtime.service.ts。更新被签名密钥变更挡住怎么办作者的签名密钥与安装时钉住的密钥不再匹配时更新被拒行上显示Update blocked — {reason}与Review链接对话框并排展示钉住的密钥指纹与当前提供的密钥指纹TREK cannot tell a legitimate key rotation apart from a takeover — both look identical from here. Confirm the new key with the author through a channel you already trust before you accept it.即TREK 无法从这一侧区分良性换钥与接管接手前必须通过你已信任的渠道向作者核实新密钥。覆盖范围被严格限定只有SIGNATURE_KEY_CHANGED可以覆盖Trust the new key update。SIGNATURE_INVALID签名无效、SIGNATURE_MISSING先签名后变未签名、SIGNATURE_INCOMPLETE半声明只有密钥没有签名或反之只给解释没有任何覆盖按钮服务端/retrust端点同样拒绝这三种情形registry.service.ts 的assertRetrustable在服务端重新推导条件UI 藏按钮只是便利不是控制。重信任要求回显对话框里展示的完整公钥——注册表条目若在渲染后被再次换钥请求被拒且重信任与更新在同一次调用内完成要么新密钥通过校验、插件落到新版本并钉住新密钥要么什么都不变杜绝钉住一个从未验证过的密钥的窗口。该操作同时写入管理员审计日志含新旧密钥指纹plugin-runtime.service.ts。卸载删什么、什么无条件删、什么义务延续⋯ → Delete的确认框会说明停止插件、移除代码、删除其全部数据可选保留不可撤销。服务端uninstallplugin-runtime.service.ts分三档总是删停止子进程、移除代码目录、plugins注册表行、设置字段出口主机与定时任务无条件删除——否则后续复用同一 id 的插件会悄悄继承前人的出口白名单和回调若是通知渠道插件渠道一并退役避免继承所有用户的选择退出。勾选删除数据时额外删插件自有数据目录、错误日志、每用户配置含加密密钥、OAuth 令牌与状态、迁移台账、能力审计日志、GDPR 擦除队列。保留数据时延续的义务待处理的用户数据擦除队列行被保留——数据目录还在可能仍含已注销用户的行擦除义务必须跟着走同 id 插件重装后会继续兑现plugin-runtime.service.ts。dev-linked 插件卸载只移除符号链接绝不触碰作者源码目录。你可以信什么徽章隔离与它们的边界核心事实徽章与隔离机制是两回事——徽章是注册表层面的信任标记隔离是进程层面的物理边界。前者可被绕过未签名插件照样装后者不能。每个徽章保证什么不保证什么Reviewed——Reviewed means a TREK maintainer scanned this plugin for malware on each version — not for quality or whether it works. It is not a guarantee that a plugin is harmless.即每个版本都做过恶意软件扫描不保证质量、可用性也不是无害担保。Signed——安装时文件字节已对照作者签名密钥校验且该密钥在首次安装时被 TOFU 钉住。checksum 证明文件是注册表担保的字节签名进一步证明这些字节来自作者不保证代码行为符合作者描述也不能阻止作者故意写恶意逻辑。Unsigned——文件匹配注册表担保的字节但没有东西把它绑定到作者。少一层保证不是不安全目前注册表里多数插件未签名所以这是琥珀色提示而非警报。Sideloaded / Dev-Link——对自己诚实这些只是卡片上的标签。它们记录代码来源不触发额外检查、不同沙箱、不同限制旁路加载的插件以它声明的权限原样运行与注册表插件一样且没有恶意软件扫描、没有签名。徽章的存在只为让你一眼看出除了你没有人为此代码背书。隔离模型插件物理上做不到什么每个活动插件运行在独立 OS 子进程中由 Node 权限模型--permission启动文件系统读取限定在其自身代码目录plugin-supervisor.ts 与 wiki/Plugins.md无法访问JWT_SECRET、数据库连接或任何 TREK 机密——这些对其进程物理不可达。不能打开trek.db、写文件、派生子进程、使用 worker 线程、加载原生模块其自有数据是独立 SQLite 文件且只能通过 TREK 访问。只通过内部 RPC 通道与 TREK 通信TREK 只应答 manifest声明且你批准的能力未授予的调用被拒绝而非忽略。RPC 通道本身对插件代码是封死的插件的原始 IPC 原语process.send、process.on(message)在其代码加载前被吊销——它既不能伪造宿主消息伪造路由表、冒充其他请求身份也不能窃听其他在途请求一切交互被迫经过能力校验的 SDK。页面/widget 界面运行在密封的浏览器 frame中读不到会话 cookie碰不到外围 TREK 页面。崩溃、挂起、内存耗尽时只有它自己的进程死掉supervisor 带退避重启5 分钟窗口内最多 5 次崩溃、退避上限 30 秒超限自动停用TREK 继续运行。最坏情况权限清单是真实边界不是标签⚠️ 你批准的权限列表是真实边界但它界定的是插件能触及什么不约束它在授权范围内的意图一个被允许读取行程且能连接某主机的插件完全可以把行程数据发往那里。它能做到这一步它做不到的是读未授权的数据、碰 TREK 机密、绕过成员校验。所以安装前读权限清单和出口主机不是走形式而是唯一一道由你控制的关口。审计谁做了什么、谁看得见核心事实TREK 为插件维护一条哈希链防篡改的能力审计每个宿主中介动作在插件够不到的地方落记录——操作者由宿主绑定插件无法自称以谁的名义、触达的资源、结果wiki/Audit-Log.md。两个视图面向两类人管理员在Admin → Plugins看到按插件维度的视图GET /api/admin/plugins/:id/audit——某插件对所有用户做过的每次核心数据读取、广播、通知、AI 调用与跨插件调用。每个最终用户在Settings → Plugins看到以他本人名义发生的全部插件动作跨插件、最新在前GET /api/plugin-activity。该视图不设管理员门槛——这是刻意设计让宽泛的只读授权对数据所属者本人可问责。关键权限的确切授予范围完整清单见 wiki/Plugin-Permissions.md只读类db:read:trips——经ctx.trips读行程/地点/预订/日程等每个调用都对操作者做 membership 校验插件读不到该用户看不到的行程。写入类db:write:places——创建/更新/删除地点要求行程访问place_edit权限输入按 TREK schema 校验每次写入都审计。宿主中介类notify:send——收件人被强制限定为操作者本人或其所属行程拒绝scope:admin插件只提供纯文本标题/正文200/1000 字符上限与相对路径链接。宿主中介类oauth:client——宿主跑完整个 OAuth 流程PKCE state并持有client secret 与 refresh token令牌按用户加密存储插件只拿到操作者名下短期access token。每插件的审计保留行数由TREK_PLUGIN_AUDIT_MAX_ROWS封顶默认 20000 行保留窗口内哈希链保持防篡改性质wiki/Environment-Variables.md。决策速查状态 / 错误提示 / 错误码含义处理方式面板显示 turned off (TREK_PLUGINS_ENABLED)运行时总开关关闭操作一律 503打开TREK_PLUGINS_ENABLED并重启已装插件仍在磁盘按钮Incompatible禁用没有任何版本兼容当前 TREK升级 TREK或等作者发兼容版本按钮变为Install {version}最新版要求更新的 TREK旧版仍兼容安装提示的旧版本或升级 TREK 后更新CONSENT_REQUIRED409新版本拓宽了权限/出口需重新同意对话框选Approve turn on或Keep off for nowADDON_DISABLED409必需 addon 未启用在Admin → Addons打开后重试DEPENDENCY_MISSING409依赖插件缺失或版本不匹配依赖对话框逐条Download / UpdateDEPENDENCY_CYCLE409插件依赖成环修正 manifest 依赖声明后重装Update blockedSIGNATURE_KEY_CHANGED作者签名密钥与安装时钉住的不一致Review对比两侧指纹 → 经可信渠道向作者核实 →Trust the new key updateSIGNATURE_INVALID/SIGNATURE_MISSING/SIGNATURE_INCOMPLETE签名无效 / 先签后撤 / 半声明无任何覆盖按钮不要信任向作者与注册表报告TREK_VERSION_INCOMPATIBLE/TREK_VERSION_UNKNOWN409宿主版本超出声明范围 / 未声明范围升级 TREK后者联系作者补声明NO_COMPATIBLE_UPDATE最新兼容版本不比已装版本新无需操作健康圆点红Error子进程启动失败或反复崩溃5 分钟 5 次上限⋯ → View error log查 stderr 记录修复后重新启用琥珀色Add allowed hostchip声明operatorEgress的插件尚无可用主机⋯ → Allowed hosts添加主机目标在局域网时另设TREK_PLUGIN_ALLOW_PRIVATE_EGRESSon行标Sideloaded/Dev-Link非注册表来源未签名、未审查、无自动更新视为只有你背书的代码生产上避免长期运行 dev-link扩展阅读wiki/Plugins.md——插件系统全貌类型、隔离模型、依赖、活动日志wiki/Plugin-Permissions.md——每条权限的确切授予范围与http:outbound细节wiki/Admin-Plugins.md——管理面板逐操作说明wiki/Plugin-Development.md——SDK 与 manifest 编写wiki/Plugin-Publishing.md——注册表提交流程与trek-pluginCLIwiki/Admin-Addons.md——插件可能依赖的 addon 管理wiki/Audit-Log.md——实例审计日志与插件能力审计wiki/Environment-Variables.md——插件相关环境变量完整参考server/src/nest/plugins/——服务端插件模块源码安装管线、运行时、supervisor、出口策略client/src/components/Admin/AdminPluginsPanel.tsx——管理面板前端实现【免费下载链接】TREKA self-hosted travel/trip planner with real-time collaboration, interactive maps, PWA support, SSO, budgets, packing lists, and more.项目地址: https://gitcode.com/GitHub_Trending/nomad22/TREK创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表