ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

SkillHub FAQ 实战:企业级技能注册中心的部署、CLI 与安全扫描完整运维指南

SkillHub FAQ 实战:企业级技能注册中心的部署、CLI 与安全扫描完整运维指南
  • 人工智能
  • AI Agent
  • AI 技能
  • 后端
  • 前端

【免费下载链接】skillhub

Self-hosted, open-source agent skill registry for enterprises. Publish & version skill packages, govern with RBAC and audit logs, deploy on-premise with Docker or Kubernetes.

项目地址:https://gitcode.com/gh_mirrors/sk/skillhub
点击查看免费下载

本文基于 SkillHub 官方 FAQ 整理成篇,覆盖部署升级、认证与账号管理、技能包发布限制、CLI 日常操作、内置 Skill Scanner 安全扫描,以及登录跳转、502、PostgreSQL 权限等高频故障的排查路径。读完本文,你可以独立完成 SkillHub 的一键部署与升级、通过 CLI 管理技能包、理解扫描器两种工作模式的取舍,并在配置不生效、发布报错等场景下快速定位根因。

1. 产品定位:SkillHub 与 ClawHub 的区别

SkillHub 是企业级的自托管(self-hosted)agent skill 注册中心,提供命名空间 RBAC、多级审核与治理能力;ClawHub 则是类似 npm 的公共注册中心。两者的核心差异如下:

特性SkillHubClawHub
部署方式自托管公共云
权限控制命名空间 RBAC基础权限
审核机制多级审核无
安全扫描内置 Skill Scanner无
数据主权完全自主托管在云端
适用场景企业内部公开分享

从源码结构看,SkillHub 的治理能力(审核队列、安全扫描、审计日志)集中在server/后端与独立的scanner/扫描服务中,这也解释了为什么它定位为企业内部使用:数据全程留在自己的基础设施上。

2. 部署、升级与外部依赖

2.1 推荐部署方式:官方一键脚本

官方推荐使用仓库内的 scripts/runtime.sh 一键部署脚本,不建议自己拉取镜像手动部署——手动部署容易出现数据库初始化、依赖顺序、登录跳转等问题。默认依赖从公共镜像仓库拉取,SkillHub 应用镜像来自 GHCR:

# 标准部署 curl -fsSL https://imageless.oss-cn-beijing.aliyuncs.com/runtime.sh | sh -s -- up --public-url https://skillhub.your-company.com

国内网络无法访问 GHCR 时,使用阿里云镜像源(--aliyun会切换到预配置的阿里云 ACR 地址,见 runtime.sh 中的SKILLHUB_ALIYUN_REGISTRY默认值):

curl -fsSL https://imageless.oss-cn-beijing.aliyuncs.com/runtime.sh | sh -s -- up --aliyun --public-url https://skillhub.your-company.com --version latest

从 scripts/runtime.sh 的源码可以看到,脚本支持--version、--aliyun、--mirror-registry、--home、--ref等参数;生成的运行时配置默认位于/tmp/skillhub-runtime/(可用--home覆盖),其中包含.env.release和 docker-compose 文件,脚本会执行一系列初始化操作后再拉起服务。

2.2 升级 SkillHub

升级采用「拉新镜像 → 停旧实例 → 起新实例」的三步方式:

# 拉取最新镜像并重启 curl -fsSL https://imageless.oss-cn-beijing.aliyuncs.com/runtime.sh | sh -s -- pull curl -fsSL https://imageless.oss-cn-beijing.aliyuncs.com/runtime.sh | sh -s -- down curl -fsSL https://imageless.oss-cn-beijing.aliyuncs.com/runtime.sh | sh -s -- up # 或直接指定版本升级 curl -fsSL https://imageless.oss-cn-beijing.aliyuncs.com/runtime.sh | sh -s -- up --version v0.2.0

注意:升级前建议先备份数据库和对象存储。数据库迁移由 Flyway 自动执行,升级不会清空数据库,已录入的技能包不会丢失。

一个典型的版本相关问题是「管理员(admin)和普通用户都无法创建命名空间」——这是较旧版本尚未引入该功能导致的,升级到latest即可:

curl -fsSL https://imageless.oss-cn-beijing.aliyuncs.com/runtime.sh | sh -s -- up --version latest

2.3 运行时外部依赖

  • PostgreSQL:必需,数据库仅支持 PostgreSQL,不支持 MySQL;
  • Redis:必需;
  • 对象存储:支持local与 S3 两种模式,由SKILLHUB_STORAGE_PROVIDER控制。

这一点在 compose.release.yml 中得到印证:server 服务的SKILLHUB_STORAGE_PROVIDER回退默认值是s3(第 82 行),而 .env.release.example 显式配置为local。因此如果直接用compose.release.yml且完全未设置该变量,实际会走 S3 模式——FAQ 建议始终显式设置,生产环境推荐 S3(通过SKILLHUB_STORAGE_S3_*系列变量配置)。

发布版 Compose 已内置 PostgreSQL 与 Redis 容器,默认只绑定在127.0.0.1(POSTGRES_BIND_ADDRESS、REDIS_BIND_ADDRESS默认值均为127.0.0.1),对外不暴露数据库端口。

3. 认证、账号与 SSO 管理

3.1 支持的认证方式

  • OAuth2:GitHub、GitLab、飞书(feishu)、钉钉(dingtalk)等;
  • 本地账号:用户名/密码登录(内置管理员:admin/ChangeMe!2026);
  • 企业 SSO:可集成 LDAP、SAML 等。

内置管理员凭据可以在 compose.release.yml 中得到验证:BOOTSTRAP_ADMIN_USERNAME默认admin、BOOTSTRAP_ADMIN_PASSWORD默认ChangeMe!2026,由BOOTSTRAP_ADMIN_ENABLED控制是否启用 bootstrap 管理员。

3.2 隐藏登录页的第三方 SSO 入口

登录入口是配置驱动的:/api/v1/auth/methods只返回配置了真实 client id 的注册项;client id 为空或包含placeholder时,该入口不会出现在登录页(前端在 web/src/api/client.ts 中拉取该接口渲染登录方式)。隐藏某个入口有两种方式:

  1. 留空对应环境变量:例如不设置OAUTH2_FEISHU_CLIENT_ID,无需改动配置文件。从 compose.release.yml 可以看到OAUTH2_GITHUB_CLIENT_ID、OAUTH2_FEISHU_CLIENT_ID、OAUTH2_DINGTALK_CLIENT_ID等的缺省值均为local-placeholder,即未配置时登录页不会出现对应入口;
  2. 修改application.yml:注释或删除spring.security.oauth2.client.registration下对应的注册块(github、gitlab、feishu、dingtalk)及其provider段,Spring Boot 启动时便不会创建该注册。

3.3 修改/找回密码与 SMTP

默认必须通过邮箱验证码修改或找回密码,因此需要先配置 SMTP(Compose 中对应SPRING_MAIL_HOST、SPRING_MAIL_SMTP_AUTH、SPRING_MAIL_SMTP_STARTTLS_ENABLE等变量,验证码有效期由SKILLHUB_AUTH_PASSWORD_RESET_CODE_EXPIRY控制,默认PT10M)。具体配置步骤参见仓库内文档 docs/19-smtp-password-reset-email-setup.md。管理员也可以直接在.env.release中重置密码。

3.4 OAuth 账号如何获得管理员权限

OAuth(GitHub / GitLab 等)首次登录创建的是普通用户。需要由已有的SUPER_ADMIN(例如初始化时创建的 bootstrap admin)在管理后台将其提升为管理员。

权限边界:USER_ADMIN可以管理用户状态、分配除SUPER_ADMIN之外的平台角色;但不能向任何账号授予SUPER_ADMIN,也不能修改已有SUPER_ADMIN账号的角色——这两类操作只有SUPER_ADMIN可以执行。

4. 数据备份与存储故障

4.1 备份策略

SkillHub 的数据存储在 PostgreSQL 和对象存储中,定期备份这两部分即可。

备份 PostgreSQL:

pg_dump -h localhost -U postgres skillhub > backup.sql

备份对象存储:

  • 使用 MinIO 时,备份 MinIO 数据目录;
  • 使用 S3 时,使用 AWS CLI 或 S3 备份工具。

若使用官方 Compose 的local模式,对象存储落在 Docker 命名卷skillhub_storage(挂载到容器内/var/lib/skillhub/storage),备份该卷即可。

4.2 PostgreSQL 报operation not permitted(写 postmaster.pid / pg_wal)

SkillHub 默认的 Compose 和runtime.sh使用 Docker named volume(postgres_data,见 compose.release.yml 第 28 行与 volumes 段),通常不需要手工处理宿主机目录权限。该错误更常见于把 PostgreSQL 数据目录改成宿主机 bind mount(例如/data/skillhub/postgres:/var/lib/postgresql/data)。按以下顺序排查:

  1. 优先恢复为 Docker named volume,或使用官方runtime.sh,避免手写 Compose 时漏配权限;
  2. 如果必须使用 bind mount,先确认.env.release或runtime.sh参数最终选择的POSTGRES_IMAGE(Compose 默认postgres:16-alpine),导出该值后运行docker run --rm "$POSTGRES_IMAGE" id postgres,再按输出的实际 UID/GID 执行chown -R <uid>:<gid> <数据目录>。不要固定假设镜像是postgres:16-alpine,也不要假设所有环境都是999:999;
  3. 在 RHEL/CentOS 上检查 SELinux;使用 AppArmor、rootless Docker、NFS、CIFS 或 NAS 时,确认宿主文件系统允许 PostgreSQL 写入、加锁和更改权限;
  4. 不建议把PGDATA放在缺少完整 POSIX 权限语义的网络文件系统上,生产环境优先使用本地盘、Docker named volume、块存储或外部 PostgreSQL。

5. 技能包限制与发布排错

5.1 包大小限制

默认大小限制为100MB,可通过spring.servlet.multipart调整:

# application.yml spring: servlet: multipart: max-file-size: 100MB max-request-size: 100MB

除 Servlet 层限制外,服务端还有技能包发布策略值:从 server/skillhub-app/src/main/resources/application.yml 可以看到skillhub.publish段中max-package-size: 104857600(100MB)、max-single-file-size: 10485760(单文件 10MB)。这些值由 SkillPublishProperties 绑定,并在校验器中生效。

5.2 文件数量限制

默认上限为100 个文件(与 100MB 的大小限制是两回事),对应skillhub.publish.max-file-count: 100(application.yml 第 236 行)。如需放宽,修改该配置项,或在部署时用环境变量覆盖:

SKILLHUB_PUBLISH_MAX_FILE_COUNT=500

修改后需重新创建容器才会生效;仅执行restart不会重新注入环境变量。注意 compose.release.yml 中也需引用该变量;较旧版本(如 v0.2.6)可能将该值写死,建议升级到最新版本。从源码结构看,Java 类 SkillPublishProperties 的代码级兜底默认值是 500,实际生效值以配置文件为准。

5.3 目录结构要求与命名规则

  • 技能包根目录必须包含一个SKILL.md文件,其 frontmatter 需包含name、description等字段;
  • 技能名不支持中文:skill name 一般使用英文,在 OpenClaw 中使用中文技能名会报错;
  • 未审核的 skill 可以下载:只要拥有可查看的权限,一般都可以下载;
  • Plugin 分发暂不支持,当前 SkillHub 只分发技能包;
  • 发布时包内文件类型、大小、路径都受校验策略约束(允许的文件扩展名可通过SKILLHUB_PUBLISH_ALLOWED_FILE_EXTENSIONS覆盖,README 中有示例)。

5.4 发布报「校验失败 / malformed input」

该错误发生在 zip 解包读取文件名阶段,通常是压缩包不是 UTF-8 编码(例如用 Windows 自带压缩工具生成)或包内含中文路径导致。请使用 UTF-8 编码重新打包,并避免中文/特殊字符路径。

5.5skillhub publish报registry returned 400

400 通常意味着后端校验未通过,常见原因:

  • SKILL.md不在技能包根目录;
  • SKILL.md的 frontmatter 缺少name/description或格式错误;
  • 名称或版本冲突(如error.skill.publish.nameConflict,表示该 namespace 下已存在同名已发布技能)——可改SKILL.md里的name、换 namespace,或让管理员处理已有同名技能;
  • namespace 不存在,或你不是该 namespace 的成员;
  • 包内含疑似 token/secret,CLI 无法确认跳过;
  • 文件类型 / 大小 / 路径不合规。

可用以下命令查看服务端日志定位:

docker logs --tail=300 <skillhub-server 容器名> 2>&1 | grep -Ei 'publish|SKILL.md|namespace|400|BadRequest'

6. CLI 日常操作

6.1 搜索、安装与发布

SkillHub 兼容 OpenClaw CLI,使用npx clawhub命令即可操作:

# 配置注册中心地址 export CLAWHUB_REGISTRY=http://your-skillhub-host:8080 # 搜索技能包 npx clawhub search email # 安装技能包 npx clawhub install my-skill # 发布技能包(ClawHub CLI 的发布协议不兼容 SkillHub) export SKILLHUB_REGISTRY=http://your-skillhub-host:8080 export SKILLHUB_TOKEN=YOUR_API_TOKEN npx @astron-team/skillhub@latest publish ./my-skill

操作指定命名空间中的技能包时,使用<namespace>--<skill-name>格式(搜索、安装均适用)。如果在网页端搜索遇到问题,也可以通过「先导出技能包、再导入到目标命名空间」完成跨空间操作。

6.2 版本要求

  • 使用 CLI(发布/下载等)需要 SkillHub 服务端镜像v0.2.7 及以上;
  • 查看服务端镜像版本:
docker image inspect ghcr.io/iflytek/skillhub-server:latest --format '{{index .Config.Labels "org.opencontainers.image.version"}}'
  • 查看 CLI 版本:skillhub version;
  • 如需定制(如修改 logo),建议基于最新代码 fork 后二次开发并自行构建 Docker 镜像。

6.3 批量安装多个技能包

CLI 的install一次处理一个技能包。以下示例通过--dir将技能批量安装到同一目标根目录,每个技能实际位于$target_dir/<skill-slug>/:

target_dir=/opt/skillhub-skills # 逐个安装 for skill in skill-a skill-b skill-c; do skillhub install "$skill" --dir "$target_dir" done # 或从清单文件读取(每行一个技能名) xargs -a skills.txt -I {} skillhub install "{}" --dir "$target_dir"

自SkillHub Server v0.2.12起,公开技能支持匿名搜索与安装。注意:配置了无效 Bearer Token 时命令会直接失败而不再回退匿名访问,遇到这种情况请更新凭据或先移除无效 Token。

7. 安全扫描(Skill Scanner)

7.1 实现构成与许可

SkillHub 内置安全扫描能力:扫描接入、任务编排、审计落库和部署集成由 iFLYTEK 团队实现;底层扫描服务使用 Cisco 的cisco-ai-skill-scanner(Apache License 2.0,版权归 Cisco)。

scanner/Dockerfile 已固定cisco-ai-skill-scanner==2.1.0(基于python:3.11-slim-bookworm,即 glibc Linux),Scanner 镜像支持linux/amd64和linux/arm64,监听 8000 端口并内置/health健康检查。

7.2 upload mode 还是 local mode?

官方 Compose 和 Kubernetes 部署使用uploadmode,通过POST /scan-upload上传技能包。从 compose.release.yml 可以看到 server 服务固定配置SKILLHUB_SECURITY_SCANNER_MODE: upload、SKILLHUB_SECURITY_SCANNER_URL: http://skill-scanner:8000,且 server 的健康检查依赖 scanner 先通过健康检查(depends_on的service_healthy条件),保证扫描服务就绪前不会接收流量。

上传大小上限由SKILLHUB_SCANNER_MAX_UPLOAD_SIZE_BYTES控制,默认110100480字节(105 MiB),与 100MB 发布上限留出了余量。

localmode 仅适用于 Server 与 Scanner 能在相同路径看到同一目录的部署:双方需要共享挂载路径,并在 Scanner 中设置允许的根目录;使用标准路径时配置SKILL_SCANNER_ALLOWED_ROOTS=/tmp/skillhub-scans(scanner/Dockerfile 中已预建该目录)。

7.3 “未发现高风险问题” ≠ 零 findings

Scanner 返回is_safe=true、UI 显示「未发现高风险问题」,仅表示没有发现高风险问题;低等级 findings 仍可能存在,findingsCount也可能大于 0。请继续查看 findings 明细,不要把该状态理解为无条件安全保证。

7.4 滚动升级到 Scanner 2.1.0

升级顺序很关键:

  1. 先部署兼容 2.1.0 协议的 Server;
  2. 在旧 Scanner 仍运行时,排空并下线所有旧 Server 实例及其进行中的扫描;
  3. 再升级 Scanner,验证/health和一次 upload mode 扫描;
  4. 不要让旧 Server 连接 Scanner 2.1.0。

混合版本期间,upload 和 local mode 都应保持 AI Defense 关闭(默认SKILLHUB_SCANNER_USE_AI_DEFENSE=false)。如果升级前必须继续使用 AI Defense,应按旧 Scanner 版本支持的环境变量把凭据直接配置到旧 Scanner 环境中;不要把 AI Defense key 放入 URL query 参数或请求体。

8. HTTPS、监控与多租户

8.1 配置 HTTPS

生产环境建议使用 Nginx 或 Traefik 作为反向代理并配置 SSL 证书。Nginx 配置示例:

server { listen 443 ssl; server_name skillhub.example.com; ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; location / { proxy_pass http://localhost:3000; } location /api { proxy_pass http://localhost:8080; } }

8.2 监控手段

  • 健康检查:GET /actuator/health(Compose 中 server 容器健康检查即访问该端点);
  • Scanner 健康检查:GET http://localhost:8000/health;
  • 指标监控:GET /actuator/metrics(Prometheus 格式);
  • 审计日志:所有关键操作都会记录到审计日志;
  • 应用日志:使用 ELK 或 Loki 收集(Compose 中SKILLHUB_LOG_FORMAT默认为json,便于采集)。

8.3 多租户

SkillHub 通过命名空间实现逻辑上的多租户隔离:每个命名空间相当于一个租户,拥有独立的成员、权限和技能包。如果需要物理隔离,可以为每个租户部署独立的 SkillHub 实例。

9. 高频故障排查

9.1 登录正确凭据却跳回登录页

该现象多见于手动部署场景(接口异常或初始化未完成导致)。建议:

  1. 改用 2.1 节的一键脚本部署;
  2. 必要时清空 PostgreSQL 数据卷后重建再登录;
  3. 若前置了反向代理,检查代理配置是否正确转发。

9.2 页面能打开但登录/注册接口 502

页面由web容器提供,登录、注册等接口由web转发给server(默认SKILLHUB_API_UPSTREAM=http://server:8080,见 compose.release.yml 第 171 行)。出现「页面正常但 API 502」时,先检查server是否正常启动;upstream 配置、DNS 或容器网络异常也可能返回 502。

排查顺序:

# 1. 看 server 是否处于运行状态 docker compose --env-file .env.release -f compose.release.yml ps # 2. 看 server 启动日志中的第一条错误 docker compose --env-file .env.release -f compose.release.yml logs server | head -50

一条常见的启动失败日志是:

SKILLHUB_DOWNLOAD_ANON_COOKIE_SECRET must not use the default placeholder

这说明server读到的仍是模板占位值。在.env.release中替换为自己的随机字符串(至少 32 个字符)后重建容器即可:

SKILLHUB_DOWNLOAD_ANON_COOKIE_SECRET=<替换成你自己的随机字符串,至少 32 个字符>

Compose 中该变量写作${SKILLHUB_DOWNLOAD_ANON_COOKIE_SECRET:?required}(必填项),启动前可先执行make validate-release-config(对应 scripts/validate-release-config.sh),它会校验.env.release,提前暴露占位值和缺失项。

9.3 改了配置为什么不生效

两个高频原因:

  1. 改错了文件:.env.release.example只是模板,Compose 实际读取的是--env-file指定的.env.release。请先cp .env.release.example .env.release,再修改.env.release;
  2. 只重启没重建:环境变量在容器创建时注入,restart不会重新注入。改完配置需要重建容器:
docker compose --env-file .env.release -f compose.release.yml up -d --force-recreate

修改 admin 密码同理:编辑/tmp/skillhub-runtime/.env.release(参考仓库根目录的 .env.release.example),然后执行:

docker compose \ --env-file /tmp/skillhub-runtime/.env.release \ -f /tmp/skillhub-runtime/compose.release.yml \ up -d --force-recreate

若此前密码已写入数据库导致仍不生效,可能需要清理对应数据后重新初始化。

10. 本地开发启动失败

make dev-all(Makefile 中的「一键启动本地开发环境」目标:依赖 + scanner + 后端 + 前端)后端启动失败时会显示详细错误提示,常见问题如下。

10.1 Maven 依赖下载失败(网络超时)

症状:后端日志显示Could not transfer artifact或连接超时。

解决方案:配置阿里云镜像——仓库内置了镜像配置文件,可直接复制:

mkdir -p ~/.m2 cp server/.mvn/settings.xml ~/.m2/settings.xml

或手动创建~/.m2/settings.xml:

<?xml version="1.0" encoding="UTF-8"?> <settings> <mirrors> <mirror> <id>aliyun</id> <url>https://maven.aliyun.com/repository/public</url> <mirrorOf>central</mirrorOf> </mirror> </mirrors> </settings>

10.2 Java 版本不匹配

症状:Unsupported class file major version或java.lang.NoSuchMethodError。

解决方案:安装 Java 21+。server/pom.xml 中java.version、maven.compiler.source、maven.compiler.target均为 21,即后端要求 JDK 21。

# macOS brew install openjdk@21 # 验证版本 java -version

10.3 端口被占用

症状:Port 8080 already in use。

解决方案:

# 查看占用端口的进程 lsof -i :8080 # 终止进程 kill -9 <PID>

10.4 查看详细日志

make dev-logs SERVICE=backend # 或直接查看 cat .dev/server.log

11. 遇到问题去哪里找答案

建议按以下顺序查阅仓库内资料:

  • README.md:项目总览、快速开始与认证配置说明(中文见 README_zh.md);
  • docs/skillhub/en/faq.md 与 docs/skillhub/faq.md:官方 FAQ 原始版本;
  • docs/security-scanning.md:安全扫描专题文档,覆盖 Scanner 配置参数与故障影响分析(配合 scanner/docs/ 下的配置、自定义规则、监控指南);
  • docs/19-smtp-password-reset-email-setup.md:SMTP 与密码重置邮件配置;
  • deploy/k8s/ 与 charts/skillhub/:Kubernetes 部署的 kustomize 与 Helm Chart 资源;
  • CONTRIBUTING.md:贡献与协作规范。

更多实现细节可结合源码继续深入:后端位于 server/(多模块 Maven 工程,含 skillhub-app、skillhub-domain、skillhub-auth 等),CLI 位于 cli/,前端位于 web/,内置技能目录见 builtin-skills/。

  • 人工智能
  • AI Agent
  • AI 技能
  • 后端
  • 前端

【免费下载链接】skillhub

Self-hosted, open-source agent skill registry for enterprises. Publish & version skill packages, govern with RBAC and audit logs, deploy on-premise with Docker or Kubernetes.

项目地址:https://gitcode.com/gh_mirrors/sk/skillhub
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进