
proxy v0.7.0
パッケージレジストリ向けの軽量キャッシングプロキシ。
git-pkgs プロキシ
パッケージレジストリ用のキャッシングプロキシです。アーティファクトをローカルにキャッシュすることでパッケージのダウンロードを高速化し、帯域幅の使用量を削減して信頼性を向上させます。
バージョン・クールダウン
ほとんどのサプライチェーン攻撃は速度に依存しています。悪意のあるバージョンが公開されると、誰も気づかないうちに数分以内に自動化パイプラインに消費されてしまいます。クールダウン機能は、新しく公開されたバージョンに検疫期間を追加します。有効にすると、プロキシは設定可能なしきい値を超えて経過するまで、メタデータ応答からバージョンを除外します。```yaml 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`を公開しても、3日間が経過するまでビルドは`4.17.21`を使い続けることを意味します。新しいリリースが侵害されていたとしても、あなたは決して露出されません。
解決順序: パッケージのオーバーライド、次にエコシステムのオーバーライド、最後にグローバルデフォルトです。これにより、保守的なデフォルトを設定しつつ、より迅速な更新が必要なパッケージには例外を設けることができます。完全な設定リファレンスについては、[docs/configuration.md](https://github.com/git-pkgs/proxy/blob/main/docs/configuration.md)を参照してください。
## 対応レジストリ
| レジストリ | 言語/プラットフォーム | クールダウン | 完了 |
|----------|-------------------|:--------:|:---------:|
| npm | JavaScript | あり | ✓ |
| Cargo | Rust | あり | ✓ |
| RubyGems | Ruby | あり | ✓ |
| Go proxy | Go | | ✓ |
| Hex | Elixir | あり* | ✓ |
| pub.dev | Dart | あり | ✓ |
| PyPI | Python | あり | ✓ |
| Maven | Java | | ✓ |
| Gradle Build Cache | Java/Kotlin | | ✓ |
| NuGet | .NET | あり | ✓ |
| Composer | PHP | あり | ✓ |
| Conan | C/C++ | | ✓ |
| Conda | Python/R | あり | ✓ |
| CRAN | R | | ✓ |
| Julia | Julia | | ✓ |
| Container | Docker/OCI | | ✓ |
| Debian | Debian/Ubuntu | | ✓ |
| RPM | RHEL/Fedora | | ✓ |
| Alpine | Alpine Linux | | ✗ |
| Arch | Arch Linux | | ✗ |
| Chef | Chef | | ✗ |
| Generic | 任意 | | ✗ |
| Helm | Kubernetes | | ✗ |
| Swift | Swift | | ✗ |
| Vagrant | Vagrant | | ✗ |
クールダウンには、メタデータ内の公開タイムスタンプが必要です。クールダウン列に「あり」がないレジストリは、タイムスタンプを公開していないか、まだ配線されていません。
\* Hexのクールダウンには、レジストリの署名検証を無効にする必要があります(`HEX_NO_VERIFY_REPO_ORIGIN=1`)。プロキシがprotobufペイロードを再エンコードするためです。
## インストール```bash
brew install git-pkgs/git-pkgs/proxy
リリースページ](https://github.com/git-pkgs/proxy/releases)からバイナリをダウンロードすることもできます。
クイックスタート```bash
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仕様を生成します。
仕様を生成するには:```bash
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/
環境変数を使用する場合:```bash npm_config_registry=http://localhost:8080/npm/ npm install
### Cargo
`~/.cargo/config.toml` を作成または編集します:```toml
[source.crates-io]
replace-with = "proxy"
[source.proxy]
registry = "sparse+http://localhost:8080/cargo/"
Or set per-project in .cargo/config.toml in your project root.
RubyGems / Bundler
Set the gem source in your Gemfile:```ruby
source "http://localhost:8080/gem"
Or configure globally:```bash
gem sources --add http://localhost:8080/gem/
bundle config mirror.https://rubygems.org http://localhost:8080/gem
Go モジュール
GOPROXY 環境変数を設定します:```bash export GOPROXY=http://localhost:8080/go,direct
Or in your shell profile for persistence.
### Hex (Elixir)
Configure in `~/.hex/hex.config`:```erlang
{default_url, <<"http://localhost:8080/hex">>}.
Or set the environment variable:```bash export HEX_MIRROR=http://localhost:8080/hex
### pub.dev (Dart/Flutter)
`PUB_HOSTED_URL` 環境変数を設定します:```bash
export PUB_HOSTED_URL=http://localhost:8080/pub
PyPI (pip)
プロキシを使用するようにpipを設定します:```bash pip install --index-url http://localhost:8080/pypi/simple/ package_name
Or set in `~/.pip/pip.conf`:```ini
[global]
index-url = http://localhost:8080/pypi/simple/
Maven
~/.m2/settings.xml に追加します:```xml
proxy
central
http://localhost:8080/maven/
`/maven/` エンドポイントは、プライマリのアップストリームとして Maven Central を使用し、プライマリのアップストリームが not found を返した場合には、Gradle Plugin Portal を Gradle プラグインのマーカーメタデータおよび関連アーティファクトのフォールバックとして使用します。
同じプロキシエンドポイントを介した Gradle プラグインの解決については、以下を参照してください。```kotlin
pluginManagement {
repositories {
maven(url = "http://localhost:8080/maven/")
}
}
Gradle HTTP ビルドキャッシュ
settings.gradle(.kts) で設定します:```kotlin
buildCache {
local {
enabled = false
}
remote {
url = uri("http://localhost:8080/gradle/")
push = true
}
}
### NuGet
`nuget.config` で設定します:```xml
<configuration>
<packageSources>
<clear />
<add key="proxy" value="http://localhost:8080/nuget/v3/index.json" />
</packageSources>
</configuration>
またはCLIを使用します:```bash dotnet nuget add source http://localhost:8080/nuget/v3/index.json -n proxy
### Composer (PHP)
`composer.json` で設定します:```json
{
"repositories": [
{
"type": "composer",
"url": "http://localhost:8080/composer"
}
]
}
Or set globally:
グローバルに設定する場合:```bash composer config -g repositories.proxy composer http://localhost:8080/composer
### Conan (C/C++)
プロキシをリモートとして追加します:```bash
conan remote add proxy http://localhost:8080/conan
conan remote disable conancenter
~/.conan2/remotes.json で設定します。
Conda
~/.condarc で設定します:```yaml
channels:
- http://localhost:8080/conda/main
- http://localhost:8080/conda/conda-forge default_channels:
- http://localhost:8080/conda/main
またはコマンドで設定します:```bash
conda config --add channels http://localhost:8080/conda/main
CRAN (R)
Rでリポジトリを設定します:```r options(repos = c(CRAN = "http://localhost:8080/cran"))
~/.Rprofile` に記述して永続化することもできます:```r
local({
r <- getOption("repos")
r["CRAN"] <- "http://localhost:8080/cran"
options(repos = r)
})
Julia
Julia を起動する前に Pkg サーバーを設定します:```bash export JULIA_PKG_SERVER=http://localhost:8080/julia
Or inside a running session:
実行中のセッション内で:```julia
ENV["JULIA_PKG_SERVER"] = "http://localhost:8080/julia"
using Pkg; Pkg.update()
Docker / コンテナレジストリ
プロキシをレジストリミラーとして使用するようにDockerを /etc/docker/daemon.json で設定します:```json
{
"registry-mirrors": ["http://localhost:8080"]
}
Docker を再起動します:```bash
sudo systemctl restart docker
画像を直接プルすることもできます:```bash docker pull localhost:8080/library/nginx:latest
### Helm
各HTTPチャートリポジトリに名前を付けて設定し、対応するプロキシURLをHelmに追加します。```yaml
upstream:
helm:
bitnami: "https://charts.bitnami.com/bitnami"
I need the input content to translate. Please provide the chunk of Markdown content you'd like me to translate from English to Japanese.```bash helm repo add bitnami http://localhost:8080/helm/bitnami helm repo update helm pull bitnami/nginx
プロキシは通常のメタデータキャッシュ設定を使用して`index.yaml`をキャッシュし、インデックスからSHA-256ダイジェストを検証した後にチャートアーカイブをキャッシュします。
OCIレジストリに保存されているチャートの場合、名前付きOCIアップストリームを設定し、チャート参照に予約済みの`upstream/{name}`プレフィックスを追加します。```yaml
upstream:
oci:
ghcr: "https://ghcr.io"
The -h flag displays the help menu, which includes all available options and their descriptions. This is useful for quickly understanding the tool's capabilities without needing to consult external documentation.```bash
helm pull oci://localhost:8080/upstream/ghcr/owner/charts/mychart --version 1.0.0 --plain-http
### Debian / APT
`/etc/apt/sources.list.d/proxy.list` でプロキシを使用するように APT を設定します:```
deb http://localhost:8080/debian stable main contrib
既存の sources.list エントリを置き換えてから、次のようにします。```bash sudo apt update
The upstream defaults to `http://deb.debian.org/debian`. To proxy a different APT repository (e.g. Ubuntu), set `upstream.debian` in the config file or `PROXY_UPSTREAM_DEBIAN` in the environment:
上流のデフォルトは `http://deb.debian.org/debian` です。別のAPTリポジトリ(例:Ubuntu)をプロキシするには、設定ファイルで `upstream.debian` を設定するか、環境変数で `PROXY_UPSTREAM_DEBIAN` を設定します:```yaml
upstream:
debian: "http://archive.ubuntu.com/ubuntu"
RPM / Yum / DNF
/etc/yum.repos.d/proxy.repo で yum/dnf がプロキシを使用するように設定します:```ini
[proxy-fedora]
name=Fedora via Proxy
baseurl=http://localhost:8080/rpm/releases/$releasever/Everything/$basearch/os/
enabled=1
gpgcheck=0
Then:```bash
sudo dnf clean all
sudo dnf update
設定
プロキシは以下の方法で設定できます:
- コマンドラインフラグ(最優先)
- 環境変数
- 設定ファイル(YAMLまたはJSON)
コマンドラインフラグ```
-config string Path to configuration file -listen string Address to listen on (default ":8080") -base-url string Public URL of this proxy (default "http://localhost:8080") -storage-url string Storage URL (file://, s3://, gs://, azblob://) -storage-path string Path to artifact storage directory (deprecated, use -storage-url) -database-driver string Database driver: sqlite or postgres (default "sqlite") -database-path string Path to SQLite database file (default "./cache/proxy.db") -database-url string PostgreSQL connection URL -log-level string Log level: debug, info, warn, error (default "info") -log-format string Log format: text, json (default "text") -access-log string Path to the JSONL access log -version Print version and exit
### 環境変数```bash
PROXY_LISTEN=:8080
PROXY_BASE_URL=http://localhost:8080
PROXY_UI_URL=http://localhost:8080 # Optional; defaults to PROXY_BASE_URL
PROXY_STORAGE_URL=file:///var/cache/proxy/artifacts
PROXY_DATABASE_DRIVER=sqlite
PROXY_DATABASE_PATH=./cache/proxy.db
PROXY_DATABASE_URL=postgres://user:pass@localhost/proxy?sslmode=disable
PROXY_LOG_LEVEL=info
PROXY_LOG_FORMAT=text
PROXY_ACCESS_LOG_PATH=/var/log/proxy/access.jsonl
設定ファイル```yaml
listen: ":8080" base_url: "http://localhost:8080"
storage: url: "file:///var/cache/proxy/artifacts" max_size: "10GB" # Optional: evict LRU when exceeded
database: driver: "sqlite" path: "/var/lib/proxy/cache.db"
log: level: "info" format: "text"
access_log: path: "/var/log/proxy/access.jsonl" # Optional JSONL activity log
Optional: override upstream URLs
upstream: npm: "https://registry.npmjs.org" cargo: "https://index.crates.io"
Optional: version cooldown (see above)
cooldown: default: "3d"
[設定リファレンス](https://github.com/git-pkgs/proxy/blob/main/docs/configuration.md#upstream-registries)で、すべてのアップストリームキー、環境変数、デフォルトURLを確認してください。
設定ファイルで実行:```bash
./proxy -config /etc/proxy/config.yaml
PostgreSQL
SQLiteはデフォルトであり、単一ノードのデプロイメントには適しています。マルチノード構成の場合、またはマネージドデータベースを希望する場合は、Postgresに切り替えてください:```yaml database: driver: "postgres" url: "postgres://user:password@localhost:5432/proxy?sslmode=disable"
または環境変数を使用する場合:```bash
PROXY_DATABASE_DRIVER=postgres
PROXY_DATABASE_URL=postgres://user:password@localhost:5432/proxy?sslmode=disable
プロキシは初回実行時にテーブルを自動的に作成します。
S3ストレージ
プロキシは、ローカルファイルシステムの代わりに、S3またはS3互換サービス(MinIO、R2など)にキャッシュされたアーティファクトを保存できます。```yaml storage: url: "s3://my-bucket-name?region=us-east-1"
For S3互換サービス(MinIOなど)の場合:```yaml
storage:
url: "s3://my-bucket?endpoint=http://localhost:9000&disableSSL=true&s3ForcePathStyle=true"
標準的なAWS環境変数(AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_REGION)を使用して認証情報を設定します。
Google Cloud Storage
プロキシは、gs:// URLスキームを使用して、キャッシュされたアーティファクトをGCSバケットに保存できます。```yaml
storage:
url: "gs://my-bucket-name"
認証には[アプリケーションのデフォルト資格情報](https://docs.cloud.google.com/docs/authentication/application-default-credentials)を使用します。つまり、設定や環境に資格情報を埋め込む必要はありません。サポートされるソースは、優先順に次のとおりです。
- **GKE Workload Identity** — プロキシを実行するKubernetesサービスアカウントを、バケットに対して`roles/storage.objectAdmin`を持つGoogleサービスアカウントにバインドします。プロキシはワークロードのトークンを自動的に使用します。
- GCE、Cloud Run、Cloud Functionsなどでの**アタッチされたサービスアカウント**。
- サービスアカウントのJSONキーファイルを指す**`GOOGLE_APPLICATION_CREDENTIALS`**環境変数。
- ローカル開発用の**`gcloud auth application-default login`**。
#### GKE Workload Identityのセットアップ```bash
# 1. Create a Google service account
gcloud iam service-accounts create git-pkgs-proxy \
--project=PROJECT_ID
# 2. Grant it access to the bucket
gsutil iam ch \
serviceAccount:git-pkgs-proxy@PROJECT_ID.iam.gserviceaccount.com:objectAdmin \
gs://my-bucket-name
# 3. Bind the Kubernetes service account to it
gcloud iam service-accounts add-iam-policy-binding \
git-pkgs-proxy@PROJECT_ID.iam.gserviceaccount.com \
--role=roles/iam.workloadIdentityUser \
--member="serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]"
# 4. Annotate the Kubernetes service account
kubectl annotate serviceaccount KSA_NAME \
--namespace=NAMESPACE \
iam.gke.io/gcp-service-account=git-pkgs-proxy@PROJECT_ID.iam.gserviceaccount.com
Workload Identity を使用した直接配信(署名付き URL)
direct_serve: true が有効な場合、プロキシは事前署名された GCS URL への HTTP 302 リダイレクトを発行します。Workload Identity は秘密鍵を提供しないため、GCS バックエンドは IAM Credentials signBlob API を呼び出します。サービスアカウントに、それ自体に対する token-creator ロールを付与してください。```bash
gcloud iam service-accounts add-iam-policy-binding
git-pkgs-proxy@PROJECT_ID.iam.gserviceaccount.com
--role=roles/iam.serviceAccountTokenCreator
--member="serviceAccount:git-pkgs-proxy@PROJECT_ID.iam.gserviceaccount.com"
## CLI コマンド
### serve (デフォルト)
プロキシサーバーを起動します。コマンドが指定されていない場合のデフォルトコマンドです。```bash
proxy serve [flags]
proxy [flags] # same as 'proxy serve'
mirror
PURL、SBOMファイル、またはレジストリ全体からキャッシュを事前に投入します。オフラインでの利用可能性を確保したり、デプロイ前にキャッシュをウォームアップするのに役立ちます。```bash
Mirror specific package versions
proxy mirror pkg:npm/[email protected] pkg:cargo/[email protected]
Mirror all versions of a package
proxy mirror pkg:npm/lodash
Mirror from a CycloneDX or SPDX SBOM
proxy mirror --sbom sbom.cdx.json
Preview what would be mirrored
proxy mirror --dry-run pkg:npm/lodash
Control parallelism
proxy mirror --concurrency 8 pkg:npm/[email protected]
ミラーコマンドは、`serve`と同じストレージおよびデータベースフラグを受け入れます。すでにキャッシュされたアーティファクトはスキップされます。
サーバーが実行中の場合は、ミラーAPIも利用できます。```bash
# Start a mirror job
curl -X POST http://localhost:8080/api/mirror \
-H "Content-Type: application/json" \
-d '{"purls": ["pkg:npm/[email protected]"]}'
# Check job status
curl http://localhost:8080/api/mirror/mirror-1
# Cancel a running job
curl -X DELETE http://localhost:8080/api/mirror/mirror-1
stats
サーバーを起動せずにキャッシュ統計情報を表示します。```bash
Text output
proxy stats
JSON output
proxy stats -json
Custom database path
proxy stats -database-path /var/lib/proxy/cache.db
With PostgreSQL
proxy stats -database-driver postgres -database-url postgres://user:pass@localhost/proxy
Show top 20 most popular packages
proxy stats -popular 20
例出力:```
Cache Statistics
================
Packages: 45
Versions: 128
Artifacts: 128
Total size: 892.4 MB
Total hits: 1547
Packages by ecosystem:
npm 32
cargo 13
Most popular packages:
1. npm/lodash (342 hits, 24.7 KB)
2. npm/react (198 hits, 89.3 KB)
3. cargo/serde (156 hits, 234.1 KB)
Recently cached:
npm/[email protected] (2024-01-15 14:32, 54.2 KB)
cargo/[email protected] (2024-01-15 14:28, 412.8 KB)
API エンドポイント
レジストリプロトコル
| エンドポイント | 説明 |
|---|---|
GET / | ダッシュボード(Web UI) |
GET /health | ヘルスチェック(JSON。HTTP 200 で正常、503 で異常) |
GET /stats | キャッシュ統計(JSON) |
GET /metrics | Prometheus メトリクス |
GET /npm/* | npm レジストリプロトコル |
GET /cargo/* | Cargo sparse index プロトコル |
GET /gem/* | RubyGems プロトコル |
GET /go/* | Go モジュールプロキシプロトコル |
GET /hex/* | Hex.pm プロトコル |
GET /pub/* | pub.dev プロトコル |
GET /pypi/* | PyPI simple/JSON API |
GET /maven/* | Maven リポジトリプロトコル |
GET /nuget/* | NuGet V3 API |
GET /composer/* | Composer/Packagist プロトコル |
GET /conan/* | Conan C/C++ プロトコル |
GET /conda/* | Conda/Anaconda プロトコル |
GET /cran/* | CRAN(R)プロトコル |
GET /julia/* | Julia Pkg サーバープロトコル |
GET /helm/{repository}/* | HTTP Helm チャートリポジトリプロトコル |
GET /v2/* | OCI/Docker レジストリプロトコル |
GET /debian/* | Debian/APT リポジトリプロトコル |
GET /rpm/* | RPM/Yum リポジトリプロトコル |
ミラー API
| エンドポイント | 説明 |
|---|---|
POST /api/mirror | ミラージョブを開始(purls を含む JSON ボディ) |
GET /api/mirror/{id} | ジョブのステータスと進捗を取得 |
DELETE /api/mirror/{id} | 実行中のジョブをキャンセル |
エンリッチメント API
このプロキシは、パッケージメタデータのエンリッチメント、脆弱性スキャン、および古いバージョン検出のための REST エンドポイントを提供します。
| エンドポイント | 説明 |
|---|---|
GET /api/package/{ecosystem}/{name} | パッケージメタデータを取得 |
GET /api/package/{ecosystem}/{name}/{version} | 脆弱性を含むバージョンメタデータを取得 |
GET /api/vulns/{ecosystem}/{name} | パッケージのすべての脆弱性を取得 |
GET /api/vulns/{ecosystem}/{name}/{version} | 特定バージョンの脆弱性を取得 |
POST /api/outdated | 複数のパッケージの古いバージョンをチェック |
POST /api/bulk | パッケージメタデータの一括検索 |
パッケージメタデータを取得```bash
curl http://localhost:8080/api/package/npm/lodash
The `-p` flag is used to specify the port number, and the `-t` flag is used to specify the target IP address. The `-m` flag is used to specify the mode, which can be `tcp`, `udp`, or `icmp`. The `-f` flag is used to specify the output file name. The `-v` flag is used to enable verbose output. The `-h` flag is used to display the help menu.```json
{
"ecosystem": "npm",
"name": "lodash",
"latest_version": "4.17.21",
"license": "MIT",
"license_category": "permissive",
"description": "Lodash modular utilities",
"homepage": "https://lodash.com/",
"repository": "https://github.com/lodash/lodash",
"registry_url": "https://registry.npmjs.org"
}
脆弱性のあるバージョンを取得する```bash
curl http://localhost:8080/api/package/npm/lodash/4.17.0
The `-p` flag is used to specify the port number, and the `-h` flag is used to specify the hostname or IP address. The `-t` flag is used to specify the timeout value in seconds. The `-v` flag is used to enable verbose output. The `-q` flag is used to specify the number of queries to send. The `-r` flag is used to specify the number of retries. The `-w` flag is used to specify the wait time between queries. The `-s` flag is used to specify the source IP address. The `-d` flag is used to specify the destination IP address. The `-c` flag is used to specify the number of packets to send. The `-i` flag is used to specify the interval between packets. The `-o` flag is used to specify the output file. The `-e` flag is used to specify the error file. The `-a` flag is used to specify the authentication method. The `-u` flag is used to specify the username. The `-p` flag is used to specify the password. The `-k` flag is used to specify the key file. The `-l` flag is used to specify the log file. The `-m` flag is used to specify the mode. The `-n` flag is used to specify the number of threads. The `-x` flag is used to specify the proxy. The `-y` flag is used to specify the proxy type. The `-z` flag is used to specify the proxy port. The `-A` flag is used to specify the user agent. The `-B` flag is used to specify the base URL. The `-C` flag is used to specify the cookie. The `-D` flag is used to specify the data. The `-E` flag is used to specify the encoding. The `-F` flag is used to specify the file. The `-G` flag is used to specify the GET request. The `-H` flag is used to specify the header. The `-I` flag is used to specify the HEAD request. The `-J` flag is used to specify the JSON data. The `-K` flag is used to specify the key. The `-L` flag is used to specify the location. The `-M` flag is used to specify the method. The `-N` flag is used to specify the name. The `-O` flag is used to specify the output. The `-P` flag is used to specify the path. The `-Q` flag is used to specify the query. The `-R` flag is used to specify the redirect. The `-S` flag is used to specify the status. The `-T` flag is used to specify the type. The `-U` flag is used to specify the URL. The `-V` flag is used to specify the version. The `-W` flag is used to specify the wordlist. The `-X` flag is used to specify the XML data. The `-Y` flag is used to specify the YAML data. The `-Z` flag is used to specify the zip file.```json
{
"package": {
"ecosystem": "npm",
"name": "lodash",
"latest_version": "4.17.21",
"license": "MIT",
"license_category": "permissive"
},
"version": {
"ecosystem": "npm",
"name": "lodash",
"version": "4.17.0",
"license": "MIT",
"published_at": "2016-06-17T03:59:56Z",
"yanked": false,
"is_outdated": true
},
"vulnerabilities": [
{
"id": "GHSA-p6mc-m468-83gw",
"summary": "Prototype Pollution in lodash",
"severity": "HIGH",
"cvss_score": 7.4,
"fixed_version": "4.17.12"
}
],
"is_outdated": true,
"license_category": "permissive"
}
古いパッケージを確認する```bash
curl -X POST http://localhost:8080/api/outdated
-H "Content-Type: application/json"
-d '{
"packages": [
{"ecosystem": "npm", "name": "lodash", "version": "4.17.0"},
{"ecosystem": "pypi", "name": "requests", "version": "2.25.0"}
]
}'
The `-p` flag is used to specify the port number, and the `-t` flag is used to specify the target IP address. The `-m` flag is used to specify the mode, which can be `tcp`, `udp`, or `icmp`. The `-s` flag is used to specify the source IP address, and the `-d` flag is used to specify the destination IP address. The `-c` flag is used to specify the number of packets to send, and the `-i` flag is used to specify the interval between packets. The `-v` flag is used to enable verbose output, and the `-h` flag is used to display the help message.```json
{
"results": [
{
"ecosystem": "npm",
"name": "lodash",
"version": "4.17.0",
"latest_version": "4.17.21",
"is_outdated": true
},
{
"ecosystem": "pypi",
"name": "requests",
"version": "2.25.0",
"latest_version": "2.31.0",
"is_outdated": true
}
]
}
一括パッケージ検索```bash
curl -X POST http://localhost:8080/api/bulk
-H "Content-Type: application/json"
-d '{
"purls": [
"pkg:npm/[email protected]",
"pkg:pypi/[email protected]"
]
}'
The `-p` flag is used to specify the port number, and the `-t` flag is used to specify the target IP address. The `-m` flag is used to specify the mode, which can be `tcp`, `udp`, or `icmp`. The `-f` flag is used to specify the output file name. The `-v` flag is used to enable verbose output. The `-h` flag is used to display the help menu.```json
{
"packages": {
"pkg:npm/lodash": {
"ecosystem": "npm",
"name": "lodash",
"latest_version": "4.17.21",
"license": "MIT",
"license_category": "permissive"
},
"pkg:pypi/requests": {
"ecosystem": "pypi",
"name": "requests",
"latest_version": "2.31.0",
"license": "Apache-2.0",
"license_category": "permissive"
}
}
}
Stats Response (HTTP endpoint)```json
{ "cached_artifacts": 142, "total_size_bytes": 523456789, "total_size": "499.2 MB", "storage_url": "file:///path/to/cache/artifacts", "database_path": "./cache/proxy.db" }
## 動作の仕組み
1. パッケージマネージャーがプロキシにパッケージのメタデータを要求する
2. プロキシがアップストリームからメタデータを取得し、アーティファクトのURLをプロキシを指すように書き換える
3. パッケージマネージャーがアーティファクト(tarball、crateなど)を要求する
4. プロキシがローカルキャッシュを確認する:
- **キャッシュヒット**: ローカルストレージから配信する
- **キャッシュミス**: アップストリームから取得し、ローカルに保存してクライアントに配信する
5. 同じアーティファクトへの後続の要求はキャッシュから配信される```
┌─────────────┐ ┌─────────┐ ┌──────────┐
│ npm/cargo │────▶│ proxy │────▶│ upstream │
│ client │◀────│ │◀────│ registry │
└─────────────┘ └─────────┘ └──────────┘
│
▼
┌─────────┐
│ cache │
│ storage │
└─────────┘
Web インターフェース
プロキシは /ui 配下で Web UI を提供します。別途フロントエンドのビルドは不要です。テンプレートとアセットはバイナリに埋め込まれています。GET / は /ui/ にリダイレクトされます。UI は独自のプレフィックスの下にマウントされるため、リバースプロキシはパッケージエンドポイントとは異なるアクセスルールを UI に適用できます(たとえば、PathPrefix(/ui) に認証を要求しつつ、/npm、/pypi などはビルドマシンに開放したままにするなど)。
- ダッシュボード (
/ui/) -- キャッシュ統計、人気パッケージ、最近キャッシュされたアーティファクト、脆弱性の概要。 - インストールガイド (
/ui/install) -- エコシステムごとの設定手順。ここで調べ直す必要はありません。 - パッケージブラウザ (
/ui/packages) -- キャッシュされたすべてのパッケージを、エコシステムによるフィルタリングと、ヒット数・サイズ・名前・脆弱性数による並べ替えで閲覧できます。 - 検索 (
/ui/search?q=...) -- キャッシュされたパッケージを名前で検索します。 - パッケージ詳細 (
/ui/package/{ecosystem}/{name}) -- パッケージのメタデータ、ライセンス、脆弱性、バージョン一覧。2 つのバージョンを選択して比較できます。 - バージョン詳細 (
/ui/package/{ecosystem}/{name}/{version}) -- バージョンごとのメタデータ、整合性ハッシュ、アーティファクトのキャッシュ状態、ヒット数。 - ソースブラウザ (
/ui/package/{ecosystem}/{name}/{version}/browse) -- キャッシュされたアーカイブ内のファイルを、テキストファイルのシンタックスハイライトと画像プレビュー付きで閲覧できます。 - バージョン差分 (
/ui/package/{ecosystem}/{name}/compare/{v1}...{v2}) -- キャッシュされた 2 つのバージョンのサイドバイサイド差分を表示し、追加・削除・変更されたファイルを示します。
モニタリング
プロキシは GET /metrics で Prometheus メトリクスを公開します。すべてのメトリクス名には proxy_ というプレフィックスが付きます。
| メトリクス | タイプ | ラベル | 説明 |
|---|---|---|---|
proxy_requests_total | counter | ecosystem, status | パッケージエコシステムと HTTP ステータス別のプロキシ応答 |
proxy_request_duration_seconds | histogram | ecosystem, status | プロキシリクエストの所要時間 |
proxy_cache_hits_total | counter | ecosystem | キャッシュヒット数 |
proxy_cache_misses_total | counter | ecosystem | キャッシュミス数 |
proxy_cache_size_bytes | gauge | キャッシュされたアーティファクトの合計サイズ | |
proxy_cached_artifacts_total | gauge | キャッシュされたアーティファクトの数 | |
proxy_upstream_fetch_duration_seconds | histogram | ecosystem | アップストリームからの取得に費やした時間 |
proxy_upstream_errors_total | counter | ecosystem, error_type | アップストリーム取得の失敗 |
proxy_storage_operation_duration_seconds | histogram | operation | ストレージの読み取り/書き込みレイテンシ |
proxy_storage_errors_total | counter | operation | ストレージの読み取り/書き込みの失敗 |
proxy_active_requests | gauge | 処理中のリクエスト数 | |
proxy_health_probe_failures_total | counter | step | 失敗したステップ別のストレージヘルスプローブ失敗数(write、size、read、verify、delete)。 |
キャッシュサイズとアーティファクト数は 60 秒ごとに更新されます。残りのメトリクスは各リクエストのたびに更新されます。
ヘルスチェック
/health はサブシステムの健全性に関する構造化された JSON レポートを返します。すべてのチェックが成功した場合は HTTP 200、いずれかが失敗した場合は 503 を返します。```json
{
"status": "ok",
"checks": {
"database": {"status": "ok"},
"storage": {"status": "ok"}
}
}
失敗したチェックには`"error"`フィールドが含まれます。ストレージの失敗には、どのプローブステップが失敗したかを示す`"step"`フィールド(`write`、`size`、`read`、`verify`、`delete`)も含まれます。データベースチェックが失敗した場合、ストレージエントリは`{"status": "skipped"}`を報告するため、レスポンスには常に同じキーセットが含まれます。
ストレージプローブの結果は、リモートバックエンドのプローブコストを抑えるために、`health.storage_probe_interval`(デフォルト30秒)の間キャッシュされます。プローブは最大10秒間(ハードコードされたプローブごとのタイムアウト)内部ミューテックスを保持するため、`/health`はKubernetesの**readiness**プローブとして意図されており、livenessプローブではありません。遅いS3ラウンドトリップはポッドをローテーションから外すべきであり、再起動させるべきではありません。
Prometheus用のスクレイプ設定:```yaml
scrape_configs:
- job_name: git-pkgs-proxy
static_configs:
- targets: ["localhost:8080"]
Production Deployment
Systemd サービス
/etc/systemd/system/proxy.service を作成します:```ini
[Unit]
Description=git-pkgs proxy
After=network.target
[Service] Type=simple User=proxy ExecStart=/usr/local/bin/proxy -config /etc/proxy/config.yaml Restart=always RestartSec=5
[Install] WantedBy=multi-user.target
有効にして起動します:```bash
sudo systemctl enable proxy
sudo systemctl start proxy
Docker
Dockerfile がリポジトリに含まれています。ビルドして実行します:```bash docker build -t proxy . docker run -p 8080:8080 -v proxy-data:/data proxy
Postgres と S3 を使用する場合:```bash
docker run -p 8080:8080 \
-e PROXY_DATABASE_DRIVER=postgres \
-e PROXY_DATABASE_URL=postgres://user:pass@db:5432/proxy \
-e PROXY_STORAGE_URL=s3://my-bucket?region=us-east-1 \
-e AWS_ACCESS_KEY_ID=... \
-e AWS_SECRET_ACCESS_KEY=... \
proxy
リバースプロキシの背後で
nginx、Apache、またはその他のリバースプロキシの背後で実行する場合、base_url を公開URLに設定します:```yaml
base_url: "https://proxy.example.com"
UI がパッケージエンドポイントとは異なるホスト名で到達される場合(たとえば、UI がパブリックにドメイン上で公開され、ビルドマシンが Docker ネットワークエイリアスにアクセスする場合)は、`ui_base_url` を個別に設定してください。`base_url` はパッケージマネージャーとメタデータ書き換えが使用する URL です。`ui_base_url` は Web UI を訪れる人間に表示される URL(canonical/`og:url` タグとインストールガイドのバナー)です。```yaml
base_url: "http://pkg-proxy:8080" # internal alias for build machines
ui_base_url: "https://proxy.example.com/ui" # public UI URL
ui_base_url が未設定の場合、base_url にデフォルト設定されます。
警告: プロキシはUIとパッケージエンドポイントを同じリスナーで提供します。
ui_base_urlを設定しても、UIが人間に公開するURLが変わるだけで、同じホスト名とポートでパッケージエンドポイントに到達できなくなるわけではありません。プロキシを公開リバースプロキシの背後に配置する場合は、公開ルートをPathPrefix(/ui)(またはプロキシの同等の設定)に制限してください。そうしないと、/npm、/pypi、およびその他のパッケージエンドポイントがUIと一緒に公開されたままになります。
nginxの例。パッケージエンドポイントは内部リスナーでのみ到達可能にし、公開ホストをUIに制限します:```nginx server { listen 443 ssl; server_name proxy.example.com;
location /ui/ {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_buffering off;
}
location / {
return 404;
}
}
Traefikの例では、`PathPrefix(/ui)`を使用して、パブリックルーターがUIトラフィックのみに一致するようにしています。```yaml
labels:
traefik.enable: "true"
traefik.http.services.pkg-proxy.loadbalancer.server.port: "8080"
traefik.http.routers.pkg-proxy.rule: "Host(`proxy.example.com`) && PathPrefix(`/ui`)"
traefik.http.routers.pkg-proxy.entrypoints: "websecure"
キャッシュ管理
プロキシは、設定されたストレージディレクトリにアーティファクトを以下の構造で保存します:``` cache/artifacts/ ├── npm/ │ └── lodash/ │ └── 4.17.21/ │ └── lodash-4.17.21.tgz ├── cargo/ │ └── serde/ │ └── 1.0.193/ │ └── serde-1.0.193.crate ├── oci/ │ └── library/nginx/ │ └── sha256:abc123.../ │ └── sha256:abc123... ├── deb/ │ └── nginx/ │ └── 1.18.0-6/ │ └── nginx_1.18.0-6_amd64.deb └── rpm/ └── nginx/ └── 1.24.0-1.fc39/ └── nginx-1.24.0-1.fc39.x86_64.rpm
キャッシュメタデータはSQLite(デフォルト)またはPostgreSQLに保存されます。ローカルキャッシュをクリアするには:```bash
rm -rf ./cache/artifacts/*
rm ./cache/proxy.db
プロキシは次回起動時にデータベースを再作成します。
ソースからのビルド
要件:
- Go(プロジェクトのバージョンは
go.modに宣言されています)```bash git clone https://github.com/git-pkgs/proxy.git cd proxy go build -o proxy ./cmd/proxy
テストを実行:```bash
go test ./...
ライセンス
GPL-3.0-or-later