دليل عملي

تثبيت GitLab CE على VPS: دليل شامل

النشر17 دقيقةً للقراءةعدد الخطوات: 9

تستضيف GitHub وBitbucket مستودعاتك، لكنهما يفرضان قواعدهما: دقائق CI محدودة، ملكية غامضة للكود، وأسعار ترتفع مع نمو الفريق. يجمع GitLab CE (النسخة المجتمعية، رخصة MIT/EE Core) على خادم واحد منصةً git كاملة، ومحرك CI/CD بلا حصص دقائق مفروضة، وسجل Docker خاصاً، ووثائق wiki — دون اشتراك SaaS. يرشدك هذا الدليل إلى تثبيته في أقل من ثلاثين دقيقة على VPS باستخدام Docker Compose، وضبط SMTP، وتوصيل Runner، وتجنب الأخطاء الشائعة: إعداد GITLAB_OMNIBUS_CONFIG بشكل خاطئ، وانتهاء صلاحية SSL لغياب ACME، وRunner غير مسجّل.

المحتويات· لماذا GitLab CE بدلًا من GitHub أو Bitbucket1/12
  1. 01لماذا GitLab CE بدلًا من GitHub أو Bitbucket
  2. 02ما يتضمنه GitLab CE افتراضيًا
  3. 03المتطلبات الأساسية قبل البدء
  4. 04من التثبيت إلى أول مشروع
  5. 05إعداد runner Docker وكتابة أول pipeline CI/CD
  6. 06ضبط إشعارات SMTP بالتفصيل
  7. 07النسخ الاحتياطي واستعادة GitLab
  8. 08استكشاف الأخطاء: أكثر ثلاث مشكلات شيوعًا
  9. 09استكشاف متقدم: Sidekiq متوقف وPuma timeout وOOM على Gitaly
  10. 10تحسين استخدام RAM: الـswap وعمال Puma
  11. 11GitLab CE أو Forgejo أو Gitea: كيف تختار
  12. 12متى تختار GitLab CE ومتى تختار Forgejo

لماذا GitLab CE بدلًا من GitHub أو Bitbucket

GitHub وBitbucket خدمتان مُدارتان: عمليتان في البداية، لكن نموذج أسعارهما يتطور مع حجم الفريق، ودقائق CI محدودة في الخطط المجانية، وشفرتك مستضافة على بنية تحتية تابعة لجهة خارجية. يعكس GitLab CE هذه المعادلة: تنشر المنصة على VPS الخاص بك، وتحتفظ بالتحكم الكامل في الكود والبيانات، وCI/CD مدمجة دون حصص دقائق مفروضة من طرف ثالث. للوكالات والفرق التي تتعامل مع بيانات حساسة أو تفوتر العملاء، هذا التحكم غير قابل للتفاوض في أغلب الأحيان. GitLab CE هو اليوم أحد أكثر منصات git self-hosted انتشارًا: قاعدة كوده مفتوحة المصدر، ونواته حرة، وعشر سنوات من الوجود جعلت مجتمعه المساهم نشطاً.

ما يتضمنه GitLab CE افتراضيًا

  • منصة git كاملة: مستودعات خاصة وعامة، طلبات دمج، مراجعة الكود، حماية الفروع وCODEOWNERS.
  • CI/CD مدمجة بلا حد مفروض للدقائق: pipelines بصيغة YAML (‎.gitlab-ci‎.yml)، environments، deploy tokens والـartifacts.
  • سجل Docker خاص مستضاف على نطاقك: docker pull git‎.yourdomain‎.com/group/image:tag دون حساب Docker Hub.
  • Wiki وصفحات لكل مشروع ومجموعة، مع عرض Markdown كامل.
  • تتبع المشكلات والمراحل: لوحة kanban، تسميات، تكرارات ومخطط burndown مضمّنة.
  • Runners متوازية: سجّل أي عدد من الـrunners على بنيتك التحتية أو عمال CI.
  • Webhooks لإشعار أداة خارجية (Slack، PagerDuty، خادم النشر) عند كل push أو merge.
  • RBAC دقيق بخمسة مستويات وصول (Guest، Reporter، Developer، Maintainer، Owner) ودعم اختياري لـLDAP/SAML.

المتطلبات الأساسية قبل البدء

GitLab CE كثيف الاستهلاك للذاكرة — وهذا من أبرز عيوبه مقارنةً بـForgejo أو Gitea. خطّط لـ4 غيغابايت RAM كحد أدنى للاستخدام الخفيف (أقل من عشرة مستخدمين نشطين)؛ يُوصى بـ8 غيغابايت بمجرد إضافة runners على الجهاز نفسه أو تفعيل سجل Docker. تحت 4 غيغابايت، يتنافس Puma وSidekiq على الذاكرة ويستجيب GitLab بـ502 تحت الحمل. للتخزين، خصص 20 غيغابايت على الأقل للتثبيت والمستودعات الأولية — خطط لـ50 غيغابايت إن كنت ستخزّن صور Docker في السجل. تحتاج أيضًا إلى: اسم نطاق يشير إلى IP الـVPS (مثلاً git‎.yourdomain‎.com) لكي تُصدر Let's Encrypt شهادة TLS؛ وفتح المنافذ 80 و443 و22 في جدار الحماية؛ وتثبيت Docker Engine وإضافة Compose v2.

من التثبيت إلى أول مشروع

  1. إنشاء هيكل المجلدات

    أنشئ مجلدًا مخصصًا والمجلدات الثلاثة الدائمة التي يستخدمها GitLab: mkdir -p /opt/gitlab/{config,logs,data}. ستُوصل هذه المجلدات داخل الحاوية؛ دونها تختفي الإعدادات والمستودعات عند كل docker compose down.

  2. كتابة ملف docker-compose‎.yml

    أنشئ /opt/gitlab/docker-compose‎.yml. يُركّز مفتاح GITLAB_OMNIBUS_CONFIG كل الإعدادات الخاصة بنسختك — استبدل git‎.yourdomain‎.com بنطاقك الفعلي. عرّف خدمة gitlab بالصورة gitlab/gitlab-ce:17.2.1-ce.0، restart: unless-stopped، اسم المضيف، متغيرات البيئة، المنافذ 80 و443 و22، الـvolumes الثلاثة، shm_size: 256m وenv_file: ‎.env.

  3. ضبط GITLAB_OMNIBUS_CONFIG

    داخل GITLAB_OMNIBUS_CONFIG، عرّف على الأقل: external_url 'https://git‎.yourdomain‎.com'؛ letsencrypt['enable'] = true؛ معاملات SMTP — gitlab_rails['smtp_enable'] = true، العنوان، المنفذ 587، اسم المستخدم، كلمة المرور من ENV، المصادقة login، smtp_enable_starttls_auto = true. يجب أن تكون جميع الأسطر داخل كتلة GITLAB_OMNIBUS_CONFIG.

  4. إنشاء ملف ‎.env للأسرار

    أنشئ /opt/gitlab/‎.env وقيّد صلاحياته: touch /opt/gitlab/‎.env && chmod 600 /opt/gitlab/‎.env. أضف متغيراتك الحساسة — كحد أدنى GITLAB_SMTP_PASSWORD=كلمة_مرور_smtp.

  5. تشغيل GitLab والانتظار حتى اكتمال الإعداد

    أطلق الـstack: docker compose -f /opt/gitlab/docker-compose‎.yml up -d. انتظر نحو 5 دقائق قبل الوصول إلى واجهة الويب. تابع التقدم بـdocker compose -f /opt/gitlab/docker-compose‎.yml logs -f gitlab وانتظر رسالة gitlab Reconfigured!.

  6. استرداد كلمة مرور root الأولية

    استرجع كلمة المرور بـ: docker exec -it gitlab-gitlab-1 grep 'Password:' /etc/gitlab/initial_root_password. يُحذف هذا الملف تلقائيًا بعد 24 ساعة — دوّن كلمة المرور فورًا.

  7. تسجيل الدخول وتغيير كلمة المرور وتعطيل التسجيل المفتوح

    افتح https://git‎.yourdomain‎.com. سجّل دخولك بـroot. غيّر كلمة المرور من User Settings → Password. عطّل التسجيل العام: Admin Area → Settings → General → Sign-up restrictions.

  8. تسجيل GitLab Runner

    ثبّت gitlab-runner واسترجع رمز التسجيل من Admin Area → Runners. سجّل الـrunner: gitlab-runner register --url https://git‎.yourdomain‎.com --registration-token YOUR_TOKEN --executor docker --docker-image alpine:latest.

  9. التحقق من إرسال البريد الإلكتروني

    اختبر SMTP من وحدة تحكم Rails: docker exec -it gitlab-gitlab-1 gitlab-rails console ثم Notify‎.test_email('your@email‎.com', 'Test GitLab', 'Hello')‎.deliver_now.

النسخ الاحتياطي التلقائي. يتضمن GitLab أمر نسخ احتياطي كامل: docker exec -t gitlab-gitlab-1 gitlab-backup create. جدوله في crontab -e بالسطر 0 3 * * * docker exec -t gitlab-gitlab-1 gitlab-backup create CRON=1. زامن مجلد النسخ مع تخزين خارجي (S3، rclone) — النسخة المحلية وحدها ليست نسخةً احتياطية.

إعداد runner Docker وكتابة أول pipeline CI/CD

يُعدّ منفّذ Docker الخيار الموصى به لمعظم المشاريع: يعمل كل job في حاوية معزولة. بعد تسجيل الـrunner، يحتوي ملف /etc/gitlab-runner/config‎.toml على كتلة [runners‎.docker]. أضف volumes = ["/cache"] للاحتفاظ بالـcache بين الـbuilds، وpull_policy = ["if-not-present"] لتجنب سحب الصورة في كل job.

مثال pipeline أساسي بـ‎.gitlab-ci‎.yml:

stages:
  - test
  - build
  - deploy

variables:
  DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA

test:unit:
  stage: test
  image: node:20-alpine
  cache:
    key: $CI_COMMIT_REF_SLUG
    paths:
      - node_modules/
  script:
    - npm ci
    - npm test
  only:
    - merge_requests
    - main

build:image:
  stage: build
  image: docker:26
  services:
    - docker:26-dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - docker build -t $DOCKER_IMAGE .
    - docker push $DOCKER_IMAGE
  only:
    - main

deploy:prod:
  stage: deploy
  image: alpine:latest
  before_script:
    - apk add --no-cache openssh-client
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | ssh-add -
  script:
    - ssh -o StrictHostKeyChecking=no user@yourserver‎.com "docker pull $DOCKER_IMAGE && docker compose up -d"
  only:
    - main
  when: manual

تُحقن المتغيرات CI_REGISTRY_USER وCI_REGISTRY_PASSWORD وCI_REGISTRY تلقائيًا من GitLab CE. أما SSH_PRIVATE_KEY فتُعرَّف في Settings → CI/CD → Variables مع تفعيل Masked. job النشر deploy:prod مضبوط على when: manual — لا يُطلق تلقائيًا.

ضبط إشعارات SMTP بالتفصيل

يُرسل GitLab بريدًا إلكترونيًا عند كل merge request أو ذكر أو pipeline مكتمل أو تنبيه أمني. إعداد SMTP غائب أو خاطئ يقطع هذه الإشعارات في صمت.

الكتلة الكاملة في GITLAB_OMNIBUS_CONFIG لخادم SMTP مصادَق بـSTARTTLS على المنفذ 587:

gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = 'smtp‎.yourdomain‎.com'
gitlab_rails['smtp_port'] = 587
gitlab_rails['smtp_user_name'] = 'gitlab@yourdomain‎.com'
gitlab_rails['smtp_password'] = ENV['GITLAB_SMTP_PASSWORD']
gitlab_rails['smtp_authentication'] = 'login'
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['gitlab_email_from'] = 'gitlab@yourdomain‎.com'
gitlab_rails['gitlab_email_reply_to'] = 'noreply@yourdomain‎.com'

إن كان المُرحِّل يشترط TLS مباشر (المنفذ 465)، استبدل smtp_enable_starttls_auto = true بـsmtp_tls = true. المفاتيح خارج كتلة omnibus تُهمَل في صمت — اختبر دائمًا بـNotify‎.test_email(…)‎.deliver_now من وحدة تحكم Rails.

النسخ الاحتياطي واستعادة GitLab

ينشئ الأمر docker exec -t gitlab-gitlab-1 gitlab-backup create أرشيف tar كاملًا يضم المستودعات وقاعدة بيانات PostgreSQL والـartifacts. تنبيه: لا يشمل الأرشيف ملفَّي /etc/gitlab/gitlab‎.rb و/etc/gitlab/gitlab-secrets‎.json — احتفظ بهما بشكل منفصل:

tar czf /opt/gitlab/config-secrets-$(date +%Y%m%d)‎.tar‎.gz \
  /opt/gitlab/config/gitlab‎.rb \
  /opt/gitlab/config/gitlab-secrets‎.json

الاستعادة — ثلاث خطوات بالترتيب: ثبّت نفس الإصدار الذي أنتج النسخة؛ انسخ الأرشيف إلى /opt/gitlab/data/backups/؛ ثم:

docker exec -it gitlab-gitlab-1 gitlab-ctl stop puma
docker exec -it gitlab-gitlab-1 gitlab-ctl stop sidekiq
docker exec -it gitlab-gitlab-1 gitlab-backup restore BACKUP=<timestamp>_<version>
docker exec -it gitlab-gitlab-1 gitlab-ctl restart
docker exec -it gitlab-gitlab-1 gitlab-rake gitlab:check SANITIZE=true

جدول النسخ الاحتياطي الكامل ليلًا وزامنه مع تخزين خارجي.

استكشاف الأخطاء: أكثر ثلاث مشكلات شيوعًا

502 Bad Gateway عند الإقلاع. يستغرق GitLab نحو 5 دقائق ليصبح جاهزًا. إن استمر الـ502، تحقق من بدء Puma: docker exec gitlab-gitlab-1 gitlab-ctl status puma. نقص الذاكرة هو السبب الأكثر شيوعًا. SMTP لا يعمل. تحقق أولًا: هل كتلة gitlab_rails['smtp_*'] داخل GITLAB_OMNIBUS_CONFIG؟ مفتاح خارج الكتلة يُهمَل في صمت. Runner غير متصل. تحقق بـgitlab-runner verify --url https://git‎.yourdomain‎.com. شهادة TLS موقّعة ذاتيًا أو نطاق غير قابل للحل هما السببان المعتادان.

استكشاف متقدم: Sidekiq متوقف وPuma timeout وOOM على Gitaly

Sidekiq queue stuck. تحقق من الحالة:

docker exec gitlab-gitlab-1 gitlab-ctl status sidekiq
docker exec gitlab-gitlab-1 gitlab-rake gitlab:sidekiq:check

لتفريغ قائمة انتظار بعينها: docker exec -it gitlab-gitlab-1 gitlab-rails console -e production ثم Sidekiq::Queue‎.new('mailers')‎.clear. لإعادة تشغيله دون فقدان الـjobs المعلّقة: docker exec gitlab-gitlab-1 gitlab-ctl restart sidekiq.

Puma timeout. أضف في GITLAB_OMNIBUS_CONFIG: puma['worker_timeout'] = 90 (الافتراضي 60 ثانية). إن استمرت الـtimeouts، السبب في الغالب نقص RAM أو عدد workers غير ملائم.

OOM على Gitaly. تحقق بـdmesg | grep -i kill. قلّل الـcache: gitaly['configuration']['git']['catfile_cache_size'] = 5 (الافتراضي 100).

حاوية تخرج فور الإقلاع. راجع السجلات: docker compose logs gitlab | tail -50. الأسباب الشائعة: تعارض المنفذ 22، volume غير قابل للكتابة، أو صيغة Ruby خاطئة في GITLAB_OMNIBUS_CONFIG.

تحسين استخدام RAM: الـswap وعمال Puma

تقليل عمال Puma. في GITLAB_OMNIBUS_CONFIG:

puma['worker_processes'] = 2
puma['min_threads'] = 1
puma['max_threads'] = 4

كل عامل Puma يستهلك 200 إلى 300 ميغابايت. عاملان يكفيان لأقل من خمسة عشر مستخدمًا نشطًا.

إضافة swap. على VPS بلا swap:

fallocate -l 4G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab

توصيات RAM وCPU حسب حجم الفريق

| حجم الفريق | RAM موصى بها | vCPU | ملاحظات |
|---|---|---|---|
| 1–5 مطورين | 4 غيغابايت | 2 | Runners على الجهاز ذاته ممكنة مع swap |
| 5–15 مطورًا | 8 غيغابايت | 4 | Runner مخصص منصوح به فوق 8 pipelines/يوم |
| 15–30 مطورًا | 16 غيغابايت | 8 | سجل Docker نشط، Gitaly تحت الحمل |
| 30+ مطورًا | 32 غيغابايت+ | 16+ | فصل Gitaly وSidekiq على أجهزة مخصصة |

GitLab CE أو Forgejo أو Gitea: كيف تختار

مرّر الجدول أفقيًا

المعيارGitLab CEForgejo / Gitea
الرخصةMIT / EE CoreMIT
ذاكرة الخمول300–600 ميغابايت (Puma + Sidekiq)30–50 ميغابايت
CI/CD أصيلةنعم (`‎.gitlab-ci‎.yml`، runners)Forgejo: نعم عبر Woodpecker CI؛ Gitea: لا يوجد
سجل Docker مدمجنعمForgejo: نعم؛ Gitea: غير أصيل
Wiki لكل مشروعنعمنعم
LDAP / SAMLنعم (CE)Forgejo: نعم؛ Gitea: LDAP نعم، SAML لا
منحنى التعلممرتفع (واجهة غنية)منخفض إلى متوسط
الأنسب لـفرق 5+ تحتاج CI وسجل Docker وRBACفرق خفيفة، منصة بسيطة، بصمة RAM منخفضة

متى تختار GitLab CE ومتى تختار Forgejo

GitLab CE هو الاختيار الصحيح إن احتاج فريقك إلى CI/CD قوية مدمجة مباشرةً في المنصة، وسجل Docker خاص على نطاقك، وpipelines نشر مع environments، أو إدارة مشاريع بمشكلات ومراحل ولوحة kanban دون أداة خارجية. بصمته الذاكرية (4–8 غيغابايت) هي ثمن هذا الثراء الوظيفي. Forgejo أو Gitea هما الخيار حين تكون الذاكرة القيد الرئيسي، وحين المنصة هي الحاجة الوحيدة (دون CI مدمجة). على VPS بـ2 غيغابايت، GitLab CE غير قابل للتطبيق؛ Forgejo يعمل بـ256 ميغابايت. على VPS بـ8 غيغابايت مخصص لفريق تطوير، يوفر GitLab CE بيئة كاملة تضعها GitHub على منصتها SaaS — تحت سيطرتك ودون اشتراك شهري بحسب عدد المستخدمين.

VPS جاهز لـGitLab CE

يحتاج GitLab CE إلى VPS بذاكرة 4 إلى 8 غيغابايت وقرص سخي وعنوان IP مخصص. تأتي VPS ServOrbit مزوّدة بنظام التشغيل الذي تختاره (Ubuntu 24.04 LTS أو Ubuntu 22.04 LTS أو Debian 12 أو AlmaLinux 9) وصلاحية root فورية — ما يكفي لإطلاق منصتك خلال ثلاثين دقيقة.

بحاجة إلى مساعدة؟

تصفّح مركز المساعدة والأسئلة الشائعة، أو تواصل مع فريقنا — معاودة اتصال أو WhatsApp أو بريد إلكتروني. الدعم بـالعربية والفرنسية والإنجليزية.

راسلنا على WhatsAppيُفتح في علامة تبويب جديدة