Vercel無料プラン、個人リポなら動くのに組織リポは取り扱いが違った話
自社プロダクトをpushしたら、Vercelから「デプロイできません」メールが来た
自社プロダクトのコードを GitHub に push して、いつものように Vercel が自動でデプロイしてくれるはずだった。なのに、しばらく経ってもプレビューURLが更新されない。メールボックスを開いたら、Vercel から英語のメールが届いていた。
要約するとこんな内容。A commit from a private repository on your GitHub organization couldn't deploy to your-org's projects, which is on the Hobby plan. Make your repository public, or Upgrade to Pro.
「GitHub の組織アカウント(Organization)配下にある private のリポは、Hobby プランじゃデプロイできないよ。public にするか、Pro にアップグレードしてね」というやつ。これ、知らないと「え、無料プランで private 動いてたじゃん?」と戸惑う取り扱い差なので、自分が出会った経緯と回避策を書き残しておく。
個人リポはOK、組織リポはNG。同じprivateでも取り扱いが違う
Vercel の Hobby プラン(無料)は、この2つで挙動が違う。
- Hobby プランでもデプロイ可能
- 追加課金なしで運用できる
- 個人開発の小さなサービス向き
- Hobby プランではデプロイ拒否
- Pro プラン(月20ドル)が必須
- 知らずに置いておくと、ある日突然止まる
つまり「個人開発でも GitHub の組織アカウントにリポを置いていると、無料の Vercel ではデプロイできない」ということ。自分の場合、ブランド整理のために npc 系のリポは組織アカウント配下に集めていたので、その流れで自社プロダクトのリポも組織配下に置いていた。これで進行がさまたげられた。
Vercel 側にもメリットがあるのは分かる。組織で複数人開発するなら Pro が筋。ただ、個人事業主が「ブランド名のGitHub組織で管理したい」だけで組織に置いているケースもあるので、ここで戸惑う人は意外と多そう。
取れる選択肢は3つ。public化が一番現実的だった
このメールを受け取ったときに考えられる選択肢は3つある。
自分は迷わず1番(public化)を選んだ。理由は2つ。
ひとつは、開発しているのが「特にコードを隠す必要のないクライアント向けアプリ」だったこと。コードを公開しても誰かが同じものをコピーして運用するハードルは高いし、それより「無料でデプロイし続けられる」ほうが事業上のメリットが大きい。
もうひとつは、Vercel の Pro 化には別の落とし穴があること。以前 v0.app を試したときに、v0 の Team プランと Vercel 本体の Pro プランが連鎖的に有効化されて、気づかないうちに月50ドルの課金が走った経験がある。「とりあえずPro」は安易に踏まないほうがいい。
Claude Codeと組んだ、public化前の機密チェック5点セット
private を public にするということは、コードが世界中の誰からでも見える状態になるということ。.env の中身、APIキー、ハードコードされたパスワードなんかが混ざっていたら一発でアウト。
自分は public化する前に、必ずチェックを通したい。とはいえどこから見ればいいか整理しきれていなかったので、Claudeに「public化前にやっておくべき機密チェックをまとめて」とお願いしてみた。返ってきたのが、以下の5点セットだった。
Claudeが出してくれたコマンドはこんな感じ。
# 1. .gitignoreで .env* が除外されているか
grep -E "^\.env|^\*\.env" .gitignore
# 2. 作業ツリーに機密候補ファイルがないか
find . -type f \( -name "*.env*" -o -name "*serviceAccount*" \
-o -name "*adminsdk*" -o -name "*.pem" -o -name "*.key" \) \
! -path "./node_modules/*" ! -path "./.git/*"
# 3. git管理下に機密候補ファイルがないか
git ls-files | grep -iE "(\.env|serviceAccount|adminsdk|\.pem$|\.key$)"
# 4. 履歴に .env* がコミットされた形跡がないか
git log --all --full-history --oneline -- ".env*"
# 5. ハードコード機密のスキャン
git ls-files | xargs grep -nE "sk-ant-|sk-proj-|ghp_|AIza[0-9A-Za-z_-]{30,}" 2>/dev/null
1〜4は「ファイルとして混入していないか」、5は「ソースコード本文にAPIキーが直書きされていないか」のチェック。地味だけど、これを通さないと安心して public 化できない、とClaudeから教わった。
ハードコードを見つけたら、その場でClaudeと一緒に差し替える
自分のケースだと、5番のスキャンでテストアカウントのパスワードがソースコードに直書きされているのを見つけた。開発初期に「とりあえず動かしたいから」とコードに埋めて、そのまま残っていたやつ。public化したら世界中に晒される。
テストアカウントだろうと本気アカウントだろうと、見つけた以上は「新パスワードを発行 → コードを書き換える → 旧パスワードを無効化」の順で差し替える。それは知っていたが、Firebase Auth で安全にやる手順までは詳しくない。これもclaudeに「Firebase Auth のパスワードをサーバー側から安全に差し替えるやり方を教えて」と頼んでみた。
返ってきたのは Firebase Auth REST API を2段使う流れ。
# 1. signIn で id_token を取得
# https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key={API_KEY}
# 2. accounts:update で新パスワードに変更
# https://identitytoolkit.googleapis.com/v1/accounts:update?key={API_KEY}
# body: {"idToken": id_token, "password": new_password}
新パスワードを発行したら、.env.local に書き出して、コード側は process.env.XXX 経由で参照するように書き換える。.env.local は .gitignore 済みであることを忘れずに確認。Node.js v20.6 以降なら --env-file フラグが使えるので、スクリプトを node --env-file=.env.local scripts/xxx.mjs みたいに呼び出せる、というところまでclaudeがまとめてくれた。
Firebase Web SDK の apiKey は public 化してOK
機密チェックをしていると、Firebase の設定オブジェクト(apiKey: "AIza..." みたいなやつ)がコードに直書きされているのを見つけることがある。これは「機密じゃない」ので差し替え不要。
Firebase Web SDK の apiKey は、本番JSバンドルから誰でも抽出できる「公開前提の識別子」。実際のセキュリティは Firestore Rules や Authentication 側で担保するのが正解。NEXT_PUBLIC_ プレフィックスで環境変数化していても、ビルド時に inline されてバンドルに焼き込まれるので、隠しても意味がない。
ここを誤解して「APIキーが見えちゃう!」と慌てると無駄な手戻りが発生する。Firebase の場合は Rules が守ってくれている前提で、apiKey は晒してOKと割り切る。
まとめ:Vercel Hobbyと組織privateリポは相性が悪い
今回の学びをまとめると、こんな感じ。
個人開発で GitHub の組織アカウントを使っている人は、最初から「無料で運用したいなら個人アカウントに置く・組織に置くならコードを公開して問題ない作りにする」のどちらかに腹を決めておくと、あとで戸惑わない。自分はこれを機に、自社プロダクト系のリポは原則 public 運用に切り替えた。
無料プランで個人開発を続けるなら、こういう「サービス側の取り扱い差」を一個ずつ越えていくしかない。地味だけど、気づいた落とし穴は次の自分と仲間を守る材料になる。