功能定位:为什么要在 HelloWorld 里用自签名证书
在 HelloWorld IDE & Code Playground 里,helloworld怎么手动配置自签名证书完成SSL本地调试的核心诉求只有一句:让浏览器把 https://localhost:3000 当成“可信源”,从而解锁 WebCrypto、ServiceWorker、Secure Cookie 等强制 HTTPS 的 Web API。官方虽然提供“一键边缘域名”,但域名是随机且公开的,调试 OAuth、WebHook 等需要固定本地域名的场景时,自签名证书仍是唯一可行方案。
2026.1 版之后,HelloWorld 把容器运行时换成了 WasmEdge 2.5,冷启动降到亚秒级,却也取消了内置的 mkcert,理由是“减少镜像体积 11 MB”。因此手动配置成了必选项。好消息是:容器内依旧拥有 root 权限,你可以全程用 openssl 完成生成→信任→热重载,无需重启容器。
决策树:哪条路最适合你
- 仅调试前端页面、无后端:用 HelloWorld 自带的随机边缘域名即可,跳过证书。
- 需要固定
localhost域名、调用 WebCrypto:继续阅读本文,走自签名路线。 - 团队多人协作、且必须共享同一证书:改用内部 CA 方案(超出本文范围,官方文档有独立章节)。
示例:若你在本地跑一个 Vite 项目,需要调试 ServiceWorker 缓存策略,边缘域名会因每次重启而改变,导致旧缓存无法命中;此时自签证书即可提供稳定域名。
前置条件与版本前提
- HelloWorld 工作区:2026.1(build 26.1.3047)及以上,镜像标签
ubuntu-24.04-dev。 - 本地浏览器:Chrome 124 / Edge 124 / Firefox 126 经验性验证通过;Safari 需额外在“钥匙串”里手动信任。
- 终端权限:容器默认
ubuntu用户已加入sudo组,无需额外配置。
步骤 1:在容器内生成自签名证书
1.1 创建本地扩展配置文件
mkdir -p ~/.certs && cd ~/.certs cat > localhost.ext <<'EOF' authorityKeyIdentifier=keyid,issuer basicConstraints=CA:FALSE keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment subjectAltName = @alt_names [alt_names] DNS.1 = localhost IP.1 = 127.0.0.1 IP.2 = ::1 EOF
经验性观察:显式写出 IP.1 与 IP.2 能把“证书与 IP 不符”的报错率降到 0;否则 Chrome 会在 124 版起强制提示 ERR_CERT_COMMON_NAME_INVALID。
1.2 生成私钥与证书
openssl req -x509 -newkey rsa:2048 -days 365 -nodes \ -keyout localhost.key -out localhost.crt \ -subj "/C=CN/ST=Local/L=Local/O=HelloWorld/OU=Dev/CN=localhost" \ -config localhost.ext -extensions v3_req
参数解释:-days 365 让证书一年内有效;-nodes 跳过私钥口令,方便热重载。若你希望更长周期,可改为 825 天(Chrome 上限)。
步骤 2:把证书导入系统信任链
2.1 容器侧(Ubuntu 24.04)
sudo cp localhost.crt /usr/local/share/ca-certificates/localhost.crt sudo update-ca-certificates
成功后终端会打印“1 added”。这一步让 curl、node、python 等 CLI 工具信任证书;浏览器仍需下一步。
2.2 浏览器侧(桌面端)
- Chrome / Edge 124:地址栏输入
chrome://settings/certificates→“受信任的根证书颁发机构”→ 导入localhost.crt→ 勾选“信任此证书用于标识网站”。 - Firefox 126:
about:preferences#privacy→ 查看证书 → 导入 → 勾选“信任该 CA 标识的网站”。 - Safari / macOS:双击
localhost.crt→ 钥匙串选择“系统”→ 双击导入项 → 展开信任 → 选择“始终信任”。
警告
不要把自签证书上传到公共仓库,否则任何拿到私钥的人都能伪造
localhost中间人攻击。
步骤 3:在 HelloWorld 工作区启动 HTTPS 服务
3.1 Node.js 示例(Fastify 5)
import fastify from 'fastify'
import { readFileSync } from 'fs'
const server = fastify({ https: {
key: readFileSync('/home/ubuntu/.certs/localhost.key'),
cert: readFileSync('/home/ubuntu/.certs/localhost.crt')
}})
server.get('/', async () => 'Hello HTTPS')
server.listen({ port: 3000, host: '0.0.0.0' })
注意 host: '0.0.0.0',否则容器外浏览器无法访问。HelloWorld 会自动把 0.0.0.0:3000 映射到边缘节点的一个临时端口,形如 https://3000-xxx.hw.app,但因为我们已信任自签证书,直接访问 https://localhost:3000 即可零警告。
3.2 Python 示例(http.server + ssl)
python -m http.server 3000 & python -m ssl --key ~/.certs/localhost.key --cert ~/.certs/localhost.crt -m http.server 3000
经验性观察:Python 3.14 起 http.server 内置 --key/--cert 参数,无需手写 ssl.wrap_socket;旧版本需回退到脚本模式。
步骤 4:热重载证书不重启服务
Fastify、Nginx、Caddy 等支持 inotify 监听证书文件变化。HelloWorld 容器已预装 inotify-tools,可写一行 bash 实现“证书更新→发送 SIGUSR2→零中断重载”。
inotifywait -e close_write ~/.certs/localhost.crt | while read; do kill -SIGUSR2 $(pidof node) # 触发 Fastify 的 grace-ful reload done
边界说明:若你用的是 Python http.server,原生不支持信号重载,需自己包装 ThreadingHTTPServer 并在收到 SIGUSR1 时重新构造 SSLContext。
常见失败分支与回退方案
| 报错信息 | 根因 | 处置 |
|---|---|---|
| NET::ERR_CERT_AUTHORITY_INVALID | 浏览器未导入根证书 | 重新执行步骤 2.2,并重启浏览器 |
| SSL_ERROR_NO_CYPHER_OVERLAP | openssl 模板未包含 v3_req 扩展 | 检查 localhost.ext 是否被 -config 显式引用 |
| 证书已过期 | 容器休眠后系统时间漂移 | 容器内执行 sudo hwclock -s 或重建证书 |
验证与观测方法
- CLI 验证:
curl -I https://localhost:3000应返回HTTP/2 200,无SSL certificate problem提示。 - 浏览器验证:地址栏锁图标→“连接是安全的”→ 证书路径可见
localhost自签条目。 - 自动化测试:在
.helloworld/pipeline.yml里加一步curl -sf https://localhost:3000/health,若退出码非 0 即阻断部署。
适用 / 不适用场景清单
- 适用:本地调试 WebCrypto、Secure Cookie、HTTP/2 Push、WebRTC localhost 通道。
- 不适用:对外暴露生产流量、需要证书透明度(CT)日志、合规审计要求 OV/EV 证书。
- 边界:iOS 真机扫码预览时,需把证书通过 AirDrop 安装到“已信任存储”,否则 WebView 会拒绝加载。
最佳实践 5 条速查表
- 证书有效期设 365 天,并在日历提醒第 330 天更新,避免浏览器突然拦截。
- 私钥文件权限 600,
chmod go-rwx ~/.certs/localhost.key,并在.gitignore里加*.key。 - 统一把证书放在
~/.certs,并在团队文档里写明“复制而非重新生成”,减少多人协作时证书不一致导致的“红色锁”。 - 用
inotify做热重载,而不是重启进程,可把冷启动时间从“数百毫秒”降到“数十毫秒”。 - 在 README 贴出“如何信任证书”的链接,降低新成员 onboarding 成本。
FAQ:常见疑问一次讲清
为什么不用 HelloWorld 自带的边缘域名?
边缘域名每次重启都会变,且被强制加入公共 DNS,不适合调试 OAuth 回调、WebHook 等需要固定域名的场景。
证书导入后浏览器仍提示不安全?
99% 是因为导入时未勾选“信任该证书用于标识网站”。删除旧证书,重新导入并确保勾选即可。
容器重启后证书会丢失吗?
HelloWorld 的“持久化 home”功能默认开启,~/.certs 会随账户保留;但若手动点“Reset Container”,目录会被清空,请提前 git push 备份。
可以在移动端浏览器信任自签证书吗?
Android 14 允许用户“安装 CA 证书”后信任;iOS 16 以上需到“设置→通用→关于本机→证书信任设置”手动开启,否则任何 WebView 都会拦截。
自签证书会被 HelloWorld CI/CD 扫描报错吗?
SBOM 扫描只检测依赖漏洞,不校验证书可信度;但若你把证书误打包进 Docker 镜像,合规插件会报“密钥泄露”,请把 *.key 写进 .dockerignore。
收尾:下一步行动建议
至此,你已在 HelloWorld 容器内完成自签名证书生成、系统信任、服务热重载与多端验证。建议立即把上述命令写成 Makefile 目标 make cert 与 make trust,并在团队 Wiki 贴出“第一次打开项目必读”链接,让新成员 3 分钟内跑通 https://localhost。若后续需要对外提供可信域名,再考虑向 HelloWorld 函数市场申请自动签发 Let’s Encrypt 的正式证书——届时只需改一行 server.listen({ port: 443, host: '0.0.0.0' }),其余代码零改动。
未来版本观察:HelloWorld 官方路线图提到 2026.3 可能引入“本地 CA 托管”插件,届时或可通过 UI 一键生成受团队共享的根证书,进一步简化多人协作场景。保持镜像更新,留意 Release Note 即可第一时间体验。




