infra-deploy について
infra-deployは、Cal.comのインフラをデプロイ・管理するスキルで、セルフホスト運用やローカル開発を対象とします。GCP Cloud Run、Supabase PostgreSQL、Docker Compose、Pushover用Webhookリレーを扱います。
主な機能
- 01GCP Cloud Runへのデプロイ
- 02Supabase PostgreSQLの設定
- 03Docker Composeでローカル実行
- 04Cal.comからPushoverへのWebhookリレーをデプロイ
- 05データベース接続確認とマイグレーション
活用シーン
- 01GCP Cloud RunでCal.comをデプロイ
- 02Docker Composeでローカル開発環境を実行
- 03Cal.com Webhook用Pushoverリレーをデプロイ
- 04Supabaseに接続してデータベースを移行
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ terrylica/ cc-skills --skill infra-deployインストール後、Claude Code で/infra-deployを入力して読み込まれたか確認します。
同梱ファイルreferences/evolution-log.md
詳細
インフラストラクチャのデプロイ
Supabase PostgreSQL を使用して、セルフホスト版の Cal.com を GCP Cloud Run にデプロイするか、Docker Compose を使ってローカルで実行します。
自己進化するスキル:このスキルは使用を通じて改善されます。手順が間違っている場合、パラメーターにずれが生じた場合、または回避策が必要だった場合は、後回しにせず、直ちにこのファイルを修正してください。実際に再現できる問題がある場合にのみ更新してください。
必須の事前確認
Step 1:GCP プロジェクトの設定を確認する
echo "CALCOM_GCP_PROJECT: ${CALCOM_GCP_PROJECT:-NOT_SET}"
echo "CALCOM_GCP_ACCOUNT: ${CALCOM_GCP_ACCOUNT:-NOT_SET}"
echo "CALCOM_GCP_REGION: ${CALCOM_GCP_REGION:-us-central1}"
NOT_SET の場合:シェルで環境変数をエクスポートする(env-setup.md を参照)か、セットアップコマンドを実行してください。
Step 2:GCP 認証を確認する
gcloud auth list --filter="status=ACTIVE" --format="value(account)" 2>/dev/null
Step 3:Supabase の設定を確認する
echo "SUPABASE_PROJECT_REF: ${SUPABASE_PROJECT_REF:-NOT_SET}"
echo "SUPABASE_DB_URL_REF: ${SUPABASE_DB_URL_REF:-NOT_SET}"
Step 4:Cal.com のシークレットを確認する
echo "CALCOM_NEXTAUTH_SECRET_REF: ${CALCOM_NEXTAUTH_SECRET_REF:-NOT_SET}"
echo "CALCOM_ENCRYPTION_KEY_REF: ${CALCOM_ENCRYPTION_KEY_REF:-NOT_SET}"
echo "CALCOM_CRON_API_KEY_REF: ${CALCOM_CRON_API_KEY_REF:-NOT_SET}"
1Password の参照がすべて SET である必要があります。 シークレットは Claude Automation vault に保存されています。
デプロイ先:GCP Cloud Run
Step 1:GCP API が有効になっていることを確認する
gcloud services list --enabled \
--project="$CALCOM_GCP_PROJECT" \
--account="$CALCOM_GCP_ACCOUNT" 2>/dev/null | grep -E "run|artifact|build"
必要な API:Cloud Run、Artifact Registry、Cloud Build。
Step 2:コンテナをビルドする
# From the cal.com fork directory
cd ~/fork-tools/cal.com
# Build Docker image
docker build -t calcom-self-hosted .
Step 3:Artifact Registry にプッシュする
# Tag for Artifact Registry
docker tag calcom-self-hosted \
"${CALCOM_GCP_REGION}-docker.pkg.dev/${CALCOM_GCP_PROJECT}/calcom/calcom:latest"
# Push
docker push \
"${CALCOM_GCP_REGION}-docker.pkg.dev/${CALCOM_GCP_PROJECT}/calcom/calcom:latest"
Step 4:Cloud Run にデプロイする
# Resolve secrets from 1Password
NEXTAUTH_SECRET=$(op read "$CALCOM_NEXTAUTH_SECRET_REF")
ENCRYPTION_KEY=$(op read "$CALCOM_ENCRYPTION_KEY_REF")
CRON_API_KEY=$(op read "$CALCOM_CRON_API_KEY_REF")
DATABASE_URL=$(op read "$SUPABASE_DB_URL_REF")
gcloud run deploy calcom \
--image="${CALCOM_GCP_REGION}-docker.pkg.dev/${CALCOM_GCP_PROJECT}/calcom/calcom:latest" \
--region="$CALCOM_GCP_REGION" \
--project="$CALCOM_GCP_PROJECT" \
--account="$CALCOM_GCP_ACCOUNT" \
--platform=managed \
--allow-unauthenticated \
--port=3000 \
--memory=512Mi \
--cpu=1 \
--min-instances=0 \
--max-instances=2 \
--set-env-vars="DATABASE_URL=${DATABASE_URL}" \
--set-env-vars="NEXTAUTH_SECRET=${NEXTAUTH_SECRET}" \
--set-env-vars="CALENDSO_ENCRYPTION_KEY=${ENCRYPTION_KEY}" \
--set-env-vars="CRON_API_KEY=${CRON_API_KEY}" \
--set-env-vars="NEXT_PUBLIC_WEBAPP_URL=https://calcom-${CALCOM_GCP_PROJECT}.run.app" \
--set-env-vars="NEXT_PUBLIC_API_V2_URL=https://calcom-${CALCOM_GCP_PROJECT}.run.app/api/v2"
デプロイ先:Docker Compose(ローカル開発)
docker-compose.yml のテンプレート
version: "3.9"
services:
calcom:
image: calcom/cal.com:latest
restart: unless-stopped
ports:
- "3000:3000"
env_file:
- .env
depends_on:
database:
condition: service_healthy
database:
image: postgres:15
restart: unless-stopped
volumes:
- calcom-db:/var/lib/postgresql/data
environment:
POSTGRES_USER: calcom
POSTGRES_PASSWORD: calcom
POSTGRES_DB: calcom
healthcheck:
test: ["CMD-SHELL", "pg_isready -U calcom"]
interval: 10s
timeout: 5s
retries: 5
volumes:
calcom-db:
ローカルの .env テンプレート
DATABASE_URL=postgresql://calcom:calcom@database:5432/calcom
NEXTAUTH_SECRET=<generate-with-openssl>
CALENDSO_ENCRYPTION_KEY=<generate-with-openssl>
CRON_API_KEY=<generate-with-openssl>
NEXT_PUBLIC_WEBAPP_URL=http://localhost:3000
NEXT_PUBLIC_API_V2_URL=http://localhost:3000/api/v2
デプロイ先:Webhook Relay(Pushover 通知)
Cal.com の Webhook と Pushover の緊急アラートをつなぐ、軽量な Cloud Run サービスです。依存関係はありません(Python 標準ライブラリのみ)。
Step 1:Pushover の認証情報を確認する
echo "PUSHOVER_APP_TOKEN: ${PUSHOVER_APP_TOKEN:+SET}"
echo "PUSHOVER_USER_KEY: ${PUSHOVER_USER_KEY:+SET}"
echo "PUSHOVER_SOUND: ${PUSHOVER_SOUND:-dune}"
すべて SET である必要があります。 認証情報の設定については、pushover-setup.md を参照してください。
Step 2:Webhook Relay を Cloud Run にデプロイする
RELAY_SOURCE="$HOME/.claude/plugins/marketplaces/cc-skills/plugins/calcom-commander/scripts/webhook-relay"
gcloud run deploy calcom-pushover-webhook \
--source "$RELAY_SOURCE" \
--project="$CALCOM_GCP_PROJECT" \
--account="$CALCOM_GCP_ACCOUNT" \
--region="$CALCOM_GCP_REGION" \
--platform managed \
--allow-unauthenticated \
--set-env-vars="PUSHOVER_TOKEN=$PUSHOVER_APP_TOKEN,PUSHOVER_USER=$PUSHOVER_USER_KEY,PUSHOVER_SOUND=${PUSHOVER_SOUND:-dune}" \
--memory=128Mi \
--cpu=1 \
--min-instances=0 \
--max-instances=1 \
--timeout=30 \
--quiet
出力に表示される Service URL を控えてください。これを ~/gh/<org>/<automation-repo>/.env.launchd(デーモン用)とシェルに WEBHOOK_RELAY_URL として保存します。
Step 3:ヘルスチェックを確認する
curl -s "$WEBHOOK_RELAY_URL" | python3 -m json.tool
# Expected: {"status": "healthy", "service": "calcom-pushover-webhook"}
Step 4:Cal.com Webhook を登録する
CALCOM_API_KEY=$(op item get "$CALCOM_OP_UUID" --vault "Claude Automation" --fields password --reveal)
curl -s -X POST "https://api.cal.com/v1/webhooks?apiKey=$CALCOM_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"subscriberUrl\":\"$WEBHOOK_RELAY_URL\",\"eventTriggers\":[\"BOOKING_CREATED\",\"BOOKING_RESCHEDULED\",\"BOOKING_CANCELLED\"],\"active\":true}"
Step 5:予約をシミュレートしてテストする
curl -s -X POST "$WEBHOOK_RELAY_URL" \
-H "Content-Type: application/json" \
-d '{"triggerEvent":"BOOKING_CREATED","payload":{"title":"Test Meeting","attendees":[{"name":"Test User"}],"startTime":"2026-01-01T10:00:00Z","endTime":"2026-01-01T10:30:00Z"}}'
期待される結果:デバイスで「dune」サウンドの Pushover 緊急アラートが届きます。
Supabase データベースの管理
接続を確認する
DATABASE_URL=$(op read "$SUPABASE_DB_URL_REF")
psql "$DATABASE_URL" -c "SELECT version();"
マイグレーションを実行する
cd ~/fork-tools/cal.com
DATABASE_URL=$(op read "$SUPABASE_DB_URL_REF") npx prisma migrate deploy
1Password のシークレット参照
シークレットはすべて Claude Automation vault にあります(生体認証なしでアクセスできます)。
| シークレット | 1Password の参照 |
|---|---|
NEXTAUTH_SECRET | op://Claude Automation/<item-id>/NEXTAUTH_SECRET |
CALENDSO_ENCRYPTION_KEY | op://Claude Automation/<item-id>/CALENDSO_ENCRYPTION_KEY |
CRON_API_KEY | op://Claude Automation/<item-id>/CRON_API_KEY |
DATABASE_URL | op://Claude Automation/<item-id>/DATABASE_URL |
DATABASE_DIRECT_URL | op://Claude Automation/<item-id>/DATABASE_DIRECT_URL |
変更後のチェックリスト
- YAML frontmatter が有効である(description にコロンが含まれていない)
- トリガーキーワードが最新である
- パスのパターンで、ハードコードされたパスではなく $HOME を使用している
- 1Password の参照が特定の UUID に依存していない
実行後の振り返り
このスキルの実行後、タスクを終了する前に振り返ってください。
- 現在の場所を確認する。 — 編集する前に、この SKILL.md の正式なパスを確認してください。
- 何が失敗したか? — 原因となった手順を修正してください。
- 予想以上にうまくいったことは? — 推奨プラクティスとして取り入れてください。
- 何にずれが生じたか? — 現状に合わなくなったスクリプト、参照、依存関係を修正してください。
- 記録する。 — トリガー、修正内容、根拠を含む進化ログのエントリーを追加してください。
後回しにしないでください。次回の実行では、あなたが残した状態が引き継がれます。