GitHub Actionsのコストを見て、自宅にCI・セキュリティ基盤を建てた

上原正吉(EarthLink Network Co., Ltd.)。Claude Codeを開発の主体に据え、20を超えるプロダクトを1人で同時に開発・運用しています。これは、その現場の実測記です。

GitHub Actionsのコストを見て、自宅にCI・セキュリティ基盤を建てた

GitHub Actionsのコストを見て、自宅にCI・セキュリティ基盤を建てた

2026 年 6 月下旬、組織の GitHub Actions が課金の上限で止まりました。PR(プルリクエスト)の CI(継続的インテグレーション。変更のたびに自動でテストを回す仕組み)チェックは毎回 2 秒で FAILURE、ログは空。同じころ、プラグインのリリース通知も Slack に届かなくなっていました。コードは 1 行も悪くありません。外部サービスが、課金を理由にある日インフラを止めたのです。

止まった Actions は、お金を払えば戻せます。ただ、払って元に戻すだけでは、同じコストが毎月続きます。開発を続ける以上、CI でテストを回すのは前提で、そこを削るつもりはありません。だから問いは「テストを減らして安くするか」ではなく、「必要なテストを、どこで一番安く回すか」でした。試算すると、GitHub Actions を使い続けるコストは無視できない額です。しかも、これから入れたいセキュリティ検査ツール(DefectDojo など)にも、動かす場所が要ります。ならば、テストもセキュリティ検査も監視も、自宅に 1 つのインフラ基盤を建てて全部そこで回すのが一番いい。そう判断して動いた記録です。当時の記録では、この基盤の monorepo(複数のリポジトリを 1 つに束ねた構成)は初コミットから約 1 か月で 330 コミット・ADR 35 本まで育ちました。

結論を先に置きます(本文の読了は約 6 分)。

  • どの run も一瞬(2 秒)で失敗し、ログが空になるのは、GitHub Actions の課金ブロックの目印だった — 外部サービスはある日、無音でインフラを止める。異常を知らせる仕組みを、止まる仕組みに依存させない
  • 止まらない基盤を自分で建て、古い方も捨てなかった — self-hosted(自前で持つ)ランナーへ切り替えつつ、GitHub Actions 側の workflow は残し、課金が戻れば無改修で戻せるようにした
  • 配布したセキュリティ用の workflow が、全 PR を止めた — gitleaks(コードに紛れ込んだ秘密情報を検出するツール)の全履歴スキャンは、健全な PR まで落とす。ゲートは「落とせる」だけでなく「正しく通す」ことも検証しないと、全員の作業を止める
  • 高可用(HA、High Availability。1 台落ちても止めない構成)の合格判定は、実機で電源やネットワークを実際に落とすこと — ユニットテストが全て緑でも、実機で落として初めて出たバグが 3 件あった

症状: どの run も一瞬で失敗し、ログが空になる

最初、私は自分たちの workflow を疑いました。しかし CI チェックは 2 件とも決まって 2 秒で FAILURE。ログを開いても中身が無い。切り分けのため、まず Slack 通知の経路を疑って webhook を直接叩きました。

# webhook 単体は生きているか? → HTTP 200 で Slack に着信した = コードは無罪
curl -s -o /dev/null -w "%{http_code}\n" -X POST "$SLACK_WEBHOOK" \
  -H 'content-type: application/json' \
  -d '{"text":"probe from local"}'
# => 200

webhook は 200。ローカルの通知スクリプトも正常。つまり通知ロジックは無罪でした。次に CI 側を gh run view で覗くと、全 run が 2 秒・空ログで終わっている。ここで像が結びます。ランナーそのものが起動していない。原因は GitHub Actions の課金ブロックで、組織の GitHub Actions が丸ごと止まっていました。どの run も、動き出す前に一瞬(2 秒)で失敗し、ログには何も残らない——この挙動そのものが、いま思えば課金ブロックの目印でした。そして厄介なのは、止まった仕組みが無音だったこと。Slack 通知という「異常を知らせる仕組み」自体が Actions 依存で沈黙していたため、気づくまでに数日かかりました。

gh run view で見ると、どの run も一瞬(2 秒)で失敗しログが空。ランナーが起動せず、課金ブロックで組織の GitHub Actions が無音で止まっていた(実端末の再構成・ホスト名/ID は匿名)

転換: hosted に依存しない CI を「コードで」建てる

外部 SaaS(サービスとして提供されるソフトウェア)の課金事情は、ある日突然インフラを止める。ならば止まらない基盤を自分で持つしかない。しかも自宅に基盤を建てるなら、CI だけを載せるのはもったいない。テストも、これから入れるセキュリティ検査も、監視も、同じ 1 つのインフラに集約する。それが一番いいと考えました。方針は「SSH(サーバーへ遠隔ログインしてコマンドを打つ仕組み)で直接コマンドを打つ運用をやめ、Ansible / Docker Compose / Terraform(いずれも構成をコードで定義して適用するツール)で自宅サーバー群を宣言的に管理する」ことにしました。既存の CI サーバー 1 台の状態を回収(harvest)して monorepo 化し、self-hosted ランナー、脆弱性台帳、Grafana/Loki/Prometheus(可視化・ログ・メトリクスを担う監視スタック)による observability(可観測性。稼働状態を外から見えるようにする仕組み)、ログ基盤までを初日〜2 日でほぼ一気に codify(コードとして定義)しました。

各プロダクトの workflow は、hosted 前提から self-hosted ランナーへ機械的に張り替えます。

# hosted (ubuntu-latest) 依存をやめ、自宅ランナーのラベルへ寄せる
jobs:
  test:
    runs-on: [self-hosted, linux, docker]   # 自前ランナー群のラベル
    steps:
      - uses: actions/checkout@v4
      - run: pnpm install --frozen-lockfile && pnpm test

Actions 側の workflow は消さずに残しました。課金が復活したら無改修で戻せるようにするためです。「壊れたら別の基盤に切り替え、壊れた方も捨てない」——これが基本方針になりました。

罠 1: 配った security workflow が組織全体の PR を止めた

移行して間もなく、共通配布していたセキュリティ用 workflow が、配布先の全 PR をブロックする事故を起こしました。当時この workflow は組織の非アーカイブ 102 リポジトリのうち 25 に配布済みで、影響範囲は広い。本命の原因は gitleaks の使い方でした。

gitleaks detect --source . は、対象を全 ref (実質 git log --all) までスキャンします。つまり過去ブランチに残ったテスト用のダミーシークレットや古い漏洩痕跡を拾って、健全な PR まで必ず落ちる。さらに self-hosted ランナーのワークスペース汚染で、「その PR には存在しないはずのファイル」を検出する誤検知も出ました。修正は、スキャン範囲を PR の差分に限定することです。

# 全 ref をスキャンして PR を必ず落とす、をやめる。差分だけ見る
gitleaks detect --source . --redact \
  --log-opts="origin/${BASE_REF}..HEAD"

念のため、PASS すべきブランチと FAIL すべきブランチの両方で E2E(端から端まで通しで動かす)検証を行う self-test の workflow まで用意しました。セキュリティゲートは「落とせる」だけでは駄目で、「正しく通す」ことも検証しないと、全員の作業を止めてしまうという学びです。

罠 2: self-hosted 化の代償で Docker ビルドが崩れる

移行にはツケもありました。hosted ランナーを全廃した直後から、複数プロダクトで CDK(コードでクラウド構成を定義するツール)の Docker bundling が動かなくなったのです。「コンテナ内ランナー + ホストの docker socket」という構成で、bundling が使うボリュームマウントが空振りする。あるプロダクトではデプロイ workflow がしばらく全滅し、ローカル Mac から手動デプロイする生活になりました。対処は、Docker bundling をランナー上の pip install --target によるローカル依存展開に置き換えることで、最終的にデプロイ workflow の 5 連続成功を実測で確認してクローズしました。基盤を移すと、その上のビルド前提が静かに崩れる。ここでも「動いた」は実測でしか確認しない方針が効きました。

HA: split-brain を起こし、その日のうちに実機で落として直す

ランナーが 1 台だと、それが落ちれば、また CI が止まります。そこで 2 ノード構成にしたのですが、ここで最大のインシデントが起きました。NVMe(高速なストレージ規格)の増設のため ci1 から ci2 へ failover したあと、ci1 を再起動すると 両ノードが active になり、同一のジョブキューを非協調に奪い合う split-brain(両系が同時に主系になってしまう状態)を深夜に観測したのです。web からのジョブ投入は ci2、実行は ci1、という気持ちの悪い状態でした。

原因は「起動系に、自分が designated active かを判定する gate が無い」という構造問題。ci1 は ci2 が active であることを知らずに自動起動していました。同日中に atomic lease fencing(古い主系を確実に締め出して二重起動を防ぐ仕組み)(ハートビート 2 秒 / TTL(有効期限) 6 秒 / grace 6 秒の fence-agent を両ノードに常駐)を実装し、実機の kill-test(電源やネットワークを実際に落とす試験)を通しました。自動 failover 18 秒、NFS(ネットワーク越しの共有ファイルシステム)分断時の self-fence + takeover 17 秒、データ差分は完全一致。ここで一番の教訓は、failover ≠ fencing です。手動 failback は忘れられる。そして、ユニットテスト(bats。bash 用のテストフレームワーク)が全緑でも、実機で電源やネットワークを実際に落として初めて出たバグが 3 件ありました(grace 中にハートビートが互いに譲り合って進まない livelock、hard-mount による I/O の無限ブロック、他系の lease を確認せず主系を奪う盲目的 steal)。合格ラインは設計文書ではなく実機の kill-test だ、と Mission に明記したのはこの日です。

Infra Portal: 全プロダクトを 1 画面に集約する

最後に、CI 状態・デプロイ昇格・複数プロバイダのコスト・バックアップ充足・サーバとローカル LLM(大規模言語モデル)の死活を 1 画面に集約する自作ポータル(Infra Portal と呼んでいます)を育てました。設計思想は 2 つあります。ひとつは「登録情報を信じず、リポジトリとライブ環境の実測で capability を自動検出する」。もうひとつは「HTTP 200 で生きていることにせず、実応答の意味を見る」。前者は自己申告のズレを、後者は「サーバは応答するが中身は壊れている」を捕まえるためです。ここでも笑える障害があり、あるノードのカードが 62 時間前で凍結していたのは、HA の非対称インストール——passive 側に必要なレポート用スクリプトを入れ忘れていた——が原因でした。両ノードを対称化して直しました。

自宅CI基盤の Infra Portal。HA の2ノード(ci1 active / ci2 standby)と、1基盤に集約したCIランナー・セキュリティ検査・監視。ノード名は伏せた再構成、HAの実測値は検証済み

まとめ — 転用できる教訓

  • テストは省けない。だからコストを見て、自前の 1 つの基盤に集約した。無料枠に収めるのではなく、回し続ける前提でコストを見積もり、CI・セキュリティ・監視を 1 台のインフラに寄せた
  • どの run も一瞬で失敗しログが空になるのは、課金ブロックの目印。外部サービスはある日、無音でインフラを止める。異常を知らせる仕組みを、止まる仕組みに依存させない
  • 基盤は自分で建て、古い方は捨てない。self-hosted へ切り替えつつ hosted の workflow は残し、無改修で戻せるようにする
  • 配布するゲートは「正しく通す」ことまで検証する。gitleaks の全 ref スキャンのように、落とせるだけのゲートは全員の作業を止めてしまう
  • HA の合格判定は実機 kill-test。failover ≠ fencing。bats 全緑でも、実機で実際に落とさないと出ないバグがある

筆者について

上原正吉。EarthLink Network Co., Ltd. でAI開発をしています。2025年からClaude Codeを開発の主体に据え、今は20を超えるプロダクトを1人で同時に開発・運用しています。この連載では、その現場で実際に起きたこと(うまくいったことも、失敗も)を、数字と一緒に書いていきます。

また、AIで業務や開発を組み替えたい会社・チーム向けに、AI活用のコンサルティングも受け付けています。ご相談は www.eln.ne.jp からどうぞ。

GitHub Actionsのコストを見て、自宅にCI・セキュリティ基盤を建てた