التوفير الآلي (Cloud)
تصف هذه الوثيقة كيف يتم إنشاء RoqueOS Cloud VM من الصفر في ~3-5 دقائق بعد اشتراك العميل. لا تحتاج إلى فهم أي من هذا لاستخدامه — إنه مرجع تقني للتصحيح والدعم أو لمن يريد تكييف التدفق لأعماله الخاصة.
مخطط التدفق
1. العميل ينقر "اشترك في Cloud Pro" في /pricing
│
▼
2. Stripe Checkout (البرازيل) يعالج البطاقة/Pix
│
▼
3. Stripe webhook → Cloud Function `provisionServer`
│
▼
4. Cloud Function يستدعي Hetzner API (ينشئ CX32 VM)
+ يولد رمزًا قصير الأجل (TTL 30 دقيقة)
│
▼
5. VM يقلع مع cloud-init الذي ينفذ
`curl https://roqueos.com.br/install.sh | bash`
يمرر --customer-id، --tier، --provisioning-token،
--provisioning-callback
│
▼
6. install.sh يعمل داخل VM:
- يسحب صور Docker
- ينشئ مجلدات دائمة
- يشغل roqueos-server + الحاويات الجانبية (guacd، cloudflared)
- ينتظر استجابة /health بـ 200
- POST محلي /admin/setup لتوليد admin key
- POST callback إلى Firebase Functions مع
{customerUid, token, apiKey, apiSecret}
│
▼
7. Cloud Function `provisioningCallback` يتحقق من الرمز،
يحدد الاشتراك كـ `active`، يحفظ بيانات الاعتماد (TTL 24س)،
يطلق بريد الترحيب عبر SMTP
│
▼
8. العميل يستلم بريدًا مع URL + بيانات الاعتماد
تسجيل الدخول إلى /app مكوّن بالفعل للخادم الجديدالمكونات المشاركة
Frontend (roqueos-front)
src/pages/PricingPage.vue— زر "اشترك" يقود إلى Stripe Checkoutfunctions/index.js— Cloud FunctionsprovisionServerوprovisioningCallbackpublic/install.sh— مرآة المثبت القانوني لـroqueos-server
Backend (roqueos-server)
install/install.shv1.1.0-cloud-callback — مثبت سطر واحد بدعم callbacksrc/modules/admin/admin.controller.ts— endpoint مثلوثPOST /admin/setup(يولد admin key)
بنية تحتية خارجية
- Hetzner Cloud API (
https://api.hetzner.cloud/v1) — إنشاء الخوادم - Cloudflare API — إنشاء النطاق الفرعي
<id>.cloud.roqueos.com.br(مخطط v1.2) - Firebase Secret Manager — يحفظ
HCLOUD_TOKEN،PROVISIONER_SSH_KEY_ID،STANDARD_FIREWALL_ID - Stripe Brasil — checkout BRL عبر البطاقة/Pix
Tier → مواصفات Hetzner
| RoqueOS Tier | Hetzner SKU | vCPU | RAM | قرص SSD | COGS €/شهر |
|---|---|---|---|---|---|
| Starter | cx22 | 2 shared | 4 GB | 40 GB | 4.51 |
| Pro | cx32 | 4 shared | 8 GB | 80 GB | 7.55 |
| Power | ccx23 | 4 dedicated | 16 GB | 160 GB | 31.20 |
| Enterprise | ad-hoc | varia | varia | varia | varia |
الموقع: فالكنشتاين، ألمانيا (fsn1). الصورة: ubuntu-22.04.
نقاط Cloud Function
provisionServer (admin onCall)
المشغل: Stripe webhook customer.subscription.created. داخليًا هو https.onCall يتطلب context.auth.token.admin === true.
Input:
{
"customerUid": "abc123",
"tier": "pro"
}Output:
{
"ok": true,
"vmId": "12345678",
"vmIp": "65.108.x.x",
"provisioningToken": "<64 hex chars>",
"callbackUrl": "https://southamerica-east1-roqueos.cloudfunctions.net/provisioningCallback",
"tokenExpiresAt": 1716800000000
}يتم عرض provisioningToken للمسؤول مرة واحدة فقط (لا يبقى في السجل). يبقى تجزئة SHA-256 الخاصة به في Firestore في subscriptions/{uid}.provisioning.tokenHash، مع TTL 30 دقيقة.
provisioningCallback (HTTP عام)
المشغل: VM المنشأة حديثًا تستدعي POST لهذه النقطة عبر install.sh.
URL العام: https://southamerica-east1-roqueos.cloudfunctions.net/provisioningCallback
لماذا عام بدون مصادقة Firebase: VM الجديدة لا تحتوي على بيانات اعتماد Firebase. تتم المصادقة بواسطة الرمز قصير الأجل (لمرة واحدة، مقارنة تجزئة SHA-256).
Input (POST JSON):
{
"customerUid": "abc123",
"token": "<64 hex chars>",
"apiKey": "ros_xxxx",
"apiSecret": "ros_secret_xxxx"
}التحقق:
- شكل الحمولة (regex على token + apiKey + apiSecret)
tokenHashيطابق المسجل في Firestore- الرمز لم ينتهِ
- الاشتراك لا يزال في
provisioning(لم يكتمل من قبل)
Output ok: 200 { "ok": true }Output خطأ: HTTP 400/401/404/409/410 + { "error": "<code>" }
الأخطاء المحتملة:
400 missing_fields— حمولة غير مكتملة400 invalid_*— شكل غير صالح401 token_mismatch— رمز خاطئ (هجوم محتمل، يسجل IP)404 subscription_not_found— customerUid غير موجود409 already_completed— callback تم استدعاؤه بنجاح مسبقًا (dedup)409 no_pending_provisioning— الاشتراك ليس في حالة provisioning410 token_expired— تجاوز الـ 30 دقيقة
install.sh أعلام cloud-init
Cloud Function provisionServer يولد user_data (cloud-init) الذي ينفذ:
#!/bin/bash
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
apt-get update -y
apt-get install -y curl ca-certificates
curl -fsSL https://roqueos.com.br/install.sh | bash -s -- \
--customer-id "${CUSTOMER_UID}" \
--tier "${TIER}" \
--provisioning-token "${TOKEN}" \
--provisioning-callback "${CALLBACK_URL}" \
--skip-promptsتمت إضافة 4 أعلام --customer-id، --tier، --provisioning-token، --provisioning-callback في install.sh v1.1.0-cloud-callback (INSTALLER_VERSION في أعلى البرنامج النصي). عندما تكون الأربعة موجودة، يطلق المثبت do_provisioning_callback() بعد أن يعود wait_for_server بـ healthy.
التحقق من جانب المشغل
اختبر callback يدويًا (استبدال customerUid/token مزيفين):
curl -sS -X POST \
"https://southamerica-east1-roqueos.cloudfunctions.net/provisioningCallback" \
-H 'Content-Type: application/json' \
-d '{
"customerUid":"smoke-test",
"token":"0000000000000000000000000000000000000000000000000000000000000000",
"apiKey":"ros_smoketestkey",
"apiSecret":"ros_secret_smoketest_secret_xyz"
}'
# متوقع: HTTP 404 {"error":"subscription_not_found"}استكشاف الأخطاء وإصلاحها
| العرض | السبب المحتمل | الإصلاح |
|---|---|---|
| لم يصل بريد الترحيب | SMTP_HOST/USER/PASS مفقود في Secret Manager | gcloud secrets list --project=roqueos | grep SMTP + إعادة التكوين |
VM تم إنشاؤه لكن الاشتراك بقي provisioning | install.sh فشل داخل VM (لم يستدعِ callback) | SSH إلى VM: journalctl -u cloud-init -f + docker logs roqueos-server |
Callback يعيد token_expired | استغرق التوفير >30 دقيقة (VM بطيء) | شغل provisionServer مرة أخرى لإعادة توليد الرمز + cloud-init |
Callback يعيد token_mismatch | خطأ أو محاولة هجوم | تحقق من IP المصدر في سجل Function؛ إذا كان مشبوهًا، قم بالتدوير وإطلاق التنبيه |
vmIp: null في وثيقة Firestore | Hetzner API timeout أو رد بدون public_net | أعد محاولة provisionServer؛ سجلات في gcloud functions logs read provisionServer |
غير موثق هنا (لكن ذو صلة)
- التجديد التلقائي للاشتراك: Stripe يعالج بمفرده عبر
customer.subscription.updatedwebhook. VM تستمر في الحياة. - الإلغاء: webhook
customer.subscription.deleted→ دالة مستقبليةdecommissionServerتوقف VM + snapshot نهائي + بريد "بياناتك محفوظة لمدة 30 يومًا". - ترقية Tier (Pro → Power): مخطط v1.2 — ربما migration عبر
hcloud server change-type. - Cloudflare Tunnel لكل عميل: مخطط — اليوم كل VM يكشف عبر IP عام + المنافذ 80/443. Tunnel يضيف TLS عبر edge SP (زمن استجابة أقل لـ BR).
مراجع متقاطعة
- نظرة عامة على RoqueOS Cloud — الخطط، الأسعار، الأساس المنطقي
- Self-host install — نفس
install.shالذي يعمل داخل cloud-init - Server Admin Panel — لإدارة الخادم الذي تم توفيره حديثًا
- ذاكرة تقنية:
hetzner_architecture_decision.mdفي الريبو (داخلي)