لماذا تغادر GitLab.com إلى نسخة مستضافة ذاتيا
عندما تتغير أسعار أداة SaaS، مثل الزيادة الأخيرة في Atlassian Cloud التي شرحناها في مقالنا عن الصدمة السعرية المزدوجة، تعيد الفرق تقييم أدوات التطوير كلها. بالنسبة لوكالة، السؤال ملموس: شيفرة عشرة عملاء في حساب واحد لدى طرف ثالث، بمدة احتفاظ وصلاحيات وصول لا تحددها بنفسك.
النسخة المستضافة ذاتيا تنقل هذه القرارات إليك: أين تُخزَّن المستودعات، وكم تُحفظ الملفات الناتجة، ومن يستطيع الدخول، وكم يكلف ذلك شهريا. ثمن هذه الحرية عمل ترحيل لا تنجزه GitLab كاملا نيابة عنك.
لا يكرر هذا الدليل اختيار المنصة الذي تناوله مقارن منصات Git، ولا التثبيت الموصوف في دليل تثبيت GitLab CE. ينطلق من نسخة GitLab تعمل أصلا، ويغطي فقط الانتقال من GitLab.com إليها.
ما تكسبه باستعادة الاستضافة
- وصول تحت سيطرتك — الحسابات والمجموعات والأدوار تُدار على نسختك، لا في حساب SaaS مشترك بين العملاء.
- احتفاظ تحدده أنت — مدة حفظ الملفات الناتجة والسجلات وحجم السجل تُضبط كلها من لوحة الإدارة.
- فاتورة تتبع خادمك — التكلفة تتوقف على الجهاز الذي تحدد حجمه، لا على عدد المقاعد.
- اسم نطاق خاص بك — يستجيب المستودع على
git.your-domain.comبشهادتك وجدارك الناري. - ترحيل على مراحل — يبقى المشروع القديم في مكانه للقراءة فقط حتى يُعتمد الجديد.
ما لا ينقله الترحيل ويجب جرده أولا
توثيق التصدير الرسمي للمشاريع يسرد ما لا يُصدَّر: سجل خطوط الأنابيب الفرعية، ومشغلات خطوط الأنابيب، وسجلات مهام CI/CD وملفاتها الناتجة، وصور سجل الحاويات والحزم، ومتغيرات CI/CD، وwebhooks، والرموز المشفرة، وعدد الموافقات المطلوبة، ومفاتيح النشر المسموح لها بالدفع إلى الفروع المحمية، والملفات الآمنة، ومتغيرات جداول خطوط الأنابيب. ولا تُستورد مفاتيح النشر كذلك: عليك تفعيلها من جديد في المشروع المستورد.
للنقل المباشر قائمة استثناءات خاصة به تتقاطع مع الأولى: متغيرات CI/CD وwebhooks وصور سجل الحاويات وسجل الحزم وسجلات المهام وملفاتها الناتجة. وعلى مستوى المجموعة لا تنتقل أيضا متغيرات CI/CD ورموز النشر وقواعد الدفع.
اكتب هذا الجرد في جدول قبل أن تبدأ: صف لكل مشروع، وعمود لكل عنصر ناقص، وعمود للشخص الذي يعيد إنشاءه. هذه الوثيقة، أكثر من التصدير نفسه، تحميك يوم يُغلق الوصول القديم.
تصدير المشروع أم النقل المباشر: ما الذي تغطيه كل طريقة
مرّر الجدول أفقيًا
| العنصر | تصدير المشروع (ملف) | النقل المباشر |
|---|---|---|
| الدقة | مشروع واحد في كل مرة عبر ملف يُنزَّل | مجموعات كاملة، مع مشاريعها أو بدونها، من الواجهة |
| متغيرات CI/CD | لا تُصدَّر | لا تُنقل |
| صور سجل الحاويات | لا تُصدَّر | لا تُنقل |
| Webhooks | لا تُصدَّر | لا تُنقل |
| سجلات المهام وملفاتها الناتجة | لا تُصدَّر | لا تُنقل |
| الأعضاء | يُربطون إذا طابق البريد العام في المصدر البريد الأساسي في الوجهة | يُربطون إذا طابق البريد العام في المصدر بريدا مؤكدا في الوجهة |
| ما تتطلبه النسخة | مسؤول يجري الاستيراد | ميزة يفعّلها مسؤول، ورمز بنطاق `api` في المصدر |
المتطلبات: الإصدارات والصلاحيات وموارد نسختك
القاعدة الأولى هي الإصدار. استيراد الملف يقبل تصديرات من إصدار يتأخر حتى إصدارين فرعيين عن الوجهة، ويطلب التوثيق أن تكون الوجهة على إصدار المصدر نفسه أو أحدث. أما النقل المباشر فيوصي التوثيق بـ GitLab 16.8 أو أحدث على الجانبين، ويشترط ألا يتأخر المصدر أكثر من إصدارين فرعيين عن الوجهة. وبما أن GitLab.com يتقدم باستمرار، استهدف أحدث إصدار مستقر متاح لنسختك، وحدّثها قبل الترحيل لا بعده، وأعد قراءة الفارق المسموح به في التوثيق يوم التنفيذ.
من حيث الصلاحيات تحتاج دور Owner في المجموعة المصدر، ومسؤولا في النسخة الهدف، ورمز وصول شخصيا بنطاق api أُنشئ على GitLab.com. يجب أن تتصل النسختان عبر HTTPS مع مساحة حرة في /tmp.
من حيث الموارد، توصيتنا التحريرية: 4 vCPU و8 غيغابايت من الذاكرة لنسخة تستضيف السجل أيضا، وقرص NVMe بحجم مجموع المستودعات والصور، وrunners على VPS منفصل حين تثقل عمليات البناء. التثبيت نفسه موصوف في دليل GitLab CE على VPS.
خطط ونفذ الترحيل من الجرد إلى التحويل
جرد المجموعات والمشاريع والاعتمادات
اسرد كل مجموعة وكل مشروع ومتغيراته وwebhooks وrunners وتكاملاته. دوّن من يملك كلا منها لدى العميل.
تحديث النسخة الهدف
تحقق من الإصدار في لوحة الإدارة واستهدف أحدث إصدار مستقر متاح، بما لا يقل عن إصدار GitLab.com، قبل أي استيراد.
إنشاء المستخدمين في الهدف
لا يُنشأ الأعضاء أثناء الترحيل. أنشئ الحسابات قبله بالبريد الأساسي الذي يستخدمه كل شخص على GitLab.com.
تخصيص مجموعة لكل عميل
أنشئ في الهدف مجموعة أو مجموعة فرعية لكل عميل بأدنى الصلاحيات قبل الاستيراد.
جعل البريد العام منشورا في المصدر
يحدد كل عضو بريدا عاما في ملفه على GitLab.com، على الأقل إلى أن ينتهي الاستيراد.
تفعيل النقل المباشر في النسخة الهدف
يفعّل مسؤول ترحيل المجموعات بالنقل المباشر من إعدادات التطبيق. وهو معطل افتراضيا في النسخة المستضافة ذاتيا.
بدء استيراد المجموعة
في الهدف اختر Create new ثم New group ثم Import group، وأدخل
https://gitlab.comورمزك، ثم Connect instance. حدد المجموعات باستخدام Import with projects.تصدير المشاريع المنفردة يدويا
لمشروع خارج أي مجموعة افتح Settings ثم General ثم Advanced ثم Export project، ونزّل الملف واستورده في الهدف.
متابعة الاستيراد وقراءة الأخطاء
يوضح عمود Status التقدم. وعند فشل الاستيراد أو اكتماله جزئيا يفصّل Show errors السبب. توقع ساعات عدة إذا كانت المشاريع كثيرة.
ربط السجل وCI
أعد بناء المتغيرات والصور كما يلي أدناه، ثم شغّل خط أنابيب كاملا في الهدف قبل لمس المشروع القديم.
الأعضاء والمكلفون: قاعدة الربط
في نسخة مستضافة ذاتيا القاعدة المنشورة هي: يجب أن يكون المستخدمون موجودين مسبقا في الوجهة، وأن يطابق البريد العام للحساب المصدر البريد الأساسي لحساب الوجهة. إذا تحققت الشروط أُضيف الشخص عضوا مباشرا. وإلا ينتقل الربط إلى المستخدم الذي ينفذ الاستيراد: فيصبح كتّاب التعليقات والمكلفون كلهم باسمك.
قبل الاستيراد تحقق من حقل Public email في كل ملف على GitLab.com. وفي تصدير المشروع يمكنك أيضا إضافة بريد عام بتعديل الملف project_members.ndjson داخل الأرشيف. يجب أن يجري مالك المجموعة العليا التصدير لتشمل النتيجة الأعضاء المباشرين والموروثين، وأن ينفذ مسؤول الاستيراد.
مع النقل المباشر تُربط العضويات المستوردة أولا بمستخدمين بدلاء ريثما يُعاد إسنادها. كما يتيح مربع Import user memberships عدم استيراد العضويات. في هذه الحالة يحسم الربط البريد العام في المصدر مقابل بريد مؤكد في الوجهة، لا البريد الأساسي كما في استيراد الملف.
وبالنسبة لوكالة، هيّئ الوجهة قبل الاستيراد: مجموعة عليا لكل عميل، أو مجموعة فرعية لكل عميل تحت مجموعة الوكالة. امنح كل عميل أدنى دور ممكن على مجموعته وحدها (Reporter أو Developer بدل Owner)، واحتفظ بدور Owner للفريق الداخلي، فتستطيع لاحقا إخراج عميل بنقل مجموعته أو تصدير مشاريعه دون المساس بالآخرين.
متغيرات CI/CD وسجل الحاويات: أعد البناء يدويا
لا تسافر المتغيرات لأن GitLab تعدها حساسة. اسردها في المصدر عبر الواجهة البرمجية: curl --header "PRIVATE-TOKEN: <token>" "https://gitlab.com/api/v4/projects/<id>/variables". تعطي القائمة المفتاح والخاصيتين masked وprotected وعادة القيمة؛ لكن ليست كل القيم قابلة للقراءة بالضرورة، بحسب الإصدار وطريقة إنشاء المتغير.
ثم أعد إنشاءها في الهدف عبر curl --request POST --header "PRIVATE-TOKEN: <token>" --form "key=NAME" --form "value=value" "https://git.your-domain.com/api/v4/projects/<id>/variables". يقبل المفتاح 255 حرفا من A-Z وa-z و0-9 و_. وحين تغيب القيمة أو تبقى مخفية، أعد إنشاء السر لدى مزوده واحفظه في خزنة الوكالة.
تُعاد متغيرات المجموعة من إعدادات CI/CD للمجموعة. أما runners فتُسجَّل من جديد في النسخة الجديدة: رموزها لا تنتقل.
نقل صور السجل إلى العنوان الجديد
تفعيل السجل في النسخة الهدف
في
/etc/gitlab/gitlab.rbحددregistry_external_urlعبر HTTPS، مثلhttps://registry.your-domain.com، ثم شغّلsudo gitlab-ctl reconfigure. يتطلب السجل شهادة TLS.إنشاء رمز لكل جانب
يكفي رمز بنطاق
read_registryلسحب الصور، ومعهwrite_registryلدفعها.سحب كل صورة من العنوان القديم
سجّل الدخول بـ
docker login registry.gitlab.comثمdocker pull registry.gitlab.com/group/project/image:tag.إعادة الوسم ثم الدفع إلى الهدف
نفذ
docker tag registry.gitlab.com/group/project/image:tag registry.your-domain.com/group/project/image:tagثمdocker login registry.your-domain.comوdocker push registry.your-domain.com/group/project/image:tag. تُكتب مسارات مستودعات السجل بأحرف صغيرة.
أبقِ طريق العودة مفتوحا
لا تحذف شيئا في المصدر. أرشف المشروع القديم أو اسحب صلاحيات الكتابة، وأبقه مقروءا، ثم شغّل خط أنابيب وgit clone كاملا من الهدف. ما دام العميل لم يوقّع على المصادقة يبقى التحويل قابلا للعكس: يكفي إعادة فتح المشروع القديم.
استكشاف الأخطاء: أخطاء المصادقة والاستيراد
عند docker login أو docker push تعني الرسالة access forbidden بحسب التوثيق أن ترويسة Authorization أُزيلت قبل وصولها إلى GitLab، غالبا بسبب وكيل أمام النسخة. راجع إعداد الوكيل العكسي.
يشير الخطأ UNAUTHORIZED (401) إلى بيانات اعتماد خاطئة أو منتهية، أو نطاقات ناقصة، أو كلمة مرور استُخدمت مع تفعيل المصادقة الثنائية: استخدم حينها رمزا. ويعني DENIED (403) أن البيانات صحيحة لكن بلا حق على السجل.
في صورة كبيرة تدل الرسالة unauthorized: authentication required على رمز انتهت صلاحيته قبل اكتمال الدفع. يمكن للمسؤول تمديد مدته.
وعند الاستيراد، يحصل عنوان المعلَم الموجود مسبقا على لاحقة فريدة من نوع 18.0 (imported-…): غيّر اسم المعلَم قبل الترحيل لتجنب ذلك.
فحوص قبل قطع الوصول القديم
- مستودعات متطابقة — قارن الفروع والوسوم، ثم أجرِ استنساخا كاملا من الهدف.
- خط أنابيب كامل أخضر — خط أنابيب على الفرع الرئيسي بعد إعادة إنشاء المتغيرات وتسجيل runners من جديد.
- الصور موجودة — كل وسم يستخدمه نشر موجود في السجل الجديد.
- الأعضاء والأدوار مراجعون — لم ينتقل أي كاتب أو مكلف إلى الحساب الذي بدأ الاستيراد.
- Webhooks ومفاتيح النشر أُعيد إنشاؤها — بما فيها تكاملات المراسلة والنشر والمراقبة.
- مصادقة مكتوبة من العميل — لا يُغلق المشروع القديم إلا بعد هذا الاتفاق.
التوثيق الرسمي
مصدر قواعد هذا الدليل هو توثيق GitLab: تصدير المشاريع واستيرادها، وترحيل المجموعات بالنقل المباشر، والعناصر المنقولة، وواجهة متغيرات المشروع، والمصادقة على السجل، والسجل في نسخة مستضافة ذاتيا. أعد قراءتها في تاريخ ترحيلك فقوائم العناصر المنقولة تتغير.
بعد ذلك: التوحيد حول نسختك
بعد اعتماد المشاريع تصبح النسخة النقطة المركزية لمحفظة الوكالة. ولسجل أثقل يمكن لـ Harbor على VPS أن يتولى المهمة. وإذا كان ترحيلك قادما من أداة تذاكر أخرى فإن دليل الانتقال من Jira إلى OpenProject أو Plane يتبع منطق الجرد نفسه. وإن كنت ما زلت مترددا في اختيار المنصة فإن الانتقال من GitLab إلى Gitea يبقى خيارا أخف.