Hoppscotch Self-Hosted Admin(sh-admin):本地开发、构建产物与 Caddy 部署全解
本文以 packages/hoppscotch-sh-admin/README.md 为核心,系统讲解 Hoppscotch 自托管实例的管理后台 hoppscotch-sh-admin 的定位与功能边界、技术栈构成,以及从 .env 环境配置、GraphQL 代码生成到 pnpm run dev 本地开发、Docker 构建与 Caddy 静态部署的完整实操流程;读完后可独立搭建并运行该管理后台,并理解其前端配置、认证与路由机制的源码实现。
一、sh-admin 是什么:自托管实例的管理端
Hoppscotch 自托管版(self-hosted)由后端服务(hoppscotch-backend,NestJS + Prisma + PostgreSQL)与多个前端应用组成,其中 packages/hoppscotch-sh-admin 就是 README 所称的 Self Hosted Admin Dashboard——面向自托管管理员(infra admin)的 Web 管理面板。
从源码的页面与组件结构可以确认,它承担的能力包括:
- 实例配置管理:
src/components/settings/下提供了认证配置(AuthConfigurations.vue)、OAuth 提供者配置(OAuthProviderConfigurations.vue)、SMTP 配置(SmtpConfiguration.vue)、代理 URL 配置(ProxyURLConfiguration.vue)、限流配置(RateLimit.vue)、Mock Server 配置(MockServerConfig.vue)、历史数据开关(HistoryConfiguration.vue)、数据共享设置(DataSharing.vue)、服务重启(ServerRestart.vue)与重置(Reset.vue)等模块; - 团队与用户管理:
src/components/teams/(团队增删、成员、邀请)与src/components/users/(用户详情、共享请求、邀请); - 管理令牌管理:
src/components/tokens/提供 Infra Token 的生成、列表与概览; - 引导流程(Onboarding):
src/components/onboarding/中的 SMTP 配置、OAuth 配置、认证提供者选择等引导页面,对应src/pages/onboarding.vue与src/pages/setup.vue。
后端对应的 GraphQL 接口位于 hoppscotch-backend 的 admin 模块(admin.resolver.ts、admin.service.ts、infra.resolver.ts 等),sh-admin 通过 GraphQL 请求与之交互。
二、技术栈:Built with 清单及其在工程中的落点
README 给出的技术栈为 HTML、CSS/SCSS/Tailwind CSS、JavaScript、TypeScript、Vue、Vite。对照 package.json 可以确认各技术的具体版本与配套工具:
| 技术 | 依赖/工具 | 说明 |
|---|---|---|
| Vue | vue: 3.5.38、vue-router: 4.6.4 |
单页应用框架与路由 |
| Vite | vite: 7.3.2、@vitejs/plugin-vue: 6.0.7 |
开发服务器与构建器 |
| TypeScript | typescript: 5.9.3、vue-tsc: 2.1.6 |
类型系统与类型检查 |
| 样式 | tailwindcss: 3.4.16、sass: 1.101.0、postcss: 8.5.15 |
原子化 CSS 与 SCSS |
| GraphQL 客户端 | @urql/vue: 2.1.1、@urql/exchange-auth: 3.0.0、graphql: 16.13.2 |
类型安全的 GraphQL 请求 |
| GraphQL 代码生成 | @graphql-codegen/cli: 6.3.1 及一系列 typescript* preset |
从 .graphql 文档生成 TS 类型 |
| 国际化 | vue-i18n: 11.4.6、@intlify/unplugin-vue-i18n |
翻译文件位于 locales/ |
| UI 组件 | @hoppscotch/ui: 0.2.6、vue-tippy、tippy.js |
Hopp 前缀组件自动解析自该包 |
此外,@fontsource-variable/* 提供 Inter、Material Symbols Rounded、Roboto Mono 三款可变字体(在 main.ts 中直接 import),@import-meta-env/* 支持运行时环境变量注入。
三、环境准备与 .env 配置(README 第 0 步详解)
README 的第一步要求:把仓库根目录的 .env.example 更新为自己的密钥并改名为 .env。仓库根目录的 .env.example 中,与 sh-admin 直接相关的变量如下:
# Base URLs
VITE_BASE_URL=http://localhost:3000
VITE_SHORTCODE_BASE_URL=http://localhost:3000
VITE_ADMIN_URL=http://localhost:3100
# Backend URLs
VITE_BACKEND_GQL_URL=http://localhost:3170/graphql
VITE_BACKEND_WS_URL=ws://localhost:3170/graphql
VITE_BACKEND_API_URL=http://localhost:3170/v1
# Set to `true` for subpath based access
ENABLE_SUBPATH_BASED_ACCESS=false
结合 vite.config.ts 可以看到这些变量为什么能生效:
envDir: path.resolve(__dirname, '../..'):Vite 的.env查找目录被显式指到仓库根目录,因此 README 第 0 步所说的“仓库根目录的.env.example”才是真正被加载的配置源(README 第 2 步表述为 sh-admin 目录下的.env.example,以 vite 配置实际行为为准);envPrefix: process.env.HOPP_ALLOW_RUNTIME_ENV ? 'VITE_BUILDTIME_' : 'VITE_':默认只注入VITE_前缀的变量;若设置HOPP_ALLOW_RUNTIME_ENV,则构建期前缀切换为VITE_BUILDTIME_,并同时启用ImportMetaEnv.vite({ example: '../../.env.example', env: '../../.env' })插件,把.env以import.meta.env的形式打进产物,支持部署后再改配置;server.port: 3100:这就是 README 最后一步要求打开http://localhost:3100的由来;- 别名
~指向src/,@modules指向src/modules/,源码中大量使用~/导入。
后端侧变量(DATABASE_URL、DATA_ENCRYPTION_KEY、WHITELISTED_ORIGINS、PROXY_APP_URL、TRUST_PROXY 等)服务于 hoppscotch-backend,其中 WHITELISTED_ORIGINS 默认白名单已包含 http://localhost:3100,即 sh-admin 开发服务器本身。
四、本地开发流程:README 步骤逐条落实
README 的 Local development environment 共 7 步,结合工程实际可以这样执行(以下命令均在 packages/hoppscotch-sh-admin 目录内):
- 用 git 克隆仓库;
- 按上一节把仓库根目录
.env.example改为.env并填入自己的配置; - 安装 pnpm:
npm install -g pnpm(仓库为 pnpm workspace,根目录含pnpm-workspace.yaml); - 在
hoppscotch-sh-admin目录内执行pnpm install安装依赖; - 前提:后端已启动。README 明确要求假定 backend 正在运行(当前仓库中即 hoppscotch-backend,GraphQL 端点默认
http://localhost:3170/graphql); - 启动开发服务器:
pnpm run dev; - 浏览器访问
http://localhost:3100。
pnpm run dev 实际做了什么
对照 package.json 的 scripts:
"dev": "pnpm exec npm-run-all -p -l dev:*",
"dev:vite": "vite",
"dev:gql-codegen": "graphql-codegen --require dotenv/config --config gql-codegen.yml --watch dotenv_config_path=\"../../.env\"",
"postinstall": "pnpm run gql-codegen"
dev通过npm-run-all -p并行启动所有dev:*任务,即dev:vite(Vite 开发服务器)与dev:gql-codegen(graphql-codegen 的--watch监听模式);- codegen 的
dotenv_config_path指向仓库根目录的.env,保证监听 GraphQL schema 时环境变量可用; postinstall钩子会在pnpm install结束后自动执行一次gql-codegen,所以第 4 步安装完依赖后类型文件已生成。
GraphQL 代码生成的具体规则
gql-codegen.yml 定义了生成规则:
overwrite: true
schema: "../../gql-gen/*.gql"
generates:
src/helpers/backend/graphql.ts:
documents: 'src/**/*.graphql'
plugins:
- 'typescript'
- 'typescript-operations'
- 'typed-document-node'
- 'urql-introspection'
src/helpers/backend/graphql.schema.json:
plugins:
- 'introspection'
- schema 来源于仓库根目录下的
gql-gen/*.gql(由后端 GraphQL schema 导出); - 组件中散落的 41 个
.graphql文件(位于src/helpers/backend/gql/)会被编译进 src/helpers/backend/graphql.ts,配合typed-document-node与urql-introspection插件,在 urql 客户端中获得类型安全的查询; - 开发模式下该过程处于 watch 状态,修改
.graphql文档会触发类型重新生成。
五、运行时机制:认证、请求与错误回退
sh-admin 的入口 src/main.ts 揭示了它作为管理端的运行时骨架:
- URQL 客户端创建:
url: import.meta.env.VITE_BACKEND_GQL_URL(即.env中配置的http://localhost:3170/graphql),requestPolicy: 'network-only'保证管理操作不走缓存,credentials: 'include'允许携带 Cookie 完成自托管后端的会话认证; - 认证刷新(authExchange):当请求返回未授权错误(
GRAPHQL_UNAUTHORIZED)时触发refreshAuth,调用auth.performAuthRefresh()刷新会话令牌;源码中还专门引入createAuthRetryGuard(见 helpers/retryAuthGuard.ts),防止令牌永久失效时进入无限刷新循环,登录成功后会自动reset()该守卫; - 模块初始化:
HOPP_MODULES.forEach((mod) => mod.onVueAppInit?.(app)),src/modules/下按 admin、i18n、router、tippy、toast、ui 等拆分初始化逻辑; - 失败回退:若初始化失败(典型场景是后端未启动),会挂载
src/pages/_.vue错误页,提示“Failed to connect to the backend server”——这也解释了 README 第 5 步“假定后端正在运行”是硬性前提。
页面由 vite-plugin-pages(routeStyle: 'nuxt',目录 src/pages)按文件生成路由:index.vue(重定向/入口)、enter.vue(登录)、dashboard.vue、onboarding.vue、settings.vue、setup.vue 以及 teams/、users/ 子目录页面;布局由 vite-plugin-vue-layouts 提供(default/empty 两种,位于 src/layouts/)。
六、构建与 Docker 部署:从 dist 到 Caddy 静态站
sh-admin 的产物是纯静态 SPA,Dockerfile 采用两阶段构建:
# Initial stage, just build the app
FROM node:lts as builder
WORKDIR /usr/src/app
RUN npm i -g pnpm
COPY . .
RUN pnpm install --force --frozen-lockfile
WORKDIR /usr/src/app/packages/hoppscotch-sh-admin/
RUN pnpm run build
# Final stage, take the build artifacts and package it into a static Caddy server
FROM caddy:2-alpine
WORKDIR /site
COPY packages/hoppscotch-sh-admin/Caddyfile /etc/caddy/Caddyfile
COPY --from=builder /usr/src/app/packages/hoppscotch-sh-admin/dist/ .
EXPOSE 8080
要点:
- 构建阶段在仓库根目录执行 workspace 级
pnpm install --frozen-lockfile(保证锁文件一致),再进入packages/hoppscotch-sh-admin执行pnpm run build(即vite build,产物落在dist/); - 运行阶段只用
caddy:2-alpine镜像承载静态文件,镜像体积很小; - Caddyfile 监听
:8080,try_files {path} /把未命中的路径回退到index.html,这是 SPA history 路由能正常刷新的关键配置。
针对两种常见部署形态,仓库还提供了两个备用 Caddyfile:
- sh-admin-multiport-setup.Caddyfile:在
:80与:3100上提供管理端,站点根为/site/sh-admin-multiport-setup,适合管理端与主站分端口部署; - sh-admin-subpath-access.Caddyfile:通过
handle_path /admin*将/admin子路径映射到管理端静态目录(/site/sh-admin-subpath-access),其余路径返回 404,与.env中的ENABLE_SUBPATH_BASED_ACCESS=true配合使用,适合管理端与主站同域共存。
七、小结:一条最短可用路径
按 README 的骨架 + 仓库配置的实际行为,最小可用的开发环境是:
- 根目录
.env.example→.env,确认VITE_BACKEND_GQL_URL(默认http://localhost:3170/graphql)与VITE_ADMIN_URL(默认http://localhost:3100); - 启动 hoppscotch-backend 并保证 GraphQL 端点可达;
pnpm install(触发 postinstall 的 gql-codegen)后pnpm run dev;- 访问
http://localhost:3100,登录页为enter.vue; - 生产形态:
docker build使用 Dockerfile,容器以 Caddy 服务 8080 端口,按需切换多端口或子路径 Caddyfile。
sh-admin 本身无数据库、无独立后端,其全部能力依赖 hoppscotch-backend 的 admin GraphQL 接口;理解 .env 变量注入、graphql-codegen 工作流与 Vite 插件链(pages/layouts/i18n/components/icons/fonts),是阅读和扩展这个管理后台源码的三把钥匙。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00