dokhanehدوخانه
v0.1.0 · open source · MITنسخهٔ ۰٫۱٫۰ · متن‌باز · MIT

One release, two homes. Always installable.یک نسخه، دو خانه. همیشه قابل نصب.

dokhaneh publishes every release to GitHub and to domestic hosts (ArvanCloud, Liara, a Gitea mirror) in one step. An Ed25519-signed manifest proves every copy is identical, and a fallback install.sh keeps working when the internet goes national-only.دوخانه هر نسخه را در یک گام هم در گیت‌هاب و هم در میزبان‌های داخلی (آروان‌کلاد، لیارا و آینهٔ گیتی) منتشر می‌کند. یک مانیفست امضاشده با Ed25519 ثابت می‌کند همهٔ نسخه‌ها یکسان‌اند و یک install.sh جایگزین وقتی اینترنت ملی می‌شود هم کار می‌کند.

$pip install git+https://github.com/mrzroot/dokhaneh

Not a circumvention tool: it only uses legitimate hosts you control.ابزار دور زدن فیلترینگ نیست: فقط از میزبان‌های قانونی خودتان استفاده می‌کند.

dokhaneh statusv1.2.0
releasev1.2.0 · sig githubglobal● UP arvans3.ir-thr-at1 · domestic● UP liarastorage.c2 · domestic● UP giteagit.example.ir · domestic● UP
Why two homesچرا دو خانه

Your users shouldn't lose your software overnight.کاربرانتان نباید یک‌شبه نرم‌افزارتان را از دست بدهند.

When Iran's internet goes national-only or GitHub drops off a whitelist, release downloads, install scripts and docs disappear for everyone inside the country. dokhaneh keeps a second, verifiable home for them.وقتی اینترنت ایران ملی می‌شود یا گیت‌هاب از فهرست سفید بیرون می‌افتد، فایل‌های انتشار، اسکریپت نصب و مستندات برای همهٔ کاربران داخل کشور ناپدید می‌شوند. دوخانه برایشان یک خانهٔ دوم و قابل‌راستی‌آزمایی نگه می‌دارد.

withoutبدون دوخانه

curl … | sh → timeoutcurl … | sh ← مهلت تمام شد

Install scripts hard-code github.com. Users copy random re-uploads from Telegram channels with no way to know if they were tampered with.اسکریپت‌های نصب به github.com گره خورده‌اند. کاربران نسخه‌های دست‌به‌دست‌شده را از کانال‌های تلگرام برمی‌دارند و راهی برای فهمیدن دست‌کاری ندارند.

with dokhanehبا دوخانه

github ✖ → arvan ✓ verifiedgithub ✖ ← arvan ✓ تأییدشده

The installer tries GitHub first, falls back to your domestic mirrors, checks the Ed25519 signature and every SHA-256, and installs the exact bytes you published.نصب‌کننده اول گیت‌هاب را امتحان می‌کند، بعد سراغ آینه‌های داخلی می‌رود، امضای Ed25519 و همهٔ هش‌های SHA-256 را بررسی می‌کند و دقیقاً همان بایت‌هایی را نصب می‌کند که شما منتشر کرده‌اید.

How it worksروش کار

Sign once. Mirror everywhere. Verify anywhere.یک بار امضا، همه‌جا آینه، هر جا راستی‌آزمایی.

One command in your tag workflow does all four steps. One mirror failing never blocks the others.یک دستور در گردش‌کار تگ هر چهار گام را انجام می‌دهد. خرابی یک آینه بقیه را متوقف نمی‌کند.

Manifestمانیفست

Hashes every artifact, the docs archive and install.sh into manifest.json (SHA-256 + size).هش همهٔ فایل‌ها، آرشیو مستندات و install.sh را در manifest.json (SHA-256 و اندازه) می‌نویسد.

Signامضا

Signs it with your Ed25519 key from DOKHANEH_SIGNING_KEY; refuses if the key doesn't match the public one.با کلید Ed25519 از DOKHANEH_SIGNING_KEY امضا می‌کند و اگر کلید با کلید عمومی نخواند، امضا نمی‌کند.

Publishانتشار

Uploads byte-identical copies to GitHub Releases, ArvanCloud and Liara S3, and a Gitea release plus a git mirror.نسخه‌های کاملاً یکسان را در GitHub Releases، فضای S3 آروان‌کلاد و لیارا و انتشار و آینهٔ گیتی بارگذاری می‌کند.

Verifyراستی‌آزمایی

verify --deep proves every mirror serves the same signed release; status shows what's reachable from here.verify --deep ثابت می‌کند همهٔ آینه‌ها همان نسخهٔ امضاشده را دارند و status نشان می‌دهد از همین‌جا چه چیزی در دسترس است.

🏠

Four targetsچهار مقصد

GitHub, ArvanCloud and Liara object storage, and Gitea, described in one dokhaneh.yml. Secrets only come from env vars.گیت‌هاب، فضای ذخیره‌سازی آروان‌کلاد و لیارا و گیتی در یک فایل dokhaneh.yml. کلیدها فقط از متغیرهای محیطی خوانده می‌شوند.

🔏

One key verifies allیک کلید برای همه

Every mirror gets the same bytes, so one public key checks them all. A compromised mirror can withhold files but can't modify them.همهٔ آینه‌ها همان بایت‌ها را دارند، پس یک کلید عمومی همه را بررسی می‌کند. آینهٔ آلوده می‌تواند فایل را نگه دارد، اما نمی‌تواند تغییرش دهد.

🧯

Fallback installerنصب‌کنندهٔ جایگزین

POSIX sh, global then domestic, signature via openssl pkeyutl, version pinning against rollback, SHA-256 per file.POSIX sh، اول جهانی بعد داخلی، امضا با openssl pkeyutl، قفل نسخه در برابر بازگشت به نسخهٔ قدیمی و SHA-256 برای هر فایل.

📡

status from anywhereوضعیت از هر جا

Run it inside Iran, outside, or in CI: each target is UP, MISSING or DOWN with latency.داخل ایران، خارج یا در CI اجرا کنید: هر مقصد UP، MISSING یا DOWN با زمان پاسخ.

📚

Docs, mirroredمستندات هم آینه می‌شوند

Your MkDocs or Docusaurus build becomes a browsable site on the S3 mirrors and a signed docs archive everywhere.خروجی MkDocs یا Docusaurus شما روی آینه‌های S3 سایت قابل‌مرور و در همه‌جا آرشیو امضاشده می‌شود.

🤖

GitHub ActionGitHub Action

One step in your tag workflow with publish, sign, verify or status, and outputs for succeeded and failed targets.یک گام در گردش‌کار تگ با publish، sign، verify یا status و خروجی برای مقصدهای موفق و ناموفق.

Quick startشروع سریع

Five commands to two homes.پنج دستور تا دو خانه.

# install (Python 3.10+)
pip install git+https://github.com/mrzroot/dokhaneh

# config + Ed25519 keypair
dokhaneh init      # commented dokhaneh.yml
dokhaneh keygen    # public → yml, private → secret

# publish, prove, check
dokhaneh publish --version 1.2.0 --dry-run
dokhaneh publish --version 1.2.0
dokhaneh verify  --version 1.2.0 --deep
dokhaneh status  --version 1.2.0

End users install with one line from your domestic mirror:کاربران نهایی با یک خط از آینهٔ داخلی شما نصب می‌کنند:

curl -fsSL https://myapp-releases.s3.ir-thr-at1.arvanstorage.ir/install.sh | sh
dokhaneh.ymldokhaneh.yml

One file describes it all.یک فایل همه‌چیز را توصیف می‌کند.

project: { name: myapp, tag: "v{version}" }
artifacts: ["dist/*.tar.gz"]
docs: site/
signing:
  private_key_env: DOKHANEH_SIGNING_KEY
  public_key: "…output of dokhaneh keygen…"
targets:
  - { name: github, type: github, repo: me/myapp }
  - { name: arvan,  type: arvan,  bucket: myapp-releases }
  - { name: liara,  type: liara,  bucket: myapp }
  - { name: gitea,  type: gitea,
      url: https://git.example.ir, repo: me/myapp, mirror: true }
# keys: *_ACCESS_KEY / *_SECRET_KEY / *_TOKEN env vars
In CIدر CI

Add one step to your tag workflow.یک گام به گردش‌کار تگ اضافه کنید.

on: { push: { tags: ["v*"] } }
permissions: { contents: write }
jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # … build dist/ and site/ …
      - uses: mrzroot/dokhaneh@v0.1.0
        with:
          signing-key: ${{ secrets.DOKHANEH_SIGNING_KEY }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          ARVAN_ACCESS_KEY: ${{ secrets.ARVAN_ACCESS_KEY }}
          ARVAN_SECRET_KEY: ${{ secrets.ARVAN_SECRET_KEY }}
Security modelمدل امنیتی

Trust the key, not the mirror.به کلید اعتماد کنید، نه به آینه.

  • The private key is only read from an env var and never written to disk by publish.کلید خصوصی فقط از متغیر محیطی خوانده می‌شود و publish هرگز آن را روی دیسک نمی‌نویسد.
  • publish refuses to sign if the private key doesn't match signing.public_key.اگر کلید خصوصی با signing.public_key نخواند، publish امضا نمی‌کند.
  • The installer checks that the manifest is for the expected version, so an old signed release can't be replayed.نصب‌کننده بررسی می‌کند مانیفست برای همان نسخهٔ مورد انتظار باشد تا نسخهٔ امضاشدهٔ قدیمی دوباره جا زده نشود.
  • Gitea tokens stay in-process and are redacted from all error output.توکن گیتی فقط در حافظهٔ فرایند می‌ماند و از همهٔ پیام‌های خطا حذف می‌شود.
  • Publish your public key in more than one place: README, website and the script itself.کلید عمومی را در بیش از یک جا منتشر کنید: README، وب‌سایت و خود اسکریپت.
FAQپرسش‌های پرتکرار

Questionsپرسش‌ها

Is dokhaneh a filter-circumvention tool?آیا دوخانه ابزار دور زدن فیلترینگ است؟

No. It doesn't tunnel, proxy or bypass anything. It publishes your own files to hosts you have accounts with, and lets users verify they are genuine.خیر. هیچ تونل، پراکسی یا دور زدنی ندارد. فقط فایل‌های خودتان را در میزبان‌هایی که در آن حساب دارید منتشر می‌کند و به کاربران امکان می‌دهد اصالتشان را بررسی کنند.

Which hosts are supported?چه میزبان‌هایی پشتیبانی می‌شوند؟

GitHub Releases, ArvanCloud and Liara object storage (any S3-compatible bucket works through the s3 type), and Gitea releases plus a git mirror of your branch and tags.GitHub Releases، فضای ذخیره‌سازی آروان‌کلاد و لیارا (هر سطل سازگار با S3 هم با نوع s3 کار می‌کند) و انتشار گیتی به‌همراه آینهٔ گیت از شاخه و تگ‌ها.

What do end users need?کاربران نهایی به چه چیزی نیاز دارند؟

A POSIX shell, curl or wget, and OpenSSL 3.0 or newer for Ed25519 verification. The public key is embedded in install.sh.یک شل POSIX، curl یا wget و OpenSSL نسخهٔ ۳٫۰ یا جدیدتر برای راستی‌آزمایی Ed25519. کلید عمومی داخل install.sh قرار دارد.

Has it been tested against real Arvan, Liara and Gitea accounts?روی حساب واقعی آروان، لیارا و گیتی آزموده شده است؟

Not yet. The 42 tests use mocked GitHub, S3 and Gitea APIs and run the real install.sh against local mirrors. Reports from real deployments are very welcome.هنوز نه. ۴۲ آزمون با APIهای شبیه‌سازی‌شدهٔ گیت‌هاب، S3 و گیتی اجرا می‌شوند و install.sh واقعی را روی آینه‌های محلی می‌آزمایند. گزارش استفادهٔ واقعی بسیار ارزشمند است.

Is it on PyPI?در PyPI هست؟

Not yet: install it from GitHub with pip, or use the composite GitHub Action.هنوز نه؛ با pip از گیت‌هاب نصب کنید یا از GitHub Action استفاده کنید.