Skip to content

自動プロビジョニング(Cloud)

このドキュメントは、クライアントが契約してから ~3-5 分以内にRoqueOS Cloud VMがゼロから作成される方法 を説明します。使用するために何も理解する必要はありません — これは、デバッグ、サポート、または自分のビジネスのためにフローを適応させたい人のための技術リファレンスです。

フロー図

1. クライアントが /pricing で「Cloud Proを契約」をクリック


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を生成
   - {customerUid, token, apiKey, apiSecret}でFirebase Functionsにcallback POST


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 provisionServerprovisioningCallback
  • public/install.shroqueos-server の正規インストーラーのミラー

Backend (roqueos-server)

  • install/install.sh v1.1.0-cloud-callback — callbackサポート付きのワンライナーインストーラー
  • src/modules/admin/admin.controller.ts — べき等エンドポイント POST /admin/setup(admin keyを生成)

外部インフラ

  • Hetzner Cloud API (https://api.hetzner.cloud/v1) — サーバー作成
  • Cloudflare API — サブドメイン <id>.cloud.roqueos.com.br の作成(v1.2予定)
  • Firebase Secret ManagerHCLOUD_TOKENPROVISIONER_SSH_KEY_IDSTANDARD_FIREWALL_ID を保管
  • Stripe Brasil — カード/Pix経由のBRL checkout

Tier → Hetzner spec

RoqueOS TierHetzner SKUvCPURAMSSD ディスクCOGS €/月
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。内部的には context.auth.token.admin === true を必要とする https.onCall です。

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 は admin に 一度だけ 表示されます(ログには残りません)。そのSHA-256ハッシュはFirestoreの subscriptions/{uid}.provisioning.tokenHash に TTL 30 分で保持されます。

provisioningCallback(HTTP 公開)

トリガー: 新しく作成されたVMが install.sh 経由でこのエンドポイントに POST します。

公開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"
}

検証:

  • ペイロードのシェイプ(token + apiKey + apiSecretのregex)
  • 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分を超過

cloud-init の install.sh フラグ

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-callbackinstall.sh v1.1.0-cloud-callback で追加されました(スクリプトの先頭の INSTALLER_VERSION)。4つすべてが存在する場合、インストーラーは wait_for_server がhealthyを返した後 do_provisioning_callback() をトリガーします。

オペレーター側で検証

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"}

トラブルシューティング

症状考えられる原因修正
ウェルカムメールが届かないSecret ManagerにSMTP_HOST/USER/PASSが欠落gcloud secrets list --project=roqueos | grep SMTP + 再設定
VMは作成されたがサブスクリプションが provisioninginstall.shがVM内で失敗(callback呼ばず)VMにSSH: journalctl -u cloud-init -f + docker logs roqueos-server
Callbackが token_expired を返すプロビジョニングに30分以上かかった(VM遅延)provisionServer を再実行してトークン + cloud-initを再生成
Callbackが token_mismatch を返すバグまたは攻撃の試みFunctionのログで送信元IPを確認;疑わしい場合はローテートしてアラート
Firestoreドキュメントで vmIp: nullHetzner APIタイムアウトまたは 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予定 — おそらく hcloud server change-type 経由のマイグレーション。
  • カスタマー毎のCloudflare Tunnel: 予定 — 今日各VMはパブリックIP + ポート80/443で公開。Tunnelはedge SP経由でTLSを追加(BRへの低レイテンシ)。

クロスリファレンス