一、为什么需要 Vanity Import
在 Go 项目中,我们通常会引用公司内部 Git 仓库的模块:
import "code.example.com/common/util"但 Go 在拉取模块时,必须知道这个 import path 对应的真实仓库地址。
如果不做任何处理,go get 会直接访问该域名,却拿不到仓库信息。
通过 Nginx + Go Vanity Import 机制,我们可以:
隐藏真实 Git 仓库地址
统一公司内部 Go 模块命名规范
让其他项目组透明引用,无需关心底层 Git 地址
二、服务端原理简述
Go 工具链在拉取模块时,会访问:
https://code.example.com/common/util?go-get=1如果返回的 HTML 中包含如下 <meta> 标签:
<meta name="go-import"
content="code.example.com/common/util git https://git.example.com/team/util.git">Go 就会自动执行:
git clone https://git.example.com/team/util.git三、服务端 Nginx 完整配置(可直接复制)
HTTP → HTTPS 强制跳转
# ============================================================
# HTTP → HTTPS
# ============================================================
server {
listen 80;
server_name code.example.com;
return 301 https://$host$request_uri;
}模块映射表
# ============================================================
# 模块映射表 —— 用 $uri(不含查询参数)
# ============================================================
map $uri $go_vcs_prefix {
/common/util "code.example.com/common/util git https://git.example.com/team/util.git";
/sdk/logger "code.example.com/sdk/logger git https://git.example.com/team/logger.git";
}HTTPS 主服务
# ============================================================
# HTTPS 主服务
# ============================================================
server {
listen 443 ssl;
server_name code.example.com;
# 证书路径
ssl_certificate /etc/nginx/cert/example.com/cert.crt;
ssl_certificate_key /etc/nginx/cert/example.com/cert.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# ---- Go Vanity Import(核心) ----
location ~ ^/(common|sdk)/[^/]+$ {
if ($go_vcs_prefix = "") {
return 404;
}
default_type text/html;
return 200 '<!DOCTYPE html>
<html>
<head>
<meta name="go-import" content="$go_vcs_prefix">
</head>
<body>Go Module Redirect</body>
</html>';
}
# ---- 根路径健康检查 ----
location = / {
return 200 'Go module vanity import server\n';
}
# ---- 其他全部 404 ----
location / {
return 404;
}
}四、客户端需要哪些配置(重点)
告诉 Go 这是私有模块(必须)
如果不配置,Go 会尝试走公共代理(如 proxy.golang.org),导致拉取失败。
go env -w GOPRIVATE="code.example.com"效果:
不走公共 proxy
不走 checksum 校验(避免
sum.golang.org报错)
确保 Git 能访问真实仓库
Vanity Import 只负责“指路”,最终仍然由 Git 拉取代码。
方式一:SSH(推荐)
git config --global url."git@example.com:team/".insteadOf "https://git.example.com/team/"方式二:HTTPS + Token
git config --global url."https://<token>@git.example.com/team/".insteadOf "https://git.example.com/team/"在项目中引用模块
import "code.example.com/common/util"go get code.example.com/common/util五、验证是否生效
curl https://code.example.com/common/util?go-get=1应返回:
<meta name="go-import"
content="code.example.com/common/util git https://git.example.com/team/util.git">六、常见问题
为什么一定要配置 GOPRIVATE?
因为 Go 默认会尝试通过公共代理拉取模块,私有模块必须显式声明。
能否支持子模块?
支持,只要仓库结构一致即可:
import "code.example.com/common/util/subpkg"一个 import path 能对应多个仓库吗?
不建议,Go 以模块根路径为准。
七、完整配置如下
# ============================================================
# HTTP → HTTPS
# ============================================================
server {
listen 80;
server_name code.example.com;
return 301 https://$host$request_uri;
}
# ============================================================
# 模块映射表 —— 用 $uri(不含查询参数)
# ============================================================
map $uri $go_vcs_prefix {
/common/util "code.example.com/common/util git https://codeup.aliyun.com/697822a7cf8993734af2c8c3/util.git";
}
# ============================================================
# HTTPS 主服务
# ============================================================
server {
listen 443 ssl;
server_name code.example.com;
#证书路径
ssl_certificate /usr/local/nginx/cert/example.com/cert.crt;
#私钥路径
ssl_certificate_key /usr/local/nginx/cert/example.com/cert.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# ---- Go Vanity Import(核心) ----
# 匹配 /common/xxx 和 /sdk/xxx(不含子路径)
location ~ ^/(common|sdk)/[^/]+$ {
# 没匹配到映射表的,直接 404
if ($go_vcs_prefix = "") {
return 404;
}
default_type text/html;
return 200 '<!DOCTYPE html>
<html>
<head>
<meta name="go-import" content="$go_vcs_prefix">
</head>
<body>Go Module Redirect</body>
</html>';
}
# ---- 根路径 ----
location = / {
return 200 'Go module vanity import server\n';
}
# ---- 其他全部 404 ----
location / {
return 404;
}
}八、总结
通过这套方案,你可以:
用 Nginx 实现一个轻量级 Go Module 路由层
统一内部模块命名
让多个项目组无感知引用
服务端集中维护,客户端配置简单