r.RunTLS()是最简HTTPS启动方式,但要求fullchain.pem证书链完整、privkey.pem私钥无密码且权限0600、端口如8443避免root依赖,路径须可读,HTTP重定向需另起服务。

直接用 r.RunTLS() 就能跑 HTTPS,但证书路径、私钥权限、端口权限这三处错一个,服务就起不来——而且往往不报明确错误,只卡在启动或连接拒绝。
用 RunTLS 启动 HTTPS 的最小可行配置
这是开发和轻量部署最快的方式,封装了底层 http.ListenAndServeTLS,但要求严格:
-
r.RunTLS(":443", "fullchain.pem", "privkey.pem")两个文件参数必须是非空字符串,不能是""或nil,否则 panic 报tls: failed to find any PEM data in certificate input - 证书必须是 PEM 格式;若你手头是
.pfx或.p12,先用 openssl 转换:openssl pkcs12 -in cert.pfx -clcerts -nokeys -out fullchain.pem和openssl pkcs12 -in cert.pfx -nocerts -nodes -out privkey.pem - 私钥不能有密码保护,否则
RunTLS会直接崩溃 - 开发时别硬扛
:443,改用:8443避免要 root 权限;上线前再切回
fullchain.pem 和 cert.pem 到底该用哪个?
浏览器报 NET::ERR_CERT_AUTHORITY_INVALID 多半是因为证书链不全。Let’s Encrypt 等 CA 发的证书通常分三部分:域名证书 + 中间 CA 证书 + 根 CA(根一般已内置)。cert.pem 往往只含域名证书,而 fullchain.pem 是域名证书拼接中间证书的结果。
- 务必用
fullchain.pem(不是cert.pem),否则客户端无法构建信任链 - 合并方法很简单:
cat domain.crt intermediate.crt > fullchain.pem - 验证是否完整:用
openssl crl2pkcs7 -nocrl -certfile fullchain.pem | openssl pkcs7 -print_certs -noout查看是否输出多张证书
Linux 下私钥权限为 0644 会导致静默失败
Go 的 TLS 库对私钥文件权限极其敏感。即使文件存在、内容正确,只要权限不是 0600,就会拒绝加载,并给出误导性错误:tls: private key does not match public key(实际根本没读到私钥)。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
立即学习“go语言免费学习笔记(深入)”;
- 修复命令:
chmod 0600 privkey.pem - 检查命令:
ls -l privkey.pem,确认输出类似-rw------- 1 user user ... privkey.pem - CI/CD 或容器部署时容易忽略这点——镜像构建阶段就得设好权限,不能靠启动脚本临时 chmod
HTTP 自动跳转 HTTPS 必须起第二个服务
r.RunTLS() 只监听 HTTPS 端口,完全不管 HTTP 请求。用户访问 http://example.com 不会自动跳转,而是连接超时或被拦截。
- 必须额外起一个纯 HTTP 服务监听
:80(或开发用:8080),用http.Redirect返回 301 - 关键点:跳转 URL 要复用原请求的
Host和完整Path + Query,不能写死域名;示例:http.Redirect(w, r, "https://"+r.Host+r.RequestURI, http.StatusMovedPermanently) - 用 goroutine 异步启动它,避免阻塞主 HTTPS 服务:
go func() { http.ListenAndServe(":80", redirectHandler) }() - 注意:Nginx / ALB / CLB 等前置代理已做跳转时,这里无需重复实现,否则可能形成跳转循环
最易被忽略的是证书路径的运行时上下文——"./cert.pem" 在 IDE 里能跑,在 systemd 里常因工作目录不同而打不开;上线前务必用 filepath.Abs() 拼绝对路径,并加 os.Stat 校验。

















