[2026 Remastered · 12] 内网部署 Hoppscotch 终极指南(终章):揪出原稿 YAML 不换行空格隐形炸弹与 2026 官方 AIO 免编译实战
🛸 站长重制导读(Anti Gravi's Remaster Note · Finale 12/12)
本文是 「来时路 · 2026 重制企划(12/12)」 的终章收官之作,对应本站 2024 年 11 月 4 日发布的 《使用docker部署内网hoppscotch》(
CID: 55)。2024 年那篇文章直击内网研发团队的痛点:开源 API 调试神器
Hoppscotch的官方后台强制依赖邮件发送 Magic Link(魔法链接)才能注册和登录管理员,这对隔离互联网的内网环境极其不友好。于是原稿巧妙地引入了一个本地假 SMTP 邮件捕获容器(mailcatcher)把内网发出的登录邮件拦截在 Web 界面上点击登录,思路非常干脆漂亮!在这篇收官重制版中,我们对 2024 年原稿进行了二进制级的文本体检,结果在原稿的
docker-compose.yml代码块里揪出了一颗肉眼完全看不见、但谁复制粘贴谁当场报错的U+00A0(不换行空格)隐形炸弹,修正了末尾命令缺失参数的笔误,并将整套架构升级为 2026 免docker build的官方 All-in-One (AIO) + Mailpit 现代化方案。
一、 2024 原稿 (CID: 55) 四大错误筛查与勘误表
我们先调出 2024 年原稿里的几个关键片段:
# 2024 原稿 (CID: 55) 第 151~155 行启动服务命令:
mkdir /home/hoppscotch-aio
cp /root/docker-compose.yml # ❌ 错误 1:cp 只写了源文件,漏掉了目标路径!且下一行未 cd 进入目录!
docker compose up -d
# 2024 原稿 (CID: 55) 第 85~107 行 docker-compose.yml(注意缩进里藏着肉眼不可见的 U+00A0!):
services:
hoppscotch:
image: local/hoppscotch:24.09.01
...
environment:
- DATA_ENCRYPTION_KEY=******************************** # 加密密钥,可输入随机字符串替换,如不替换这么写也可以
我们来逐条剖析原稿中的四处问题:
| 编号 | 2024 原稿 (CID: 55) 写法 |
真实执行后果与底层原因 | 2026 Remastered 精确勘误与升级 |
|---|---|---|---|
1. docker-compose.yml 混入 U+00A0 不换行空格(隐形杀手!) |
原稿第 86~144 行 YAML 的前导缩进与行尾 # 注释前,混入了大量 UTF-8 编码为 \xc2\xa0(U+00A0 Non-Breaking Space,常见于从富文本编辑器或网页复制代码时产生) |
在浏览器里看和普通空格(0x20)一模一样,但 YAML 规范只允许使用标准 ASCII 0x20 空格作为缩进!读者只要从博客上直接复制这段 YAML 粘贴进服务器跑 docker compose up -d,会当场报错:yaml: line 4: found character that cannot start any token! |
将整份 YAML 100% 清洗为纯净的 ASCII 0x20 两空格缩进,并移除 Docker Compose v2 已废弃的顶层 version: "2.1" 声明 |
2. 第 153 行 cp 漏写目标路径且未切换工作目录 |
mkdir /home/hoppscotch-aiocp /root/docker-compose.ymldocker compose up -d |
1) cp /root/docker-compose.yml 缺少第二个参数(目标路径),终端当场报错 cp: missing destination file operand after '/root/docker-compose.yml';2) 紧接着未执行 cd /home/hoppscotch-aio,导致 docker compose up -d 在当前目录找不到配置文件 |
修正为:mkdir -p /home/hoppscotch-aio && cd /home/hoppscotch-aiomv /root/docker-compose.yml ./ && docker compose up -d |
3. DATA_ENCRYPTION_KEY 使用 32 个 * 号硬编码 |
- DATA_ENCRYPTION_KEY=******************************** # 如不替换这么写也可以 |
DATA_ENCRYPTION_KEY 是 Hoppscotch 用于在 PostgreSQL 数据库中用 AES 算法加密存储团队所有 生产 API Token、Bearer 密钥与环境变量 的主密钥(要求恰好 32 字符)。如果内网直接用 32 个星号,任何能接触到数据库备份的人都能用全星号直接解密出所有研发的私密接口凭证! |
严禁使用全星号!在部署前通过 openssl rand -hex 16 一行命令生成高熵随机 32 字符十六进制密钥 |
4. 依赖停更的第三方仓库手工 docker build |
克隆 2023 年停更的 webysther/hoppscotch-docker 仓库,手改 NODE_VERSION 后在本地漫长 docker build |
构建耗时极长且极易因 Alpine / Node.js 依赖源变动而构建失败;其实 Hoppscotch 官方现已推出原生的 hoppscotch/hoppscotch All-in-One (AIO) 镜像,开箱即用无需本地编译! |
直接采用官方 hoppscotch/hoppscotch AIO 镜像(配合 ENABLE_SUBPATH_BASED_ACCESS=true 单端口模式)与轻量级 Go 邮件捕获器 axllent/mailpit |
二、 2026 升级版:免本地 docker build 的内网 Hoppscotch + Mailpit 极速编排方案
在 2026 年,我们不再需要去克隆第三方仓库改 Dockerfile 编译半小时了:
- 官方 AIO 镜像(
hoppscotch/hoppscotch):官方已将前端界面(:3000)、Admin 管理后台(:3100)、后端 GraphQL/REST 服务(:3170)以及开启ENABLE_SUBPATH_BASED_ACCESS=true后的统一 80 端口Caddy 反代全部打包进了同一个官方镜像; - 用
axllent/mailpit替代年久失修的mailcatcher:原稿使用的dockage/mailcatcher基于老旧 Ruby 环境且多年未更新;现代内网测试环境统一使用基于 Go 语言单二进制编写的axllent/mailpit(内存占用不到 15MB,自带 WebSocket 实时收信界面,同样监听1025SMTP 与8025/1080Web 端口)。
1. 一键生成纯净无 U+00A0 污染的 docker-compose.yml
在你的内网服务器(假设内网 IP 为 192.168.0.66)上执行以下脚本,自动生成随机 32 位加密主密钥与标准 Compose 配置:
#!/usr/bin/env bash
set -Eeuo pipefail
DEPLOY_DIR="/opt/hoppscotch-aio"
HOST_IP="192.168.0.66"
# 自动生成 32 字符高强度随机密钥(彻底告别 32 个星号!)
ENCRYPT_KEY=$(openssl rand -hex 16)
DB_PASS=$(openssl rand -hex 12)
sudo mkdir -p "${DEPLOY_DIR}/postgres_data"
cd "$DEPLOY_DIR"
cat << EOF | sudo tee docker-compose.yml > /dev/null
services:
hoppscotch-db:
image: postgres:16-alpine
container_name: hoppscotch-db
restart: unless-stopped
environment:
POSTGRES_DB: hoppscotch
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${DB_PASS}
volumes:
- ./postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d hoppscotch"]
interval: 5s
timeout: 5s
retries: 5
mailpit:
image: axllent/mailpit:latest
container_name: hoppscotch-smtp
restart: unless-stopped
ports:
- "1025:1025" # SMTP 接收端口
- "1080:8025" # 内网 Web 邮件查看界面: http://${HOST_IP}:1080
hoppscotch:
image: hoppscotch/hoppscotch:latest
container_name: hoppscotch-aio
restart: unless-stopped
depends_on:
hoppscotch-db:
condition: service_healthy
mailpit:
condition: service_started
ports:
- "80:80"
environment:
DATABASE_URL: postgresql://postgres:${DB_PASS}@hoppscotch-db:5432/hoppscotch
# 开启单端口子路径访问模式(自动通过 80 端口挂载工作台与 /admin 后台)
ENABLE_SUBPATH_BASED_ACCESS: "true"
DATA_ENCRYPTION_KEY: "${ENCRYPT_KEY}"
JWT_SECRET: "${ENCRYPT_KEY}"
SESSION_SECRET: "${ENCRYPT_KEY}"
TOKEN_SALT_COMPLEXITY: "10"
MAGIC_LINK_TOKEN_VALIDITY: "3"
REFRESH_TOKEN_VALIDITY: "604800000"
ACCESS_TOKEN_VALIDITY: "86400000"
ALLOW_SECURE_COOKIES: "false" # 纯内网 HTTP 环境必须设为 false,否则登录后无法保存 Cookie!
redirect_url: "http://${HOST_IP}"
WHITELISTED_ORIGINS: "http://${HOST_IP},http://localhost"
VITE_BASE_URL: "http://${HOST_IP}"
VITE_SHORTCODE_BASE_URL: "http://${HOST_IP}"
VITE_ADMIN_URL: "http://${HOST_IP}/admin"
VITE_BACKEND_GQL_URL: "http://${HOST_IP}/backend/graphql"
VITE_BACKEND_WS_URL: "ws://${HOST_IP}/backend/graphql"
VITE_BACKEND_API_URL: "http://${HOST_IP}/backend/v1"
VITE_ALLOWED_AUTH_PROVIDERS: "EMAIL"
MAILER_SMTP_ENABLE: "true"
MAILER_USE_CUSTOM_CONFIGS: "true"
MAILER_ADDRESS_FROM: "[email protected]"
MAILER_SMTP_HOST: "mailpit"
MAILER_SMTP_PORT: "1025"
MAILER_SMTP_SECURE: "false"
MAILER_TLS_REJECT_UNAUTHORIZED: "false"
EOF
echo "[✓] Pure ASCII docker-compose.yml generated in ${DEPLOY_DIR}"
[!IMPORTANT]
纯内网 HTTP 部署最容易踩的 Cookie 坑(ALLOW_SECURE_COOKIES: "false"):
在现代 Hoppscotch 官方镜像中,默认开启了ALLOW_SECURE_COOKIES=true(即给登录 Session Cookie 打上Secure标志)。如果你在内网直接通过http://192.168.0.66(非 HTTPS)访问,浏览器会直接拒绝存储带有Secure标志的 Cookie,表现为点击邮件里的 Magic Link 显示登录成功,但跳回首页依然是未登录状态!因此在纯 HTTP 内网环境下,务必显式加上ALLOW_SECURE_COOKIES: "false"!
2. 执行数据库迁移并启动服务
cd /opt/hoppscotch-aio
# 1. 先拉起 PostgreSQL 与 Mailpit
sudo docker compose up -d hoppscotch-db mailpit
# 2. 首次部署执行 Prisma 数据库表结构初始化迁移
sudo docker compose run --rm hoppscotch pnpm --filter @hoppscotch/backend prisma migrate deploy
# 3. 正式启动 Hoppscotch All-in-One 服务
sudo docker compose up -d
启动后:
- 打开
http://192.168.0.66/admin输入任意内网邮箱(如[email protected])点击发送 Magic Link; - 打开
http://192.168.0.66:1080(Mailpit 实时收件箱),秒级收到登录邮件,点击链接即可直接成为内网 Hoppscotch 的超级管理员!
三、 十二篇「来时路 · 2026 重制版」全卷结语
从 2019 年第 1 篇 《Haproxy+Keepalived搭建》(CID: 3),到 2024 年第 12 篇 《使用docker部署内网hoppscotch》(CID: 55):
| 序号 | 历史原稿 (CID) 与发布年份 |
2026 重制版 (CID) |
核心勘误与技术升维亮点 |
|---|---|---|---|
01/12 |
CID: 3 (2019-05)《Haproxy+Keepalived搭建》 |
CID: 59 |
修正 track_interface 无法感知进程假死,实测 Debian 13 双机 VIP 漂移 |
02/12 |
CID: 12 (2019-12)《一键生成SSL证书》 |
CID: 60 |
解决缺失 subjectAltName (SAN) 导致现代浏览器 ERR_CERT_COMMON_NAME_INVALID |
03/12 |
CID: 16 (2019-12)《Mongodb未授权访问漏洞修复》 |
CID: 71 |
勘误 JS 注释语法与漏重启,剖析 authSource 与 Docker -p 绕过防火墙陷阱 |
04/12 |
CID: 20 (2019-12)《引导,分区与系统安装拓展》 |
CID: 72 |
修正 \EFI\Microsoft\Boot\BCD 路径,解密 Win7 UEFI 卡 Logo 的 INT 10h 真相 |
05/12 |
CID: 27 (2019-12)《Typecho更换域名与Let's Encrypt证书》 |
CID: 61 |
修正 REPLACE 漏写 https://、PHP serialize() 偏移量崩坏与 certbot revoke 误区 |
06/12 |
CID: 32 (2020-04)《CentOS 6升级openssl》 |
CID: 73 |
勘误 cd *.tar.gz、{, .bak} 空格与 apps/ 目录名,给出 -Wl,-rpath 隔离编译 |
07/12 |
CID: 34 (2020-08)《CentOS 6 rabbitmq-server无法启动》 |
CID: 74 |
揪出 ls -al 中漏修的 root:root mnesia 目录,详解 .erlang.cookie 0400 铁律 |
08/12 |
CID: 37 (2020-08)《通过inotify实时转移文件脚本》 |
CID: 65 |
复现 -e close 只读误触发跨盘 mv 截断抓包,实测 AppArmor -z gzip + close_write |
09/12 |
CID: 44 (2020-11)《禁止使用ip访问页面的方法》 |
CID: 75 |
勘误 Apache RewriteRule 死循环与软 404,升级 ssl_reject_handshake 零证书泄露 |
10/12 |
CID: 45 (2020-12)《MAC环境下rar的安装与命令行使用方法》 |
CID: 76 |
勘误 -p 与 -hp 加密范围写反、修正 rebulid. 笔误,适配 Apple Silicon 与防泄密 |
11/12 |
CID: 53 (2022-11)《Nginx限流策略》 |
CID: 69 |
勘误 $server_name 全站连坐与非标 512 状态码,实测 429 与 geo/map 空 Key 白名单 |
12/12 |
CID: 55 (2024-11)《使用docker部署内网hoppscotch》 |
CID: 77 |
清除 YAML U+00A0 隐形空格炸弹与 cp 缺参,升级官方 AIO 免编译 + ALLOW_SECURE_COOKIES |
十二篇原稿,十二座里程碑,至此 100% 严丝合缝、圆满收官!✨