生产环境严禁直接使用 gin.Run(":8080"),必须通过 Nginx 反向代理;需绑定 127.0.0.1:8080、启用 gin.ReleaseMode、禁用默认 Logger/Recovery,并透传 X-Real-IP/X-Forwarded-Proto 等关键请求头。

直接上生产环境跑 gin.Run(":8080") 是危险的,必须用 Nginx 做反向代理——这不是可选项,是上线硬性前提。
确认 Gin 应用已绑定本地回环并禁用调试模式
生产部署时,gin.Default() 会默认启用 gin.Recovery() 和 gin.Logger(),但你还得手动关掉开发提示。否则 404 页面会暴露路由树,500 错误会打堆栈。
- 启动前加
gin.SetMode(gin.ReleaseMode),否则日志和错误页都带敏感信息 - 监听地址必须是
127.0.0.1:8080,不能写:8080或0.0.0.0:8080,避免被外网直连 - 如果用
r.Run("127.0.0.1:8080")启动失败,检查端口是否被占用:lsof -i :8080或ss -tuln | grep 8080
Nginx 配置里 proxy_pass 末尾斜杠决定路径重写行为
这是最常踩的坑:少一个 /,Gin 路由就全 404。Nginx 的 proxy_pass 对路径处理非常严格。
- 写成
proxy_pass http://127.0.0.1:8080;(无结尾斜杠)→ 请求/api/users会被原样转发到后端/api/users - 写成
proxy_pass http://127.0.0.1:8080/;(有结尾斜杠)→ 请求/api/users会被重写为/users,即去掉 location 前缀 - Gin 默认没做 prefix 路由分组,所以推荐用后者,并在 Gin 里统一加
r.Group("/api")显式管理,避免路径错位
必须透传关键请求头,否则 c.ClientIP() 和 HTTPS 判断失效
Gin 的 c.ClientIP()、c.Request.TLS、c.Request.URL.Scheme 在 Nginx 反代后默认不可靠,不配 header 就会返回 127.0.0.1 或空 Scheme。
-
proxy_set_header X-Real-IP $remote_addr;→ 让c.ClientIP()拿到真实 IP -
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;→ 兼容多层代理链 -
proxy_set_header X-Forwarded-Proto $scheme;→ 确保c.Request.URL.Scheme是https而不是http - 别漏掉
proxy_set_header Host $host;,否则 Gin 中c.Request.Host可能变成127.0.0.1:8080
systemd 管理 Gin 二进制时,WorkingDirectory 和 Restart 策略要设对
Go 编译出的单二进制看似简单,但 systemd 不设好工作目录,静态文件读取、日志写入、配置加载全崩。
-
WorkingDirectory必须指向二进制所在目录,否则os.ReadFile("config.yaml")会报no such file -
Restart=always+RestartSec=5是基础保障,但别用Restart=on-failure——Gin 启动失败(比如端口占用)不会触发重启 - 加
KillSignal=SIGTERM,让 Gin 能优雅关闭(gin.Engine支持Shutdown()) - 检查服务状态用
systemctl status gin-app,看Active:是否为active (running),不是activating (auto-restart)
真正麻烦的从来不是写几行 Nginx 配置,而是 Gin 日志里突然冒出一堆 127.0.0.1 的 IP,或者前端发 /api/login,后端收不到请求——这时候你要翻的不是 Gin 文档,是 Nginx 的 access.log 和 error.log,确认 proxy_pass 是否命中、header 是否透传、连接是否被 reset。


















