فشل الترقية من داخل الصين بسبب مشاكل git

نقوم بتشغيل مثيل Discourse على خادم Aliyun/Alibaba يعمل بنظام Ubuntu 20.04، وكما هو الحال مع كل ما يتعلق بـ Git، نواجه مشاكل بسبب الجدار الناري العظيم. غالبًا ما يفشل الترقية اليدوية باستخدام launcher rebuild app بسبب أخطاء GnuTLS (أنواع مختلفة). لا علاقة لهذا بالإصدارات المثبتة من Git على الخادم، بل هو في الواقع مرتبط بمعالجة المصافحة داخل الجدار الناري؛ وبالطبع لا نفهم التفاصيل، لكن عدة مصادر تناقش هذه المسألة بالتفصيل. لذا فإن تجميع Git يدويًا باستخدام OpenSSL ليس خيارًا متاحًا أيضًا.

أحيانًا تنجح عملية السحب (pull) بعد تجاوز النواة، بل وتنجح في استنساخ إضافة Docker Manager، لكن بعد سحب 2-3 إضافات، يحدث عادةً انتهاء مهلة أو خطأ آخر.

مثال:

$ ./launcher rebuild app
Ensuring launcher is up to date
Fetching origin
Launcher is up-to-date
Stopping old container
+ /usr/bin/docker stop -t 60 app
app
cd /pups && git pull && git checkout v1.0.3 && /pups/bin/pups --stdin
fatal: unable to access 'https://github.com/discourse/pups.git/': gnutls_handshake() failed: The TLS connection was non-properly terminated.
76630913bae18d6b45b6b3ecc3ec390c1e69222a493f2ecf424ee06adf9d1002
** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one.
./discourse-doctor may help diagnose the problem.

هذا الخطأ شائع أيضًا:

fatal: unable to access 'https://github.com/discourse/discourse.git/': GnuTLS recv error (-54): Error in the pull function.

الحل المحتمل 1
عادةً عند الاستنساخ من GitHub، فإن استخدام بروتوكول SSH بدلاً من HTTPS يعطي نتائج أفضل أو لا يفشل، لكن نظرًا لمهمة إعادة البناء الفريدة في Discourse، لا أعرف أين أكوّن ما يجب حتى يقوم الـ Launcher بالسحب عبر SSH بدلاً من HTTPS. هل من الممكن إعداد مثيل Discourse للقيام بذلك؟

الحل المحتمل 2
كخيار آخر، يتوفر لدي وكيل SOCKS5 لتجاوز الجدار الناري لمشاهدة الأفلام الإباحية للوصول إلى الموارد المحجوبة من داخل الصين، وأعرف أن Git يمكن تكوينه لاستخدام بروتوكول socks://، لكنني للأسف لا أفهم كيف وأين أكوّن الإعدادات في Discourse بحيث تستخدم عمليات السحب الخاصة بـ Discourse Launcher الوكيل. أود تجنب القيام بذلك عبر git config --global للمستخدم الجذر، بل أن تكون هذه المعلومات في إعدادات مستودعات Discourse. هل يمكن لأي شخص أن يوجهني حول كيفية تحقيق ذلك؟

الأمر مرهق، حيث نستخدم هذا المثيل من Discourse في شبكتنا الداخلية، وحاليًا مثيلنا معطل تمامًا لأكثر من شهر، مما يؤثر بشكل كبير على عملياتنا.

إعجابَين (2)

هل يؤدي تمرير متغيرات بيئة الوكيل في app.yml تحت قسم env إلى جعله يعمل؟
وهنا حل لـ Rubygem تحت الجدار الناري العظيم:

هل رأيت Replace rubygems.org with taobao mirror to resolve network error in China

شكرًا جزيلاً لك. لا تسبب حزم Ruby أي مشاكل، حيث قمت بدمج القالب المذكور في منشورك في ملف app.yml الخاص بنا منذ البداية، ويعمل بشكل ممتاز.

الأمر يتعلق باستنساخ المستودع الرئيسي ومستودعات الإضافات.

أحتاج إلى التحقق من متغيرات البيئة الخاصة بأعلام Git، وللأسف أنا ضعيف في Docker وخاصة في ملفات docker-compose. هل لديك مصدر يمكن أن تشير إليّ إليه؟

لم يستخدم Discourse docker-compose كما أعرف.

أعتقد أن إضافة الأمر التالي إلى خطاف before_web يمكن أن يجعله يعمل، مثلما يفعل web.china.template.yml:

git config --global http.proxy socks5://yourproxy:port

وإذا لم تعد بحاجة إلى الوكيل بعد البناء، أضف ما يلي إلى خطاف after_web:

git config --global --unset http.proxy

جميع الخطافات تعمل داخل الحاوية، لذا لا أعتقد أن ذلك سيكون مشكلة.

إعجاب واحد (1)
إعجابَين (2)

دليل آخر على جهلي بـ Docker. نعم، من الواضح أن هذا ليس ملف docker-compose. هل يُسمى “ملف Docker”؟ أم أن هذا المصطلح يشير إلى config.json؟ مهما كان الأمر، فإن نصيحتك وجهتني إلى الاتجاه الصحيح، لكن يجب تسمية الخطاف before_code بدلاً من before_web.

باختصار: قم بإعداد SOCKS5 باستخدام shadowsocks-libev، واستمع على الجهاز المحلي على العنوان 172.17.0.1 (وليس localhost)، ومرر معلومات الوكيل كما في رسالتك، ثم أعد بناء التطبيق.

سأكتب دليلاً مفصلاً هنا، لأنني أفترض أن هناك أشخاصًا آخرين يمرون بنفس التجربة المؤلمة. حاليًا، لا تزال هناك مشاكل تتعلق بمستودعات مكونات السمات، لذا لم ينجح rebuild الخاص بي بعد، لكنني تجاوزت على الأقل جميع عمليات جلب الإضافات.

على الرغم من أن هذا الأمر غير ذي صلة مباشرة بالموضوع الرئيسي، إلا أن المشكلة التي أواجهها ليست في بدء تشغيل التطبيق، بل في أن إعدادات redis-server الحالية - الموجودة على جهاز آخر - لا تتطابق مع الواقع الفعلي لحالة التطبيق الحالية. لذلك لا يمكنني تشغيل الحاوية وتعطيل مكونات السمات عبر واجهة المستخدم الرسومية، حيث تواجه هذه المكونات مهلة زمنية عند استنساخها.

شكرًا جزيلاً لتوجيهي إلى شرحك، لكنني أود إضافة بعض الملاحظات، حيث لا ينطبق المثال تمامًا.

  1. لا أفهم هذا، عذرًا؟ يعطيني أمر env الكثير من المعلومات، لكن لا شيء يتعلق بملف gitconfig الخاص بي.
  2. بما أنني لم أفهم النقطة 1)، لم أستطع تحديد المتغيرات التي يجب تمريرها. كما أنني لم أضف أعلام git إلى قسم env في ملف app.yml، بل استدعيتها عبر hook.
  3. لم يكن هذا ضروريًا، لأنني لا أريد أن يمر الحاوية بأكملها عبر socks، بل فقط عملية git fetch، لكنني أعتقد أن هذه النقطة كانت أكثر خصوصية بحالة الاستخدام الأصلية في الموضوع الذي أشرت إليه.

لكن شكرًا مرة أخرى، فقد وجهت مدخلاتكني في الاتجاه الصحيح. إبهام لأعلى لفريق Discourse! :ok_hand:

إعجاب واحد (1)

هل قمت بشراء خدمة علي يين واختيار منطقة داخل البر الرئيسي للصين؟

نسخة علي يين من هونغ كونغ أو الدولية لن تواجه هذه المشكلة.

إعجاب واحد (1)

أيضًا، قد تكونون قد ناقشتم هذا التفصيل بالفعل، ولكن في حال لم تكتشفوه، إليك سكريبت يمكنك تشغيله لتثبيت git عبر openssl

ترقية يدوية خالية من المتاعب من داخل الصين

الخطوات

  1. إنشاء وكيل SOCKS5 خارج الصين
  2. إعداد وتكوين اتصال الوكيل على الخادم الصيني
  3. إنشاء قالب لتسهيل التحرير
  4. إضافة إعدادات وكيل Git إلى القالب
  5. تضمين القالب في app.yml
  6. إعادة بناء التطبيق

1 - وكيل SOCKS5 عن بُعد

للسهولة في الاستخدام (ولأسعارهم الودية)، أنصح بإعداد خادم Digital Ocean في مكان مثل سنغافورة. استخدم خادم Ubuntu قياسي، واكمل جميع إعدادات الأمان الأساسية (مفاتيح SSH، UFW، وما إلى ذلك)، ثم قم بتثبيت Shadowsocks:

على الخادم البعيد
$ sudo apt install shadowsocks-libev

قم بتكوين إعدادات الوكيل:

$ cd /etc/shadowsocks-libev

# أحب الاحتفاظ بالملفات الأصلية
$ sudo cp config.json orig.config.json
$ sudo nano config.json

انتبه جيدًا لمعاملات المهلة (timeout) وطريقة التشفير (method):

{
    "server":"123.123.123.123", # عنوان IP للخادم البعيد
    "server_port":8400, # حسب رغبتك
    "local_port":1080,
    "password":"Swordfish", 
    "timeout":600, # <= ضروري!
    "method":"chacha20-ietf-poly1305"
}

تأكد من مراجعة جميع الإعدادات في تكوين systemd (/lib/systemd/system/shadowsocks-libev-local@.service). فعّل خدمة shadowsocks-libev-local@.service، أعد تشغيل الجهاز، وتحقق من تشغيل الخدمة.

2 - إعداد اتصال الوكيل على الخادم الصيني

على جهاز Discourse

$ sudo apt install shadowsocks-libev

إذا كنت تستخدم Aliyun، ابحث عن إعدادات الجدار الناري في لوحة التحكم الخاصة بهم، وتحقق من إعدادات المنفذ (port) المناسبة.

لا داعي للعبث بإعدادات systemd على جهاز العميل، ولكن احتفظ بملفات تكوين منفصلة لاستخدام Docker والاستخدام العادي، حيث قد ترغب في استخدام وكيل SOCKS5 خارج سياق Docker، وبالتالي ستحتاج إلى استخدام 127.0.0.1 بدلاً من عناوين الشبكة القابلة للوصول من Docker.

$ cd /etc/shadowsocks-libev
$ sudo cp config.json local.json
$ sudo cp config.json docker.json

عدّل التكوين ليكون مشابهًا لهذا:

$ sudo nano local.json

{
    "server":["123.123.123.123"], # عنوان IP للجهاز البعيد
    "mode":"tcp_and_udp", # هذا التعليق يختلف بسبب إصدارات shadowsocks-libev المختلفة في إعداداتي
    "server_port":8400,
    "local_address":"127.0.0.1",
    "local_port":1080,
    "password":"Swordfish",
    "timeout":600, # <= تأكد من ذلك
    "method":"chacha20-ietf-poly1305"
}

للسهولة، دعنا نضيف اختصارًا (alias) إلى ملف .bashrc:

$ nano ~/.bashrc

# الصق
alias dockershadow='ss-local -c /etc/shadowsocks-libev/local.json'

عدّل التكوين الآخر للسماح لـ Docker بالمرور عبر شبكة الجهاز المضيف:

$ sudo nano docker.json

{
    "server":["123.123.123.123"],
    "mode":"tcp_and_udp",
    "server_port":8400,
    "local_address":"172.17.0.1",
    "local_port":1080,
    "password":"Swordfish",
    "timeout":600,
    "method":"chacha20-ietf-poly1305"
}

اضبط الاختصار لاستخدام تكوين Docker المحدد:

alias dockershadow='ss-local -c /etc/shadowsocks-libev/docker.json'

3 و 4 - إنشاء قالب للحفاظ على تنظيم ملف app.yml

هذا اختياري تمامًا ويعتمد على ذوقك؛ أنا أفضل إبقاء app.yml مقروءًا وقصيرًا، والحفاظ على المكونات في مكان آخر. أعطِ القالب أي اسم يناسب ذوقك، اخترتُ web.git.template.yml.

$ nano templates/web.git.template.yml
# الصق:

hooks:
  before_code:
    - exec:
       cmd:
         - git config --global http.proxy socks5://172.17.0.1:1080
         - git config --global https.proxy socks5://172.17.0.1:1080
         - git config --global https.sslVerify = false 

# اختياري
  after_code:
    - exec:
       cmd:
         - git config --global --unset http.proxy
         - git config --global --unset https.proxy
         - git config --global --unset https.sslVerify

لقد جربته مع الخطاف after_web، لكنه لم ينجح.

5 - تعديل ملف app.yml

استدعِ القالب في ملف app.yml:

$ cd /<discourse dir>
$ sudo nano containers/app.yml


templates:
  - "templates/web.template.yml"
  - "templates/web.china.template.yml"
  - "templates/web.ratelimited.template.yml"
  - "templates/web.socketed.template.yml"
  - "templates/web.git.template.yml"

من المرجح أن يكون قسم القوالب لديك مختلفًا، فقط تأكد من تضمين web.china و web.git-blabla (أو ما سميته أنت) من القوالب.
لا تعرض المنفذ 1080:1080 في ملف app.yml!

6 - إعادة البناء

قبل إعادة البناء، تأكد من أن إعدادات الوكيل تعمل بشكل صحيح عند النسخ باستخدام git.

$ git config --global http.proxy socks5://172.17.0.1:1080
$ git config --global https.proxy socks5://172.17.0.1:1080
$ git config --global https.sslVerify = false 

هذا بالطبع يضيف أعلام الوكيل إلى ملف .gitconfig الخاص بالمستخدم في الدليل الرئيسي، لذا انتبه لإزالتها بعد الاختبار.
اختر مستودعًا كبيرًا عشوائيًا على Github يحتوي على عدد كبير من الملفات، وتحقق من سرعة النسخ. إذا كانت إعداداتك صحيحة، يجب أن تتمكن من النسخ بسرعة تقارب 12-15 ميجابايت/ثانية، اعتمادًا على إعدادات Aliyun لديك. إذا كانت سرعة اتصالك تتصاعد ببطء من 200 كيلوبايت/ثانية إلى حوالي 10 ميجابايت/ثانية، فإن جهودك لم تنجح.

أخيرًا، أعد البناء:

$ cd /<discourse directory>

# شغل الوكيل باستخدام الاختصار الذي ضبطناه سابقًا
$ dockershadow
$ ./launcher rebuild app

ستفشل عملية إعادة البناء في كثير من الأحيان، لذا تحتاج إلى الصبر (وربما مشروب Baijiu). كلما قل عدد الإضافات (plugins) المحددة في ملف app.yml، زادت احتمالية نجاح إعادة البناء.

7 - ملاحظات

ما زلت أعتبر هذا حلاً مؤقتًا وليس إجراءً جاهزًا للإنتاج، لذا ربما يكون لدى شخص ما فكرة حول كيفية عكس (mirror) مستودع GitHub في الصين، لجعل هذه العملية أقل إيلامًا. وكما نعلم جميعًا، تتغير آليات GFW غير الشفافة باستمرار.

بالطبع، وكيل SOCKS5 هو مجرد واحد من العديد من الخيارات، لكنني أحب وجود حلول متعددة الاستخدامات تحت تصرفي.

إذا كان لدى أي شخص فكرة حول كيفية جعل هذا الحل المؤقت جاهزًا للإنتاج، فسأقدر مساهمتك. إن Discourse برنامج رائع، لكنني أفترض أن أحد أسباب عدم استخدامه على نطاق واسع في الصين هو عمليات التثبيت والصيانة المزعجة. لقد أعطتني محاولة الترقية عبر واجهة المستخدم الرسومية (GUI) نسبة فشل 100% خلال العام الماضي، بغض النظر عن إعدادات المهلة التي قمت بتكوينها في وكيل العكس (reverse proxy) الخاص بـ nGinx.

سيتم تقديم الترجمة الصينية قريبًا

7 إعجابات

بالضبط. بما أن الغرض الرئيسي من هذه الحالة هو أن تكون جزءًا من إطار عمل الشبكة الداخلية للشركة، فإن هونغ كونغ للأسف ليست خيارًا بسبب زمن الوصول. أيضًا، ستكون الحالات (القادمة) الموجهة للعملاء تتعامل مع المستخدمين في البر الرئيسي - بمجرد أن أتمكن من فهم مصادقة Weixin، لذا أحتاج إلى حل عملي لمناطق علي يوان في البر الرئيسي.

شكرًا جزيلاً لك. لقد راجعت العديد من الأدلة حول هذا الموضوع، ولكن نظرًا لأن السبب الرئيسي للمشكلة ليس مصادقة TLS الخاصة بـ Git بحد ذاتها، بل فحص المصافحة في عمليات فحص الحزم الخاصة بالجدار الناري (GFW)، فقد امتنعت عن اتباع هذا النهج. فترجمة git مع openssl قد تفتح أبوابًا لعالم جديد مليء بالألم، كما قرأت سابقًا.

يتم سحب معظم مكونات السمة أيضًا من GitHub أثناء البناء (أو بدء الحاوية؟)، لذا قد يكون هناك خطاف آخر لإضافة وكيل git قد يساعد، ولا تقم بإزالة الوكيل إذا كنت تريد أن يعمل مع واجهة المستخدم الرسومية. ولا يبدو أن خادم Redis هو السبب في ذلك.

كان خادم Redis مجرد مشكلة أخرى زادت من تعقيد عملية إعادة البناء. لقد كان أشبه بحلقة مفرغة: فقد تغيرت إعدادات Redis الخارجية، بينما كانت حالة التطبيق قبل إعادة البناء بحاجة إلى هذا التكوين المحدد لـ Redis للبدء. ومع ذلك، لم يتمكن من إعادة البناء لأن جلب مكونات السمة (theme) لم يعمل.
لكنني كنت محظوظًا؛ فبعد 20 إلى 20 عملية إعادة بناء، تم أخيرًا جلب تحديثات مكونات السمة.

في سياق التصميم العام للتطبيق، سيكون من الجيد وجود توثيق حول كيفية إعادة البناء في “الوضع الآمن”، أي إعادة بناء التطبيق بشكل مستقل عن الإضافات أو السمات. لم أتمكن من العثور على خطاف (hook) لمعالجة مكونات السمة، أو كيفية تعطيل الإضافات (على عكس إلغاء تثبيتها)، وهو ما كان محبطًا.

تعديل: واو، الآن أرى الرابط الخاص بالوضع الآمن. لم أكن أستطيع العثور عليه من قبل (لا يوجد جوجل لنا في الصين، حاول العثور على أي شيء ذي صلة باستخدام بينغ..). يا إلهي، كان ذلك سيساعد كثيرًا!

إذن، هل قمت بتحديد خادم Redis مُدار مثل Discourse with DO managed Redis - #3 by Falco وفشلت عملية إعادة البناء؟

كانت مشكلة Redis ثانوية الأهمية، لكنها أضافت تعقيدًا كبيرًا لمشكلة Git الشاملة. وكما تلاحظ من منشوري المفصل أعلاه، فقد تمكنت من حل هذه القضايا.

ونعم، كنا قد ربطنا بنية Redis الموزعة بمنصة Discourse الخاصة بنا منذ البداية. غير أنها غير مُدارة، بل تعمل على آلات أخرى.

أدى فشل الاتصال بخادم Redis إلى منع التطبيق من البدء، وبالتالي لم أستطع إلغاء تنشيط مكونات السمة عبر واجهة المستخدم الرسومية.
تطلبت تطبيق إعدادات Redis جديدة إعادة بناء التطبيق، وهو ما لم يكن ممكنًا بسبب فشل جلب البيانات من مستودعات GitHub.

https://meta.discourse.org/t/a-fork-of-discourse-docker-repo-for-china

إعجاب واحد (1)

في حال واجه شخص ما مشكلات حتى مع إضافة إعداد وكيل HTTP،

GnuTLS recv error (-110): The TLS connection was non-properly terminated.

بالإضافة إلى الحل الأصلي، أضف خصائص postBuffer أدناه إلى قالب لحل مشكلتي. يتطلب تثبيت gnutls-bin

hooks:
  before_code:
    - exec:
       cmd:
         - apt-get update -y
         - apt-get install -y gnutls-bin
         - git config --global http.proxy socks5://172.17.0.1:1080
         - git config --global https.proxy socks5://172.17.0.1:1080
         - git config --global https.sslVerify false 
         - git config --global http.postBuffer 1048576000

# optional
  after_code:
    - exec:
       cmd:
         - git config --global --unset http.proxy
         - git config --global --unset https.proxy
         - git config --global --unset https.sslVerify
         - git config --global --unset http.postBuffer
إعجابَين (2)