پیکربندی ماژولهای Provisioning
> version: 1.35 | last_updated: 2026-09-23 | audience: admin
ماژولهای موجود
| کلید | کاربرد |
|------|--------|
| `manual` | فعالسازی دستی توسط اپراتور (مثلاً Dedicated بدون نصب خودکار) |
| `ibsng` | IBSng — FTTH/ADSL/Wireless (JSON-RPC) |
| `netbill` | NetBill Enterprise — AAA/Ghasedak |
| `radius` | RADIUS عمومی (simulated) |
| `cpanel` | هاستینگ (WHM) |
| `directadmin` | هاستینگ (DirectAdmin API) |
| `plesk` | هاستینگ (Plesk XML API) |
| `hestia` | هاستینگ (HestiaCP) |
| `cyberpanel` | هاستینگ (CyberPanel) |
| `webuzo` | هاستینگ (Webuzo) |
| `ispconfig` | هاستینگ (ISPConfig) |
| `aapanel` | هاستینگ (aaPanel) |
| `zpanel` | هاستینگ (zPanel / Sentora-style API) |
| `proxmox` / `virtualizor` / `vmware` / `autovm` | VPS / هایپروایزر |
| کلودهای عمومی (`hetzner`, `digitalocean`, `gcore`, …) | دستهٔ جدا «کلود عمومی» — [cloud-vps-provisioning.md](cloud-vps-provisioning.md) |
| `nocps` | Dedicated Server — نصب OS با NOC-PS |
| `domain` | ثبت دامنه |
دستهبندی در Select
در **سرور بیرونی جدید** و **محصول → تب فنی / Provision** گزینهها گروهبندی میشوند:
| گروه | مثال |
|------|------|
| فروش اینترنت | ibsng, netbill, radius |
| فروش میزبانی | cpanel, plesk, … |
| VPS / هایپروایزر | proxmox, virtualizor, vmware, autovm |
| کلود عمومی | hetzner, digitalocean, gcore, … |
| فروش سرور اختصاصی / دامنه / انطباق | nocps, domain, shahkar |
| عمومی | manual |
پیادهسازی: `ProvisioningModuleOptions` — گزینهها با پیشوند دسته (`کلود عمومی — Hetzner`) و Select **قابلجستجو** (نه native؛ native در RTL متن را نصف میکرد).
مستندات:
صف ساخت سرویس (Create)
ساخت اکانت روی سرور مقصد **همزمان با پرداخت/fulfill سفارش اجرا نمیشود**. بعد از سفارش:
**لغو از منو:** اگر اکانت ریموت ساخته نشده باشد، اشتراک Terminated میشود تا دامنه آزاد گردد.
Suspend / Unsuspend / Terminate همچنان همزمان (sync) هستند؛ **Create** و **ChangePackage** (تغییر پلن میاندوره) صف میشوند.
صف تغییر پلن (`change_package`)
بعد از پرداخت سفارش میاندوره:
صف تمدید دوره (`renew`)
بعد از پرداخت فاکتور تمدید خودکار (کرون): کار `action=renew`:
فعلاً: `netbill` = true؛ هاستینگ/manual/VPS و … = false (در صورت نیاز روی همان ماژول override کنید).
جزئیات: [subscription-renewal.md](subscription-renewal.md)
دکمههای «Provisioning» روی سفارش/اشتراک همان صف را پر میکنند و یک تلاش فوری میزنند.
```bash
php artisan provisioning:process-queue --limit=20
```
Scheduler باید در crontab باشد (`schedule:run` هر دقیقه) — [cron-jobs.md](cron-jobs.md). ADR: ADR-048.
تنظیم سرور بیرونی
منو: **تنظیمات → پیکربندی سرورهای بیرونی**
| ترتیب | زیرمنو | کار |
|-------|--------|-----|
| ۱ | **سرورهای بیرونی** | ثبت سرور (popup وسط صفحه) + تست اتصال |
| ۲ | **گروهبندی سرورها** | ساخت گروه (popup وسط صفحه) و assign سرور با اولویت |
اگر Sandbox روشن باشد، تست اتصال همچنان واقعی است؛ فقط عملیات ایجاد/تعلیق اکانت واقعی اجرا نمیشود و در پیام موفقیت یادآوری میشود.
cPanel / WHM — احراز هویت
کلیدهای اتصال در `config` سرور:
| کلید | توضیح |
|------|--------|
| `whm_host` | آدرس WHM **با `https://`** (مثال: `https://server.example.com`) — بدون scheme تست فریبنده میشود |
| `whm_port` | پورت (پیشفرض `2087`) |
| `whm_username` | نام کاربری (معمولاً `root`) |
| `whm_token` | API Token — اگر پر باشد رمز نادیده گرفته میشود |
| `whm_password` | رمز عبور WHM — فقط وقتی توکن خالی است |
| `verify_ssl` | `0` / `1` |
تست اتصال فقط وقتی موفق است که WHM JSON معتبر و شمارهٔ نسخه برگرداند. رمز/توکن غلط → `Access denied`. ریدایرکت به صفحهٔ ورود (مثلاً host بدون `https://`) دیگر «موفق» حساب نمیشود.
حداقل یکی از `whm_token` یا `whm_password` لازم است.
DirectAdmin — اتصال و پکیج
کلیدهای اتصال سرور:
| کلید | توضیح |
|------|--------|
| `host` | آدرس **بدون پورت** (مثال: `http://1.2.3.4` یا `https://da.example.com`) |
| `port` | پیشفرض `2222` |
| `username` / `password` | Admin یا Reseller با دسترسی API |
| `verify_ssl` | `0` / `1` (گواهی self-signed → `0`) |
| عملیات | API |
|--------|-----|
| تست | `CMD_API_SHOW_RESELLER_IPS` (fallback: `CMD_API_PACKAGES_USER`) |
| لیست پکیج | `CMD_API_PACKAGES_USER` |
| ساخت اکانت | `CMD_API_ACCOUNT_USER` |
| تعلیق / رفع | `CMD_API_MODIFY_USER` (`suspended=yes/no`) |
| حذف | `CMD_API_SELECT_USERS` |
| تغییر پکیج | `CMD_API_CHANGE_USER_PACKAGE` |
| Login As | `CMD_API_LOGIN_KEYS` |
روی محصول با ماژول `directadmin`، بعد از انتخاب **گروه سرور**، فیلد `plan` مثل cPanel بهصورت Select از API پر میشود (مثلاً `1GB` / `5GB` / `10GB`).
**نکته:** یوزر/رمز اتصال سرور (`username`/`password`) برای لاگین API است؛ نام کاربری اکانت مشتری از دامنه ساخته میشود. اگر Reseller مقدار `shared` را برای IP نپذیرد، ماژول خودکار اولین IP از `CMD_API_SHOW_RESELLER_IPS` را میفرستد.
سایر پنلهای هاستینگ — پکیج و مصرف
سرویس یکپارچهٔ `HostingPackageOptions` برای همهٔ ماژولهای هاستینگ زیر، بعد از انتخاب **گروه سرور**، فیلد `plan` را بهصورت Select از `listPackages` همان سرور پر میکند:
| ماژول | لیست پکیج (خلاصه) | مصرف زنده (خلاصه) | سطح اطمینان |
|--------|-------------------|-------------------|-------------|
| `cpanel` | WHM `listpkgs` | `StatsBar::get_stats` | کامل (تأییدشده) |
| `directadmin` | `CMD_API_PACKAGES_USER` | `SHOW_USER_USAGE` + `CONFIG` (GET) | کامل (تأییدشده) |
| `plesk` | XML service-plan | `domain --info` (دیسک/ترافیک) | کامل روی API استاندارد |
| `hestia` | `v-list-user-packages` JSON | `v-list-user` JSON | کامل روی API استاندارد |
نکتهٔ Hestia: endpoint باید `…/api/` **با اسلش انتهایی** باشد. بدون اسلش nginx ۳۰۱ میدهد، POST به GET تبدیل میشود و پاسخ `HTTP 405 data received is null or invalid` میآید. کلاینت BSS همیشه `/api/` میزند. IP سرور BSS هم باید در whitelist API پنل Hestia باشد.
| `cyberpanel` | `fetchPackages` / مشابه | محدود — اغلب فقط دیسک دامنه | best-effort |
| `webuzo` | `listplans` / `list_plans` | آمار اکانت از API | وابسته به نسخه |
| `ispconfig` | `client_templates_get_all` | `client_get` (quota) | session API شکننده بین نسخهها |
| `aapanel` | `get_site_types` / plugin package | دیسک سایت (پهنای باند اغلب نیست) | وابسته به نسخه |
| `zpanel` | `get_packages` | `get_account` | وابسته به فورک API |
ISPConfig — اتصال و SSL
| کلید | توضیح |
|------|--------|
| `host` | آدرس با `https://` (مثال: `https://89.45.68.167`) — ارقام فارسی در UI نرمال میشوند |
| `port` | Remote API (پیشفرض `8080`) → مسیر `/remote/json.php` |
| `username` / `password` | **Remote User** از System → Remote Users (نه لزوماً ادمین پنل) |
| `verify_ssl` | `0` یا `1` — برای گواهی self-signed حتماً **`0`** |
اگر مقدار `verify_ssl` رشتهٔ `"null"` / خالی / `"false"` باشد، BSS آن را **خاموش** میگیرد (قبلاً `(bool)"null"` در PHP برابر true بود و خطای cURL ۶۰ میداد).
خطای `SSL certificate problem: self signed certificate` → `verify_ssl=0` و ذخیره مجدد سرور، سپس **تست اتصال**.
API این نسخه متد را در **query** میخواهد (`POST …/remote/json.php?login`)، نه فیلد `method` داخل JSON. کلاینت BSS همین سبک را استفاده میکند؛ پیام «Method not provided in json call» یعنی فراخوانی اشتباه بوده و اصلاح شده است.
اگر بعد از رفع SSL/متد پیام «ورود ناموفق / Username or password wrong» آمد، یوزر/رمز Remote API را در ISPConfig چک کنید و دسترسیهای لازم برای `client_*` / `sites_*` را بدهید.
**ساخت اکانت:** `client_add` + `sites_web_domain_add`. فیلدهای اجباری `language` (مثلاً `en`) و `ssh_chroot` (مثلاً `no`) و `web_php_options` از قالب مشتری کپی میشوند. خطای `language_error_empty` / `ssh_chroot_notempty` یعنی این فیلدها خالی رفتهاند (در BSS دیگر پیشفرض دارند). پلن محصول باید نام قالب ISPConfig باشد (مثلاً `1GB` / `5GB` / `10GB`).
CRUD مشترک روی کلاینتها: `createAccount` / `suspendAccount` / `unsuspendAccount` / `terminateAccount` (+ تغییر پکیج/SSO جایی که ماژول قبلاً داشته). شکل نرمال مصرف برای پورتال:
```php
[
'disk_used_mb' => float,
'disk_limit_mb' => ?float, // null = نامحدود
'bandwidth_used_mb' => float,
'bandwidth_limit_mb' => ?float,
'counters' => [['key','label','used','limit'], ...],
]
```
`HostingUsageService` برای همهٔ کلیدهای بالا گیج دیسک/پهنای باند (و نوار شمارندهها در صورت وجود) میسازد. اگر API پنل داده ندهد، پیام خطا در ویجت مصرف نشان داده میشود — نه گیج خالی ساکت.
اتصال به محصول
انتخاب پکیج از API سرور
برای هر ماژول هاستینگ در جدول بالا، بعد از انتخاب **گروه سرور**، فیلد `plan` بهصورت Select از API همان سرور پر میشود (نه تایپ دستی). اگر اتصال قطع باشد، پیام خطا زیر تنظیمات Provision نمایش داده میشود.
برای ماژول **Proxmox** همان الگو روی `node` / `storage` / `template_vmid` / `iso_image` / `bridge` است (`ProxmoxInventoryOptions`). `bridge` اگر خالی باشد `vmbr0` است. قالبهای متعدد در فیلد سفارش `iso` برای مشتری میآیند (خودکار با انتخاب گروه سرور). با انتخاب قالب محصول، `disk_key` و `cloudinit_drive` از تنظیمات VM پر میشوند. اگر `iso` سفارش یا `iso_image` محصول volid فایل ISO باشد، VM خالی با CD-ROM ساخته میشود (نصب از کنسول). جزئیات: [vps-provisioning.md](vps-provisioning.md).
در **تنظیمات Provision** محصول فقط `plan`، `ns1`، `ns2` (و فیلدهای خاص ماژول در صورت وجود) دیده میشود — فیلد `domain` اینجا نیست. دامنه هنگام **خرید** از فیلد سفارش `domain` گرفته میشود. اگر `ns1`/`ns2` پر شوند، در اطلاعات فنی سرویس مشتری (و ریسلر) نمایش داده میشوند. بعد از provision، نام کاربری و رمز در مدیریت سرویس مشتری نمایش داده میشود.
مصرف زنده در مدیریت هاست (پورتال / ریسلر)
صفحهٔ «مدیریت هاست» و جزئیات سرویس (`HostingPanelSsoService` + `HostingUsageService`) مصرف را زنده از پنل میخواند — جدول بالا. نمایش: گیج مایع دیسک و پهنای باند ماهانه + در صفحهٔ جزئیات، نوار ایمیل / دیتابیس / FTP / دامنه (در صورت پشتیبانی پنل).
**یکتایی دامنه:** اگر همان دامنه روی سرویس با وضعیت `pending` / `active` / `suspended` (یا سفارش باز draft/acknowledged/in_progress) باشد، خرید رد میشود با پیام ثابت «این دامنه در سیستم وجود دارد…». چک زنده هنگام تایپ در فیلد دامنه (`GET /hosting/domain-check`). سرویس `terminated` دامنه را آزاد میکند.
**ایمیل تماس WHM:** هنگام `createacct` فیلد `contactemail` از ایمیل ثبتنامی مشتری (`party` / کاربر پورتال) پر میشود.
**لغو سرویس:** از صفحه سفارش/اشتراک با «لغو سرویس». اگر اکانت در WHM ساخته نشده باشد (pending/failed)، فقط در BSS لغو میشود و وقتی همهٔ اشتراکهای سفارش تمام شوند وضعیت سفارش هم `cancelled` میشود.
نام کاربری WHM از بخش اول دامنه ساخته میشود (مثلاً `mahdi.com` → `mahdi`) و با قوانین WHM (فقط حروف کوچک و عدد، حداکثر ۱۶ کاراکتر) sanitize میشود. رمز عبور قوی تولید میشود تا از فیلتر strength رد نشود.
**یکتایی دامنه:** اشتراکهای `active` / `suspended` و `pending` (از جمله صف `queued` / `failed`) دامنه را اشغال میکنند؛ `terminated` آزاد است. آیتم سفارش باز فقط تا قبل از ساخت اشتراک قفل میکند — بعد از ساخت اشتراک، چک سفارش همان آیتم را تداخل حساب نمیکند (باگ ORD-038).
مدیریت سرویس (از سفارش)
**سفارش و اشتراک → سفارشها → مشاهده** — بخش «سرویس»
**Provisioning → صف ساخت سرویس** — موارد exhausted / در صف؛ ارسال مجدد یا لغو
لاگ
هر عملیات در جدول `provisioning_logs` ثبت میشود و در UI دیده میشود:
| سطح | مسیر نمایش |
|------|------------|
| ادمین tenant | **اشتراک → مشاهده** — بخش «لاگ Provisioning» |
| ادمین tenant | **سفارش → مشاهده** — زیر هر سرویس، لیست لاگ همان اشتراک |
| ادمین tenant | **صف ساخت سرویس** — آخرین خطای job؛ آرشیو موفق در `provisioning_completed` |
| پورتال مشتری | **سفارشها → جزئیات** و **سرویسها → جزئیات** |
| پنل ریسلر | **سفارش → جزئیات** و **سرویس مشتری → جزئیات** |
ستونها: عملیات (برچسب فارسی)، وضعیت (موفق/ناموفق)، پیام، زمان شمسی.