はじめに
GitHub Actionsでpush時に自動テストを回したいものの、テスト対象が社内・自宅サーバーなど外部からアクセスできない環境に依存している場合、GitHub側が用意するクラウド実行環境(GitHub-hosted runner)だけでは完結しないことがあります。このようなケースで使えるのが セルフホストランナー(self-hosted runner) です。本記事では、その基本的な仕組みとセットアップ、特に注意すべきセキュリティ設計を整理します。
セルフホストランナーとは
セルフホストランナーは、GitHub Actionsのジョブを実行するマシンを、GitHubのクラウド環境ではなく自分で用意・管理する仕組みです。実行環境は自分の管理下にあるコンテナ・VM・物理マシンなどで、そこにランナー用のソフトウェアを常駐させておきます。
通信の向きに注目する
セルフホストランナーの重要な特徴は、ランナー側からGitHubへアウトバウンド接続してジョブを取得しにいくという通信方向です。GitHub側からランナーへインバウンド接続する必要はありません。そのため、外部からのポート開放が一切不要な、閉じたネットワーク環境内のマシンでもランナーとして機能させられます。
セットアップの基本的な流れ
- GitHub側で、リポジトリ(またはOrganization)の「Settings → Actions → Runners」からランナー登録用のトークンを発行する
- ランナーソフトウェア(GitHub公式配布のバイナリ)を実行環境にダウンロードし展開する
- 取得したトークンを使って
config.sh(Windowsではconfig.cmd)を実行し、対象リポジトリとランナーを紐づける - 常駐サービスとして登録する(Linuxの場合
svc.sh install→svc.sh startでsystemdサービス化できる) - ワークフローファイル(
.github/workflows/*.yml)のruns-onに、GitHub-hosted runnerのラベル(ubuntu-latest等)ではなく、登録時に指定した独自ラベル(self-hostedや任意のカスタムラベル)を指定する
セキュリティ上、最も重要な注意点
GitHub公式ドキュメントが強く警告している最大の注意点は、publicリポジトリでセルフホストランナーを使わないことです。
publicリポジトリでは、誰でもPull Requestを送ることができます。もしそのPRに含まれるワークフロー変更・コードがセルフホストランナー上で実行されてしまうと、外部の第三者に自分の管理するマシン上で任意のコードを実行されてしまうことになります。これは非常に大きなセキュリティリスクであり、公式ドキュメントでも明確に非推奨とされています。privateリポジトリであれば、そのリポジトリへのアクセス権を持つ信頼できる人物のコードしか実行されないため、リスクは大きく下がります。
その他のセキュリティ設計のポイント
| 観点 | 推奨される設計 |
|---|---|
| スコープの最小化 | ランナーをOrganization全体で使い回すのではなく、リポジトリ単位で登録する。1つのランナーが乗っ取られたときの影響範囲を限定できる |
| 実行ユーザー | ランナーはroot権限ではなく、専用の非rootユーザーで実行する |
| 本番環境への接続経路 | ランナーが動くマシンに、本番サーバーへのSSH鍵やDB接続情報などの機密情報を置かない。テストは使い捨てのインメモリDB等で完結させ、本番環境には一切触れさせない設計にする |
| Secretsの利用 | ワークフローで機密情報(APIキー等)が不要なら、GitHub Actionsのsecrets機能自体を使わない選択肢も検討する |
| JIT(Just-In-Time)ランナー | より高度な対策として、1ジョブ実行ごとに使い捨てられる一時的なランナーをAPI経由で生成する方式もある(登録の永続性そのものを減らせる) |
まとめ
| 項目 | 内容 |
|---|---|
| セルフホストランナーとは | 自分で用意した環境でGitHub Actionsのジョブを実行する仕組み |
| 通信の向き | ランナー側からGitHubへアウトバウンド接続。インバウンドのポート開放は不要 |
| 最重要の注意点 | publicリポジトリでは使わない(外部PRによる任意コード実行のリスク) |
| その他の対策 | リポジトリ単位のスコープ限定、非rootユーザーでの実行、本番環境への接続経路を持たせない設計 |