يمكن تشغيل Rediacc بالكامل على بنيتك التحتية الخاصة. تتضمن صورة Docker المستقلة خادم الحساب وبوابة الويب وموقع التسويق ونقطة توزيع CLI. لا تتطلب أي اعتماديات خارجية على خدمات Rediacc المستضافة.

## صورة Docker

سحب الصورة المستقلة:

```bash
docker pull ghcr.io/rediacc/server:stable
```

التشغيل بالإعدادات الافتراضية:

```bash
docker run -p 80:80 -p 443:443 ghcr.io/rediacc/server:stable
```

تُقدم الصورة:
- Account API على `/account/api/v1/`
- بوابة الويب على `/account/`
- موقع التسويق على `/`
- قطع أثر CLI على `/releases/`
- ثنائيات Renet على `/bin/`

## تثبيت CLI من خادمك

يمكن للمستخدمين تثبيت CLI مباشرةً من خادمك المحلي. يكتشف سكريبت التثبيت قناة التحديث تلقائياً ويُكوِّن CLI للتحقق من خادمك بحثاً عن التحديثات.

```bash
curl -fsSL https://account.example.com/install.sh | \
  REDIACC_SERVER_URL=https://account.example.com bash
```

هذا الأمر الواحد يقوم بما يلي:
1. تنزيل ثنائي CLI من نقطة نهاية `/releases/` بخادمك
2. الاستعلام عن `/account/api/v1/.well-known/server-info` لاكتشاف قناة التحديث
3. كتابة `server.json` بعنوان URL للخادم وقناة التحديث ومفاتيح التشفير
4. تكوين `rdc update` للتحقق من خادمك للتحديثات المستقبلية

لا حاجة لمتغير `REDIACC_CHANNEL`. يقرأ سكريبت التثبيت القناة من تكوين خادمك تلقائياً.

## تكوين CLI بالتكوينات المسماة

للمستخدمين الذين يتصلون بخوادم متعددة (محلي، إنتاج، edge)، تُبقي التكوينات المسماة كل بيئة معزولة:

```bash
# Create a config for your on-premise server
rdc config init --name myserver --server https://account.example.com

# Log in using that config
rdc --config myserver subscription login

# All commands with --config use the on-premise server
rdc --config myserver machine query --name prod-1
```

يخزن كل تكوين مسمى عنوان URL لخادم الحساب الخاص به ورمز الاشتراك. يُؤدي التبديل بين التكوينات إلى تبديل سياق الخادم بأكمله.

## البيئات المعزولة عن الإنترنت

للبيئات التي لا تملك وصولاً إلى الإنترنت، اضبط عنوان URL للخادم وعنوان URL مخصص للإصدارات:

```bash
curl -fsSL https://account.example.com/install.sh | \
  REDIACC_SERVER_URL=https://account.example.com \
  REDIACC_RELEASES_URL=https://account.example.com/releases \
  bash
```

سيتحقق CLI من `account.example.com/releases/cli/stable/manifest.json` للتحديثات بدلاً من شبكة CDN العامة للإصدارات.

إذا كان الخادم غير متصل بالإنترنت كلياً، ثبّت CLI عبر npm من حزمة tarball المجمّعة:

```bash
npm install -g https://account.example.com/npm/rediacc-cli-latest.tgz
```

## مرجع متغيرات البيئة

| المتغير | يُستخدم بواسطة | الغرض |
|---|---|---|
| `REDIACC_SERVER_URL` | سكريبت التثبيت | عنوان URL لخادم الحساب. يكتشف القناة ومفاتيح التشفير تلقائياً. |
| `REDIACC_RELEASES_URL` | سكريبت التثبيت، مُحدِّث CLI | نقطة نهاية مخصصة للإصدارات لثنائيات CLI. الافتراضي: `https://releases.rediacc.com` |
| `REDIACC_CHANNEL` | سكريبت التثبيت | تجاوز قناة التحديث. يتم الاكتشاف التلقائي من الخادم إذا لم يُضبط. |
| `REDIACC_ACCOUNT_SERVER` | وقت تشغيل CLI | تجاوز عنوان URL لخادم الحساب لجميع أوامر CLI. |
| `RDC_UPDATE_CHANNEL` | وقت تشغيل CLI | تجاوز قناة التحديث لـ `rdc update`. |

## تكوين الخادم

تستخدم صورة Docker المحلية نفس متغير `ENVIRONMENT` الخاص بالخدمة المستضافة. اضبطه في بيئة Docker أو تكوين التنسيق:

- `ENVIRONMENT=production` (الافتراضي): حدود قياسية، قناة تحديث stable مُوصى بها للعملاء
- `ENVIRONMENT=edge`: ضعف حدود Community، قناة تحديث edge مُوصى بها للعملاء

راجع [قنوات الإصدار](/ar/docs/release-channels) للاطلاع على تفاصيل ما توفره كل بيئة.

## ما يُخبر الخادم CLI به

عند اتصال CLI بخادمك، يستعلم عن `/.well-known/server-info` لاكتشاف:

- **مفتاح التشفير العام للتشفير الشامل**: لتخزين التكوين بمعرفة صفرية
- **الحد الأدنى لإصدار CLI**: يمنع إصدارات CLI القديمة من الاتصال
- **قناة التحديث**: تُخبر CLI بقناة الإصدار التي يستخدمها للتحديثات
- **البيئة**: ما إذا كان هذا نشراً للإنتاج أو edge

يعني هذا التكوين التلقائي أن المستخدمين يحتاجون فقط إلى عنوان URL للخادم. كل شيء آخر يُكتشف تلقائياً.

## الترخيص لعمليات النشر المعزولة عن الإنترنت

تُصدر الخوادم المحلية المعزولة والمستضاتة ذاتياً التراخيص محلياً باستخدام **شهادة تفويض** موقّعة من مفتاح الرئيسي الأعلى. تُقيّد الشهادة الخادم المحلي بحدود خطته وتُنشئ سلسلة مقاومة للتلاعب. راجع [سلسلة التراخيص والتفويض](/ar/docs/license-chain) للتصميم التشفيري (سلامة السلسلة، اكتشاف الشوكة، إثباتات التدقيق).

يغطي هذا القسم الإعداد التشغيلي: توليد المفاتيح وطلب الشهادة وتكوين التجديد التلقائي وتدفق التجديد دون إنترنت.

### اشتراك واحد، تثبيت محلي واحد

قد يمتلك الاشتراك **شهادة تفويض نشطة واحدة على الأكثر في أي وقت**. يُطبق كل تثبيت محلي حدود الشهر والجهاز مقابل دفتر إصدار محلي خاص به، لذا فإن وجود شهادات نشطة متعددة سيضاعف الحصة الفعلية دون أي تسوية ممكنة.

إذا كنت بحاجة إلى بيئات منفصلة (إنتاج، تدريج، DR، متعدد المناطق)، اشترِ اشتراكاً واحداً لكل تثبيت. يُقنِّن إنفاذ الشهادة النشطة الواحدة هذا العقد: محاولة إنشاء شهادة ثانية نشطة تُعيد `409 DELEGATION_CERT_ALREADY_ACTIVE` مع معرف الشهادة الموجودة وتعليمات للتجديد (مُفضَّل - يحافظ على السلسلة) أو الإلغاء والإنشاء (يُعيد ضبط السلسلة).

### 1. توليد زوج مفاتيح Ed25519 للخادم المحلي

يستخدم الخادم المحلي زوج مفاتيح Ed25519 منفصلاً للتوقيع على التراخيص. تُخوِّل شهادة التفويض من الخادم الأعلى هذا المفتاح العام المحدد.

```bash
# Generate a fresh keypair
openssl genpkey -algorithm Ed25519 -out onprem-private.pem
openssl pkey -in onprem-private.pem -pubout -out onprem-public.pem

# Convert to base64 (the format the on-premise expects in env vars)
ON_PREMISE_PRIVATE_KEY=$(openssl pkey -in onprem-private.pem -outform DER | base64 -w 0)
ON_PREMISE_PUBLIC_KEY=$(openssl pkey -in onprem-private.pem -pubout -outform DER | base64 -w 0)
```

احتفظ بالمفتاح الخاص إلى جانب أسرارك الأخرى (مثل Docker secret أو Kubernetes Secret). لا يغادر الخادم المحلي أبداً.

### 2. طلب شهادة تفويض من الخادم الأعلى

يمكنك طلب الشهادة من بوابة الحساب الأعلى بثلاث طرق:

**الخيار A - الخدمة الذاتية للعميل (موصى به).** سجّل الدخول إلى البوابة الأعلى بوصفك مالك أو Admin للمؤسسة وانتقل إلى **/account/delegation-certs**. انقر فوق **Create New**، والصق المفتاح العام للخادم المحلي (base64 SPKI)، واختر فترة الصلاحية (أو اقبل الافتراضي لكل خطة)، ثم نزّل ملف `.json` الناتج.

**الخيار B - Admin (عبر العملاء).** يمكن لدعم Rediacc أو مسؤول النظام الأعلى استخدام `POST /admin/delegation-certs` بنفس المعاملات.

**الخيار C - CLI `rdc` (مخطط).** سيُغلِّف أمر CLI مستقبلي تدفق البوابة.

يبدو `.json` المُعاد كما يلي:

```json
{
  "payload": "eyJ2ZXJzaW9uIjoxLCJzdWJzY3JpcHRpb25JZCI6...",
  "signature": "...",
  "publicKeyId": "..."
}
```

تحكمها سياسة الصلاحية (إعدادات افتراضية وحدود قصوى لكل خطة، تجاوز لكل اشتراك، محدودة بنهاية الاشتراك + 3 أيام سماح). تتضمن الاستجابة أيضاً `effectiveDays` و`reason` لترى سبب اختياره لتلك القيمة. راجع [سلسلة التراخيص - سياسة الصلاحية](/ar/docs/license-chain) للاطلاع على القواعد الكاملة.

### 3. تثبيت الشهادة على الخادم المحلي

احفظ ملف `.json` الذي نزّلته في مسار معروف وأشر الخادم المحلي إليه:

```bash
DELEGATION_CERT_PATH=/etc/rediacc/delegation-cert.json
```

أو، لسير عمل الحاويات المؤقتة أو Docker secrets، ادمج الشهادة كـ base64 في متغير بيئة:

```bash
DELEGATION_CERT_BASE64=$(base64 -w 0 < delegation-cert.json)
```

### 4. تكوين التحقق الأعلى والتجديد التلقائي (اختياري لكنه موصى به)

إذا كان الخادم المحلي يملك وصولاً HTTPS صادراً إلى الخادم الأعلى، اضبط التجديد التلقائي لكي تتجدد الشهادة قبل انتهاء الصلاحية دون تدخل يدوي:

```bash
# Required for /onprem/cert-upload to verify uploaded certs against the upstream master key.
# Fails-fast at boot if UPSTREAM_API_KEY is set without this.
UPSTREAM_PUBLIC_KEY="<upstream master Ed25519 SPKI public key, base64>"

# Required for the auto-renew loop. Mint via the portal:
#   Org owner/admin → /account/delegation-certs → "Get auto-renew token"
# This is the ONLY way to obtain a delegation:renew-scoped api token.
UPSTREAM_URL="https://www.rediacc.com"
UPSTREAM_API_KEY="rdt_..."

# Optional tuning (defaults shown).
AUTO_RENEW_INTERVAL_HOURS=24
RENEW_THRESHOLD_DAYS=14
```

تعمل حلقة التجديد التلقائي للخادم المحلي مرةً واحدة عند الإقلاع ثم على الفاصل الزمني المكوَّن. تستخدم **عتبة تكيفية** (`min(env.RENEW_THRESHOLD_DAYS, ceil(certValidityDays / 3))`) بحيث تتجدد شهادة COMMUNITY لمدة 15 يوماً عند بقاء 5 أيام بدلاً من إطلاق التجديد في اليوم الأول. تتجدد شهادة BUSINESS لمدة 90 يوماً عند بقاء 14 يوماً (يُطبَّق الحد المكوَّن في البيئة).

إذا فشل التجديد، تظل الشهادة مستخدمةً حتى انتهاء صلاحيتها الطبيعية. يتراجع الفشل لمدة ساعة واحدة ويُسجَّل في `${DELEGATION_CERT_PATH}.status.json` ويُكشف عبر `GET /onprem/cert-status`.

### 5. التجديد المعزول عن الإنترنت (بدون HTTPS صادر)

إذا تعذَّر على الخادم المحلي الوصول إلى الخادم الأعلى، استخدم تدفق النقل اليدوي:

1. **نزّل طلب تجديد من بوابة مشرف الخادم المحلي.** بوصفك جذر نظام الخادم المحلي، اطلب `GET /onprem/renewal-request`. يُعيد هذا مانيفيست JSON يحتوي على رأس السلسلة المحلية والمفتاح العام المفوَّض وتوقيع Ed25519 مقاوم للتلاعب من مفتاحك الخاص المحلي.
2. **انقل المانيفيست إلى الخادم الأعلى** عبر USB أو البريد الإلكتروني المشفر أو أي قناة خارج النطاق. المانيفيست صغير (بضعة كيلوبايتات) ولا يحتوي على أسرار.
3. **عالج المانيفيست عند الخادم الأعلى.** يفتح مالك/Admin المؤسسة **/account/delegation-certs** ثم **Upload renewal request** ويختار ملف المانيفيست. يتحقق الخادم الأعلى من توقيع المانيفيست مقابل `delegatedPublicKey` الخاص بالشهادة النشطة (يُثبت أنه جاء من حامل المفتاح الخاص المحلي)، ويتحقق من مكافحة الإعادة (تُرفض المانيفيستات الأقدم من 7 أيام)، ثم يُصدر شهادة جديدة.
4. **نزّل الشهادة الجديدة** من بوابة الخادم الأعلى كملف `.json`.
5. **انقل الشهادة مجدداً** إلى الخادم المحلي.
6. **ارفع إلى الخادم المحلي** عبر بوابة المشرف المحلية (`POST /onprem/cert-upload`). يتحقق الخادم المحلي من الشهادة الجديدة مقابل `UPSTREAM_PUBLIC_KEY` ويتحقق من أن `genesisSequence` للشهادة لا يزال يرتبط بإدخال سلسلة في دفتر الإصدار المحلي (يُدعم تقدم السلسلة أثناء النقل - السلسلة تمتد بشكل طبيعي).

هذه الحلقة بأكملها لا تتطلب أي خروج شبكي من الخادم المحلي.

#### أوضاع فشل المانيفيست

| الكود | السبب | الإصلاح |
|---|---|---|
| `NO_ACTIVE_CERT` | لا توجد شهادة نشطة في الخادم الأعلى لهذا الاشتراك | أصدر شهادة جديدة عبر تدفق الإنشاء بدلاً من التجديد |
| `DELEGATED_KEY_MISMATCH` | `delegatedPublicKey` للمانيفيست يختلف عن الشهادة النشطة | قد يكون المانيفيست إعادة تشغيل من تثبيت محلي مختلف |
| `MANIFEST_SIGNATURE_INVALID` | التوقيع لا يتحقق مقابل المفتاح العام المفوَّض | تم العبث بالمانيفيست أثناء النقل، أو أنشأته على خادم محلي مختلف |
| `MANIFEST_EXPIRED` | المانيفيست أقدم من 7 أيام | أنشئ طلب تجديد جديداً من الخادم المحلي |

#### أوضاع فشل رفع الشهادة

| الكود | السبب | الإصلاح |
|---|---|---|
| `CHAIN_HEAD_BEHIND` | `genesisSequence` للشهادة الجديدة متقدم على رأس السلسلة المحلية | الخادم الأعلى على سلسلة متفرعة - تحقق من الأمر |
| `CHAIN_FORK_ON_UPLOAD` | تجزئة السلسلة عند `genesisSequence` للشهادة لا تتطابق مع دفتر الأستاذ المحلي | السلسلة المحلية تباعدت عن الخادم الأعلى - تحقق من الأمر |
| `Signature verification failed` | الشهادة غير موقّعة بواسطة `UPSTREAM_PUBLIC_KEY` المكوَّن | تحقق من أن `UPSTREAM_PUBLIC_KEY` يتطابق مع المفتاح العام الرئيسي للخادم الأعلى |

### 6. الحالة والمراقبة

استعلم عن حالة الشهادة المحلية للخادم المحلي في أي وقت:

```bash
curl https://onprem.example.com/account/api/v1/onprem/cert-status \
  -H "Cookie: <admin session>"
```

يُعيد `subscriptionId` و`planCode` و`validUntil` و`daysUntilExpiry` للشهادة المحملة، بالإضافة إلى كتلة `autoRenew` (`enabled` و`lastSuccessAt` و`lastErrorAt` و`lastError`). وصّل هذا بمنظومة المراقبة الخاصة بك لتنبيهك عند `lastSuccessAt` قديمة أو `lastError` غير فارغة.

للنسخ الاحتياطي والتدقيق، يمكن لمشرف الخادم المحلي أيضاً تنزيل الشهادة الموقّعة المحملة حالياً عبر `GET /onprem/cert-current` (يتطلب جلسة مرتفعة الصلاحيات).

### مرجع متغيرات بيئة شهادة التفويض

| المتغير | مطلوب؟ | الغرض |
|---|---|---|
| `ON_PREMISE_MODE` | نعم | اضبطه على `true` لتمكين مجموعة مسارات الخادم المحلي |
| `ON_PREMISE_PRIVATE_KEY` | نعم | مفتاح خاص Ed25519 بتنسيق PKCS8 base64 للتوقيع المفوَّض |
| `ON_PREMISE_PUBLIC_KEY` | نعم | مفتاح عام Ed25519 بتنسيق SPKI base64 (يجب أن يتطابق مع `delegatedPublicKey` في الشهادة) |
| `DELEGATION_CERT_PATH` | أحد هذين | مسار نظام الملفات لملف JSON للشهادة الموقّعة |
| `DELEGATION_CERT_BASE64` | أحد هذين | ملف JSON للشهادة بترميز base64 (بديل لمسار الملف) |
| `UPSTREAM_PUBLIC_KEY` | مطلوب إذا ضُبط `UPSTREAM_API_KEY`، أو لعمل `/onprem/cert-upload` | بتنسيق SPKI base64 للمفتاح العام الرئيسي للخادم الأعلى. إيقاف سريع عند الإقلاع إذا كان مفقوداً. |
| `UPSTREAM_URL` | للتجديد التلقائي | عنوان URL الأساسي لخادم الحساب الأعلى، مثل `https://www.rediacc.com` |
| `UPSTREAM_API_KEY` | للتجديد التلقائي | رمز API بنطاق `delegation:renew`. احصل عليه عبر البوابة - انظر الخطوة 4. |
| `AUTO_RENEW_INTERVAL_HOURS` | اختياري | الافتراضي 24. مدة التحقق من حاجة الشهادة للتجديد. |
| `RENEW_THRESHOLD_DAYS` | اختياري | الافتراضي 14. يعمل كحد أقصى على عتبة الثلث التكيفية. |

### ملخص نموذج التهديد

يدافع نموذج شهادة التفويض ضد:

- **التراخيص المزوّرة**: لا يستطيع الخادم المحلي التوقيع إلا ضمن حدود خطته؛ يرفض renet أي شيء خارج حدود الشهادة.
- **مشاركة الشهادة عبر عمليات النشر**: يُكتشف تباعد السلسلة عند التجديد (يُعيد `CHAIN_FORK_DETECTED`).
- **تجاوز الحصة عبر التثبيت المتعدد**: يُطبَّق عند الخادم الأعلى بواسطة الشهادة النشطة الواحدة (شهادة واحدة لكل اشتراك).
- **التراجع عن السلسلة**: يخزن renet أعلى تسلسل شوهد لكل اشتراك ويرفض أي كتلة برقم تسلسل أدنى.
- **اعتراض اعتمادات الخادم الأعلى**: رمز `delegation:renew` للبوتسراب قابل لإصداره فقط عبر نقطة نهاية البوابة المخصصة ومحمي بصلاحيات Admin. يمنح الرمز التجديد فقط - لا يمكنه قراءة أو تعديل أي مورد آخر.
- **هجمات إعادة التشغيل على المانيفيستات**: تُرفض المانيفيستات الأقدم من 7 أيام.

ما **لا** يدافع ضده:

- **المفتاح الخاص المحلي المخترق**: يتيح المفتاح المسرَّب لمهاجم التوقيع على التراخيص حتى `validUntil` الشهادة. التخفيف: دوِّر زوج المفاتيح (ألغِ الشهادة القديمة وأنشئ جديدة بمفتاح جديد) وعامل جميع التراخيص الموقّعة بالمفتاح القديم باعتبارها مشبوهة.
- **المفتاح الرئيسي للخادم الأعلى المخترق**: هذا هو جذر الثقة. إجراءات التدوير خارج نطاق هذه الصفحة.