Tutorial
12 min read
46 views

ゼロトラストCI/CD:リバーストンネルを利用した安全なセルフホストGitHub Actionsランナー構築

IT
InstaTunnel Team
Published by our engineering team
ゼロトラストCI/CD:リバーストンネルを利用した安全なセルフホストGitHub Actionsランナー構築

現代のエンジニアリングチームは、よくあるジレンマに直面しています:クラウドホストされたCI/CDランナーは高価で負荷に見合わないことも多く、しかしGitHub Actionsのようなパブリックプラットフォームをファイアウォールで保護された企業ネットワークにルーティングするのはITの悪夢のように思えます。そこに第三の道があります — それはアウトバウンド専用のリバーストンネル、エフェメラルコンテナ、そしてアイデンティティゲート認証を利用し、インバウンドポートを一つも開けずにベアメタルのパフォーマンスを実現する方法です。この記事は、そのアーキテクチャを構築するための実用的な設計図です。


「ポートを開けるだけ」の問題点

従来のセルフホストランナーのアプローチはインバウンド接続を前提としています。ローカルネットワーク上のランナーはGitHubに登録され、ジョブが送信されるのを待ち続けます。これを実現するには、GitHubがあなたのマシンに到達できる必要があり、通常はファイアウォールに穴を開けることを意味します。

この方法は、企業のセキュリティポリシーと即座に衝突します。インバウンドポートにはファイアウォールルールの変更やネットワークアーキテクチャの見直し、IP許可リストの継続的な管理が必要です。GitHubは世界中の複数のデータセンターにまたがる動的IPアドレス範囲から運用されており、それらのCIDRブロックの維持と更新は運用負荷が高く、スケールしません。

よりクリーンなモデルは、接続の方向を完全に逆にすることです。

セルフホストランナーは、HTTP(S)の長いポーリングを通じてGitHubと通信します。最大50秒間接続を開き、ジョブの割り当てを待ちます。何も来なければタイムアウトして再接続します。このトラフィックは完全にアウトバウンドで、ポート443を使用します — ブラウザがHTTPSに使うのと同じポートです。企業のファイアウォールはウェブ閲覧を許可しているため、このトラフィックも既に許可されています。例外は不要です。


リバーストンネルのアーキテクチャ

重要なポイントは、ランナーはGitHubからインバウンド接続を受け取る必要がないということです — 代わりに外に出て作業を取得します。リバーストンネルエージェントは、この利点をさらに拡張し、永続的で認証されたアウトバウンドチャネルを作り出し、Webhookやコントロールプレーンのトラフィックも必要に応じて運ぶことができます。

[ ローカルベアメタルハードウェア ]
        |
        | (Outbound TLS/QUIC on port 443)
        ▼
[ アイデンティティゲートトンネルプロキシ ]  ◄─── 相互TLS / トークン検証
        ▲
        |  (Webhook / Pollトラフィック)
        |
[ GitHub Actionsコントロールプレーン ]

この接続は、内部から開始されるため、ファイアウォールはこれを単なるHTTPSリクエストとみなします。トンネルプロキシは、トラフィックが流れる前に両端を認証し、すべてのジョブ配信はこの検証済みチャネルを通じて行われます。


アイデンティティゲートセキュリティ:トンネル以上の安全性

アウトバウンドトンネルを通じたトラフィックの送信は、それを保護する認証と同じくらい安全です。運用環境では、いくつかの層を組み合わせます:

Mutual TLS (mTLS): ランナーのクライアントとトンネルプロキシは、暗号署名された証明書を提示します。どちらも未認証のピアからの接続を受け付けません。

OIDC / OAuth2バインディング: トンネルセッションは、Okta、Google Workspace、またはGitHub組織のOIDCトークンなどの認証済みアイデンティティプロバイダーに結びつけることができ、組織に属するランナーだけがセッションを確立できます。

短命のエフェメラルトークン: GitHubにランナーを接続するための登録トークンは、各パイプライン実行の開始時にGitHub APIから動的に取得され、ジョブ完了とともに無効化されます。ディスク上に長期間有効な資格情報は存在しません。

これらの制御により、ローカルハードウェアはトンネル経由で到達可能でも、正しい暗号証明書を提示できないものには見つからず、スキャンもされず、アクセスもできません。


実際の脅威モデル(2025–2026年更新)

このインフラを構築する前に、何が起こり得るかを冷静に見極めることが重要です。

2025年11月、Shai-Huludワームは大規模な実証実験で、セルフホストランナーがGitHubの信頼されたチャネルを通じて永続的なバックドアとして武器化できることを示しました。すべてのトラフィックがgithub.comに流れるため、従来のネットワーク防御はこの脅威クラスにはほとんど無力です。GitHubのセキュリティドキュメントには明記されています:「GitHubのセルフホストランナーは、一時的なクリーンな仮想マシン上で動作する保証はなく、信頼できないコードによって永続的に侵害される可能性があります。」

以前のサプライチェーン攻撃(例:tj-actions/changed-filesアクションの汚染やCodecovの侵害)も、攻撃者がCI/CDパイプラインを標的にし、これらのパイプラインが本番インフラやクラウド資格情報、パッケージレジストリに対して特権アクセスを持つことを示しています。

この記事で説明するアーキテクチャは、これらの脅威を封じ込めるために設計されています — 無視するためのものではありません。


ステップバイステップの設計図

コンポーネント1:エフェメラルランナーコンテナ

セルフホストランナーのセキュリティの第一原則は、ホストOS上で信頼できないコードを直接実行させないことです。コンテナ化された使い捨て環境は、何か問題が起きた場合の被害範囲を限定します。

 バージョン注意: 2026年3月16日以降、GitHubはセルフホストランナーに最低バージョンv2.329.0(2025年10月15日リリース)を要求しています。これより古いバージョンは登録時にブロックされます。最新の安定版はv2.334.0です。常にactions/runnerリリースページから最新を取得してください。

FROM ubuntu:22.04

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get update  apt-get install -y \
    curl \
    sudo \
    git \
    jq \
    build-essential \
    ca-certificates \
    && rm -rf /var/lib/apt/lists/*

# 非rootユーザ
RUN useradd -m -s /bin/bash runner  
    usermod -aG sudo runner  
    echo "runner ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers

USER runner
WORKDIR /home/runner

# 特定バージョンに固定(>= v2.329.0); 最新リリースはリリースページを確認
ARG RUNNER_VERSION="2.334.0"

RUN curl -o github-runner.tar.gz -L \
    https://github.com/actions/runner/releases/download/v${RUNNER_VERSION}/actions-runner-linux-x64-${RUNNER_VERSION}.tar.gz \
    && tar xzf ./github-runner.tar.gz \
    && rm github-runner.tar.gz

COPY --chown=runner:runner entrypoint.sh /home/runner/entrypoint.sh
RUN chmod +x /home/runner/entrypoint.sh

ENTRYPOINT ["./entrypoint.sh"]

--privilegedフラグは絶対にdocker runコマンドに含めてはいけません。特権モードのコンテナは、ホストOS上のrootプロセスとほぼ同じアクセス権を持ちます。

コンポーネント2:エントリポイントスクリプト

entrypoint.shは登録、実行、クリーンアップを調整します。各呼び出し時にGitHub APIから短命の登録トークンを取得し、永続的なトークンは保存しません。

#!/bin/bash
set -e

if [ -z "$GH_OWNER" ] || [ -z "$GH_REPOSITORY" ] || [ -z "$GH_PAT" ]; then
    echo "ERROR: 必須の環境変数が不足しています。"
    exit 1
fi

echo "短命の登録トークンを取得しています..."
REG_TOKEN=$(curl -s -X POST \
    -H "Authorization: token ${GH_PAT}" \
    -H "Accept: application/vnd.github.v3+json" \
    https://api.github.com/repos/${GH_OWNER}/${GH_REPOSITORY}/actions/runners/registration-token \
    | jq -r '.token')

if [ "$REG_TOKEN" == "null" ] || [ -z "$REG_TOKEN" ]; then
    echo "ERROR: トークンの取得に失敗しました。PATの権限を確認してください。"
    exit 1
fi

./config.sh \
    --url https://github.com/${GH_OWNER}/${GH_REPOSITORY} \
    --token "${REG_TOKEN}" \
    --name "ephemeral-$(hostname)" \
    --labels "local-highperf,ephemeral" \
    --unattended \
    --replace

cleanup() {
    echo "ジョブ完了。ランナーを登録解除します..."
    REM_TOKEN=$(curl -s -X POST \
        -H "Authorization: token ${GH_PAT}" \
        -H "Accept: application/vnd.github.v3+json" \
        https://api.github.com/repos/${GH_OWNER}/${GH_REPOSITORY}/actions/runners/registration-token \
        | jq -r '.token')
    ./config.sh remove --token "${REM_TOKEN}"
}

trap 'cleanup' EXIT SIGINT SIGTERM

# --onceフラグは、1ジョブだけ受け付けて実行後に終了させる
./run.sh --once

--onceフラグは非常に重要です。これにより、ランナーは1つのジョブだけを受け付け、完了後に終了します。systemdやcronジョブと組み合わせて、コンテナを終了後に破棄し、新しいクリーンな環境を立ち上げることで、状態の持続を防ぎます。

コンポーネント3:トンネルエージェント

ランナーコンテナが準備できたら、トンネルエージェントがあなたのローカルネットワークとGitHubのコントロールプレーンを橋渡しします。Cloudflare Tunnel(cloudflared)は広く使われているオープンソースの選択肢で、Cloudflare Zero Trustアカウントと認証されたアウトバウンド接続を確立します。frpや他のエージェントも同じ論理構造に従います。

Cloudflare Tunnelの最小構成例:

tunnel: local-ci-runner-tunnel
credentials-file: /home/runner/.cloudflared/tunnel-auth.json

ingress:
  - hostname: ci-proxy.yourcompany.com
    service: http://localhost:8080
  - service: http_status:404

ホスト名ci-proxy.yourcompany.comは、Cloudflare Accessポリシーで保護されている必要があります。これにより、GitHubのドキュメント化されたIP範囲からのWebhookトラフィックだけがトンネルを通じてルーティングされ、それ以外は404を返します。

トンネルトークンは、コンテナ起動時に環境変数として渡し、イメージに埋め込まないでください:

docker run --detach \
  --restart always \
  --network runner-net \
  --name cloudflared \
  cloudflare/cloudflared:latest \
  tunnel --no-autoupdate run --token "${TUNNEL_TOKEN}"

セキュリティ強化:絶対に妥協できない制約

リバーストンネルはインバウンドの露出問題を解消しますが、ジョブ開始後に内部で悪意のあるコードが実行されるのを防ぐものではありません。運用環境では、以下の制御が必要です:

1. 強固な隔離境界

ランナーはコンテナ内で実行し、そのコンテナは可能な限り専用の仮想マシン内で動かす必要があります。Actuatedや類似サービスで使われるFirecracker microVMは、ハードウェア支援による隔離を提供します。カーネルの脆弱性を突いたコンテナの脱出があった場合でも、攻撃者は使い捨てのVM内に閉じ込められ、ホストOSやネットワークにはアクセスできません。

最低要件: - ランナーコンテナに--privilegedフラグを付けない - コンテナ内で非rootユーザを使用(上記Dockerfile参照) - ホストのファイルシステムパスを公開するボリュームマウントを行わない - 各ジョブごとにクリーンなベースイメージから再構築し、キャッシュされた状態のイメージを再利用しない

2. ネットワークのセグメント化(VLANサンドボックス化)

ホストしている物理マシンは、専用の隔離されたVLAN(開発サンドボックスやDMZセグメント)に配置し、ファイアウォールルールで以下を明示的にブロックします:

  • ランナーVLANから内部企業ネットワーク、ファイル共有、データベースクラスターへのすべてのトラフィック
  • 必要な特定ドメインへのアウトバウンドインターネットトラフィック(例:*.github.com*.githubusercontent.com、トンネル提供者のエンドポイント)

これにより、コンテナやVMの隔離層が失敗しても、侵害されたランナーが横展開に使われることを防ぎます。

3. 信頼できないプルリクエストのゲート制御

GitHubのドキュメントでは、パブリックリポジトリでのセルフホストランナーの実行は推奨されていません。外部のコントリビューターがリポジトリをフォークしプルリクエストを送ると、あなたのセルフホストランナーをトリガーする可能性があります。プライベートリポジトリでは、以下の制御を徹底してください:

  • 外部コントリビューターや初回フォークからのプルリクエストに対して、メンテナの承認を必要とする
  • 環境保護ルールやブランチ保護ルールを適用し、local-highperfランナーラベルは保護されたブランチ(mainrelease/*)からのみ呼び出せるようにする
  • ランナーは完全に信頼できないインフラとみなす。侵害されても安全な設計を心がける

4. エフェメラルランナーは絶対条件

永続的なランナーは状態を蓄積します。マルウェアバイナリをキャッシュしたり、ロ rogueプロセスを残したり、環境変数を変更したりすると、次のジョブに汚染をもたらす可能性があります。--onceフラグと破棄・再構築のループは、エフェメラルの原則を技術的に強制します。

GitHubは、「これが意図した通りに機能する保証はなく、セルフホストランナーが一つのジョブだけを実行することを保証できない」と認めています。これをスキップする理由にはなりませんが、ハードルを大きく引き上げることには変わりありません。


オートスケーリング層(2026年アップデート)

GitHubは2026年初頭に、Runner Scale Set Clientを一般公開しました。これは、Kubernetesを必要とせずにGitHub Actionsランナーのカスタムオートスケーリングを構築できるGoベースのモジュールです。Kubernetesを使わないベアメタル環境向けには、以下のようなイベント駆動のオーケストレーションが可能です: - GitHubのスケールセットAPIを通じてジョブキューイングイベントをリッスン - 利用可能なハードウェア上に新しいランナーコンテナを起動 - ジョブ完了後にコンテナを破棄

これにより、固定インフラ上での真の弾力的キャパシティが実現します。アイドル状態のハードウェアはランナーミニッツに対してコストがかからず、ビルドが実行されているときだけ容量を消費します。


2026年の価格動向と現実

2026年初頭、セルフホストランナーの経済性は変化しました。GitHubは2026年3月1日から、プライベートリポジトリ用のセルフホストランナー利用に対し$0.002/分のプラットフォーム料金を導入しました。これは、ジョブのオーケストレーションやスケジューリングを含むActionsコントロールプレーンに適用されます。この料金は、あなたのランナーがどこにホストされているかに関わらず適用されます — データセンター、AWS、または机の下のベアメタルも同様です。

パブリックリポジトリは引き続き無料です。GitHub Enterprise Serverには影響ありません。

実際には、セルフホストランナーはもはやGitHub側ではゼロコストではありません。あなたのコンピュートコストがゼロでも、月間3,000分以上の使用では、プラットフォーム料金が月額$2追加されます。ほとんどのチームにとっては微小なコストです。高負荷のCI環境では、依然としてベアメタルの方がコスト効率が良いですが、このプラットフォーム料金もコストモデルに組み込む必要があります。

また、2026年1月1日には、GitHubホストのランナー価格も約40%引き下げられ、マネージドランナーとの比較に変化が出ています。

項目 GitHubホストランナー リバーストンネル経由のベアメタル
コスト 分単位(2026年1月に約40%削減) 固定ハードウェア投資;追加コストなし
プラットフォーム料金 ランナ価格に含む プライベートリポジトリは$0.002/分(2026年3月から)
インバウンド露出 GitHubインフラ上にホスト インバウンドポート不要
ハードウェア制御 標準Tシャツサイズ 完全制御:Apple Silicon、GPUクラスター、FPGAs
隔離 管理されたエフェメラルVM 自身の責任;明示的な強化が必要
パブリックリポジトリコスト 無料 無料

実績例:macOSビルドケース

代表的な例として、iOSアプリをビルドするモバイル開発チームを考えます。2025年後半から利用可能なmacos-latest-xlargeなどのラベルを持つM2搭載のmacOSランナーは、以前のクラウドmacOSよりも圧倒的に高速です — しかし、仮想化された環境で共有リソースを使っています。

オフラインのMac Studio(M2 Ultra搭載)は、Cloudflare Tunnelを通じてセルフホストランナーとして設定されると、ネイティブのベアメタル実行を提供します。代表的なiOSアプリのビルド時間は、クラウドランナーの30〜45分から、ローカルハードウェアでは4分未満に短縮されます。年間を通じてこの差は何千時間ものエンジニアリング時間の節約につながります。

この記事で説明したアーキテクチャは、そのハードウェアをGitHub Actionsからアクセス可能にし、企業のファイアウォールの変更を必要としません。


まとめ

アウトバウンド専用のリバーストンネル、エフェメラルなコンテナ化されたランナー環境、アイデンティティゲート認証の組み合わせは、セルフホストCI/CDにおけるセキュリティとパフォーマンスの核心的な緊張を解決します:

  • インバウンドポート不要。 ランナーがすべての接続をポート443からアウトバウンドで開始します。
  • ディスク上に永続的な資格情報不要。 登録トークンは動的に取得され、即座に期限切れになります。
  • 状態の持続なし。 --onceフラグとコンテナの破棄・再構築により、各ジョブはクリーンな環境で実行されます。
  • 横展開の防止。 VLANセグメント化と明示的なファイアウォールルールにより、侵害された場合でもランナーの拡散を防ぎます。
  • コストの予測可能性。 2026年のプラットフォーム料金は多くのチームにとって小さな負担ですが、事前にモデル化しておくべきです。

 バージョンはv2.329.0以降を維持してください。2026年3月以降、古いバージョンは登録時にブロックされます。 actions/runnerリリースページを確認し、DockerfileのARG RUNNER_VERSIONを更新してください。

このアーキテクチャは意図的な設定と継続的なメンテナンスを必要としますが、計算負荷の高い作業や特殊なハードウェア要件、セキュリティポリシーによりローカル実行が求められるチームにとっては、理解され実績のある実運用の道筋です。

Continue from this article into the most relevant product guides and workflows.

Related Topics

#self-hosted CI runner tunnel, secure GitHub Actions runner, local CI/CD hardware proxy, firewall bypass DevOps, ephemeral CI/CD runners, GitLab CI local tunnel, alternative to cloud hosted runners, self-hosted runner security 2026, on-premise build runners, bare-metal CI/CD proxy, reverse proxy for GitHub Actions, identity-gated tunnels, secure webhooks for CI/CD, connecting local hardware to GitHub, hybrid CI/CD pipeline, enterprise DevOps security, Apple Silicon CI runner, custom GPU hardware build runner, docker container build runner, ephemeral build agents, zero-trust pipeline networking, tunneling for webhooks, automated build pipeline proxy, cost-effective CI/CD scaling, infrastructure as code runner, private build network, remote build executor tunnel, self-hosted runner scaling, secure reverse tunnels, cloud infrastructure cost optimization

Keep building with InstaTunnel

Read the docs for implementation details or compare plans before you ship.

Share this article

More InstaTunnel Insights

Discover more tutorials, tips, and updates to help you build better with localhost tunneling.

Browse All Articles