تجربة صعبة في الانتقال من Scaleway إلى Raspberry Pi 4

هنا توثيق لأخطائي ونجاحي في النهاية في ترحيل مثيل discourse من scaleway إلى raspberry pi 4، مع cloudflare في المقدمة.

أنشأت نسخة احتياطية من مثيل discourse الخاص بـ scaleway، وقمت بتشغيل ./launcher stop app، وأوقفت تشغيل الجهاز.

قمت بتثبيت Ubuntu Server 23.10 على قرص SSD متصل عبر USB يشغل Raspberry Pi 4
قمت بتثبيت LXD، وأنشأت مجمع تخزين loopback بحجم 100GiB بنظام btrfs.
تحديث ملف التعريف default إلى:

config:
  cloud-init.user-data: |
    #cloud-config
    ssh_pwauth: false
    package_update: true
    package_upgrade: true
    packages:
      - openssh-server
      - vim
      - git
      - rsync
    users:
      - name: root
        lock_passwd: true
        ssh_import_id: gh:balupton
description: Default LXD profile
devices:
  eth0:
    name: eth0
    network: lxdbr0
    type: nic
  root:
    path: /
    pool: default
    type: disk
name: default

إضافة ملف تعريف discourse مع:

config:
  limits.memory: 1GiB
  limits.memory.enforce: soft
  security.nesting: 'true'
description: Configuration for Discourse instances
devices: {}
name: discourse

أنشأت صورة Ubuntu 23.10 Minimal Server بهذه الملفات التعريفية. وصلت إليها عبر ما يلي في ملف ~/.ssh/config الخاص بي:

Host LXD_DISCOURCE_INSTANCE
	ProxyJump LXD_HOST
	User REDACTED
	IdentityFile ~/.ssh/REDACTED.pub

اتبعت تعليمات تثبيت discourse السحابي واستعدت تكوين discourse الخاص بي من مثيل scaleway:

templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  - "templates/cloudflare.template.yml"
  - "templates/web.ssl.template.yml"  # https
  - "templates/web.letsencrypt.ssl.template.yml"  # https
  # - "templates/web.ratelimited.template.yml" # not needed with cloudflare

expose:
  - "80:80"
  - "443:443"  # https

params:
  db_default_text_search_config: "pg_catalog.english"

env:
  LANG: en_US.UTF-8

  ## HTTPS configuration for: templates/web.letsencrypt.ssl.template.yml
  LETSENCRYPT_ACCOUNT_EMAIL: "redacted"  # https

  ## The domain name this Discourse instance will respond to
  DISCOURSE_HOSTNAME: "redacted"

  ## List of comma delimited emails that will be made admin and developer
  ## on initial signup example 'user1@example.com,user2@example.com'
  DISCOURSE_DEVELOPER_EMAILS: "redacted"

  ## The mailserver this Discourse instance will use
  DISCOURSE_SMTP_ADDRESS: "redacted"
  DISCOURSE_SMTP_PORT: redacted
  DISCOURSE_SMTP_USER_NAME: "redacted"
  DISCOURSE_SMTP_PASSWORD: "redacted"
  #DISCOURSE_SMTP_DOMAIN: discourse.example.com    # (required by some providers)
  #DISCOURSE_NOTIFICATION_EMAIL: nobody@discourse.example.com    # (address to send notifications from)
  #DISCOURSE_MAXMIND_LICENSE_KEY: 1234567890123456

## Any custom commands to run after building
run:
  - exec: rails r "SiteSetting.contact_email='redacted'"
  - exec: rails r "SiteSetting.notification_email='redacted'"

## The Docker container is stateless; all data is stored in /shared
volumes:
  - volume:
      host: /var/discourse/shared/standalone
      guest: /shared
  - volume:
      host: /var/discourse/shared/standalone/log/var-log
      guest: /var/log

## Plugins
## https://meta.discourse.org/t/19157
hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/discourse-adplugin.git
          - git clone https://github.com/discourse/discourse-affiliate.git
          - git clone https://github.com/discourse/discourse-assign.git
          - git clone https://github.com/discourse/discourse-docs.git
          - git clone https://github.com/discourse/discourse-topic-voting.git
          - git clone https://github.com/discourse/discourse-github.git
          - git clone https://github.com/discourse/discourse-saved-searches.git
          - git clone https://github.com/discourse/discourse-shared-edits.git
          - git clone https://github.com/discourse/discourse-solved.git
          # - git clone https://github.com/discourse/discourse-encrypt.git
          # - git clone https://github.com/discourse/discourse-reactions.git
          # - git clone https://github.com/discourse/discourse-subscriptions.git

قبل أن أتمكن من استعادة النسخة الاحتياطية، احتجت إلى إعادة بنائها. للأسف، توقف مجمع تخزين btrfs عند خطوة yarn install لساعات، وانتهت المهلة في النهاية، مع حد أدنى من التحميل على الجهاز.

بعد بعض القراءة، قررت تجربة استخدام مجمع تخزين zfs بدلاً من ذلك، وهذا تقدم أكثر، لكنه لا يزال يتوقف إلى أجل غير مسمى بعد Background saving terminated with sucess، مع حد أدنى من التحميل على الجهاز.

(لدي لقطات شاشة ولكن تحميلها هنا يفشل.)

قررت بعد ذلك التخلي عن LXD، وتجربته مباشرة على مثيل Ubuntu Server على Raspberry Pi 4.
لأول مرة، كانت لدي إعادة بناء ناجحة، ولكن جميع محاولات الوصول إليها كانت تعيد التوجيه إلى نفسها، في حلقة إعادة توجيه.

كان لحلقة إعادة التوجيه سببان…

إذا كان لدي ما يلي في تكوين discourse الخاص بي:

expose:
  - "8080:80"
  - "8081:443"  # https

كانت ستعيد التوجيه بلا نهاية، وترغب دائمًا في إعادة التوجيه إلى https://hostname.
كان حل هذا هو العودة إلى:

expose:
  - "80:80"
  - "443:443"  # https

ثانيًا، أي شيء تم الوصول إليه عبر نفق cloudflare كان يعيد التوجيه بلا نهاية إلى نفسه. اتضح أن السبب كان وجود نفق لكل من HTTP ونفق لـ HTTPS. تغيير النفق إلى HTTPS فقط حل المشكلة.

أشياء أخرى فعلتها ولكن في هذه المرحلة لست متأكدًا مما إذا كانت مهمة:

  1. قمت بإزالة letsencrypt حيث استخدمت شهادة Cloudflare Origin بدلاً من ذلك.
  2. قمت بتكوين Origin Sever Name في نفق HTTPS ليكون اسم المضيف المقصود.

أشياء يمكن تحسينها:

  1. يمكن تجنب HTTPS من المصدر إلى Cloudflare إذا قمت بتقييد الجهاز للسماح بالاتصالات من Cloudfare فقط، وإعداد نفق SSH. ومع ذلك، لست متأكدًا مما إذا كان Discourse يعمل بشكل أفضل مع وجود HTTPS عليه (مثل http2، إلخ).
  2. ما إذا كان letsencrypt يعمل مع نفق cloudflare (لم أتمكن من اختباره حيث كنت أحصل على حلقات إعادة التوجيه عندما كنت أستخدم letsencrypt).

كيف قمت بتصحيح حلقات إعادة التوجيه:

  • لتصحيح حلقة إعادة توجيه discourse: قمت بتعيين /etc/hosts للإشارة إلى اسم مضيف discourse الخاص بي مباشرة إلى عنوان IP، ثم استخدمت curl -k --head 'https://hostname:8081 إلخ لاختباره.
  • لتصحيح حلقة إعادة توجيه نفق cloudflare: قمت بإزالة ذلك من /etc/hosts بحيث يحل اسم المضيف عبر DNS، ثم استخدمت curl -k --head 'https://hostname إلخ لاختباره.

هناك مجموعة من الأشياء الرائعة الأخرى والدروس المستفادة على طول الطريق، ولكن يمكن أن تنتظر.

ملاحظات لمجتمع discourse:

  • إعادة البناء تحتاج إلى أن تكون أكثر وضوحًا بشأن ما تفعله. في كثير من الأحيان تكون هناك تأخيرات طويلة دون إجراء واضح يتم تنفيذه.
  • اكتشف سبب تعريض منافذ مختلفة قد يسبب حلقة إعادة توجيه.
  • منذ أن أصبح letsencrypt شيئًا، فإن توثيق كيفية تحديد شهادة SSL الخاصة بك أمر صعب العثور عليه. كما يبدو أنه لا يمكن استخدام سوى شهادة واحدة حيث يتم تثبيتها على /var/discourse/shared/standalone/ssl/ssl.key بدلاً من، على سبيل المثال، /var/discourse/shared/standalone/ssl/CONTAINER_ID.key، مثل /var/discourse/shared/standalone/ssl/app.key - يوفر cloudflare شهادات أصلية لذا هذا خيار جيد لمستخدمي cloudflare.
  • نشر دليل شامل خطوة بخطوة لـ cloudflare + raspberry pi 4 كان سيساعد بشكل كبير، حاليًا تفوض مثل هذه الأدلة الكثير من المعلومات إلى أطراف ثالثة ليس لديها وعي ببعضها البعض، وكل التعقيد وتصحيح الأخطاء يكمن في كيفية عمل الأجزاء المختلفة معًا، وليس كيف تعمل بمفردها.

مهام أخرى ليوم ما:

  • اكتشف سبب توقفه في LXD.
  • تحقق مما إذا كان يعمل في LXD على Raspberry Pi 5، أو على Multipass على macOS، أو LXD مع مجمع التخزين كقسم/محرك أقراص بدلاً من ملف loopback: حيث لا يتعين عليّ إهدار جهاز كامل عليه.
  • تحقق مما إذا كان بإمكاني جعل docker و launcher لا يحتاجان إلى sudo.
3 إعجابات