# الخدمات

إذا لم تكن متاكدا من الاداة المناسبة، راجع [rdc vs renet](/ar/docs/rdc-vs-renet).

تغطي هذه الصفحة كيفية نشر وإدارة الخدمات المحتوية: ملفات Rediaccfile، وشبكات الخدمات، والتشغيل/الإيقاف، والعمليات المجمّعة، والتشغيل التلقائي.

## ملف Rediaccfile

**Rediaccfile** هو سكريبت Bash يحدد كيفية تشغيل خدماتك وإيقافها. يجب أن يُسمّى `Rediaccfile` أو `rediaccfile` (غير حساس لحالة الأحرف) ويُوضع داخل نظام ملفات المستودع المحمّل.

يتم اكتشاف ملفات Rediaccfile في موقعين:
1. **جذر** مسار تحميل المستودع
2. **المجلدات الفرعية من المستوى الأول** لمسار التحميل (غير تكراري)

يتم تخطي المجلدات المخفية (الأسماء التي تبدأ بـ `.`).

### دوال دورة الحياة

يحتوي Rediaccfile على ما يصل إلى دالتين:

| الدالة | وقت التشغيل | الغرض | سلوك الخطأ |
|--------|------------|-------|------------|
| `up()` | عند التشغيل | تشغيل الخدمات (مثل `renet compose -- up -d`) | فشل الجذر **حرج** (يوقف كل شيء). فشل المجلدات الفرعية **غير حرج** (يُسجّل ويستمر) |
| `down()` | عند الإيقاف | إيقاف الخدمات (مثل `renet compose -- down`) | **أفضل جهد** -- يتم تسجيل الأخطاء لكن يتم تنفيذ جميع ملفات Rediaccfile دائماً |

كلتا الدالتين اختيارية. إذا لم تُعرّف دالة في Rediaccfile، يتم تخطيها بصمت.

### ترتيب التنفيذ

- **التشغيل (`up`):** Rediaccfile الجذر أولاً، ثم المجلدات الفرعية بـ**ترتيب أبجدي** (A إلى Z).
- **الإيقاف (`down`):** المجلدات الفرعية بـ**ترتيب أبجدي عكسي** (Z إلى A)، ثم الجذر أخيراً.

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

عند تنفيذ دالة Rediaccfile، تكون متغيرات البيئة التالية متاحة:

| المتغير | الوصف | مثال |
|---------|-------|------|
| `REDIACC_WORKING_DIR` | مسار تحميل المستودع | `/mnt/rediacc/mounts/abc123` |
| `REDIACC_REPOSITORY` | معرّف المستودع GUID | `a1b2c3d4-e5f6-...` |
| `REDIACC_NETWORK_ID` | معرّف الشبكة (عدد صحيح) | `2816` |
| `DOCKER_HOST` | مقبس Docker لعملية Docker المعزولة لهذا المستودع | `unix:///var/run/rediacc/docker-2816.sock` |
| `{SERVICE}_IP` | عنوان IP الحلقي لكل خدمة مُعرّفة في `.rediacc.json` | `POSTGRES_IP=127.0.11.2` |

يتم إنشاء متغيرات `{SERVICE}_IP` تلقائياً من `.rediacc.json`. تقوم قاعدة التسمية بتحويل اسم الخدمة إلى أحرف كبيرة مع استبدال الشرطات بشرطات سفلية، ثم إضافة `_IP`. على سبيل المثال، `listmonk-app` تصبح `LISTMONK_APP_IP`.

> **تحذير: لا تستخدم `sudo docker` في ملفات Rediaccfile.** يعيد أمر `sudo` تعيين متغيرات البيئة، مما يعني فقدان `DOCKER_HOST` واستهداف أوامر Docker لعملية النظام بدلاً من العملية المعزولة للمستودع. هذا يكسر عزل الحاويات وقد يسبب تعارضات في المنافذ. سيمنع Rediacc التنفيذ إذا اكتشف `sudo docker` بدون `-E`.
>
> استخدم `renet compose` في ملفات Rediaccfile -- فهو يتعامل تلقائياً مع `DOCKER_HOST`، ويحقن تسميات الشبكة لاكتشاف المسارات، ويهيئ شبكات الخدمات. راجع [الشبكات](/ar/docs/networking) لتفاصيل حول كيفية كشف الخدمات عبر الوكيل العكسي. إذا استدعيت Docker مباشرة، استخدم `docker` بدون `sudo` -- دوال Rediaccfile تعمل بالفعل بصلاحيات كافية. إذا كان يجب عليك استخدام sudo، استخدم `sudo -E docker` للحفاظ على متغيرات البيئة.

### مثال

```bash
#!/bin/bash

up() {
    echo "Starting services..."
    renet compose -- up -d
}

down() {
    echo "Stopping services..."
    renet compose -- down
}
```

> **هام:** استخدم دائماً `renet compose --` بدلاً من `docker compose`. يفرض غلاف `renet compose` شبكة المضيف، وتخصيص عناوين IP، وتسميات اكتشاف الخدمات المطلوبة من renet-proxy. تُضاف قدرات CRIU checkpoint/restore للحاويات التي تحمل تسمية `rediacc.checkpoint=true`. يتم رفض الاستخدام المباشر لـ `docker compose` بواسطة التحقق من صحة Rediaccfile. راجع [الشبكات](/ar/docs/networking) للتفاصيل.

### تخطيط متعدد الخدمات

للمشاريع التي تحتوي على مجموعات خدمات مستقلة متعددة، استخدم المجلدات الفرعية:

```
/mnt/rediacc/mounts/my-app/
├── Rediaccfile              # Root: shared setup
├── docker-compose.yml
├── database/
│   ├── Rediaccfile          # Database services
│   └── docker-compose.yml
├── backend/
│   ├── Rediaccfile          # API server
│   └── docker-compose.yml
└── monitoring/
    ├── Rediaccfile          # Prometheus, Grafana, etc.
    └── docker-compose.yml
```

ترتيب التنفيذ لـ `up`: الجذر، ثم `backend`، `database`، `monitoring` (A-Z).
ترتيب التنفيذ لـ `down`: `monitoring`، `database`، `backend`، ثم الجذر (Z-A).

## شبكات الخدمات (.rediacc.json)

يحصل كل مستودع على شبكة فرعية /26 (64 عنوان IP) في نطاق `127.x.x.x` الحلقي. ترتبط الخدمات بعناوين IP حلقية فريدة بحيث يمكنها العمل على نفس المنافذ دون تعارض.

### ملف .rediacc.json

يربط أسماء الخدمات بأرقام **الفتحات (slots)**. تتوافق كل فتحة مع عنوان IP فريد ضمن الشبكة الفرعية للمستودع.

```json
{
  "services": {
    "api": {"slot": 0},
    "postgres": {"slot": 1},
    "redis": {"slot": 2}
  }
}
```

### الإنشاء التلقائي من Docker Compose

لا تحتاج إلى إنشاء `.rediacc.json` يدوياً. عند تشغيل `rdc repo up`، يقوم Rediacc تلقائياً بما يلي:

1. فحص جميع المجلدات التي تحتوي على Rediaccfile بحثاً عن ملفات compose (`docker-compose.yml` أو `docker-compose.yaml` أو `compose.yml` أو `compose.yaml`)
2. استخراج أسماء الخدمات من قسم `services:`
3. تعيين الفتحة التالية المتاحة لأي خدمة جديدة
4. حفظ النتيجة في `{repository}/.rediacc.json`

### حساب عنوان IP

يُحسب عنوان IP للخدمة من معرّف شبكة المستودع وفتحة الخدمة. يتم توزيع معرّف الشبكة على الثُمانية الثانية والثالثة والرابعة من عنوان الاسترجاع `127.x.y.z`. تحصل كل خدمة على إزاحة `slot + 2` (الإزاحتان 0 و 1 محجوزتان).

| Offset | Address | Purpose |
|--------|---------|---------|
| .0 | `127.0.11.0` | Network address (reserved) |
| .1 | `127.0.11.1` | Gateway (reserved) |
| .2 – .62 | `127.0.11.2` – `127.0.11.62` | Services (`slot + 2`) |
| .63 | `127.0.11.63` | Broadcast (reserved) |

**مثال** لمعرّف الشبكة `2816` (`0x0B00`)، العنوان الأساسي `127.0.11.0`:

| الخدمة | الفتحة | عنوان IP |
|--------|--------|----------|
| api | 0 | `127.0.11.2` |
| postgres | 1 | `127.0.11.3` |
| redis | 2 | `127.0.11.4` |

يدعم كل مستودع ما يصل إلى **61 خدمة** (الفتحات من 0 إلى 60).

### استخدام عناوين IP للخدمات في Docker Compose

بما أن كل مستودع يشغّل عملية Docker معزولة، يقوم `renet compose` تلقائياً بتهيئة `network_mode: host` لجميع الخدمات. قم بربط الخدمات بعناوين IP الحلقية المخصصة لها:

```yaml
services:
  postgres:
    image: postgres:16
    environment:
      PGDATA: /var/lib/postgresql/data
      POSTGRES_PASSWORD: secret
    command: -c listen_addresses=${POSTGRES_IP} -c port=5432

  api:
    image: my-api:latest
    environment:
      DATABASE_URL: postgresql://postgres:secret@${POSTGRES_IP}:5432/mydb
      LISTEN_ADDR: ${API_IP}:8080
```

> **ملاحظة:** لا تضف `network_mode: host` يدوياً, يقوم `renet compose` بحقنه تلقائياً. سياسات إعادة التشغيل (مثل `restart: always`) آمنة للاستخدام, يزيلها renet تلقائياً لتوافق CRIU ويتولى watchdog استعادة الحاويات.

> **ملاحظة:** مستودعات fork تحصل على مسارات تلقائية مسطحة: `{service}-{tag}.{machine}.{baseDomain}`. يتم تخطي النطاقات المخصصة لمستودعات fork.

## تشغيل الخدمات

قم بتحميل المستودع وتشغيل جميع الخدمات:

```bash
rdc repo up --name my-app -m server-1 --mount
```

| الخيار | الوصف |
|--------|-------|
| `--mount` | تحميل المستودع أولاً إن لم يكن محمّلاً بالفعل |
| `--skip-router-restart` | Skip restarting the route server after the operation |

تسلسل التنفيذ هو:
1. تحميل المستودع المشفر بـ LUKS (إذا تم تحديد `--mount`)
2. تشغيل عملية Docker المعزولة
3. إنشاء `.rediacc.json` تلقائياً من ملفات compose
4. تشغيل `up()` في جميع ملفات Rediaccfile (بترتيب A-Z)

## إيقاف الخدمات

```bash
rdc repo down --name my-app -m server-1
```

| الخيار | الوصف |
|--------|-------|
| `--unmount` | إلغاء تحميل المستودع المشفر بعد إيقاف الخدمات. إذا لم يسرِ مفعوله، استخدم `rdc repo unmount` بشكل منفصل. |
| `--skip-router-restart` | Skip restarting the route server after the operation |

تسلسل التنفيذ هو:
1. تشغيل `down()` في جميع ملفات Rediaccfile (بترتيب Z-A عكسي، أفضل جهد)
2. إيقاف عملية Docker المعزولة (إذا تم تحديد `--unmount`)
3. إلغاء تحميل وإغلاق وحدة LUKS المشفرة (إذا تم تحديد `--unmount`)

## العمليات المجمّعة

شغّل أو أوقف جميع المستودعات على جهاز دفعة واحدة:

```bash
rdc repo up -m server-1
```

| الخيار | الوصف |
|--------|-------|
| `--include-forks` | تضمين المستودعات المنسوخة |
| `--mount-only` | التحميل فقط، بدون تشغيل الحاويات |
| `--dry-run` | عرض ما سيتم تنفيذه |
| `--parallel` | تشغيل العمليات بالتوازي |
| `--concurrency <n>` | الحد الأقصى للعمليات المتزامنة (الافتراضي: 3) |
| `--skip-router-restart` | Skip restarting the route server after the operation |

## التشغيل التلقائي عند الإقلاع

افتراضياً، يجب تحميل المستودعات وتشغيلها يدوياً بعد إعادة تشغيل الخادم. يقوم **التشغيل التلقائي** بتهيئة المستودعات للتحميل تلقائياً، وتشغيل Docker، وتنفيذ `up()` في Rediaccfile عند إقلاع الخادم.

### كيف يعمل

عند تفعيل التشغيل التلقائي لمستودع:

1. يتم إنشاء ملف مفتاح LUKS عشوائي بحجم 256 بايت وإضافته إلى فتحة LUKS رقم 1 للمستودع (تبقى الفتحة 0 لعبارة مرور المستخدم)
2. يُخزّن ملف المفتاح في `{datastore}/.credentials/keys/{guid}.key` بصلاحيات `0600` (الجذر فقط)
3. يتم تثبيت خدمة systemd (`rediacc-autostart`) تعمل عند الإقلاع لتحميل جميع المستودعات المفعّلة وتشغيل خدماتها

عند إيقاف النظام، تقوم الخدمة بإيقاف جميع الخدمات بسلاسة (Rediaccfile `down()`)، وإيقاف عمليات Docker، وإغلاق وحدات LUKS.

> **ملاحظة أمنية:** تفعيل التشغيل التلقائي يخزّن ملف مفتاح LUKS على قرص الخادم. يمكن لأي شخص لديه صلاحيات الجذر على الخادم تحميل المستودع بدون عبارة المرور. قيّم هذا بناءً على نموذج التهديد الخاص بك.

### تفعيل

```bash
rdc repo autostart enable --name my-app -m server-1
```

سيُطلب منك إدخال عبارة مرور المستودع.

### تفعيل الكل

```bash
rdc repo autostart enable -m server-1
```

### تعطيل

```bash
rdc repo autostart disable --name my-app -m server-1
```

يزيل هذا ملف المفتاح ويحذف فتحة LUKS رقم 1.

### عرض الحالة

```bash
rdc repo autostart list -m server-1
```

## مثال كامل

ينشر هذا تطبيق ويب مع PostgreSQL و Redis وخادم API.

### 1. الإعداد

```bash
curl -fsSL https://www.rediacc.com/install.sh | bash
rdc config init --name production --ssh-key ~/.ssh/id_ed25519
rdc config machine add --name prod-1 --ip 203.0.113.50 --user deploy
rdc config machine setup --name prod-1
rdc repo create --name webapp -m prod-1 --size 10G
```

### 2. التحميل والتحضير

```bash
rdc repo mount --name webapp -m prod-1
```

### 3. إنشاء ملفات التطبيق

داخل المستودع، أنشئ الملفات التالية:

**docker-compose.yml:**

```yaml
services:
  postgres:
    image: postgres:16
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: webapp
      POSTGRES_USER: app
      POSTGRES_PASSWORD: changeme
    command: -c listen_addresses=${POSTGRES_IP} -c port=5432

  redis:
    image: redis:7-alpine
    command: redis-server --bind ${REDIS_IP} --port 6379

  api:
    image: myregistry/api:latest
    environment:
      DATABASE_URL: postgresql://app:changeme@${POSTGRES_IP}:5432/webapp
      REDIS_URL: redis://${REDIS_IP}:6379
      LISTEN_ADDR: ${API_IP}:8080
```

**Rediaccfile:**

```bash
#!/bin/bash

up() {
    mkdir -p data/postgres
    renet compose -- up -d

    echo "Waiting for PostgreSQL..."
    for i in $(seq 1 30); do
        if renet compose -- exec postgres pg_isready -q 2>/dev/null; then
            echo "PostgreSQL is ready."
            return 0
        fi
        sleep 1
    done
    echo "Warning: PostgreSQL did not become ready within 30 seconds."
}

down() {
    renet compose -- down
}
```

### 4. التشغيل

```bash
rdc repo up --name webapp -m prod-1
```

### 5. تفعيل التشغيل التلقائي

```bash
rdc repo autostart enable --name webapp -m prod-1
```