Skip to content

التوفير الآلي (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 Checkout
  • functions/index.js — Cloud Functions provisionServer و provisioningCallback
  • public/install.sh — مرآة المثبت القانوني لـ roqueos-server

Backend (roqueos-server)

  • install/install.sh v1.1.0-cloud-callback — مثبت سطر واحد بدعم callback
  • src/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 TierHetzner SKUvCPURAMقرص SSDCOGS €/شهر
Startercx222 shared4 GB40 GB4.51
Procx324 shared8 GB80 GB7.55
Powerccx234 dedicated16 GB160 GB31.20
Enterprisead-hocvariavariavariavaria

الموقع: فالكنشتاين، ألمانيا (fsn1). الصورة: ubuntu-22.04.

نقاط Cloud Function

provisionServer (admin onCall)

المشغل: Stripe webhook customer.subscription.created. داخليًا هو https.onCall يتطلب context.auth.token.admin === true.

Input:

json
{
  "customerUid": "abc123",
  "tier": "pro"
}

Output:

json
{
  "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):

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 — الاشتراك ليس في حالة provisioning
  • 410 token_expired — تجاوز الـ 30 دقيقة

install.sh أعلام cloud-init

Cloud Function provisionServer يولد user_data (cloud-init) الذي ينفذ:

bash
#!/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 مزيفين):

bash
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 Managergcloud secrets list --project=roqueos | grep SMTP + إعادة التكوين
VM تم إنشاؤه لكن الاشتراك بقي provisioninginstall.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 في وثيقة FirestoreHetzner API timeout أو رد بدون public_netأعد محاولة provisionServer؛ سجلات في gcloud functions logs read provisionServer

غير موثق هنا (لكن ذو صلة)

  • التجديد التلقائي للاشتراك: Stripe يعالج بمفرده عبر customer.subscription.updated webhook. 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).

مراجع متقاطعة