Hosting
Fly.io
هدف: اجرای OpenClaw Gateway روی یک ماشین Fly.io با فضای ذخیرهسازی پایدار، HTTPS خودکار و دسترسی Discord/کانال.
آنچه نیاز دارید
- CLI flyctl نصبشده
- حساب Fly.io (پلن رایگان قابلاستفاده است)
- احراز هویت مدل: کلید API برای ارائهدهنده مدل انتخابی
- اعتبارنامههای کانال: توکن ربات Discord، توکن Telegram و غیره.
مسیر سریع برای مبتدیان
- مخزن را کلون و
fly.tomlرا سفارشیسازی کنید - برنامه و volume را ایجاد و secretها را تنظیم کنید
- با
fly deployاستقرار دهید - برای ایجاد پیکربندی با SSH وارد شوید، یا از رابط کاربری کنترل استفاده کنید
ایجاد برنامه Fly
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 عمومی است (به استقرار خصوصی مراجعه کنید).
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ها
# الزامی: توکن احراز هویت 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 باقی بمانند.
استقرار
fly deployنخستین استقرار، تصویر Docker را میسازد. پس از استقرار بررسی کنید:
fly statusfly logsپس از فعالشدن شنونده HTTP/WebSocket، گزارشهای راهاندازی Gateway عبارت gateway ready را ثبت میکنند. بررسی سلامت خود Fly مطابق fly.toml، internal_port = 3000 را پایش میکند؛ دستور Docker HEALTHCHECK در تصویر نیز علاوه بر آن، /healthz را روی پورت پیشفرض 18789 بررسی میکند که در اینجا استفاده نمیشود، زیرا این استقرار Gateway را روی --port 3000 بازنویسی میکند.
ایجاد فایل پیکربندی
برای ایجاد پیکربندی مناسب، با SSH وارد ماشین شوید:
fly ssh consolemkdir -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
برای اعمال تغییرات، راهاندازی مجدد کنید:
exitfly machine restart <machine-id>دسترسی به Gateway
رابط کاربری کنترل
fly openیا از https://my-openclaw.fly.dev/ بازدید کنید.
با secret مشترک پیکربندیشده احراز هویت کنید: توکن Gateway از OPENCLAW_GATEWAY_TOKEN، یا اگر به احراز هویت با گذرواژه تغییر دادهاید، گذرواژه خود.
گزارشها
fly logs # گزارشهای زندهfly logs --no-tail # گزارشهای اخیرکنسول SSH
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 افزایش دهید:
[[vm]] memory = "2048mb"یا یک ماشین موجود را بهروزرسانی کنید:
fly machine update <machine-id> --vm-memory 2048 -y512MB بسیار کم است. 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
که فایلسیستم کانتینر را حفظ میکند) و مانع راهاندازی شود، آن را
بهصورت دستی حذف کنید:
fly ssh console --command "rm -f /tmp/openclaw-*/gateway.*.lock"fly machine restart <machine-id>پیکربندی خوانده نمیشود
--allow-unconfigured فقط محافظ راهاندازی را دور میزند. این گزینه /data/openclaw.json را ایجاد یا ترمیم نمیکند؛ بنابراین مطمئن شوید پیکربندی واقعی شما وجود دارد و برای راهاندازی عادی Gateway محلی شامل "gateway": { "mode": "local" } است.
وجود پیکربندی را بررسی کنید:
fly ssh console --command "cat /data/openclaw.json"نوشتن پیکربندی از طریق SSH
fly ssh console -C از تغییر مسیر پوسته پشتیبانی نمیکند. برای نوشتن فایل پیکربندی:
# 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 ناموفق شود؛ ابتدا آن را حذف کنید:
fly ssh console --command "rm /data/openclaw.json"وضعیت پایدار نمیماند
اگر پس از راهاندازی مجدد، پروفایلهای احراز هویت، وضعیت کانال/ارائهدهنده یا نشستها را از دست میدهید، دایرکتوری وضعیت بهجای volume در فایلسیستم کانتینر نوشته میشود.
راهحل: مطمئن شوید OPENCLAW_STATE_DIR=/data در fly.toml تنظیم شده است و دوباره استقرار دهید.
بهروزرسانی
git pullfly deployfly statusfly logsgit pull + fly deploy در اینجا مسیر تحت نظارت است: تصویر را از Dockerfile دوباره میسازد، بنابراین نسخه CLI/Gateway، تصویر سیستمعامل پایه و هرگونه تغییر Dockerfile همگی با هم بهروزرسانی میشوند. اجرای openclaw update داخل کانتینر در حال اجرا همان عملیات نیست، زیرا تصویر بهصورت یک درخت dist/ ساختهشده با Docker عرضه میشود که هیچ checkout از .git و هیچ نصب سراسری مدیریتشده با npm برای شناسایی ندارد؛ برای این جریان در نصبهای سبک VM به بهروزرسانی مراجعه کنید.
بهروزرسانی فرمان ماشین
برای تغییر فرمان راهاندازی بدون استقرار مجدد کامل:
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 انجام میشود
- استقرار باید از اسکنرهای اینترنتی پنهان باشد
راهاندازی
fly deploy -c deploy/fly.private.tomlیا یک استقرار موجود را تبدیل کنید:
# فهرستکردن 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 نمایش دهد:
VERSION IP TYPE REGIONv6 fdaa:x:x:x:x::x private globalدسترسی به استقرار خصوصی
گزینه ۱: پراکسی محلی (سادهترین)
fly proxy 3000:3000 -a my-openclaw# بازکردن http://localhost:3000 در مرورگرگزینه ۲: VPN مبتنی بر WireGuard
fly wireguard create# واردکردن در یک کلاینت WireGuard، سپس دسترسی از طریق IPv6 داخلی# نمونه: http://[fdaa:x:x:x:x::x]:3000گزینه ۳: فقط SSH
fly ssh console -a my-openclawWebhookها در استقرار خصوصی
برای فراخوانیهای برگشتی Webhook (Twilio، Telnyx و غیره) بدون دسترسی عمومی:
- تونل ngrok: ngrok را داخل کانتینر یا بهصورت یک کانتینر جانبی اجرا کنید
- Tailscale Funnel: مسیرهای مشخصی را از طریق Tailscale در دسترس قرار دهید
- فقط خروجی: برخی ارائهدهندگان (Twilio) برای تماسهای خروجی بدون Webhook کار میکنند
نمونه پیکربندی تماس صوتی با ngrok، در بخش plugins.entries.voice-call.config:
{ 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 را ببینید.
گامهای بعدی
- کانالهای پیامرسانی را راهاندازی کنید: کانالها
- Gateway را پیکربندی کنید: پیکربندی Gateway
- OpenClaw را بهروز نگه دارید: بهروزرسانی