mkcert 是最省事的本地可信证书方案,它在系统根证书库安装专用 CA 并签发 localhost 或自定义域名证书,Go 需用未加密 PEM 格式证书和私钥,客户端需手动加载 rootCA.pem 或禁用校验(仅开发)。
macOS 和 Windows 上直接信任自签名证书很麻烦,浏览器会持续报错;mkcert 是目前最轻量、最可靠的本地 CA 工具,它会在系统根证书库中安装一个仅用于本地的 CA,并用它签发 localhost 或自定义域名(如 dev.local)的证书,浏览器和 curl 都默认信任。
brew install mkcert(macOS),或从 GitHub releases 下载预编译二进制mkcert -install(需输入系统密码)mkcert localhost 127.0.0.1 ::1 → 输出 localhost.pem(证书)和 localhost-key.pem(私钥)http.ListenAndServeTLS(":8443", "localhost.pem", "localhost-key.pem", nil)
ListenAndServeTLS 不接受 PKCS#12(.pfx)、PEM 混合格式或带密码的私钥。必须是两个独立、未加密、标准 PEM 格式的文件:
.pem 或 .crt):以 -----BEGIN CERTIFICATE----- 开头,包含完整证书链(如需中间证书,需追加在服务器证书之后).pem 或 .key):以 -----BEGIN RSA PRIVATE KEY----- 或 -----BEGIN EC PRIVATE KEY----- 开头,且不能加密(即不能含 Proc-Type: 4,ENCRYPTED)openssl rsa -in key-encrypted.pem -out key-unencrypted.pem
当你的 Go 程序作为 HTTP 客户端调用另一个本地 HTTPS 服务(比如自己写的 backend)时,若对方证书是 mkcert 签发的,标准 http.Client 仍可能报 x509: certificate signed by unknown authority。这是因为 Go 默认只信任系统根证书,不读取 macOS Keychain / Windows Certificate Store 中的用户级 CA。
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}mkcert 的根证书(通常在 $(mkcert -CAROOT)/rootCA.pem)加入 Go 的 TLS 配置:rootCAs, _ := x509.SystemCertPool()
rootCAs.AppendCertsFromPEM(pemBytes) // pemBytes 是 rootCA.pem 内容
tr := &http.Transport{
TLSClientConfig: &tls.Config{RootCAs: rootCAs},
}InsecureSkipVerify: true 绝不能出现在生产代码里,CI/PR 检查应拦截该字符串想用 https://app.test:8443 调试?光改 Hosts 不够,证书也必须覆盖该域名。
echo "127.0.0.1 app.test" | sudo tee -a /etc/hosts
mkcert app.test localhost 127.0.0.1
mkcert CA,需手动导入 rootCA.pem
真正容易被忽略的是:Go 进程启动后不会自动重载证书文件,改了 .pem 必须重启服务;而浏览器可能缓存 OCSP 响应或证书吊销状
