الاستضافة والنشر

Fly.io

الهدف: تشغيل بوابة OpenClaw على جهاز Fly.io مع تخزين مستمر، HTTPS تلقائي، ووصول إلى Discord/القنوات.

ما تحتاجه

  • تثبيت أداة سطر أوامر flyctl
  • حساب على Fly.io (النسخة المجانية تعمل)
  • مصادقة النموذج: مفتاح API لمزود النموذج الذي اخترته
  • بيانات اعتماد القناة: رمز بوت Discord، رمز Telegram، إلخ.

المسار السريع للمبتدئين

  1. استنساخ المستودع → تخصيص fly.toml
  2. إنشاء التطبيق + وحدة التخزين → تعيين الأسرار
  3. النشر باستخدام fly deploy
  4. الدخول عبر SSH لإنشاء التكوين أو استخدام واجهة التحكم

1) إنشاء تطبيق Fly

# استنساخ المستودع
git clone https://github.com/openclaw/openclaw.git
cd openclaw

# إنشاء تطبيق Fly جديد (اختر اسمك الخاص)
fly apps create my-openclaw

# إنشاء وحدة تخزين مستمرة (1 جيجابايت تكفي عادة)
fly volumes create openclaw_data --size 1 --region iad

نصيحة: اختر منطقة قريبة منك. خيارات شائعة: lhr (لندن)، iad (فرجينيا)، sjc (سان خوسيه).

2) تكوين fly.toml

قم بتحرير fly.toml ليتطابق مع اسم تطبيقك ومتطلباتك. ملاحظة أمنية: التكوين الافتراضي يعرض عنوان URL عام. لنشر محصن بدون عنوان IP عام، راجع النشر الخاص أو استخدم fly.private.toml.

app = "my-openclaw"  # اسم تطبيقك
primary_region = "iad"

[build]
  dockerfile = "Dockerfile"

[env]
  NODE_ENV = "production"
  OPENCLAW_PREFER_PNPM = "1"
  OPENCLAW_STATE_DIR = "/data"
  NODE_OPTIONS = "--max-old-space-size=1536"

[processes]
  app = "node dist/index.js gateway --allow-unconfigured --port 3000 --bind lan"

[http_service]
  internal_port = 3000
  force_https = true
  auto_stop_machines = false
  auto_start_machines = true
  min_machines_running = 1
  processes = ["app"]

[[vm]]
  size = "shared-cpu-2x"
  memory = "2048mb"

[mounts]
  source = "openclaw_data"
  destination = "/data"

الإعدادات الرئيسية:

الإعدادالسبب
--bind lanيربط بـ 0.0.0.0 حتى يتمكن وكيل Fly من الوصول إلى البوابة
--allow-unconfiguredيبدأ التشغيل بدون ملف تكوين (ستقوم بإنشاء واحد لاحقًا)
internal_port = 3000يجب أن يتطابق مع --port 3000 (أو OPENCLAW_GATEWAY_PORT) لفحوصات صحة Fly
memory = "2048mb"512 ميجابايت صغير جدًا؛ يوصى بـ 2 جيجابايت
OPENCLAW_STATE_DIR = "/data"يحفظ الحالة على وحدة التخزين

3) تعيين الأسرار

# مطلوب: رمز البوابة (للالتحام غير المحلي)
fly secrets set OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 32)

# مفاتيح API لمزودي النماذج
fly secrets set ANTHROPIC_API_KEY=sk-ant-...

# اختياري: مزودون آخرون
fly secrets set OPENAI_API_KEY=sk-...
fly secrets set GOOGLE_API_KEY=...

# رموز القنوات
fly secrets set DISCORD_BOT_TOKEN=MTQ...

ملاحظات:

  • عمليات الالتحام غير المحلية (--bind lan) تتطلب OPENCLAW_GATEWAY_TOKEN للأمان.
  • عالج هذه الرموز ككلمات مرور.
  • فضل متغيرات البيئة على ملف التكوين لجميع مفاتيح API والرموز. هذا يحفظ الأسرار بعيدًا عن openclaw.json حيث يمكن أن تتعرض أو تسجل عن طريق الخطأ.

4) النشر

fly deploy

أول عملية نشر تبني صورة Docker (~2-3 دقائق). عمليات النشر اللاحقة أسرع. بعد النشر، تحقق:

fly status
fly logs

يجب أن ترى:

[gateway] listening on ws://0.0.0.0:3000 (PID xxx)
[discord] logged in to discord as xxx

5) إنشاء ملف التكوين

ادخل عبر SSH إلى الجهاز لإنشاء تكوين مناسب:

fly ssh console

أنشئ مجلد التكوين والملف:

mkdir -p /data
cat > /data/openclaw.json << 'EOF'
{
  "agents": {
    "defaults": {
      "model": {
        "primary": "anthropic/claude-opus-4-6",
        "fallbacks": ["anthropic/claude-sonnet-4-5", "openai/gpt-4o"]
      },
      "maxConcurrent": 4
    },
    "list": [
      {
        "id": "main",
        "default": true
      }
    ]
  },
  "auth": {
    "profiles": {
      "anthropic:default": { "mode": "token", "provider": "anthropic" },
      "openai:default": { "mode": "token", "provider": "openai" }
    }
  },
  "bindings": [
    {
      "agentId": "main",
      "match": { "channel": "discord" }
    }
  ],
  "channels": {
    "discord": {
      "enabled": true,
      "groupPolicy": "allowlist",
      "guilds": {
        "YOUR_GUILD_ID": {
          "channels": { "general": { "allow": true } },
          "requireMention": false
        }
      }
    }
  },
  "gateway": {
    "mode": "local",
    "bind": "auto"
  },
  "meta": {
    "lastTouchedVersion": "2026.1.29"
  }
}
EOF

ملاحظة: مع OPENCLAW_STATE_DIR=/data، مسار التكوين هو /data/openclaw.json. ملاحظة: يمكن أن يأتي رمز Discord من:

  • متغير البيئة: DISCORD_BOT_TOKEN (موصى به للأسرار)
  • ملف التكوين: channels.discord.token

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

exit
fly machine restart <machine-id>

6) الوصول إلى البوابة

واجهة التحكم

افتح في المتصفح:

fly open

أو زر https://my-openclaw.fly.dev/ الصق رمز البوابة الخاص بك (الذي من OPENCLAW_GATEWAY_TOKEN) للمصادقة.

السجلات

fly logs              # سجلات مباشرة
fly logs --no-tail    # سجلات حديثة

وحدة التحكم عبر SSH

fly ssh console

استكشاف الأخطاء وإصلاحها

"التطبيق لا يستمع على العنوان المتوقع"

البوابة تربط بـ 127.0.0.1 بدلاً من 0.0.0.0. الإصلاح: أضف --bind lan إلى أمر العملية في fly.toml.

فحوصات الصحة تفشل / رفض الاتصال

لا يستطيع Fly الوصول إلى البوابة على المنفذ المكون. الإصلاح: تأكد من أن internal_port يطابق منفذ البوابة (اضبط --port 3000 أو OPENCLAW_GATEWAY_PORT=3000).

نفاد الذاكرة / مشاكل الذاكرة

الحاوية تستمر في إعادة التشغيل أو يتم إيقافها. علامات: SIGABRT، v8::internal::Runtime_AllocateInYoungGeneration، أو إعادة تشغيل صامتة. الإصلاح: زد الذاكرة في fly.toml:

[[vm]]
  memory = "2048mb"

أو قم بتحديث جهاز موجود:

fly machine update <machine-id> --vm-memory 2048 -y

ملاحظة: 512 ميجابايت صغير جدًا. 1 جيجابايت قد يعمل ولكن قد ينفد الذاكرة تحت الحمل أو مع تسجيل مفصل. يوصى بـ 2 جيجابايت.

مشاكل قفل البوابة

البوابة ترفض البدء مع أخطاء "قيد التشغيل بالفعل". يحدث هذا عندما تعيد الحاوية التشغيل ولكن ملف قفل PID يبقى على وحدة التخزين. الإصلاح: احذف ملف القفل:

fly ssh console --command "rm -f /data/gateway.*.lock"
fly machine restart <machine-id>

يوجد ملف القفل في /data/gateway.*.lock (ليس في مجلد فرعي).

عدم قراءة التكوين

إذا كنت تستخدم --allow-unconfigured، تنشئ البوابة تكوينًا بسيطًا. يجب قراءة تكوينك المخصص في /data/openclaw.json عند إعادة التشغيل. تحقق من وجود التكوين:

fly ssh console --command "cat /data/openclaw.json"

كتابة التكوين عبر SSH

أمر fly ssh console -C لا يدعم إعادة توجيه shell. لكتابة ملف تكوين:

# استخدم echo + tee (أنبوب من المحلي إلى البعيد)
echo '{"your":"config"}' | fly ssh console -C "tee /data/openclaw.json"

# أو استخدم sftp
fly sftp shell
> put /local/path/config.json /data/openclaw.json

ملاحظة: قد يفشل fly sftp إذا كان الملف موجودًا بالفعل. احذفه أولاً:

fly ssh console --command "rm /data/openclaw.json"

الحالة لا تستمر

إذا فقدت بيانات الاعتماد أو الجلسات بعد إعادة التشغيل، فإن مجلد الحالة يكتب على نظام ملفات الحاوية. الإصلاح: تأكد من تعيين OPENCLAW_STATE_DIR=/data في fly.toml وأعد النشر.

التحديثات

# جلب أحدث التغييرات
git pull

# إعادة النشر
fly deploy

# التحقق من الصحة
fly status
fly logs

تحديث أمر الجهاز

إذا كنت بحاجة إلى تغيير أمر بدء التشغيل بدون إعادة نشر كاملة:

# الحصول على معرف الجهاز
fly machines list

# تحديث الأمر
fly machine update <machine-id> --command "node dist/index.js gateway --port 3000 --bind lan" -y

# أو مع زيادة الذاكرة
fly machine update <machine-id> --vm-memory 2048 --command "node dist/index.js gateway --port 3000 --bind lan" -y

ملاحظة: بعد fly deploy، قد يعود أمر الجهاز إلى ما هو موجود في fly.toml. إذا أجريت تغييرات يدوية، أعد تطبيقها بعد النشر.

النشر الخاص (محصن)

بشكل افتراضي، يخصص Fly عناوين IP عامة، مما يجعل بوابتك قابلة للوصول على https://your-app.fly.dev. هذا مريح ولكن يعني أن نشرك يمكن اكتشافه بواسطة ماسحات الإنترنت (Shodan، Censys، إلخ). لنشر محصن بدون تعرض عام، استخدم القالب الخاص.

متى تستخدم النشر الخاص

  • تقوم فقط بإجراء مكالمات/رسائل صادرة (لا توجد webhooks واردة)
  • تستخدم أنفاق ngrok أو Tailscale لأي ردود اتصال webhook
  • تصل إلى البوابة عبر SSH، وكيل، أو WireGuard بدلاً من المتصفح
  • تريد إخفاء النشر عن ماسحات الإنترنت

الإعداد

استخدم fly.private.toml بدلاً من التكوين القياسي:

# النشر بتكوين خاص
fly deploy -c fly.private.toml

أو قم بتحويل نشر موجود:

# عرض عناوين IP الحالية
fly ips list -a my-openclaw

# إطلاق عناوين IP العامة
fly ips release <public-ipv4> -a my-openclaw
fly ips release <public-ipv6> -a my-openclaw

# التبديل إلى التكوين الخاص حتى لا تعيد عمليات النشر المستقبلية تخصيص عناوين IP عامة
# (احذف [http_service] أو انشر باستخدام القالب الخاص)
fly deploy -c fly.private.toml

# تخصيص IPv6 خاص فقط
fly ips allocate-v6 --private -a my-openclaw

بعد هذا، يجب أن يظهر fly ips list عنوان IP من النوع private فقط:

VERSION  IP                   TYPE             REGION
v6       fdaa:x:x:x:x::x      private          global

الوصول إلى نشر خاص

بما أنه لا يوجد عنوان URL عام، استخدم إحدى هذه الطرق: الخيار 1: وكيل محلي (الأبسط)

# توجيه المنفذ المحلي 3000 إلى التطبيق
fly proxy 3000:3000 -a my-openclaw

# ثم افتح http://localhost:3000 في المتصفح

الخيار 2: شبكة VPN WireGuard

# إنشاء تكوين WireGuard (مرة واحدة)
fly wireguard create

# استيراده إلى عميل WireGuard، ثم الوصول عبر IPv6 الداخلي
# مثال: http://[fdaa:x:x:x:x::x]:3000

الخيار 3: SSH فقط

fly ssh console -a my-openclaw

Webhooks مع نشر خاص

إذا كنت بحاجة إلى ردود اتصال webhook (Twilio، Telnyx، إلخ.) بدون تعرض عام:

  1. نفق ngrok - شغل ngrok داخل الحاوية أو كحاوية جانبية
  2. قناة Tailscale - اعرض مسارات محددة عبر Tailscale
  3. صادر فقط - بعض المزودين (Twilio) يعملون بشكل جيد للمكالمات الصادرة بدون webhooks

مثال تكوين مكالمة صوتية مع ngrok:

{
  "plugins": {
    "entries": {
      "voice-call": {
        "enabled": true,
        "config": {
          "provider": "twilio",
          "tunnel": { "provider": "ngrok" },
          "webhookSecurity": {
            "allowedHosts": ["example.ngrok.app"]
          }
        }
      }
    }
  }
}

يعمل نفق ngrok داخل الحاوية ويوفر عنوان URL عام لـ webhook بدون تعريض تطبيق Fly نفسه. عيّن webhookSecurity.allowedHosts إلى اسم المضيف العام للنفق حتى يتم قبول رؤوس المضيف التي تم توجيهها.

فوائد الأمان

الجانبعامخاص
ماسحات الإنترنتقابل للاكتشافمخفي
هجمات مباشرةممكنةمحظورة
الوصول لواجهة التحكممتصفحوكيل/VPN
تسليم Webhookمباشرعبر نفق

ملاحظات

  • يستخدم Fly.io بنية x86 (ليست ARM)
  • ملف Dockerfile متوافق مع كلا البنيتين
  • للتسجيل في WhatsApp/Telegram، استخدم fly ssh console
  • البيانات المستمرة تعيش على وحدة التخزين في /data
  • Signal يتطلب Java + signal-cli؛ استخدم صورة مخصصة واحتفظ بالذاكرة عند 2 جيجابايت+.

التكلفة

مع التكوين الموصى به (shared-cpu-2x، 2 جيجابايت ذاكرة وصول عشوائي):

  • ~10-15 دولارًا شهريًا حسب الاستخدام
  • النسخة المجانية تتضمن بعض الحصة

راجع أسعار Fly.io للتفاصيل.

استضافة VPSHetzner