返回更新列表
新发布Aug 31, 2026

proxy v0.7.0

一个用于包注册表的轻量级缓存代理。

分享

git-pkgs proxy

一个用于软件包注册表的缓存代理。通过在本地缓存构件来加速软件包下载,减少带宽占用并提升可靠性。

版本冷却

大多数供应链攻击都依赖于速度:恶意版本发布后,在任何人察觉之前,几分钟内就会被自动化流水线拉取使用。冷却功能为新发布的版本增加了一段隔离期。启用后,代理会从元数据响应中剔除那些尚未超过可配置时间阈值的版本。

cooldown:
  default: "3d"              # hide versions published less than 3 days ago
  ecosystems:
    npm: "7d"                # npm gets a longer window
    cargo: "0"               # disable for cargo
  packages:
    "pkg:npm/lodash": "0"    # exempt trusted packages

3 天冷却期意味着当 lodash 发布 4.18.0 版本时,你的构建会继续使用 4.17.21,直到 3 天过去。如果新版本被证明遭到入侵,你从未暴露于风险之中。

解析顺序:包级覆盖,然后是生态系统级覆盖,最后是全局默认值。这让你可以设置一个保守的默认值,并为需要更快更新的包划定例外。完整配置参考见 docs/configuration.md。

制品扫描

冷却期只查看版本的发布时间戳——它从不检查实际字节内容。制品扫描填补了这一空白:启用后,每个制品都会被暂存到存储中,并由一个或多个外部服务(trivy、ClamAV、Wiz,或任何遵循小型 HTTP/JSON 契约的其他服务)扫描,然后才会提交到缓存并提供给客户端。

scanning:
  enabled: true
  signing_key: ${PROXY_SCANNING_SIGNING_KEY}
  scanners:
    - name: clamav
      url: http://clamav-adapter:8080/scan
      mode: block             # a block verdict deletes the artifact and returns 403
    - name: trivy
      url: http://trivy-adapter:8081/scan
      mode: monitor            # findings are logged, never gate caching
      ecosystems: [npm, pypi]

代理从不上传制品字节到扫描器。每个扫描器会收到包元数据以及一个短期有效的签名 URL 通知;扫描器自行从代理自身的存储中拉取字节。扫描器并发运行,第一个报告判定为不允许的 block 模式扫描器立即胜出,并取消其余扫描器。完整配置参考和扫描器 HTTP 契约请参见 docs/configuration.md。

支持的注册表

注册表语言/平台冷却已完成
npmJavaScript是✓
CargoRust是✓
RubyGemsRuby是✓
Go proxyGo✓
HexElixir是*✓
pub.devDart是✓
PyPIPython是✓
MavenJava✓
Gradle Build CacheJava/Kotlin✓
NuGet.NET是✓
ComposerPHP是✓
ConanC/C++✓
CondaPython/R是✓
CRANR✓
JuliaJulia✓
SwiftSwift✓
ContainerDocker/OCI✓
HomebrewmacOS/Linux✓
DebianDebian/Ubuntu✓
RPMRHEL/Fedora✓
AlpineAlpine Linux✓
ArchArch Linux✗
ChefChef✗
GenericAny✓
HelmKubernetes✓
VagrantVagrant✗

冷却需要元数据中包含发布时间戳。冷却列中没有“是”的注册表要么不暴露时间戳,要么尚未接入。

* Hex 冷却需要禁用注册表签名验证(HEX_NO_VERIFY_REPO_ORIGIN=1),因为代理会重新编码 protobuf 负载。

安装

brew install git-pkgs/git-pkgs/proxy

或者从发布页面下载二进制文件。

Helm

从 GHCR 安装 chart,并设置包管理器客户端用于访问代理的公共 URL:

helm install proxy oci://ghcr.io/git-pkgs/charts/proxy \
  --set config.data.base_url=https://proxy.example.com

默认 chart 部署一个副本,后端使用 10 GiB 持久卷,在 /data 下使用 SQLite 和文件系统制品存储。有关 ingress、外部数据库和对象存储配置选项,请参见 deploy/charts/proxy/values.yaml。

快速开始

# Build from source
go build -o proxy ./cmd/proxy

# Run with defaults (listens on :8080)
./proxy

# Run with custom settings
./proxy -listen :3000 -base-url https://proxy.example.com

代理现已运行。配置你的包管理器以使用它。

OpenAPI (Swagger)

此仓库使用 swaggo 从带注释的处理器生成 OpenAPI 规范。

生成规范:

go install github.com/swaggo/swag/cmd/swag@latest
go generate ./internal/server

生成的文档写入 docs/swagger/。

当代理运行时,从以下地址获取实时规范:

  • http://localhost:8080/openapi.json

或将 http://localhost:8080 替换为您配置的基础 URL。此链接也会显示在仪表板上。

配置包管理器

npm

创建或编辑 ~/.npmrc:

registry=http://localhost:8080/npm/

或在 .npmrc 中按项目设置:

registry=http://localhost:8080/npm/

或使用环境变量:

npm_config_registry=http://localhost:8080/npm/ npm install

npm audit、pnpm audit、yarn npm audit 和 npm audit signatures 均可通过代理正常工作:审计和签名密钥端点会被传递到配置的上游注册表,并应用上游身份验证。因此,安全公告来自上游的数据库,而非代理自身的漏洞数据,且被冷却期扣留的版本不会被排除在报告之外。

Cargo

创建或编辑 ~/.cargo/config.toml:

[source.crates-io]
replace-with = "proxy"

[source.proxy]
registry = "sparse+http://localhost:8080/cargo/"

或在项目根目录的 .cargo/config.toml 中按项目设置。

RubyGems / Bundler

在 Gemfile 中设置 gem 源:

source "http://localhost:8080/gem"

或全局配置:

gem sources --add http://localhost:8080/gem/
bundle config mirror.https://rubygems.org http://localhost:8080/gem

Go 模块

设置 GOPROXY 环境变量:

export GOPROXY=http://localhost:8080/go,direct

或在你的 shell 配置文件中设置以实现持久化。

Homebrew

将 Homebrew 的 JSON API 和制品域名指向代理:

export HOMEBREW_API_DOMAIN=http://localhost:8080/homebrew
export HOMEBREW_ARTIFACT_DOMAIN=http://localhost:8080

该制品域在 /v2/homebrew/core/ 下代理清单和 bottle blob。GHCR 路由仅限于该仓库。源码归档、cask 应用程序下载、自定义 tap 制品以及旧式扁平文件 bottle 镜像使用 Homebrew 的正常回退 URL。通过不设置 HOMEBREW_ARTIFACT_DOMAIN_NO_FALLBACK 来保持回退启用。

启用 cache_metadata 或设置 PROXY_CACHE_METADATA=true 以保留 Homebrew JSON API 响应以供离线回退。Bottle blob 及其 OCI 清单无需此设置即可缓存。

上游默认使用 https://formulae.brew.sh/api 作为 JSON API,使用 https://ghcr.io 作为制品。要将此代理链接到另一个代理,请将其 Homebrew 端点配置为上游:

upstream:
  homebrew_api: "https://upstream-proxy.example.com/homebrew"
  homebrew_artifact: "https://upstream-proxy.example.com"

对应的环境变量是 PROXY_UPSTREAM_HOMEBREW_API 和 PROXY_UPSTREAM_HOMEBREW_ARTIFACT。

Hex (Elixir)

在 ~/.hex/hex.config 中配置:

{default_url, <<"http://localhost:8080/hex">>}.

或设置环境变量:

export HEX_MIRROR=http://localhost:8080/hex

pub.dev (Dart/Flutter)

设置 PUB_HOSTED_URL 环境变量:

export PUB_HOSTED_URL=http://localhost:8080/pub

PyPI (pip)

配置 pip 以使用代理:

pip install --index-url http://localhost:8080/pypi/simple/ package_name

或在 ~/.pip/pip.conf 中设置:

[global]
index-url = http://localhost:8080/pypi/simple/

Maven

添加到你的 ~/.m2/settings.xml:

<settings>
  <mirrors>
    <mirror>
      <id>proxy</id>
      <mirrorOf>central</mirrorOf>
      <url>http://localhost:8080/maven/</url>
    </mirror>
  </mirrors>
</settings>

/maven/ 端点使用 Maven Central 作为主要上游,当主要上游返回未找到时,回退到 Gradle Plugin Portal 以获取 Gradle 插件标记元数据和相关构件。

通过同一代理端点进行 Gradle 插件解析:

pluginManagement {
  repositories {
    maven(url = "http://localhost:8080/maven/")
  }
}

Gradle HTTP 构建缓存

在 settings.gradle(.kts) 中配置:

buildCache {
  local {
    enabled = false
  }
  remote<HttpBuildCache> {
    url = uri("http://localhost:8080/gradle/")
    push = true
  }
}

NuGet

在 nuget.config 中配置:

<configuration>
  <packageSources>
    <clear />
    <add key="proxy" value="http://localhost:8080/nuget/v3/index.json" />
  </packageSources>
</configuration>

或使用 CLI:

dotnet nuget add source http://localhost:8080/nuget/v3/index.json -n proxy

Composer (PHP)

在 composer.json 中配置:

{
    "repositories": [
        {
            "type": "composer",
            "url": "http://localhost:8080/composer"
        }
    ]
}

或全局设置:

composer config -g repositories.proxy composer http://localhost:8080/composer

Conan (C/C++)

将代理添加为远程仓库:

conan remote add proxy http://localhost:8080/conan
conan remote disable conancenter

在 ~/.conan2/remotes.json 中配置。

Conda

在 ~/.condarc 中配置:

channels:
  - http://localhost:8080/conda/main
  - http://localhost:8080/conda/conda-forge
default_channels:
  - http://localhost:8080/conda/main

或通过命令设置:

conda config --add channels http://localhost:8080/conda/main

CRAN (R)

在 R 中设置仓库:

options(repos = c(CRAN = "http://localhost:8080/cran"))

或在 ~/.Rprofile 中设置以持久化:

local({
  r <- getOption("repos")
  r["CRAN"] <- "http://localhost:8080/cran"
  options(repos = r)
})

Julia

在启动 Julia 之前设置 Pkg 服务器:

export JULIA_PKG_SERVER=http://localhost:8080/julia

或在运行中的会话内:

ENV["JULIA_PKG_SERVER"] = "http://localhost:8080/julia"
using Pkg; Pkg.update()

Swift

将代理配置为当前 Swift 包的默认注册表:

swift package-registry set --allow-insecure-http http://localhost:8080/swift

分类