انتقل إلى المحتوى الرئيسي انتقل إلى الملاحة انتقل إلى التذييل
لفترة محدودة: برنامج Design Partner — خطة BUSINESS مجانية مدى الحياة

البنية المعمارية

كيف يعمل Rediacc: بنية الأداتين، اكتشاف المحوّلات، نموذج الأمان، وهيكل الإعدادات.

البنية المعمارية

إذن: rdc على محطة عملك، renet على خوادمك، يتصلان عبر SSH. تستند بنية Rediacc الكاملة على هذا الفصل. تغطي هذه الصفحة كيف تقسم الأداتان المسؤوليات، وكيف يوجه اكتشاف المحوّل الحالة، وكيف يبدو نموذج الأمان، وكيف تُنظَّم الإعدادات.

نظرة عامة على المكدس الكامل

يتدفق حركة المرور من الإنترنت عبر وكيل عكسي إلى عمليات Docker المعزولة، يدعم كل منها تخزين مشفر:

بنية المكدس الكامل

يحصل كل مستودع على عملية Docker خاصة به، وشبكة فرعية للعنوان المحلي (/26 = 64 عنوان IP)، وحجم BTRFS مشفر بـ LUKS. يكتشف خادم التوجيه الحاويات قيد التشغيل عبر جميع العمليات ويغذّي إعدادات التوجيه إلى Traefik.

بنية الأداتين

يستخدم Rediacc ملفين تنفيذيين يعملان معاً عبر SSH:

بنية الأداتين

  • rdc يعمل على محطة عملك (macOS أو Linux أو Windows). يقرأ الإعدادات المحلية، ويتصل بالأجهزة البعيدة عبر SSH، ويستدعي أوامر renet.
  • renet يعمل على الخادم البعيد بصلاحيات الجذر. يدير صور الأقراص المشفرة بـ LUKS، وعمليات Docker المعزولة، وتنسيق الخدمات، وإعدادات الوكيل العكسي.

كل أمر تكتبه محلياً يُترجم إلى استدعاء SSH ينفّذ renet على الجهاز البعيد. لن تحتاج أبداً إلى الاتصال بالخوادم يدوياً عبر SSH.

للاطلاع على قاعدة إبهام موجهة للمشغّل، راجع rdc vs renet. يمكنك أيضاً استخدام rdc ops لتشغيل مجموعة VM محلية للاختبار، راجع الأجهزة الافتراضية التجريبية.

الإعدادات

تُخزَّن جميع حالات CLI في ملفات إعداد JSON مسطّحة تحت ~/.config/rediacc/.

محوّل المحلي (الافتراضي)

الافتراضي للاستضافة الذاتية. تعيش جميع الحالات في ملف إعداد على محطة عملك (مثلاً ~/.config/rediacc/rediacc.json).

  • اتصالات SSH مباشرة بالأجهزة
  • لا حاجة لخدمات خارجية
  • مستخدم واحد، محطة عمل واحدة
  • يُنشأ الإعداد الافتراضي تلقائياً عند أول استخدام لسطر الأوامر. تُنشأ الإعدادات المسمّاة باستخدام rdc config init --name <name>

محوّل السحابة (تجريبي)

يُفعَّل تلقائياً عند احتواء الإعداد على حقلَي apiUrl و token. يستخدم واجهة برمجة تطبيقات Rediacc لإدارة الحالة والتعاون الجماعي.

  • تُخزَّن الحالة في واجهة برمجة التطبيقات السحابية
  • فرق متعددة المستخدمين مع التحكم في الوصول بناءً على الأدوار
  • لوحة تحكم ويب للإدارة المرئية
  • يُعدّ باستخدام rdc auth login

ملاحظة: أوامر محوّل السحابة تجريبية. فعّلها بتعيين REDIACC_EXPERIMENTAL=1.

يستخدم كلا المحوّلَين نفس أوامر سطر الأوامر. يؤثر المحوّل فقط على مكان تخزين الحالة وكيفية عمل المصادقة.

مستخدم rediacc

عند تشغيل rdc config machine setup، يُنشئ renet مستخدم نظام باسم rediacc على الخادم البعيد:

  • UID: 7111
  • Shell: /sbin/nologin (لا يمكن تسجيل الدخول عبر SSH)
  • الغرض: يمتلك ملفات المستودعات ويشغّل دوال Rediaccfile

لا يمكن الوصول إلى مستخدم rediacc عبر SSH مباشرة. بدلاً من ذلك، يتصل rdc بمستخدم SSH الذي قمت بتهيئته (مثل deploy)، وينفّذ renet عمليات المستودع عبر sudo -u rediacc /bin/sh -c '...'. هذا يعني:

  1. يحتاج مستخدم SSH الخاص بك إلى صلاحيات sudo
  2. جميع بيانات المستودع مملوكة لـ rediacc، وليس لمستخدم SSH الخاص بك
  3. دوال Rediaccfile (up() و down()) تعمل بصفة rediacc

يضمن هذا الفصل أن بيانات المستودع لها ملكية متسقة بغض النظر عن مستخدم SSH الذي يديرها.

عزل Docker

يحصل كل مستودع على عملية Docker معزولة خاصة به. عند تحميل مستودع، يبدأ renet عملية dockerd مخصصة بمقبس فريد:

عزل Docker

/var/run/rediacc/docker-{networkId}.sock

على سبيل المثال، مستودع بمعرّف شبكة 2816 يستخدم:

/var/run/rediacc/docker-2816.sock

هذا يعني:

  • الحاويات من مستودعات مختلفة لا يمكنها رؤية بعضها البعض
  • كل مستودع له ذاكرة تخزين مؤقت خاصة للصور والشبكات والأحجام
  • عملية Docker المضيفة (إن وُجدت) منفصلة تماماً

تُعيّن متغير البيئة DOCKER_HOST تلقائياً للمقبس الصحيح في دوال Rediaccfile.

عندما يدخل وكيل ذكاء اصطناعي إلى مستودع عبر rdc term connect -r <repo>، يُطبَّق العزل نفسه: تعمل الجلسة بصفة المستخدم غير المميَّز rediacc (UID 7111)، في فضاء أسماء تحميل منفصل، مع DOCKER_HOST مقصور على مقبس عملية Docker الخاصة بهذا المستودع وحده. يجمع تدفق العمل القائم على التفريع أولاً بين هذا العزل في وقت التشغيل وأولية استنساخ من نوع CoW: يعمل الوكيل على نسخة متفرعة لكل مهمة، ولا يعمل أبداً على المستودعات الكبرى (الإنتاج). راجع أمان وضمانات وكلاء الذكاء الاصطناعي للاطلاع على نموذج صندوق الرمل الكامل ودلالات التجاوز وحدود مسؤولية المطور بالنسبة لبيانات اعتماد الخدمات الخارجية.

تخطيط مسار العملية

تُخزَّن بيانات Docker وإعداداتها داخل نقطة تحميل المستودع، مما يبقي كل عملية معزولة تماماً عن المضيف وعن المستودعات الأخرى.

التخطيط لكل مستودع:

{datastore}/mounts/{guid}/.rediacc/docker/data/    # جذر بيانات Docker
{datastore}/mounts/{guid}/.rediacc/docker/config/  # إعداد Docker

التخطيط المستقل (عمليات غير مرتبطة بنقطة تحميل مستودع):

{datastore}/standalone/{N}/.rediacc/docker/data/
{datastore}/standalone/{N}/.rediacc/docker/config/

مسار وقت التشغيل المشترك (غير متغيّر):

/run/rediacc/docker-{N}.sock

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

تشفير LUKS

المستودعات هي صور أقراص مشفرة بـ LUKS مخزّنة على مخزن بيانات الخادم (الافتراضي: /mnt/rediacc). كل مستودع:

  1. لديه عبارة مرور تشفير مُولّدة عشوائياً (بيانات الاعتماد)
  2. يُخزّن كملف: {datastore}/repos/{guid}.img
  3. يُحمّل عبر cryptsetup عند الوصول إليه

تُخزّن بيانات الاعتماد في ملف الإعداد الخاص بك ولكن لا تُخزّن أبداً على الخادم. بدون بيانات الاعتماد، لا يمكن قراءة بيانات المستودع. عند تفعيل التشغيل التلقائي، يُخزّن ملف مفتاح LUKS ثانوي على الخادم للسماح بالتحميل التلقائي عند الإقلاع.

هيكل الإعدادات

كل إعداد هو ملف JSON مسطّح مخزّن في ~/.config/rediacc/. الإعداد الافتراضي هو rediacc.json؛ تستخدم الإعدادات المسمّاة الاسم كاسم للملف (مثلاً production.json). تُنظّم الحقول حسب الغرض: resources يحتفظ بالنشرات، credentials يحتفظ بالأسرار، account يحتفظ بقيم السحابة الافتراضية، infra يحتفظ بـ TLS و DNS، و encryption يحتفظ بحالة في باقي الحقول. يثبّت المميز schemaVersion: 2 على المستوى الأعلى توافق الإصدارات الأمامية.

{
  "schemaVersion": 2,
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "version": 47,
  "defaults": {
    "language": "en",
    "machine": "prod-1",
    "nextNetworkId": 2880,
    "universalUser": "rediacc"
  },
  "credentials": {
    "ssh": {
      "privateKey": "-----BEGIN OPENSSH PRIVATE KEY-----\n...\n-----END OPENSSH PRIVATE KEY-----",
      "publicKey": "ssh-ed25519 AAAA...",
      "knownHosts": "..."
    },
    "cfDnsApiToken": "cf-token-xxxxxxxxxxxx"
  },
  "resources": {
    "machines": {
      "prod-1": {
        "ip": "203.0.113.50",
        "user": "deploy",
        "port": 22,
        "datastore": "/mnt/rediacc",
        "knownHosts": "203.0.113.50 ssh-ed25519 AAAA..."
      }
    },
    "storages": {
      "backblaze": {
        "provider": "b2",
        "vaultContent": { "...": "..." }
      }
    },
    "repositories": {
      "webapp": {
        "repositoryGuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "credential": "base64-encoded-random-passphrase",
        "networkId": 2816
      }
    }
  },
  "infra": {
    "certEmail": "admin@example.com",
    "cfDnsZoneId": "..."
  },
  "encryption": {
    "mode": "plaintext"
  }
}

البكتات الرئيسية:

البكتةالمحتويات
schemaVersionالمميز (حالياً 2). ترفض أدوات التحميل الإصدارات المجهولة.
id / versionمعرّف UUID غير قابل للتغيير + عدّاد أحادي الاتجاه؛ يُستخدم للقفل المتفائل على متجر الإعدادات البعيد.
defaults.*قيم افتراضية غير حساسة في وقت التشغيل (machine و language و pruneGraceDays و universalUser و nextNetworkId).
credentials.sshمفاتيح SSH مضمنة + knownHosts. يحل محل ssh.privateKeyPath القديم (لا مزيد من المسارات غير المباشرة؛ يتم حل المحتوى عند التحميل ويُخزّن مضمناً).
credentials.cfDnsApiTokenرمز Cloudflare DNS-01 ACME.
credentials.masterPasswordVerifierموجود فقط عندما encryption.mode === "master-password".
resources.machines.*تفاصيل اتصال SSH لكل جهاز.
resources.storages.*بيانات اعتماد النسخ الاحتياطي خارج الموقع متوافقة مع rclone.
resources.repositories.*معرّف GUID لكل مستودع + بيانات اعتماد LUKS + مفتاح SSH للوصول المعزول للوكيل.
infra.acmeCertCache.*ذاكرة مؤقتة Traefik acme.json، gzip + base64، مفهرسة حسب المجال.
encryption.mode"plaintext" (افتراضي) أو "master-password".
encryption.encryptedFieldsعند التشفير، خريطة بكلوب AES-GCM لكل مؤشر (/resources/repositories/webapp/credential{ciphertext, nonce, tag}). توجيه فك تشفير واحد لكل جلسة يفك تشفير الحقول عند قراءتها.
remoteموجود فقط عندما يتم مزامنة الإعداد إلى متجر الإعدادات المشفر؛ راجع متجر الإعدادات المشفر.

عدّل بأمان باستخدام CLI وليس vim:

# تعديلات حقل واحد موجهة بالمؤشر (معرّفة بناءً على المعرفة للمسارات الحساسة)
rdc config field set --pointer /resources/machines/prod-1/port --new 2222
rdc config field set --pointer /credentials/cfDnsApiToken --current "$OLD" --new "$NEW"

# محرر كامل مع إسقاط JSONC مخفي (البشر فقط)
rdc config edit

# تفريغ JSONC للقراءة فقط، آمن للنصوص البرمجية والوكلاء
rdc config edit --dump

# افحص كل طفرة + رفض + كشف في سجل التدقيق
rdc config audit log --since 24h
rdc config audit verify

يحتوي هذا الملف على بيانات حساسة (مفاتيح SSH الخاصة، بيانات اعتماد LUKS، رموز Cloudflare). يُخزّن بصلاحيات 0600 (قراءة/كتابة للمالك فقط). لا تشاركه أو تضعه في نظام التحكم بالإصدارات. عندما يقرأ أي أمر rdc الملف، تُخفي الحقول الحساسة افتراضياً الحقول الحساسة: يظهر النص العادي فقط مع --reveal على تيرمينال تفاعلي بشري.

Envelope v2 والإنفاذ من جانب الخادم

عند مزامنة الإعداد إلى متجر الإعدادات المشفر، يلف CLI كل حقل حساس في التزام HMAC لكل حقل ويحمل تلك الالتزامات في الغلاف نص واضح. يرى الخادم فقط الملخصات السادسة عشرية: لا يرى القيم أبداً: لكنه يمكنه إنفاذ بوابات المعرفة على كل كتابة:

  • فحص الشرط المسبق: على PUT /configs/<id>، يرسل العميل الملخصات التي يدّعي معرفتها للمسارات التي يريد طفرها. يقارن الخادم مقابل الالتزامات المخزّنة في غلاف الإعداد. عدم تطابق → 409 precondition_failed مع mismatchedPaths. صفري المعرفة: الخادم لا يرى نص واضح.
  • مكافحة التنزيل: يجب أن يلتزم الغلاف الجديد بكل مسار حساس التزم به الغلاف السابق. لا يمكن لوكيل إسقاط مسار من الالتزامات للالتفاف حول بوابة معرفة مستقبلية.
  • تثبيت إصدار الغلاف: يرفض الخادم الأغلفة التي تفتقد envelopeVersion: 2 مع 400 unsupported_envelope_version. لا نافذة قبول مزدوجة.
  • تشفير لكل حقل في باقي الحقول (جانب العميل): عندما encryption.mode === "master-password"، يصبح كل سر كلوب AES-GCM فردياً مفتاحه بكلمة المرور الرئيسية. القراءات لا تؤدي إلى موجه ما لم تمس الأمر الفعلي سراً (لذا rdc machine list تظل خالية من الموجهات).

يُشتقّ مفتاح الالتزام (FCK) من جانب العميل من CEK عبر HKDF-SHA256(ikm=CEK, salt=fckSalt, info="rediacc-config-fck-v1") مع ملح لكل إعداد. يلغي تدوير fckSalt كل الالتزامات السابقة، مما يفرض إعادة حساب كاملة: مفيد عند تدوير CEK.