کلود VPS عمومی (Provision واقعی)

← بازگشت به راهنما

کلود VPS عمومی (Provision واقعی)



> version: 2.14 | last_updated: 2026-09-26 | audience: admin

خلاصه



ماژول‌های Provision برای خرید/تعلیق/حذف/ارتقا روی کلودهای عمومی — **بدون Sandbox**. بدون توکن فقط خطای شفاف «api_token تنظیم نشده».

وضعیت تأیید زنده (2026-09-23)



| ماژول | وضعیت | پوشش تست زنده |
|-------|--------|----------------|
| **`linode`** | ✅ کامل | create · پاور · reboot · وضعیت زنده · reinstall · تغییر رمز (خاموش خودکار) · Weblish کنسول · username=`root` — **تعویض IP در پنل نیست** |
| **`litenode`** | ✅ کامل | create (async) · پاور · وضعیت · reinstall async · تغییر رمز · username=`root`/`Administrator` — **تعویض IP در API نیست** |

چک‌لیست per-module: [cloud-vps-inventory-checklist.md](./cloud-vps-inventory-checklist.md)

افزونه منابع (`ram_mb` / `cores` / `disk_gb` / `num_ips` / `bandwidth`) از همان [`VpsResourceAddonService`](../../modules/Provisioning/Services/VpsResourceAddonService.php) اعمال می‌شود و `changePackage` را صدا می‌زند.

پایهٔ مشترک برای ارائه‌دهندگان REST جدید: `ConfigurableRestCloudClient` + `AbstractConfigurableCloudModule`.

پروکسی خروجی (SOCKS) برای API خارجی



همهٔ درخواست‌های HTTP به کلودهای **خارجی** از `OutboundHttpProxy` رد می‌شوند (پیش‌فرض gost محلی):

| تنظیم | مقدار پیشنهادی |
|--------|----------------|
| `.env` → `PROVISIONING_FOREIGN_HTTP_PROXY` | `socks5h://127.0.0.1:11080` |
| جایگزین HTTP | `http://127.0.0.1:11081` |
| Bypass | `PROVISIONING_FOREIGN_HTTP_PROXY_BYPASS` — پیش‌فرض `arvancloud.ir,asiatech.cloud,asiatech.ir,.ir` |

روی سرور بیرونی می‌توانید `http_proxy` را override کنید یا `direct` بگذارید تا همان ارائه‌دهنده مستقیم برود. آروان/آسیاتک و دامنه‌های `.ir` پروکسی نمی‌شوند.

اگر خطای `cURL error 28: Resolving timed out` دیدید: DNS از مسیر `socks5h` (gost → آپ‌لینک) تایم‌اوت شده؛ معمولاً لحظه‌ای است. کلاینت کلود **یک‌بار retry** می‌کند و پیام فارسی واضح می‌دهد. پایدار نبود → وضعیت `gost` روی `127.0.0.1:11080` و آپ‌لینک را چک کنید.

`AbstractBearerCloudClient` برای POST/PUT/PATCH بدون بدنه، JSON را به‌صورت `{}` می‌فرستد (نه `[]`) — Linode روی `[]` خطای `Invalid JSON` / HTTP 400 می‌دهد (reboot، lish/console، shutdown، …). پیام خطا از `errors[].reason` خوانده می‌شود. تغییر رمز Linode: اگر سرور روشن باشد BSS خاموش → ریست رمز → روشن می‌کند.

پنل مدیریت سرویس (پورتال / ریسلر)



`VpsPanelEmbedService` برای همهٔ `PUBLIC_CLOUD_MODULES` حالت **native** می‌دهد (نه iframe). عملیات از `VpsHypervisorPanelService`:

| قابلیت | ارائه‌دهندگان |
|--------|----------------|
| پاور (روشن / خاموش / reboot) | همهٔ کلودهای `PUBLIC_CLOUD_MODULES` — از طریق `suspend`/`unsuspend` ماژول یا کلاینت reboot |
| وضعیت زنده (GET instance) | Hetzner · DO · Vultr · Linode · آروان · Contabo · LightNode |
| نصب مجدد OS (انتخاب ایمیج) | Hetzner · DO · Vultr · Linode · آروان · Contabo · LightNode |
| تغییر رمز ورود | LightNode / Linode / Proxmox (فرم) · Hetzner (تولید) · DigitalOcean (ایمیل) |
| کنسول | Hetzner (WSS) · Vultr (VNC host/port) · Linode (**Weblish روی دامنهٔ منطقه‌ای** `*.webconsole.linode.com:8181` — نه `lish.linode.com`) — **DigitalOcean ندارد** (API عمومی مسیر کنسول ندارد؛ فقط کنترل‌پنل DO) |

کنسول بدون URL مستقیم وب → صفحهٔ `cloud-console-bridge` (رمز/WSS/host). بقیهٔ کلودها فعلاً پاور دارند؛ rebuild/console وقتی API پایدار باشد اضافه می‌شود.

UI: همان `vps-native-panel` — برای کلود فرم «نصب مجدد OS» با `image_options` از موجودی سرور. کارت وضعیت: IP · Login · **Password** (از `root_password`/`password` ذخیره‌شده، با دکمه کپی) · OS · Provider · VM ID.

نام کاربری ورود (SSH)



روی کلود عمومی **hostname ≠ username**. `ManagesPublicCloudVps::resolveGuestUsername` و `PublicCloudGuestLogin` همیشه `root` (لینوکس) یا `Administrator` (ویندوز) یا `guest_username` محصول را می‌گذارند — نه مقدار فیلد hostname سفارش. اگر دادهٔ قدیمی اشتباه (`username === hostname`) باشد، اولین باز شدن پنل VPS آن را heal می‌کند.

گیج Resources (CPU / RAM / Disk / Uptime)



| منبع | چه چیزی نشان داده می‌شود |
|------|---------------------------|
| **Proxmox** | مصرف لحظه‌ای CPU٪ / RAM٪ / Disk٪ + uptime از boot (`metrics_live=true`) |
| **کلود عمومی** (Hetzner، DO، Vultr، Linode، LightNode، …) | API معمولاً فقط **ظرفیت اختصاص‌یافته** می‌دهد؛ گیج‌ها با برچسب `Allocated capacity` پر می‌شوند |
| **LightNode** | `instance/detail` فیلد usage ندارد؛ Uptime از `createTime` به‌صورت **سن نمونه** (Since created) محاسبه می‌شود — نه uptime از آخرین boot |

پیام راهنما زیر عنوان Resources وقتی `metrics_live=false` نمایش داده می‌شود.

LightNode — موجودی زنده (ADR-053) · ✅ تست زنده کامل



کلید ماژول در BSS: `litenode` (سازگاری لایسنس). API واقعی: [apidoc.lightnode.com](https://apidoc.lightnode.com/en)

**تأیید:** provision + پنل بومی مشتری (پاور / reinstall async / رمز / نمایش login) روی محیط واقعی انجام شده.

| محل | رفتار |
|-----|--------|
| سرور بیرونی | `api_token` → هدر `x-open-token` · `api_url=https://openapi.lightnode.com` |
| محصول | Select: region←`regionCode\|zoneCode` · server_type←packageCode · image |
| سفارش | hostname · region · image — بدون packageCode |
| create | `POST /instance/create` با `packageConfig`؛ شناسه = `ecsResourceUUID` |
| ورود | یوزر سیستم‌عامل = `root` (لینوکس) / `Administrator` (ویندوز) — **نه** hostname؛ hostname فقط نام instance است |
| وضعیت پاور | `ecsStatus` + `ecsPendingStatus` → برچسب فارسی (آنلاین / خاموش / در حال خاموش شدن — نه متن خام `PENDING`) |
| نصب مجدد | انتخاب **صریح** ایمیج مقصد (بدون پیش‌انتخاب OS فعلی و بدون fallback به ایمیج فعلی). اگر روشن باشد: stop + صف `awaiting_power_off`. قبل از `reinstallSystem` وضعیت STOPPED چک می‌شود؛ sshKey ارسال نمی‌شود (فقط password). بعد از SUCCESS، `imageResourceUUID` زنده با هدف مقایسه می‌شود |
| تعویض IP | **در OpenAPI LightNode endpoint تعویض/جایگزینی IP عمومی نیست**؛ IP فقط با ساخت instance جدید عوض می‌شود (release + create) |

Client: اگر بدنهٔ JSON با `success=false` یا `httpStatus>=400` بیاید حتی روی HTTP 200، درخواست fail می‌شود.

آروان — موجودی زنده از API (مثل Proxmox)



با ماژول `arvancloud` و **گروه سرور** (الزامی):

| محل | رفتار |
|-----|--------|
| سرور بیرونی | فقط `api_token` (+ پیش‌فرض `api_url=https://napi.arvancloud.ir`) |
| محصول → تب Provision | Select زنده برای `region` / `server_type` / `image` / `network_id` از API |
| محصول → فیلدهای سفارش | خودکار: `hostname`، `region`، `image` — **بدون** `server_type` |
| خرید مشتری | region و image را انتخاب می‌کند؛ پلن از تنظیم محصول می‌آید |

فیلدهای تنظیم Provision محصول آروان (فقط همین‌ها):

`region` · `server_type` · `image` · `network_id` · `num_ips` · `ssh_key_id` · `guest_username` · `password_type` · `root_password`

`server_type` (Flavor) فقط روی محصول است — برای ساخت، ارتقا، کاهش و تمدید. مشتری انتخاب نمی‌کند.

`cores` / `ram_mb` / `disk_gb` از flavor می‌آید و در فرم محصول آروان نشان داده نمی‌شود. `shahkar_service_type` جدا از جدول Provision است.

اگر Selectهای API خالی است: **گروه سرور را انتخاب کنید** (باید سرور فعال `arvancloud` داخل گروه باشد).

اولویت resolve در provision:

  • Custom Field سفارش فقط برای `region` / `image` (و hostname)

  • `server_type` همیشه از تنظیمات محصول / سرور

  • بقیه از تنظیم محصول / سرور


  • سرویس‌ها: `PublicCloudInventoryOptions` · `PublicCloudOrderCustomField`

    API آروان:

  • `GET ecc/v1/regions`

  • `…/sizes`

  • `…/images?type=distributions` (ساختار تو در تو → در UI تخت می‌شود)

  • `…/images/marketplace` (اپ‌های Marketplace به انتهای لیست ایمیج اضافه می‌شود)

  • `…/networks`


  • Hetzner Cloud — موجودی زنده (ADR-053)



    با ماژول `hetzner` و **گروه سرور** (الزامی):

    | محل | رفتار |
    |-----|--------|
    | سرور بیرونی | `api_token` Bearer (+ پیش‌فرض `api_url=https://api.hetzner.cloud/v1`) |
    | محصول → تب Provision | Select زنده: `region`←locations · `server_type`←server_types · `image` |
    | فیلدهای محصول | `region` · `server_type` · `image` · `num_ips` · `ssh_key` · اعتبار — بدون cores/ram/disk |
    | فیلدهای سفارش | `hostname` · `region` · `image` — **بدون** server_type |

    API: `GET /locations` · `/server_types` · `/images?type=system`

    لیست‌ها تقریباً مستقل‌اند؛ `server_type` قفل محصول برای create/change_type است.

    DigitalOcean — موجودی زنده (ADR-053)



    با ماژول `digitalocean` و گروه سرور:

    | محل | رفتار |
    |-----|--------|
    | محصول | Select: region · server_type←size · image؛ گزینه‌های backups/ipv6 |
    | سفارش | hostname · region · image — بدون size |
    | وابستگی | با انتخاب region، فقط sizeهای همان منطقه |

    API: `GET /regions` · `/sizes` · `/images?type=distribution`

    **کنسول:** دکمه Console در پنل BSS برای DO نمایش داده نمی‌شود. مسیر قدیمی `POST /v2/droplets/{id}/remote_consoles` در API عمومی DigitalOcean وجود ندارد (`404 route not found`). Web Console / Recovery Console فقط از داخل کنترل‌پنل DigitalOcean در دسترس است؛ از پنل BSS از SSH استفاده کنید.

    Linode / Akamai — موجودی زنده (ADR-053) · ✅ تست زنده کامل



    ماژول `linode`: `GET /regions` · `/linode/types` · `/images` — قفل type روی محصول؛ CF: region + image.

    | قابلیت پنل | رفتار تأییدشده |
    |------------|----------------|
    | پاور / reboot | POST با بدنهٔ `{}` (نه `[]`) |
    | کنسول | `POST …/lish` → Weblish روی `*.webconsole.linode.com:8181` (صفحهٔ BSS + xterm) — نه `lish.linode.com` |
    | تغییر رمز | در صورت روشن بودن: خاموش → ریست → روشن |
    | نام کاربری | همیشه `root` / `Administrator` — نه hostname |
    | تعویض IP | در پنل BSS نیست (API Linode هم تعویض یک‌کلیکی IP اصلی ندارد) |

    **تأیید:** create + پنل بومی روی instance واقعی (مثلاً `gb-lon`) انجام شده.

    Vultr — موجودی زنده (هم‌تراز WHMCS رسمی)



    ماژول `vultr`: `GET /regions` · `/plans` · `/os` — plan قفل محصول؛ CF: region + os_id؛ فیلتر plan بر اساس region.

    Contabo — موجودی زنده (ADR-053)



    | محل | رفتار |
    |-----|--------|
    | اتصال | OAuth: client_id · client_secret · api_user · api_password |
    | محصول | Select: region←data-centers · server_type←productId (کاتالوگ ثابت) · image · period |
    | سفارش | hostname · region · image — بدون productId |
    | پلن | Contabo API کاتالوگ create ندارد → `ContaboClient::catalogProducts()` |

    API: `GET /v1/data-centers` · `/v1/compute/images?type=standard`

    OVHcloud — موجودی زنده (ADR-053)



    | محل | رفتار |
    |-----|--------|
    | اتصال | application_key · application_secret · consumer_key · **project_id** |
    | محصول | Select: region · server_type←flavorId · image · monthly_billing · num_ips |
    | سفارش | hostname · region · image — بدون flavorId |
    | وابستگی | flavor و image با `?region=` فیلتر می‌شوند |

    API: `GET /cloud/project/{id}/region` · `/flavor?region=` · `/image?region=`

    ابر آسیاتک — موجودی (provisional / ADR-053)



    | محل | رفتار |
    |-----|--------|
    | اتصال | Bearer `api_token` · `api_url` (پیش‌فرض api.asiatech.cloud) |
    | محصول | region · server_type←plan · image · num_ips — بدون cores/ram/disk |
    | سفارش | hostname · region · image |
    | مسیرها | `v1/regions` · `v1/plans` · `v1/images` — قابل override با `inventory_paths` |

    **توجه:** سند عمومی API منتشر نشده؛ مسیرها از قرارداد create فعلی گرفته شده‌اند. با توکن زنده تأیید کنید.

    Gcore — موجودی زنده (ADR-053)



    | محل | رفتار |
    |-----|--------|
    | اتصال | `apikey` + **project_id** |
    | محصول | region←id · server_type←flavor_name · image |
    | سفارش | hostname · region · image |
    | وابستگی | flavors/images زیر `project_id` + `region_id` |

    API: `GET /cloud/v1/regions` · `/flavors/{project}/{region}` · `/images/{project}/{region}`

    IONOS — موجودی زنده (ADR-053)



    | محل | رفتار |
    |-----|--------|
    | اتصال | Bearer یا Basic (email+token) · `datacenter_id` پیش‌فرض |
    | محصول | region←datacenter UUID · server_type←templateUuid · image |
    | سفارش | hostname · region · image |
    | وابستگی | ایمیج‌ها با `location` دیتاسنتر فیلتر می‌شوند |

    API: `GET /datacenters` · `/templates` · `/images`

    Aeza — موجودی زنده (ADR-053)



    | محل | رفتار |
    |-----|--------|
    | اتصال | `X-API-Key` |
    | محصول | region←group · server_type←productId · image←os · period |
    | سفارش | hostname · region · image |
    | create | `POST /services/orders` |

    API: `GET /services/groups` · `/services/products` · `/os`

    Alibaba / Aruba / فاز۴ / Hyperscalers



  • **Alibaba:** RPC امضا · Describe* · InstanceType قفل محصول

  • **Aruba + trabia…ipxon:** path-based `v1/regions|plans|images` + `inventory_paths`

  • **AWS:** SigV4 · AMI کاتالوگ محدود (نه همهٔ AMI حساب)

  • **GCP:** zones + machineTypes + image families

  • **Azure:** locations + vmSizes + Marketplace catalog ثابت


  • فاز ۱–۴ ماژول‌ها



    | کلید | ارائه‌دهنده | احراز |
    |------|-------------|-------|
    | `hetzner` / `digitalocean` / `vultr` / `linode` | کلود عمومی | Bearer |
    | `contabo` / `ovh` / `arvancloud` / `abrasiatech` | فاز ۲ | OAuth / Apikey / Bearer |
    | `aws` / `gcp` / `azure` | فاز ۳ | کلیدهای ابری |
    | `gcore` / `ionos` / `aeza` … `ipxon` | فاز ۴ REST | Bearer / X-API-Key |

    با انتخاب ماژول در سرور بیرونی، `api_url` / `verify_ssl` / `timeout` از `connectionFieldDefaults` پر می‌شود.

    محدودیت‌ها



  • **کاهش دیسک** در اکثر کلودها رد می‌شود.

  • موجودی زنده: همهٔ کلیدهای `PublicCloudInventoryOptions::INVENTORY_MODULES` (شامل AWS/GCP/Azure و فاز۴ path-based). جزئیات: چک‌لیست.

  • پنل مشتری: native برای همهٔ کلودها؛ کنسول فقط Hetzner/DO/Vultr/Linode؛ reinstall فقط ماژول‌های `PUBLIC_CLOUD_REINSTALL_MODULES`.


  • راه‌اندازی آروان



  • سرور بیرونی → آروان + توکن → تست اتصال → گروه سرور

  • محصول VPS → ماژول آروان + **گروه سرور** → `region` را از لیست انتخاب کنید

  • تب فیلدهای سفارش را ذخیره کنید (`region` / `image` خودکار می‌آید)

  • مشتری هنگام خرید دیتاسنتر و OS را انتخاب می‌کند


  • تست



    ```bash
    php artisan test --filter='InventoryTest|RemainingCloudInventoryTest|PublicCloudVpsPanelTest'
    ```

    مرتبط



  • [vps-provisioning.md](./vps-provisioning.md) (Proxmox / Virtualizor / VMware / AutoVM)

  • [portal-dashboard.md](../customer/portal-dashboard.md) (UI پنل بومی مشتری)