构建内网离线的"github.com",完美解决内网Go开发依赖

本文提供一种方案解决在离线的内网环境下搭建相同域名私有"github.com"服务,用于解决内网离线场景下 Go 语言编译构建依赖问题, 让您的内网 DevOps 实践更加完善。

对于其他语言的依赖一般可以通过修改配置文件的的方式调整为内部私有的仓库,但是Go语言比较特殊,Go 项目依赖通过 import 直接从网络导入。

go 复制代码
import "github.com/google/uuid"

对于可以访问互联网的开发/CI环境还可以通过配置 GOPROXY='https://goproxy.cn,direct' 来加速国内访问,但是对于内网离线环境则网络不通

内网离线Go开发常见的解决方案:

  • 通过 vendor 模式进行缓存。但对于离线环境的项目开发过程中,会动态的新增很多新的功能和依赖,引入的依赖包还可能再依赖。这种情况下想缓存到 vendor 耗时很长,研发效率极低,无法进行自动化CI/CD。并且 vendor 目录会使项目体积变得非常大,因为包含了所有依赖的源代码。
  • 修改 go.mod 文件,使用 replace 进行替换。但是依赖的开源项目还会有新依赖,go mod 动态更新的 mod 文件导致维护难度极大,效率也极低。

期望有一种解决方案能够实现如下能力:

  • 由运维团队统一搭建Go基础设施和服务,研发人员和CI/CD环境不需要关注服务提供的细节
  • 运维人员从互联网上进行定期的同步更新,增量离线同步到公司内网,保持代码的时效性
  • 研发人员和CI/CD环境只需要几行配置即可实现和互联网一致的开发体验,甚至性能和延迟更好

本文提供一种解决方案,主要有以下几个步骤:

  1. 搭建私有代码仓库,定时增量同步源仓库
  2. 制作github.com域名证书
  3. 配置github.com nginx服务
  4. 配置DNS解析
  5. 修改客户端配置忽略证书告警
  6. 验证代码拉取
  7. 验证go mod 依赖拉取
  8. 解决非github.com域名重定向的代码仓库

1.搭建私有代码仓库

搭建私有的代码仓库服务是提供github.com的基础,它提供了核心的代码同步、存储、下载的功能,你可以选择任意你熟悉的私有代码仓库软件,比如 Gitlab、Gitea、Gogs 等。

本文以 Gitea 为例,使用 Docker Compose 来部署

yaml 复制代码
services:
  gitea:
    image: harbor.cncfstack.com/docker.io/gitea/gitea:1.21.1
    container_name: gitea
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=postgres
      - GITEA__database__HOST=1.2.3.4:5432
      - GITEA__database__NAME=aaa
      - GITEA__database__USER=bbb
      - GITEA__database__PASSWD=ccc
      - TLSMinVersion=TLSv1.2
    restart: always
    volumes:
      - /data/gitea-data/git:/data/git
      - /data/gitea-data/gitea:/data/gitea
      - /data/gitea-data/ssh:/data/ssh
      - /etc/timezone:/etc/timezone:ro
      - /etc/localtime:/etc/localtime:ro
      - ./app.ini:/data/gitea/conf/app.ini:ro
    ports:
      - "3000:3000"
      - "22:10022"

对于运行依赖的数据库也可以使用 docker-compose 来部署,对于 app.ini 配置文件可以参考官网的配置或者不挂载使用默认的配置也可以。

2.制作github.com域名证书

在上一篇文章 《一张图了解HTTPS证书的CA、签发、校验和数据加密流程。详解OpenSSL自签证书,并封装自动化脚本》 中详细介绍了如何制作自签名证书。

使用文章中提供的自动化脚本 make_https_crt.sh 来创建自签名证书,需要特别注意的是需要制作 github.com 的证书。

在整理上一篇文章时,我已经制作好了github.com的证书。

bash 复制代码
#./make_https_crt.sh github.com

  域名私钥: /tmp/aa/github.com/github.com.key
  域名公钥: /tmp/aa/github.com/github.com.pem
  域名证书请求文件: /tmp/aa/github.com/github.com.csr
  域名证书: /tmp/aa/github.com/github.com.crt

......

3.配置github.com nginx服务

Gitea 启动后不直接对外提供服务,而是通过一个 Nginx 来进行代理。这样做主要是为了更好的控制一些配置,比如:证书、跨域等问题。

这样的话可以添加 github.com 的虚拟主机以及对应的自签名证书。

Nginx 最简配置如下:

bash 复制代码
server {
    listen 443 ssl;
    server_name github.com;
    ssl_certificate /tmp/aa/github.com/github.com.crt;
    ssl_certificate_key /tmp/aa/github.com/github.com.key;
    location / {
        proxy_pass   http://gitea:3000;
    }
}

4.配置DNS解析

在搭建完成私有代码仓库服务后,需要将 github.com 添加到 DNS 解析中,这样私有的 "github.com" 才能提供服务。

对于公司级别的服务,建议在公司或者机房的统一DNS服务器中添加解析。

对于少量机器或个人设备可以添加到 hosts 文件中

  • 对于Windows设备修改文件路径
bash 复制代码
C:\Windows\System32\drivers\etc\hosts

对于 Linux/Mac 修改文件路径

bash 复制代码
/etc/hosts

如下是藏云阁的DNS配置,可以作为国内代码拉取的配置,合法证书的入口地址为 gitea.cncfstack.com。如果缺少对应的代码仓库,可创建自动同步的仓库。

复制代码
120.55.240.206 github.com

5.修改客户端配置忽略证书告警

在上面步骤中,已经搭建好了私有 "github.com" 的服务,但由于 https 的证书是自签名的,所以需要配置忽略证书验证。

提示:如果有运维团队维护企业私有的CA自签的证书,该CA可预置到所有的节点,那么可以忽略当前步骤。

以下提供了3种方法来忽略证书,内网离线环境推荐使用方法3配置全局忽略验证。

  • 方法1: 对于一次性的克隆操作,你可以选择临时忽略证书验证:

使用环境变量,在克隆命令前设置 GIT_SSL_NO_VERIFY 环境变量。

bash 复制代码
GIT_SSL_NO_VERIFY=true git clone https://github.com/user/project.git
  • 方法2: 使用Git配置参数:在克隆时通过 -c 参数临时禁用SSL验证。
bash 复制代码
git -c http.sslVerify=false clone https://github.com/user/project.git
  • 方法3: 配置全局忽略验证

如果确实需要,可以使用以下命令:

bash 复制代码
git config --global http.sslVerify false

6.验证代码拉取

没有添加证书安全忽略时克隆下载代码会提示 SSL certificate problem 如下错误:

bash 复制代码
% git clone https://github.com/google/uuid
Cloning into 'uuid'...
fatal: unable to access 'https://github.com/google/uuid/': SSL certificate problem: unable to get local issuer certificate

由于是自签名的证书,添加证书忽略后,可以拉取成功。

bash 复制代码
% git -c http.sslVerify=false clone https://github.com/google/uuid
Cloning into 'uuid'...
remote: Enumerating objects: 604, done.
remote: Counting objects: 100% (604/604), done.
remote: Compressing objects: 100% (236/236), done.
remote: Total 604 (delta 368), reused 577 (delta 359), pack-reused 0
Receiving objects: 100% (604/604), 181.49 KiB | 4.43 MiB/s, done.
Resolving deltas: 100% (368/368), done.

7. 验证go mod依赖拉取

准备一个简单的 Go 代码,并且有一个依赖项,这里选择 Google 的 uuid 包。

golang 复制代码
package main

import (
    "fmt"
    "github.com/google/uuid"
)

func main() {
    uuidV4 := uuid.New()
    fmt.Println("UUID v4:", uuidV4)
}

默认的使用 go mod tidy 时会有以下的请求路径

  • 步骤1. 电脑执行 go mod tidy 或者 go get github.com/google/uuid
  • 步骤2. 访问 goproxy 获取代码 :proxy.golang.org/github.com/...
  • 步骤3. 访问sum.golang.org校验哈希

这个步骤在内网离线会有以下几个问题

问题1: github.com 证书校验不通过

提示 SSL certificate problem异常

bash 复制代码
/go/test # go mod tidy
go: finding module for package github.com/google/uuid
go: main imports
	github.com/google/uuid: module github.com/google/uuid: git ls-remote -q origin in /go/pkg/mod/cache/vcs/c3a7687c436b44e1c0c389b1d5515300d44b6949685144fd082c00abc5f758a4: exit status 128:
	fatal: unable to access 'https://github.com/google/uuid/': SSL certificate problem: unable to get local issuer certificate

需要添加git证书忽略。

bash 复制代码
git config --global http.sslVerify false

问题2: 内网无法访问 goproxy

Go 1.13+ 默认启用 GOPROXY=https://proxy.golang.org,direct,内网无法访问 goproxy

bash 复制代码
github.com/google/uuid: module github.com/google/uuid: Get "https://proxy.golang.org/github.com/google/uuid/@v/list": dial tcp 142.250.73.145:443: i/o timeout

可以通过设置direct直接访问 github.com

bash 复制代码
go env -w GOPROXY=direct

问题3: 内网无法访问 sum.golang.org

访问sum.golang.org校验哈希,内网也是网络不通

bash 复制代码
/go/test # go get github.com/google/uuid
go: downloading github.com/google/uuid v1.6.0
go: github.com/google/uuid@v1.6.0: verifying module: github.com/google/uuid@v1.6.0: Get "https://sum.golang.org/lookup/github.com/google/uuid@v1.6.0": dial tcp 142.251.34.209:443: i/o timeout

可以通过关闭 GOSUMDB 来跳过校验

bash 复制代码
go env -w GOSUMDB=off

完整的执行过程

开发人员或CI/CD环境,通过添加如下3行配置即可完成依赖拉取

bash 复制代码
go env -w GOSUMDB=off
go env -w GOPROXY=direct
git config --global http.sslVerify false

示例基于一个全新的 golang 容器镜像,运行结果如下:

bash 复制代码
% docker run -it --rm  harbor.cncfstack.com/docker.io/library/golang:1.25.2-alpine3.22 /bin/sh

/go # apk add git &> /dev/null
/go # echo '120.55.240.206 github.com' >> /etc/hosts
/go # cat /etc/hosts |grep github.com
120.55.240.206 github.com
/go # mkdir demo && cd demo
/go/demo # cat > main.go <<EOF
> package main
>
> import (
>     "fmt"
>     "github.com/google/uuid"
> )
>
> func main() {
>     uuidV4 := uuid.New()
>     fmt.Println("UUID v4:", uuidV4)
> }
> EOF
/go/demo # go env -w GOSUMDB=off
/go/demo # go env -w GOPROXY=direct
/go/demo # git config --global http.sslVerify false
/go/demo # go mod init main
go: creating new go.mod: module main
go: to add module requirements and sums:
	go mod tidy
/go/demo # go mod tidy
go: finding module for package github.com/google/uuid
go: downloading github.com/google/uuid v1.6.0
go: found github.com/google/uuid in github.com/google/uuid v1.6.0
/go/demo # go run main.go
UUID v4: 8f166ed5-af61-46cd-ad03-08de12cfe4da

8. 解决非github.com域名重定向的代码仓库

有些 Go 代码的依赖源代码会通过非 "github.com" 的域名进行访问,比如 "golang.org"、"gopkg.in"、"go.uber.org" 等。

对于这些域名基本上后端的代码仓库依然是 github.com,只是做了域名的重定向调整了URL路径。解决方法是配置代理重定向到github.com即可。

即使后端不是github.com的域名,比如gitlab.com,也可以通过上述类似的方法建立对应的代码仓库,然后通过代理重定向到对应的代码仓库解决。

总结

本文提供了一种企业级的内网 Go 语言依赖拉取解决方案,可由运维人员统一维护服务,研发人员和CI/CD环境只需要3行配置即可实现内网 Go 开发自由。

虽然收集和同步代码仓库以及维护重定向的域名配置列表是个费时费力的人力工作,但是一旦完成,后续的代码依赖拉取管理就非常轻松了。

如果选择藏云阁提供服务,则这些费时费力的人力工作则不需要了,因为藏云阁已经完成了大量的代码仓库的收集和同步,以及域名重定向的配置维护,企业直接内网落地即可。

相关推荐
逛逛GitHub9 小时前
国产首个开源 AI 原生后端平台,这次是真起飞了。
后端·github
utmhikari11 小时前
【GitHub探索】代码开发AI辅助工具trae-agent
人工智能·ai·大模型·llm·github·agent·trae
咖啡の猫11 小时前
Vue-github 用户搜索案例
前端·vue.js·github
掘金安东尼12 小时前
🧭 前端周刊第428期(2025年10月28日–11月3日)
前端·github
散峰而望12 小时前
C语言刷题(一)
c语言·开发语言·编辑器·github·visual studio
CoderJia程序员甲13 小时前
GitHub 热榜项目 - 日榜(2025-11-02)
ai·开源·大模型·github·ai教程
FinClip13 小时前
工行APP深夜惊魂!账户一夜清零,金融机构如何筑牢数字防火墙?
前端·javascript·github
我就是全世界13 小时前
告别手动部署!GitHub Workflow与Action完全指南:从零构建自动化CI_CD流水线
ci/cd·自动化·github
ruanCat13 小时前
在使用 changeset 时,如何在更新底部依赖时,触发上层依赖更新
前端·github