Hosting

Fly.io

هدف: اجرای OpenClaw Gateway روی یک ماشین Fly.io با فضای ذخیره‌سازی پایدار، HTTPS خودکار و دسترسی Discord/کانال.

آنچه نیاز دارید

  • CLI ‏flyctl نصب‌شده
  • حساب Fly.io (پلن رایگان قابل‌استفاده است)
  • احراز هویت مدل: کلید API برای ارائه‌دهنده مدل انتخابی
  • اعتبارنامه‌های کانال: توکن ربات Discord، توکن Telegram و غیره.

مسیر سریع برای مبتدیان

  1. مخزن را کلون و fly.toml را سفارشی‌سازی کنید
  2. برنامه و volume را ایجاد و secretها را تنظیم کنید
  3. با fly deploy استقرار دهید
  4. برای ایجاد پیکربندی با SSH وارد شوید، یا از رابط کاربری کنترل استفاده کنید
  • ایجاد برنامه Fly

    bash
    git clone https://github.com/openclaw/openclaw.gitcd openclaw # نام دلخواه خود را انتخاب کنیدfly apps create my-openclaw # معمولاً 1GB کافی استfly volumes create openclaw_data --size 1 --region iad

    منطقه‌ای نزدیک به خود انتخاب کنید. گزینه‌های رایج: lhr (لندن)، iad (ویرجینیا)، sjc (سن‌خوزه).

  • پیکربندی fly.toml

    fly.toml را متناسب با نام برنامه و نیازهای خود ویرایش کنید. فایل fly.toml تحت رهگیری مخزن، الگوی عمومی نمایش‌داده‌شده در ادامه است؛ deploy/fly.private.toml گونه سخت‌سازی‌شده و بدون IP عمومی است (به استقرار خصوصی مراجعه کنید).

    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"

    نقطه ورود تصویر Docker مربوط به OpenClaw برابر با tini است و به‌طور پیش‌فرض node openclaw.mjs gateway را اجرا می‌کند. [processes] در Fly، مقدار CMD در Docker را جایگزین می‌کند (در اینجا node dist/index.js gateway ...، یعنی همان نقطه ورود کامپایل‌شده را مستقیماً اجرا می‌کند) بدون اینکه ENTRYPOINT را تغییر دهد؛ بنابراین فرایند همچنان تحت tini اجرا می‌شود.

    تنظیمات کلیدی:

    تنظیم دلیل
    --bind lan به 0.0.0.0 متصل می‌شود تا پراکسی Fly بتواند به Gateway دسترسی پیدا کند
    --allow-unconfigured بدون فایل پیکربندی شروع می‌شود (بعداً آن را ایجاد می‌کنید)
    internal_port = 3000 برای بررسی‌های سلامت Fly باید با --port 3000 (یا OPENCLAW_GATEWAY_PORT) مطابقت داشته باشد
    memory = "2048mb" 512MB بسیار کم است؛ 2GB توصیه می‌شود
    OPENCLAW_STATE_DIR = "/data" وضعیت را روی volume پایدار نگه می‌دارد
  • تنظیم secretها

    bash
    # الزامی: توکن احراز هویت Gateway برای اتصال غیر loopbackfly secrets set OPENCLAW_GATEWAY_TOKEN=$(openssl rand -hex 32) # کلیدهای API ارائه‌دهندگان مدلfly secrets set ANTHROPIC_API_KEY=example-anthropic-key-not-real # اختیاری: سایر ارائه‌دهندگانfly secrets set OPENAI_API_KEY=example-openai-key-not-realfly secrets set GOOGLE_API_KEY=... # توکن‌های کانالfly secrets set DISCORD_BOT_TOKEN=example-discord-bot-token

    اتصال‌های غیر loopback ‏(--bind lan) به یک مسیر معتبر احراز هویت Gateway نیاز دارند. این مثال از OPENCLAW_GATEWAY_TOKEN استفاده می‌کند، اما gateway.auth.password یا یک استقرار پراکسی معتمد غیر loopback که به‌درستی پیکربندی شده باشد نیز این الزام را برآورده می‌کند. برای قرارداد SecretRef به مدیریت secretها مراجعه کنید.

    با این توکن‌ها مانند گذرواژه رفتار کنید. برای کلیدهای API و توکن‌ها، متغیرهای محیطی/fly secrets را به فایل پیکربندی ترجیح دهید تا secretها خارج از openclaw.json باقی بمانند.

  • استقرار

    bash
    fly deploy

    نخستین استقرار، تصویر Docker را می‌سازد. پس از استقرار بررسی کنید:

    bash
    fly statusfly logs

    پس از فعال‌شدن شنونده HTTP/WebSocket، گزارش‌های راه‌اندازی Gateway عبارت gateway ready را ثبت می‌کنند. بررسی سلامت خود Fly مطابق fly.toml، ‏internal_port = 3000 را پایش می‌کند؛ دستور Docker ‏HEALTHCHECK در تصویر نیز علاوه بر آن، /healthz را روی پورت پیش‌فرض 18789 بررسی می‌کند که در اینجا استفاده نمی‌شود، زیرا این استقرار Gateway را روی --port 3000 بازنویسی می‌کند.

  • ایجاد فایل پیکربندی

    برای ایجاد پیکربندی مناسب، با SSH وارد ماشین شوید:

    bash
    fly ssh console
    bash
    mkdir -p /datacat > /data/openclaw.json << 'EOF'{  "agents": {    "defaults": {      "model": {        "primary": "anthropic/claude-opus-4-6",        "fallbacks": ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4"]      },      "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",    "controlUi": {      "allowedOrigins": [        "https://my-openclaw.fly.dev",        "http://localhost:3000",        "http://127.0.0.1:3000"      ]    }  },  "meta": {}}EOF

    با OPENCLAW_STATE_DIR=/data، مسیر پیکربندی /data/openclaw.json است.

    https://my-openclaw.fly.dev را با مبدأ واقعی برنامه Fly خود جایگزین کنید. راه‌اندازی Gateway، مبدأهای محلی رابط کاربری کنترل را بر اساس مقادیر زمان اجرای --bind و --port مقداردهی اولیه می‌کند تا نخستین راه‌اندازی پیش از وجود پیکربندی انجام شود، اما دسترسی مرورگر از طریق Fly همچنان به مبدأ دقیق HTTPS فهرست‌شده در gateway.controlUi.allowedOrigins نیاز دارد.

    توکن Discord می‌تواند از یکی از این منابع تأمین شود:

    • متغیر محیطی DISCORD_BOT_TOKEN (برای secretها توصیه می‌شود)؛ نیازی به افزودن آن به پیکربندی نیست، Gateway آن را به‌طور خودکار می‌خواند
    • فایل پیکربندی channels.discord.token

    برای اعمال تغییرات، راه‌اندازی مجدد کنید:

    bash
    exitfly machine restart <machine-id>
  • دسترسی به Gateway

    رابط کاربری کنترل

    bash
    fly open

    یا از https://my-openclaw.fly.dev/ بازدید کنید.

    با secret مشترک پیکربندی‌شده احراز هویت کنید: توکن Gateway از OPENCLAW_GATEWAY_TOKEN، یا اگر به احراز هویت با گذرواژه تغییر داده‌اید، گذرواژه خود.

    گزارش‌ها

    bash
    fly logs              # گزارش‌های زندهfly logs --no-tail    # گزارش‌های اخیر

    کنسول SSH

    bash
    fly ssh console
  • عیب‌یابی

    «برنامه روی نشانی مورد انتظار گوش نمی‌دهد»

    Gateway به‌جای 0.0.0.0 به 127.0.0.1 متصل می‌شود.

    راه‌حل:--bind lan را به فرمان فرایند در fly.toml اضافه کنید.

    ناموفق‌بودن بررسی‌های سلامت / ردشدن اتصال

    Fly نمی‌تواند روی پورت پیکربندی‌شده به Gateway دسترسی پیدا کند.

    راه‌حل: مطمئن شوید internal_port با پورت Gateway ‏(--port 3000 یا OPENCLAW_GATEWAY_PORT=3000) مطابقت دارد.

    مشکلات OOM / حافظه

    کانتینر پیوسته راه‌اندازی مجدد می‌شود یا خاتمه می‌یابد. نشانه‌ها: SIGABRT، ‏v8::internal::Runtime_AllocateInYoungGeneration یا راه‌اندازی‌های مجدد بدون پیام.

    راه‌حل: حافظه را در fly.toml افزایش دهید:

    toml
    [[vm]]  memory = "2048mb"

    یا یک ماشین موجود را به‌روزرسانی کنید:

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

    512MB بسیار کم است. 1GB ممکن است کار کند، اما تحت بار یا با گزارش‌گیری مفصل ممکن است دچار OOM شود. 2GB توصیه می‌شود.

    مشکلات قفل Gateway

    پس از راه‌اندازی مجدد کانتینر، Gateway به‌دلیل خطاهای «از قبل در حال اجرا است» از شروع به کار خودداری می‌کند.

    فایل‌های قفل زمان اجرا در <tmpdir>/openclaw-<uid>/gateway.<hash>.lock و gateway.state.<hash>.lock قرار دارند (در Linux: /tmp/openclaw-<uid>/gateway.*.lock)، نه روی volume پایدار /data؛ بنابراین راه‌اندازی مجدد کامل کانتینر معمولاً آن‌ها را همراه با بقیه فایل‌سیستم کانتینر پاک می‌کند. اگر یک قفل باقی بماند (برای مثال، یک fly machine restart که فایل‌سیستم کانتینر را حفظ می‌کند) و مانع راه‌اندازی شود، آن را به‌صورت دستی حذف کنید:

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

    پیکربندی خوانده نمی‌شود

    --allow-unconfigured فقط محافظ راه‌اندازی را دور می‌زند. این گزینه /data/openclaw.json را ایجاد یا ترمیم نمی‌کند؛ بنابراین مطمئن شوید پیکربندی واقعی شما وجود دارد و برای راه‌اندازی عادی Gateway محلی شامل "gateway": { "mode": "local" } است.

    وجود پیکربندی را بررسی کنید:

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

    نوشتن پیکربندی از طریق SSH

    fly ssh console -C از تغییر مسیر پوسته پشتیبانی نمی‌کند. برای نوشتن فایل پیکربندی:

    bash
    # echo + tee (ارسال از محلی به راه‌دور با pipe)echo '{"your":"config"}' | fly ssh console -C "tee /data/openclaw.json" # یا sftpfly sftp shell> put /local/path/config.json /data/openclaw.json

    اگر فایل از قبل وجود داشته باشد، ممکن است fly sftp ناموفق شود؛ ابتدا آن را حذف کنید:

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

    وضعیت پایدار نمی‌ماند

    اگر پس از راه‌اندازی مجدد، پروفایل‌های احراز هویت، وضعیت کانال/ارائه‌دهنده یا نشست‌ها را از دست می‌دهید، دایرکتوری وضعیت به‌جای volume در فایل‌سیستم کانتینر نوشته می‌شود.

    راه‌حل: مطمئن شوید OPENCLAW_STATE_DIR=/data در fly.toml تنظیم شده است و دوباره استقرار دهید.

    به‌روزرسانی

    bash
    git pullfly deployfly statusfly logs

    git pull + fly deploy در اینجا مسیر تحت نظارت است: تصویر را از Dockerfile دوباره می‌سازد، بنابراین نسخه CLI/Gateway، تصویر سیستم‌عامل پایه و هرگونه تغییر Dockerfile همگی با هم به‌روزرسانی می‌شوند. اجرای openclaw update داخل کانتینر در حال اجرا همان عملیات نیست، زیرا تصویر به‌صورت یک درخت dist/ ساخته‌شده با Docker عرضه می‌شود که هیچ checkout از .git و هیچ نصب سراسری مدیریت‌شده با npm برای شناسایی ندارد؛ برای این جریان در نصب‌های سبک VM به به‌روزرسانی مراجعه کنید.

    به‌روزرسانی فرمان ماشین

    برای تغییر فرمان راه‌اندازی بدون استقرار مجدد کامل:

    bash
    fly machines listfly 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های عمومی اختصاص می‌دهد، بنابراین Gateway شما در https://your-app.fly.dev قابل‌دسترسی و برای اسکنرهای اینترنتی (Shodan، Censys و غیره) قابل‌کشف است.

    برای استقرار سخت‌سازی‌شده با بدون IP عمومی از deploy/fly.private.toml استفاده کنید: این مورد [http_service] را حذف می‌کند، بنابراین هیچ ورودی عمومی اختصاص نمی‌یابد.

    چه زمانی از استقرار خصوصی استفاده کنید

    • فقط تماس‌ها/پیام‌های خروجی (بدون Webhook ورودی)
    • تونل‌های ngrok یا Tailscale هرگونه callback مربوط به Webhook را مدیریت می‌کنند
    • دسترسی به Gateway به‌جای مرورگر از طریق SSH، پراکسی یا WireGuard انجام می‌شود
    • استقرار باید از اسکنرهای اینترنتی پنهان باشد

    راه‌اندازی

    bash
    fly deploy -c deploy/fly.private.toml

    یا یک استقرار موجود را تبدیل کنید:

    bash
    # فهرست‌کردن IPهای فعلیfly ips list -a my-openclaw # آزادکردن IPهای عمومیfly ips release <public-ipv4> -a my-openclawfly ips release <public-ipv6> -a my-openclaw # تغییر به پیکربندی خصوصی تا استقرارهای آینده IP عمومی را دوباره تخصیص ندهندfly deploy -c deploy/fly.private.toml # تخصیص IPv6 فقط‌خصوصیfly ips allocate-v6 --private -a my-openclaw

    پس از این کار، fly ips list باید فقط یک IP از نوع private نمایش دهد:

    text
    VERSION  IP                   TYPE             REGIONv6       fdaa:x:x:x:x::x      private          global

    دسترسی به استقرار خصوصی

    گزینه ۱: پراکسی محلی (ساده‌ترین)

    bash
    fly proxy 3000:3000 -a my-openclaw# بازکردن http://localhost:3000 در مرورگر

    گزینه ۲: VPN مبتنی بر WireGuard

    bash
    fly wireguard create# واردکردن در یک کلاینت WireGuard، سپس دسترسی از طریق IPv6 داخلی# نمونه: http://[fdaa:x:x:x:x::x]:3000

    گزینه ۳: فقط SSH

    bash
    fly ssh console -a my-openclaw

    Webhookها در استقرار خصوصی

    برای فراخوانی‌های برگشتی Webhook ‏(Twilio، Telnyx و غیره) بدون دسترسی عمومی:

    1. تونل ngrok: ‏ngrok را داخل کانتینر یا به‌صورت یک کانتینر جانبی اجرا کنید
    2. Tailscale Funnel: مسیرهای مشخصی را از طریق Tailscale در دسترس قرار دهید
    3. فقط خروجی: برخی ارائه‌دهندگان (Twilio) برای تماس‌های خروجی بدون Webhook کار می‌کنند

    نمونه پیکربندی تماس صوتی با ngrok، در بخش plugins.entries.voice-call.config:

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

    تونل ngrok داخل کانتینر اجرا می‌شود و بدون در معرض دسترس عمومی قراردادن خود برنامه Fly، یک URL عمومی برای Webhook فراهم می‌کند. webhookSecurity.allowedHosts را روی نام میزبان تونل تنظیم کنید تا سرآیندهای میزبانِ فورواردشده پذیرفته شوند.

    موازنه‌های امنیتی

    جنبه عمومی خصوصی
    اسکنرهای اینترنتی قابل‌شناسایی پنهان
    حملات مستقیم ممکن مسدود
    دسترسی به رابط کنترل مرورگر پراکسی/VPN
    تحویل Webhook مستقیم از طریق تونل

    نکات

    • Fly.io از معماری x86 استفاده می‌کند؛ Dockerfile با هر دو معماری x86 و ARM سازگار است.
    • برای راه‌اندازی اولیه WhatsApp/Telegram، از fly ssh console استفاده کنید.
    • داده‌های ماندگار روی ولوم در /data قرار دارند.
    • Signal به signal-cli (یک CLI مبتنی بر Java) در ایمیج نیاز دارد؛ از یک ایمیج سفارشی استفاده کنید و حافظه را روی 2GB یا بیشتر نگه دارید.

    هزینه

    با پیکربندی توصیه‌شده (shared-cpu-2x، ‏2GB RAM)، بسته به میزان استفاده، هزینه‌ای حدود $10-15/month انتظار می‌رود؛ سطح رایگان بخشی از سهمیه پایه را پوشش می‌دهد. برای نرخ‌های فعلی، قیمت‌گذاری Fly.io را ببینید.

    گام‌های بعدی

    مرتبط

    Was this useful?
    On this page

    On this page