آینه برای pypi.org، npm، crates.io، Rust، Zig و کامپایلرهایشان
وقتی crates.io، گیتهاب، static.rust-lang.org یا ziglang.org کند یا در دسترس نیستند، دانلودهای cargo، rustup و zig را از راه زرین بگیرید. هر فایل با هشی که ابزارهایتان از قبل میدانند سنجیده میشود، پس آینه نمیتواند چیزی را عوض کند.
**آینه** (mirror) رونوشتی از فایلهای یک سایت دیگر است که نزدیکتر به شما نگه داشته میشود. وقتی pypi.org، npmjs.com، crates.io، گیتهاب یا ziglang.org کند، مسدود یا از کار افتادهاند، pip، uv، npm، cargo، rustup و zig میتوانند از راه زرین دانلود کنند.
## چرا میشود به این آینه اعتماد کرد
معمولاً آینه یک خطر است: کسی که آن را میگرداند میتواند فایل تغییریافتهای به شما بدهد. این آینهها طوری ساخته شدهاند که چنین چیزی ممکن نباشد:
1. زرین پیش از نگه داشتن هر فایل، آن را با هشی میسنجد که از منبع اصلی میآید: sha256 فهرست pypi.org برای بستههای پایتون، مقدار integrity سند بستهٔ npm برای بستههای npm، چکسام فهرست crates.io برای crateها، و هشی که در `build.zig.zon` شما نوشته شده برای بستههای Zig.
2. وقتی فایل به شما میرسد، cargo یا zig همان هش را دوباره روی رایانهٔ خودتان میسنجد. فایلی که جور نباشد رد میشود.
پس بدترین کاری که آینه میتواند بکند پاسخ ندادن است؛ هرگز نمیتواند کد دیگری به شما بدهد. (نصب خود Rust با rustup کمی فرق دارد؛ [بخش خودش](#خود-rust-rustup) میگوید چطور.) فایلی هم که زرین یک بار آورده، وقتی سایت اصلی از کار افتاده باشد همچنان کار میکند.
## همه با هم: zev mirror
اگر دستور `zev` را دارید ([نصبش کنید](/docs/fa/installation))، یک خط pip، uv، npm، cargo و rustup را تنظیم میکند:
```bash
zev mirror on
```
`zev mirror` نشان میدهد چه چیزی تنظیم شده، `zev mirror on pip cargo` فقط چندتا را انتخاب میکند، و `zev mirror off` همه را برمیگرداند. zev فقط یک بخش با علامت روشن به فایل تنظیمات خود هر ابزار اضافه میکند و هرگز تنظیمی را که خودتان گذاشتهاید عوض نمیکند: اگر مثلاً `~/.npmrc` شما از قبل به رجیستری دیگری اشاره دارد، zev آن را دست نمیزند و به شما میگوید. برای پروژهٔ Zig، دستور `zev mirror zig` (در پوشهٔ پروژه) `build.zig.zon` را به آینه ارجاع میدهد و آنچه وابستگیهایش لازم دارند را میآورد؛ `zev mirror zig --undo` نشانیها را برمیگرداند.
بخشهای زیر هر ابزار را دستی توضیح میدهند.
## پایتون: pip و uv
فهرست پایتون زرین هم پروژههای خودتان در زرین را دارد و هم همهٔ pypi.org را:
```bash
pip config set global.index-url https://api.zaryn.xyz/v1/packages/pypi/all/simple/
# uv
export UV_DEFAULT_INDEX=https://api.zaryn.xyz/v1/packages/pypi/all/simple/
# و خود پایتون، برای uv python install
export UV_PYTHON_INSTALL_MIRROR=https://api.zaryn.xyz/v1/packages/python/-/standalone
```
هر فایل pypi.org با sha256 فهرست pypi.org سنجیده میشود و ساختهای پایتون با SHA256SUMS انتشار خودشان. نامی که در زرین هست همیشه از زرین میآید، پس بستهٔ همنامی که کسی در pypi.org منتشر کند نمیتواند وارد شود. بیشتر در [بستههای پایتون](/docs/fa/packages-pypi).
## جاوااسکریپت: npm
```bash
npm config set registry https://api.zaryn.xyz/v1/packages/npm-mirror/
```
pnpm، yarn و bun همین تنظیم را میخوانند. هر tarball با مقدار *integrity* (sha512) سند بستهٔ npm سنجیده میشود؛ همان مقداری که npm پس از دانلود میسنجد. بستههایی که در زرین منتشر میکنید خط scope خودشان را در `.npmrc` نگه میدارند ([بستههای npm](/docs/fa/packages-npm) را ببینید)؛ آینه برای بقیه است.
## crateهای Rust
این را به `~/.cargo/config.toml` اضافه کنید (فایل تنظیماتی که cargo هر بار میخواند؛ اگر نیست بسازیدش):
```toml
[source.crates-io]
replace-with = "zaryn"
[source.zaryn]
registry = "sparse+https://api.zaryn.xyz/v1/packages/cargo/mirror/index/"
```
- `[source.crates-io] replace-with = "zaryn"` به cargo میگوید: هر وقت میخواستی به crates.io بروی، به منبعی به نام `zaryn` برو.
- `[source.zaryn]` میگوید آن کجاست.
همین. `cargo build`، `cargo add`، `cargo update` و `cargo install` حالا crateهای crates.io را از راه زرین میگیرند و در پروژههایتان چیز دیگری عوض نمیشود: `Cargo.toml` و `Cargo.lock` همان میمانند، و همتیمیهایی که این تنظیم را ندارند همچنان از crates.io دانلود میکنند.
پشت صحنه چه میشود:
- cargo فایل فهرست یک crate را (فهرست نسخهها و چکسامهایشان) از زرین میخواهد. اگر رونوشت زرین کمتر از ۵ دقیقه عمر داشته باشد همان را میدهد، وگرنه از crates.io میپرسد. اگر crates.io پاسخ ندهد، رونوشتی را که زرین دارد میگیرید.
- cargo یک فایل `.crate` میخواهد. زرین رونوشتش را میفرستد، یا آن را از crates.io دانلود میکند، SHA-256 اش را با چکسام فهرست مقایسه میکند، و فقط آن وقت نگهش میدارد و میفرستد.
برای کنار گذاشتن آینه، همان خطها را پاک کنید.
## خود Rust (rustup)
rustup، ابزاری که Rust را نصب و بهروز میکند، هم میتواند از راه زرین دانلود کند. پیش از اجرایش دو متغیر را تنظیم کنید:
```bash
export RUSTUP_DIST_SERVER=https://api.zaryn.xyz/v1/packages/rust/-
export RUSTUP_UPDATE_ROOT=https://api.zaryn.xyz/v1/packages/rust/-/rustup
```
- `RUSTUP_DIST_SERVER` جایی است که خود Rust از آن میآید (کامپایلر، cargo، کتابخانهٔ استاندارد).
- `RUSTUP_UPDATE_ROOT` جایی است که rustup نسخههای تازهٔ خودش را از آن میگیرد.
این دو خط را در `~/.bashrc` (یا فایل شروع شل خودتان) بگذارید تا همیشه تنظیم بمانند. سپس rustup را مثل همیشه به کار ببرید:
```bash
# نصب اول، با اسکریپت نصب که آن هم از راه زرین میآید
curl -sSf https://api.zaryn.xyz/v1/packages/rust/-/rustup/rustup-init.sh | sh
# بعدها
rustup update
rustup target add wasm32-unknown-unknown
```
زرین پیش از نگه داشتن هر فایل، آن را با فایل `.sha256` که static.rust-lang.org کنارش منتشر میکند میسنجد، و rustup هر دانلود را با چکسامهای فایل channel میسنجد. خود فایل channel را زرین از static.rust-lang.org با HTTPS گرفته و به شما میدهد؛ این تنها جایی است که به زرین تکیه میکنید، مثل هر آینهٔ دیگر Rust. وقتی static.rust-lang.org در دسترس نیست، آخرین channel که زرین دارد کار میکند.
## وابستگیهای Zig
Zig تنظیمی برای آینه ندارد: هر وابستگی در `build.zig.zon` نشانی خودش را دارد. پس به جایش نشانیها عوض میشوند تا از راه زرین بروند، در حالی که هشها دقیقاً همان میمانند (و zig همچنان میسنجدشان).
**در وب:** [بستهها](/packages) را باز کنید، تا **آینهها** پایین بروید، `build.zig.zon` تان را بچسبانید و **ارجاع به زرین** را بزنید؛ یا **ارجاع به زرین و بررسی همه** تا زرین همین حالا هر وابستگی را دانلود کند و هر مشکلی را گزارش دهد. نتیجه را کپی یا دانلود کنید و جای فایلتان بگذارید.
**از ترمینال** (`jq` فایل را از پاسخ بیرون میکشد):
```bash
curl --data-binary @build.zig.zon \
"https://api.zaryn.xyz/v1/packages/zig/-/mirror-zon?warm=1" | jq -r .zon > build.zig.zon.new
mv build.zig.zon.new build.zig.zon
```
وابستگیای مثل
```zig
.known_folders = .{
.url = "https://github.com/ziglibs/known-folders/archive/207c34a16e4365edc20d92c7892f962b3bed46e8.tar.gz",
.hash = "known_folders-0.0.0-Fy-PJsbKAACbDh9bBxR0MMThxZSS6A9RH4apWphNHY70",
},
```
میشود
```zig
.known_folders = .{
.url = "https://api.zaryn.xyz/v1/packages/zig/-/mirror/known_folders-0.0.0-Fy-PJsbKAACbDh9bBxR0MMThxZSS6A9RH4apWphNHY70/github.com/ziglibs/known-folders/archive/207c34a16e4365edc20d92c7892f962b3bed46e8.tar.gz",
.hash = "known_folders-0.0.0-Fy-PJsbKAACbDh9bBxR0MMThxZSS6A9RH4apWphNHY70",
},
```
نشانی تازه هش و نشانی اصلی را در خود دارد، پس دستی هم میشود نوشتش: `https://api.zaryn.xyz/v1/packages/zig/-/mirror/<هش>/<نشانی اصلی بدون https://>`. زرین نسخهٔ اصلی را یک بار دانلود میکند، بررسی میکند هش Zig آن همان هش نشانی باشد، و نگهش میدارد. اگر فایل نشانی اصلی تغییر کرده باشد، زرین ردش میکند؛ درست همان کاری که zig میکرد.
برای برگشتن به نشانیهای اصلی، در وب **برگرداندن** را بزنید، یا به جای `?warm=1` از `?undo=1` استفاده کنید.
### وابستگیهای وابستگیهایتان
وابستگیهایتان `build.zig.zon` خودشان را با نشانیهای خودشان دارند که نمیتوانید عوضشان کنید. ولی zig فقط بستهای را دانلود میکند که از قبل ندارد؛ پس یک بار آنها را از راه زرین بگیرید تا zig به سایت اصلی نیازی نداشته باشد. **ارجاع به زرین و بررسی همه** آنها را فهرست میکند و برای هر بسته دستوری آماده میدهد:
```bash
zig fetch https://api.zaryn.xyz/v1/packages/zig/-/mirror/<hash>/<address>
```
### چه چیزهایی آینه میشوند
- آرشیوهای `https://` از گیتهاب، Codeberg، GitLab، SourceHut، Bitbucket، ziglang.org و چند میزبان کد شناختهشدهٔ دیگر (مدیر سرور میتواند بیشتر اضافه کند). نشانیهای دیگر همانطور میمانند.
- آرشیوهای `.tar.gz`، `.tar.xz`، `.tar.zst`، `.tar` و `.zip`.
- وابستگیهای `git+https://` با `#ref` (zig fetch --save همان commit را آنجا مینویسد). زرین آن commit را همانطور که zig میکند checkout میکند و به شکل `.tar.gz` میدهد؛ هش همان است، چون zig فایلها را هش میکند نه آرشیو را. نشانی آینه این شکلی است: `…/mirror/<hash>/git/github.com/owner/repo?ref=<commit>`.
- وابستگیهایی که از قبل `.hash` دارند. وابستگی تازه اولین بار که `zig build` یا `zig fetch --save` را اجرا میکنید هش میگیرد؛ پس از آن آینهاش کنید.
هر بستهای که زرین از قبل دارد با هشش بهتنهایی هم گرفتنی است: `https://api.zaryn.xyz/v1/packages/zig/-/hash/<هش>`.
## کامپایلرهای Zig
خود کامپایلر Zig از ziglang.org، با نام فایلش:
```bash
curl -LO https://api.zaryn.xyz/v1/packages/zig/-/toolchain/zig-x86_64-linux-0.15.1.tar.xz
curl -LO https://api.zaryn.xyz/v1/packages/zig/-/toolchain/zig-x86_64-linux-0.15.1.tar.xz.minisig
```
- نام دقیق فایلها را از [ziglang.org/download](https://ziglang.org/download/) بردارید: نسخههای منتشرشده (`zig-<cpu>-<system>-<version>.tar.xz`، و `.zip` برای ویندوز) و ساختهای dev (`…-0.16.0-dev.…`).
- ساختهای dev پس از اینکه ziglang.org پاکشان کرد در زرین میمانند، پس پروژهای که به یکی از آنها بسته است همچنان ساخته میشود.
- `https://api.zaryn.xyz/v1/packages/zig/-/toolchain/index.json` فهرست نسخههای ziglang.org است.
دانلود را با کلید بنیاد نرمافزار Zig بسنجید، درست مثل وقتی از ziglang.org دانلود میکنید:
```bash
minisign -Vm zig-x86_64-linux-0.15.1.tar.xz -P RWSGOq2NVecA2UPNdBUZykf1CCb147pkmdtYxgb3Ti+JO/wCYvhbAb/U
```
ابزارهایی که آینههای جامعهٔ Zig را پشتیبانی میکنند میتوانند `https://api.zaryn.xyz/v1/packages/zig/-/toolchain` را یکی از آنها قرار دهند.
## آینهها چقدر نگه میدارند
`https://api.zaryn.xyz/v1/packages/-/mirrors` نشان میدهد هر آینه چه دارد و در ۳۰ روز گذشته به چند دانلود پاسخ داده. وقتی کش پر شود، فایلهایی که مدت بیشتری کسی نخواستهشان جا باز میکنند؛ اگر کسی دوباره لازمشان داشت دوباره دانلود میشوند.
آینه (mirror) رونوشتی از فایلهای یک سایت دیگر است که نزدیکتر به شما نگه داشته میشود. وقتی pypi.org، npmjs.com، crates.io، گیتهاب یا ziglang.org کند، مسدود یا از کار افتادهاند، pip، uv، npm، cargo، rustup و zig میتوانند از راه زرین دانلود کنند.
معمولاً آینه یک خطر است: کسی که آن را میگرداند میتواند فایل تغییریافتهای به شما بدهد. این آینهها طوری ساخته شدهاند که چنین چیزی ممکن نباشد:
زرین پیش از نگه داشتن هر فایل، آن را با هشی میسنجد که از منبع اصلی میآید: sha256 فهرست pypi.org برای بستههای پایتون، مقدار integrity سند بستهٔ npm برای بستههای npm، چکسام فهرست crates.io برای crateها، و هشی که در build.zig.zon شما نوشته شده برای بستههای Zig.
وقتی فایل به شما میرسد، cargo یا zig همان هش را دوباره روی رایانهٔ خودتان میسنجد. فایلی که جور نباشد رد میشود.
پس بدترین کاری که آینه میتواند بکند پاسخ ندادن است؛ هرگز نمیتواند کد دیگری به شما بدهد. (نصب خود Rust با rustup کمی فرق دارد؛ بخش خودش میگوید چطور.) فایلی هم که زرین یک بار آورده، وقتی سایت اصلی از کار افتاده باشد همچنان کار میکند.
اگر دستور zev را دارید (نصبش کنید)، یک خط pip، uv، npm، cargo و rustup را تنظیم میکند:
Terminal
zev mirror on
zev mirror نشان میدهد چه چیزی تنظیم شده، zev mirror on pip cargo فقط چندتا را انتخاب میکند، و zev mirror off همه را برمیگرداند. zev فقط یک بخش با علامت روشن به فایل تنظیمات خود هر ابزار اضافه میکند و هرگز تنظیمی را که خودتان گذاشتهاید عوض نمیکند: اگر مثلاً ~/.npmrc شما از قبل به رجیستری دیگری اشاره دارد، zev آن را دست نمیزند و به شما میگوید. برای پروژهٔ Zig، دستور zev mirror zig (در پوشهٔ پروژه) build.zig.zon را به آینه ارجاع میدهد و آنچه وابستگیهایش لازم دارند را میآورد؛ zev mirror zig --undo نشانیها را برمیگرداند.
فهرست پایتون زرین هم پروژههای خودتان در زرین را دارد و هم همهٔ pypi.org را:
Terminal
pip config set global.index-url https://api.zaryn.xyz/v1/packages/pypi/all/simple/# uvexport UV_DEFAULT_INDEX=https://api.zaryn.xyz/v1/packages/pypi/all/simple/# و خود پایتون، برای uv python installexport UV_PYTHON_INSTALL_MIRROR=https://api.zaryn.xyz/v1/packages/python/-/standalone
هر فایل pypi.org با sha256 فهرست pypi.org سنجیده میشود و ساختهای پایتون با SHA256SUMS انتشار خودشان. نامی که در زرین هست همیشه از زرین میآید، پس بستهٔ همنامی که کسی در pypi.org منتشر کند نمیتواند وارد شود. بیشتر در بستههای پایتون.
npm config set registry https://api.zaryn.xyz/v1/packages/npm-mirror/
pnpm، yarn و bun همین تنظیم را میخوانند. هر tarball با مقدار integrity (sha512) سند بستهٔ npm سنجیده میشود؛ همان مقداری که npm پس از دانلود میسنجد. بستههایی که در زرین منتشر میکنید خط scope خودشان را در .npmrc نگه میدارند (بستههای npm را ببینید)؛ آینه برای بقیه است.
[source.crates-io] replace-with = "zaryn" به cargo میگوید: هر وقت میخواستی به crates.io بروی، به منبعی به نام zaryn برو.
[source.zaryn] میگوید آن کجاست.
همین. cargo build، cargo add، cargo update و cargo install حالا crateهای crates.io را از راه زرین میگیرند و در پروژههایتان چیز دیگری عوض نمیشود: Cargo.toml و Cargo.lock همان میمانند، و همتیمیهایی که این تنظیم را ندارند همچنان از crates.io دانلود میکنند.
پشت صحنه چه میشود:
cargo فایل فهرست یک crate را (فهرست نسخهها و چکسامهایشان) از زرین میخواهد. اگر رونوشت زرین کمتر از ۵ دقیقه عمر داشته باشد همان را میدهد، وگرنه از crates.io میپرسد. اگر crates.io پاسخ ندهد، رونوشتی را که زرین دارد میگیرید.
cargo یک فایل .crate میخواهد. زرین رونوشتش را میفرستد، یا آن را از crates.io دانلود میکند، SHA-256 اش را با چکسام فهرست مقایسه میکند، و فقط آن وقت نگهش میدارد و میفرستد.
RUSTUP_DIST_SERVER جایی است که خود Rust از آن میآید (کامپایلر، cargo، کتابخانهٔ استاندارد).
RUSTUP_UPDATE_ROOT جایی است که rustup نسخههای تازهٔ خودش را از آن میگیرد.
این دو خط را در ~/.bashrc (یا فایل شروع شل خودتان) بگذارید تا همیشه تنظیم بمانند. سپس rustup را مثل همیشه به کار ببرید:
Terminal
# نصب اول، با اسکریپت نصب که آن هم از راه زرین میآیدcurl -sSf https://api.zaryn.xyz/v1/packages/rust/-/rustup/rustup-init.sh | sh# بعدهاrustup updaterustup target add wasm32-unknown-unknown
زرین پیش از نگه داشتن هر فایل، آن را با فایل .sha256 که static.rust-lang.org کنارش منتشر میکند میسنجد، و rustup هر دانلود را با چکسامهای فایل channel میسنجد. خود فایل channel را زرین از static.rust-lang.org با HTTPS گرفته و به شما میدهد؛ این تنها جایی است که به زرین تکیه میکنید، مثل هر آینهٔ دیگر Rust. وقتی static.rust-lang.org در دسترس نیست، آخرین channel که زرین دارد کار میکند.
Zig تنظیمی برای آینه ندارد: هر وابستگی در build.zig.zon نشانی خودش را دارد. پس به جایش نشانیها عوض میشوند تا از راه زرین بروند، در حالی که هشها دقیقاً همان میمانند (و zig همچنان میسنجدشان).
در وب:بستهها را باز کنید، تا آینهها پایین بروید، build.zig.zon تان را بچسبانید و ارجاع به زرین را بزنید؛ یا ارجاع به زرین و بررسی همه تا زرین همین حالا هر وابستگی را دانلود کند و هر مشکلی را گزارش دهد. نتیجه را کپی یا دانلود کنید و جای فایلتان بگذارید.
نشانی تازه هش و نشانی اصلی را در خود دارد، پس دستی هم میشود نوشتش: https://api.zaryn.xyz/v1/packages/zig/-/mirror/<هش>/<نشانی اصلی بدون https://>. زرین نسخهٔ اصلی را یک بار دانلود میکند، بررسی میکند هش Zig آن همان هش نشانی باشد، و نگهش میدارد. اگر فایل نشانی اصلی تغییر کرده باشد، زرین ردش میکند؛ درست همان کاری که zig میکرد.
برای برگشتن به نشانیهای اصلی، در وب برگرداندن را بزنید، یا به جای ?warm=1 از ?undo=1 استفاده کنید.
وابستگیهایتان build.zig.zon خودشان را با نشانیهای خودشان دارند که نمیتوانید عوضشان کنید. ولی zig فقط بستهای را دانلود میکند که از قبل ندارد؛ پس یک بار آنها را از راه زرین بگیرید تا zig به سایت اصلی نیازی نداشته باشد. ارجاع به زرین و بررسی همه آنها را فهرست میکند و برای هر بسته دستوری آماده میدهد:
آرشیوهای https:// از گیتهاب، Codeberg، GitLab، SourceHut، Bitbucket، ziglang.org و چند میزبان کد شناختهشدهٔ دیگر (مدیر سرور میتواند بیشتر اضافه کند). نشانیهای دیگر همانطور میمانند.
آرشیوهای .tar.gz، .tar.xz، .tar.zst، .tar و .zip.
وابستگیهای git+https:// با #ref (zig fetch --save همان commit را آنجا مینویسد). زرین آن commit را همانطور که zig میکند checkout میکند و به شکل .tar.gz میدهد؛ هش همان است، چون zig فایلها را هش میکند نه آرشیو را. نشانی آینه این شکلی است: …/mirror/<hash>/git/github.com/owner/repo?ref=<commit>.
وابستگیهایی که از قبل .hash دارند. وابستگی تازه اولین بار که zig build یا zig fetch --save را اجرا میکنید هش میگیرد؛ پس از آن آینهاش کنید.
هر بستهای که زرین از قبل دارد با هشش بهتنهایی هم گرفتنی است: https://api.zaryn.xyz/v1/packages/zig/-/hash/<هش>.
نام دقیق فایلها را از ziglang.org/download بردارید: نسخههای منتشرشده (zig-<cpu>-<system>-<version>.tar.xz، و .zip برای ویندوز) و ساختهای dev (…-0.16.0-dev.…).
ساختهای dev پس از اینکه ziglang.org پاکشان کرد در زرین میمانند، پس پروژهای که به یکی از آنها بسته است همچنان ساخته میشود.
https://api.zaryn.xyz/v1/packages/zig/-/toolchain/index.json فهرست نسخههای ziglang.org است.
دانلود را با کلید بنیاد نرمافزار Zig بسنجید، درست مثل وقتی از ziglang.org دانلود میکنید:
https://api.zaryn.xyz/v1/packages/-/mirrors نشان میدهد هر آینه چه دارد و در ۳۰ روز گذشته به چند دانلود پاسخ داده. وقتی کش پر شود، فایلهایی که مدت بیشتری کسی نخواستهشان جا باز میکنند؛ اگر کسی دوباره لازمشان داشت دوباره دانلود میشوند.