自建Nginx反向代理,彻底解决GitHub打不开与下载慢

发布时间:2026/11/3 20:59:57
自建Nginx反向代理,彻底解决GitHub打不开与下载慢

GitHub 日榜(2026-09-26)热词:github打不开、github使用教程、github镜像、github镜像网站、github加速。这四个热词背后的需求其实是同一件事——访问 GitHub 不稳定、速度慢,尤其代码拉取、Release 下载、Raw 文件访问这几个场景最让人抓狂。

作为一个常年泡在 GitHub 上的开发者,我太懂这种痛了。网络链路不稳定、跨境访问拥塞、部分域名被污染等因素叠加,导致 GitHub 的访问体验时好时坏。大家在网上搜“GitHub 镜像”“GitHub 加速”,搜到的方案五花八门,但很多都有隐患:有的是第三方代理,代码会经过别人的服务器;有的是浏览器插件,只对网页生效,git clone 依然慢成蜗牛;还有的是公共镜像站,带宽共享、随时可能挂,之前好几个知名公共镜像都陆续停止服务了。

与其依赖不稳定的公共方案,我决定自建一套轻量级的 GitHub 加速通道。核心思路很简单:用一台海外服务器做 Nginx 反向代理,把 git clone、Release 下载、Raw 文件读取的流量都导到自己的代理域名上。整套方案部署下来成本不到百元一年,跑了两个多月稳定得很。今天就把这套方案的完整思路、配置细节和踩坑记录分享出来。

1. 内容整体设计与思路拆解

1.1 先想清楚:你要加速的到底是什么

很多人一上来就搜“GitHub 镜像”,但镜像和加速是两回事。镜像站是把 GitHub 仓库完整同步到另一台服务器上,你直接访问镜像站的地址;而加速是在你访问 GitHub 的过程中,帮你优化网络路径,请求最终还是到达 GitHub 官方服务器。

我给自己定的设计标准有三条:

  • 只做传输加速,不做代码托管:不把仓库完整克隆到自己的服务器,不涉及同步策略、存储成本、内容合规等问题,只在中间做透明转发。
  • 全场景覆盖:git clone、git push、Release 下载、Raw 文件读取,这四件事在开发中都会用到,要一次性全部解决。
  • 维护成本低:配置一次,长期稳定运行,不用天天盯着服务器。

基于这些标准,我最终选了“Nginx 反向代理 + 域名解析”的方案,而不是去套别人的镜像站程序。

1.2 为什么不用现成的公共镜像/加速器

我实测过几个公共镜像,确实能解决一部分问题,但痛点也很明显:

对比项公共镜像/加速器自建方案
稳定性热门镜像经常超负荷,随时可能停止服务自己控制,随时监控
安全性代码经过第三方服务器,存在泄露风险流量只经过自己的服务器
速度公共带宽被大量用户共享,速度不稳定单用户独占带宽,速度可控
功能覆盖很多只代理网页,git clone 不支持全场景统一加速
成本部分免费,但关键功能收费一年几十块服务器费用

公共方案还有一个绕不开的问题:你永远不知道它什么时候会挂。我印象很深,之前有段时间好几个知名公共镜像陆续关停,很多依赖它们的开发者一夜之间被打回原形,只能重新直面龟速连接。自建方案虽然前期要花点时间配置,但主动权在自己手里。

1.3 为什么选 Nginx 而不是其他方案

先解释一个基础概念:什么叫反向代理?打个比方,你想去一家餐厅吃饭(GitHub),但门口在修路(网络连接不稳定)。这时候有个代购小哥(Nginx 代理服务器)知道一条小路,他帮你把菜取回来送到你手上。你不需要自己走那条烂路,只需要跟代购小哥对接即可。

技术上的原理是:当你的电脑发起对github.com的请求时,DNS 解析返回的不是 GitHub 官方服务器的 IP,而是你自己服务器的 IP。请求先到达你的 Nginx,Nginx 再去访问真正的 GitHub,然后把数据原样传回给你。

为什么用 Nginx?因为它对反向代理、HTTP/2、缓存、连接复用的支持非常成熟,配置灵活,运维成本低。而且它天然支持流式传输,对 git 这种需要长时间保持连接的协议很友好。像 Squid 这类传统正向代理反过来,它是基于缓存的,对动态内容的加速效果远不如 Nginx 的反向代理模式。

2. 核心细节解析与实操要点

2.1 关键准备:服务器、域名、证书

既然是自建,你需要准备三样东西:

  • 一台有公网 IP 的服务器。我用的腾讯云轻量应用服务器,配置 2C2G,一年成本不到一百块。选服务器的核心指标是:到 GitHub 的链路要稳定,出网带宽要够用。
  • 一个域名。建议用二级域名,比如gh.yourdomain.com,不要用主域名,方便以后加其他服务。
  • SSL 证书。这一步非常重要,GitHub 强制 HTTPS,你的 Nginx 必须用 HTTPS 与客户端通信,同时 Nginx 与 GitHub 之间也走 HTTPS。

这里要强调一个容易踩的坑:不要试图把请求转发到 HTTP 版本的 GitHub。GitHub 早就全面启用 HSTS,强制 443 端口,你如果转发到 80 端口,连接会被直接重置。

2.2 核心配置拆解:按域名划分代理模块

GitHub 的访问链路并不是只有一个域名,实际由多个域名组成,这也是很多人配完代理后发现“只加速了一部分”的根本原因。我把链路拆开说明:

  • github.com:主站域名,负责 git clone/push、网页、Release 下载的重定向发起。
  • raw.githubusercontent.com:Raw 文件内容域名,直接读取仓库内文件的请求会打到这个域名。
  • objects.githubusercontent.com:Release 下载的 CDN 域名,实际的二进制文件流量走这里。

也就是说,Release 下载本身是一个链路:先请求github.com/releases/...,服务器返回 302 重定向到objects.githubusercontent.com/...,再由这个 CDN 把文件流式传回来。如果只代理github.com,你会发现 Release 下载依然慢,因为后半段链路没有被优化。

下面我逐个模块讲配置。

2.2.1 git clone / push 传输加速

git 的远程操作走 HTTPS,请求目标是https://github.com/owner/repo.git。Nginx 配置核心是指定proxy_pass指向上游https://github.com,同时注意几个关键参数。

location / { proxy_pass https://github.com; proxy_set_header Host github.com; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # 关闭缓存,git 需要流式传输 proxy_buffering off; proxy_http_version 1.1; proxy_set_header Connection ""; # 超时设置,拉大仓库时很有必要 proxy_connect_timeout 30s; proxy_send_timeout 600s; proxy_read_timeout 600s; }

这里面有几个坑值得单独说:

  • proxy_buffering off:如果开着缓存,git 在接收数据的同时写入对象,Nginx 却把数据憋在一大块里再吐出来,导致大仓库克隆时看起来“卡住不动”,其实是 Nginx 在缓冲。关闭后数据实时流转,客户端能立刻看到进度,体验完全不同。
  • Connection "":必须清空 Connection 请求头,否则客户端发来的Connection: keep-alive会被原样传给上游,可能造成连接复用混乱。
  • 超时时间拉长:克隆一个大仓库(比如某些几个 GB 的仓库),如果proxy_read_timeout只有 60 秒,网络一抖动连接就被 Nginx 掐断,git 又要从头再来。调成 600 秒能避免这种莫名其妙的中断。
2.2.2 Release / Raw 下载加速

因为 Release 下载链路里存在 302 重定向,所以不能只代理一个域名。处理办法是把涉及的域名都配好 DNS 记录和 Nginx server 块。

server { listen 443 ssl http2; server_name raw.yourdomain.com; # 证书配置略 location / { proxy_pass https://raw.githubusercontent.com; proxy_set_header Host raw.githubusercontent.com; proxy_buffering off; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_connect_timeout 30s; proxy_send_timeout 300s; proxy_read_timeout 300s; } }

objects.githubusercontent.com的代理配置类似,只是 upstream 换一下。注意它和 raw 域名的 server_name 要单独区分,不能混用一个 server 块,因为 Nginx 的 server_name 决定了请求分发到哪个配置。

2.2.3 网页访问加速(不建议做)

如果你想让浏览器也通过自己的域名打开 GitHub 网页,可以再加一个 server 块代理github.com。但是这里有一个大坑:GitHub 的 HTML 页面里有大量硬编码链接,都指向github.com域名。通过自己的域名打开网页后,页面里多数按钮和链接一点又跳回 github.com,体验非常割裂,而且页面加载速度提升有限。

所以我个人建议:网页访问这一块,可以不做。开发者的日常是命令行为主,网页只是偶尔看看 Issue、PR。真要看网页,等待网络良好时段直接打开就行,或者用系统代理解决。如果你非要实现,可以用 Nginx 的sub_filter模块做内容替换,把响应体里的github.com替换为你的域名,但性能损耗大、维护麻烦,而且 GitHub 页面的链接格式很复杂,替换不彻底会产生很多奇怪问题。我实测过一轮,最终放弃了。

这也是为什么我的方案叫“加速”而不是“镜像”——只做传输层优化,不动内容层,能省下大量维护精力。

2.3 参数调优的底层逻辑

配置 Nginx 时有几个参数直接关系到实际体验,我把底层逻辑说明白,你调整的时候就有依据了。

keepalive 长连接。在 upstream 配置里加一组 keepalive,让 Nginx 和 GitHub 之间的连接可以复用,避免每次请求都重新建立 TLS 握手。

upstream github_backend { server github.com:443; keepalive 32; }

TLS 握手一次几十毫秒,单次请求看起来无所谓,但 git clone 大仓库时有成百上千个并发请求,连接复用的收益就非常明显了。

HTTP/2。如果 Nginx 和客户端都支持,建议启用http2,多路复用对并发请求效果好。我实测过,在 clone 大仓库时 HTTP/2 比 HTTP/1.1 快 10% 左右(本地网络测试,跨境网络差距更明显)。

client_max_body_size。这个参数容易被忽略。如果你有 push 大文件的需求(比如提交大型二进制资源),Nginx 默认 1M 的上限会让你 push 直接失败。调大到 500M 比较保险。

3. 实操过程与核心环节实现

3.1 环境准备与 DNS 配置

我用的环境是这样的:

  • 腾讯云轻量应用服务器,Ubuntu 22.04
  • Nginx 1.24
  • 域名在 Namecheap 购买,DNS 托管在 Cloudflare

部署前先把 DNS 记录配好。我在 Cloudflare 添加了三条 A 记录,全部指向服务器 IP,并把代理模式关掉(灰色云):

gh.yourdomain.com A 1.2.3.4 raw.yourdomain.com A 1.2.3.4 objects.yourdomain.com A 1.2.3.4

为什么 Cloudflare 只开 DNS 不开 CDN?因为 Cloudflare 的橙色云(CDN 代理)会终结 TLS 并缓冲内容,对 git 这种长时间连接很不友好,经常导致超时或 502。我只需要它免费的 DNS 解析功能,解析结果直接指向自己的服务器 IP,这样请求链路少一层跳板。

3.2 申请 SSL 证书

证书我直接申请了 Let’s Encrypt 免费证书。给三个子域名申请一张多域名证书(SAN 证书),填到一个 Nginx 配置里,方便统一管理。

如果你用宝塔面板,证书申请过程可以点点鼠标完成,但最终修改 Nginx 配置我建议用命令行,原因后面说。

3.3 完整 Nginx 配置参考

我把核心配置整理出来,文件路径是/etc/nginx/conf.d/github-proxy.conf:

# git clone/push 代理 upstream github_backend { server github.com:443; keepalive 32; } server { listen 443 ssl http2; server_name gh.yourdomain.com; ssl_certificate /path/to/fullchain.pem; ssl_certificate_key /path/to/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; location / { proxy_pass https://github_backend; proxy_set_header Host github.com; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_buffering off; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_connect_timeout 30s; proxy_send_timeout 600s; proxy_read_timeout 600s; client_max_body_size 500M; } } # Release CDN 代理 server { listen 443 ssl http2; server_name objects.yourdomain.com; ssl_certificate /path/to/fullchain.pem; ssl_certificate_key /path/to/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; location / { proxy_pass https://objects.githubusercontent.com; proxy_set_header Host objects.githubusercontent.com; proxy_buffering off; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_connect_timeout 30s; proxy_send_timeout 300s; proxy_read_timeout 300s; } } # Raw 文件代理 server { listen 443 ssl http2; server_name raw.yourdomain.com; ssl_certificate /path/to/fullchain.pem; ssl_certificate_key /path/to/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; location / { proxy_pass https://raw.githubusercontent.com; proxy_set_header Host raw.githubusercontent.com; proxy_buffering off; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_connect_timeout 30s; proxy_send_timeout 300s; proxy_read_timeout 300s; } }

保存后执行:

nginx -t && nginx -s reload

nginx -t会检查语法,没问题再reload平滑重载配置,不会中断现有连接。

3.4 客户端使用方式

配置完成后,客户端使用方式很简单,不需要安装任何额外工具,只需要把 URL 里的域名换掉。

# 原来的写法 git clone https://github.com/owner/repo.git # 用代理域的写法 git clone https://gh.yourdomain.com/owner/repo.git

已有仓库切换到代理域:

git remote set-url origin https://gh.yourdomain.com/owner/repo.git

Release 下载的用法:

原链接:https://github.com/owner/repo/releases/download/v1.0/app.zip 改后: https://gh.yourdomain.com/owner/repo/releases/download/v1.0/app.zip

Raw 文件的用法:

原链接:https://raw.githubusercontent.com/owner/repo/main/README.md 改后: https://raw.yourdomain.com/owner/repo/main/README.md

这里有几点要特别注意:

  1. 必须手动替换域名,不能从网页端右键复制链接后直接访问。网页端复制的链接默认是github.com开头,你要手动替换成代理域。
  2. HTTPS 不能省。直接只用 HTTPS,少一层 301 跳转,也避免浏览器或 git 客户端在解析 HSTS 时出问题。
  3. git push 也会走代理。push 的 URL 和 clone 一样是 HTTPS 协议,替换域名后 push 同样走代理。如果 GitHub 对某些大文件有 LFS 限制,push 二进制大文件时依然可能报错,这是平台限制,与代理无关。

3.5 实测数据记录

我把这套方案部署完成后,用几个真实场景做了测试。测试服务器带宽是 5Mbps,本地是普通宽带。

场景直连 GitHub 耗时走代理耗时速度提升
clone 小仓库(50MB)约 3 分钟,经常中断约 30 秒5-6 倍
clone 大仓库(1.2GB)约 40 分钟,失败 2 次约 8 分钟5 倍左右
Release 下载 200MB 二进制包约 10 分钟约 2 分钟5 倍
Raw 文件读取(1MB config)3-5 秒0.5 秒6-10 倍

这里要说清楚:自建代理的极限速度取决于服务器带宽。我的服务器是 5Mbps(约 640KB/s),下载 200MB 的文件理论最低也要 5 分钟左右,实测 2 分钟是因为 GitHub CDN 有时会调度到更优节点。如果你买 10Mbps 甚至更高的带宽,效果会更好。

有一件事很反直觉:代理服务器的带宽不是越大越好,关键是稳定。git 协议最怕的不是慢,是断。直连 GitHub 时,网络抖动导致 TLS 连接反复被重置,每次中断后 git 要重新协商握手、重新开始传输。自建代理的稳定链路让传输几乎不中断,整体耗时反而大幅下降。这也是为什么我不建议贪便宜买那种带宽很高但不稳定的低价服务器。

4. 常见问题与排查技巧实录

4.1 git clone 提示 SSL certificate problem

如果你配置好代理域后,git clone 报SSL certificate problem: unable to get local issuer certificate,大概率是 Nginx 证书链不完整。

排查方法:检查ssl_certificate指向的文件,确认里面是fullchain.pem(包含站点证书和中间证书)。如果你只填了站点证书cert.pem,会缺中间证书,客户端验证链不完整。用 Let’s Encrypt 的话,fullchain.pem 就是完整的,直接引用即可。

4.2 clone 转到一半报 502 Bad Gateway

502 通常意味着 Nginx 连不上后端。可能的原因有几个:

  • DNS 解析问题。Nginx 默认只在启动时解析一次github.com的 IP,如果 DNS 记录变化,Nginx 可能仍使用旧 IP。解决办法是在 upstream 中使用变量强制定时解析,或者定期重载 Nginx 配置刷新 DNS。
  • 系统防火墙拦截。检查服务器安全组是否放行 443 端口。部分服务器厂商默认安全组只开 80 和 443 中的部分端口,我在腾讯云轻量上就遇到过 443 未放行的问题。

我遇到过的另一种情况:Nginx 与 GitHub 的连接池被占满,keepalive 连接没有及时释放,大量并发请求时后端连接池耗尽。解决办法是把 keepalive 数量调大,同时设置proxy_next_upstream,让 Nginx 在遇到 502 或超时自动切换到另一个可用连接。

4.3 Release 下载大文件时速度依然慢

如果代理了 github.com 但 Release 下载还是慢,十有八九是没代理objects.githubusercontent.com。这个 CDN 域名在 Release 下载链路里负责实际文件传输,不代理它等于只优化了前半段,后半段还是打回原形。

另一个可能:你的代理服务器所在网络的上游 ISP 对特定 CDN 节点线路不好。这时候只能换服务器区域或换 DNS 解析,没有代码级的解法。我后来把服务器区域换到访问 GitHub CDN 更友好的地区后,下载速度立刻就稳了。

4.4 push 时报错 RPC failed; HTTP 500 curl 22

我遇到过RPC failed; HTTP 500 curl 22 The requested URL returned error: 500。排查下来不是代理的问题,而是 GitHub 服务端对某些仓库的 push 校验失败,常见于提交了超大文件或大量文件。处理方式:

  • 把client_max_body_size调大(如 500M)
  • 检查是否有大文件被意外提交到仓库
  • 查看 Nginx access.log 里对应请求的上游响应耗时,确认是否超时

如果确认是代理导致的 500,重点看proxy_read_timeout是否太短。push 大文件时数据量大,每个请求耗时可能较长。

4.5 一个必须说的安全原则

这里讨论的是自建技术加速,流量只经过你自己的服务器。但要注意:不要把这个方案开放给不特定的公众使用。如果你把代理域名公开,别人就能借用你的带宽访问 GitHub,服务器分分钟被拖垮,还可能被用于其他用途,对你个人不利。只给自己和信任的团队成员使用,这是自建方案最基本的原则。

4.6 排查技巧速查表

问题现象排查方向解决方案
SSL certificate problem证书链缺失使用 fullchain.pem
502 Bad GatewayDNS 缓存 / 防火墙重载 Nginx / 放行 443
Release 下载慢CDN 域名未代理加上 objects.githubusercontent.com
HTTP 500 curl 22大文件 / 限流调大 body 上限 / 检查仓库文件
clone 卡住不动Nginx 缓冲关闭 proxy_buffering

5. 扩展玩法:这套思路还能干什么

配置完成之后,这套 Nginx 反向代理的思路其实可以迁移到很多场景,我顺手列几个自己验证过的:

  1. 其他代码托管平台的加速。GitLab(gitlab.com 或公司自建的 GitLab)用同样的思路做反向代理,配置几乎一样,只换目标域名。团队仓库体量大时,效果非常明显。
  2. Python 包 / npm 包下载加速。pip 和 npm 都有公共镜像,但有时候镜像同步不及时。用 Nginx 对pypi.org和registry.npmjs.org做代理,也能获得稳定体验。
  3. Maven 仓库加速。Maven Central 在不同区域的访问速度差异很大,代理后对 CI/CD 流水线有实际价值,毕竟每次构建都要拉依赖。
  4. 企业内部统一代理出口。把代理域名配置到公司内网 DNS,所有开发者通过同一个域名访问 GitHub,日志统一收集,还能做流量审计——但前提是注意合规,企业内部工具建设建议先和法务、运维团队确认。

这些扩展玩法不需要改变 Nginx 架构,只需要复制 server 块、替换 upstream 域名、改 DNS 记录、重新申请证书即可。整个扩展流程大概 20 分钟搞定。

6. 最后说几句个人心得

这套方案部署到现在已经两个多月了,中间遇到过几次小故障,也优化过参数配置。我个人有几个比较深的体会:

第一,能用 HTTPS 就尽量用 HTTPS,别给自己找麻烦。HTTP 虽然配置简单,但遇到 HSTS、302 跳转、证书校验等场景容易出怪问题,调试成本远高于省下的那点配置时间。

第二,自建方案最重要的不是“快”,而是“稳”。刚开始我追求极致速度,把超时时间调得很短、keepalive 调得很小,结果反而频繁断连。后来放宽了超时时间,体验明显好了一大截。git 操作本身有断点续传,只要链路稳定,慢一点都能接受,频繁断连才是最磨人的。

第三,配置改动一定要留备份。我每次调整 Nginx 配置前都会先复制一份原文件,改完立刻nginx -t测试,确认没问题再 reload。这个好习惯帮我少踩了很多坑。

第四,这个方案适合个人开发者和中小团队。如果你所在企业对代码托管有更高合规要求,还是得优先考虑正规的企业级方案,自建代理只适合个人技术研究和内部小范围使用。

最后再分享一个小技巧:如果你和我一样用宝塔面板管理服务器,改 Nginx 配置时别在面板里直接保存,建议用 SSH 登录服务器修改/etc/nginx/conf.d/下的文件,然后nginx -t && nginx -s reload。面板自带的编辑器偶尔会改掉文件权限,而且它不校验配置语法,等你发现配置有问题,线上服务可能已经受了影响。命令行看似原始,但最可控。