GitHub Actions のセルフホストランナーの立て方と注意点:セキュリティは任せて使う
セルフホストランナーを立てること自体は、むずかしくありません。リポジトリか組織の Settings → Actions → Runners でトークンを発行し、マシンにランナーのアプリを入れて登録し、サービスとして起動すれば、runs-on: self-hosted のジョブが動きます。むずかしいのは、そのあとのセキュリティです。GitHub のセキュリティのリファレンスは、セルフホストランナーには使い捨てのクリーンな VM で動く保証がなく、信頼できないコードに一度動かれると乗っ取られたままになりうる、と書いています。
Skipbox は、その対策まで済んだセルフホストランナーです。マシンはアカウント専用で、ジョブのたびに認証情報を消し、ランナーはジョブ 1つだけのために登録し、書き込み権限のない人のコードは新しい VM で動かします。毎回クリーン をオンにすれば、すべてのジョブが新しい VM で動きます。月 6,000 円の定額で実行時間は無制限。runs-on を 1行書き換えるだけです。
GitHub が挙げている注意点
GitHub のセキュリティのリファレンスと、セルフホストランナーのドキュメントからです。
- マシンは前のジョブを覚えている。セルフホストランナーは、ジョブごとにクリーンな環境である必要がありません。前のジョブのファイル、プロセス、コンテナ、トークンが、次のジョブにそのまま残ります。
- プライベートリポジトリも例外ではない。フォークしてプルリクエストを出せる人(ふつうは読み取り権限のある人)は、ランナーの環境を侵害でき、シークレットと
GITHUB_TOKENに届きます。 - パブリックリポジトリ。だれでもプルリクエストを出せるので、セルフホストランナーは「ほぼ使うべきでない」とされています。
- 1台のランナーに、複数のリポジトリ。組織に登録したランナーは、使えるリポジトリすべてのジョブを受け取ります。1つの侵害が全体に広がるので、ランナーグループで届く範囲を区切ります。
- マシンに置いてあるもの。SSH の秘密鍵、API のトークン、社内のサービスやクラウドのメタデータサービスへの経路は、ジョブから手が届きます。
- ジョブのあとにマシンを消すだけでは足りない。ランナーが 1つのジョブしか動かさない保証がないからです。GitHub が勧めるのは、ジョブを 1つだけ動かすジャストインタイムのランナーを、自動化でクリーンな環境に立てることです。
- 承認の設定はマシンを守らない。フォークのワークフローの実行が許されると、そのコードはセルフホストランナーの上でそのまま動きます。
安全に立てるには、何が要るか
GitHub の勧めを、仕事として並べます。
| GitHub の勧め | 自分で立てたランナーでは | Skipbox では |
|---|---|---|
| ジョブ 1つだけのランナー | ジョブのたびに REST API でジャストインタイムの設定を発行し、それでランナーを起動する | どのランナーも、ジョブ 1つのためにそのジョブのラベルで登録し、終われば削除 |
| クリーンな環境 | ジョブごとに VM を作って消すか、信頼できる後片付けを自分で書く | ジョブのたびに認証情報、プロセス、コンテナ、認証情報のファイルを削除。「毎回クリーン」ならジョブごとに新しい VM |
| 外部のコードを分ける | フォーク用のマシンを別に持ち、混ざらないように振り分ける | 書き込み権限のない人のコードは、いつも新しい VM |
| マシンに余計なものを置かない | 鍵、トークン、社内ネットワークへの経路をホストから外す | 自社のネットワークの外にある VM。外からは接続できない |
| 届く範囲を絞る | リポジトリやチームごとのランナーグループ | マシンで動くのはそのアカウントのジョブだけ。個人アカウントでは、ランナーをジョブのリポジトリに登録 |
| 更新 | OS、Docker、ランナーを自分の予定で | イメージは Skipbox が更新(少なくとも月に一度) |
自分で組めば、オートスケーラーと、イメージを作る仕組みと、ランナーの置き場がもう 1つ要ります。Skipbox では、これが最初からの動きです。
Skipbox が分けているもの
アカウント専用のマシン
プランごとに、またトライアルのあいだも、アカウント専用の VM を 1台用意します。そのアカウントのジョブだけを 1つずつ動かし、ジョブのあいだも残します。Docker のイメージとビルドキャッシュ、パッケージのキャッシュ、入れたツールが残るので、次のジョブが速くなります。
ジョブが終わるたびに、Skipbox は次のことをします。
- ランナーの認証情報を消す
- ランナーのユーザーのプロセスをすべて止め、コンテナをすべて消す
- 認証情報のファイルを消す:
~/.docker/config.json、~/.npmrc、~/.git-credentials、~/.config/gh、~/.aws/credentials、~/.kube/config、~/.ssh/id_* - チェックアウト内とホームディレクトリの Git の設定にある認証情報、チェックアウトのフック、追跡されていないファイルを消す
- マシンを検査し(ディスク、パッケージ、Docker、ランナー、DNS、残ったプロセスとコンテナ)、通らなければイメージから作り直す
2026年11月13日からは、チェックアウトしたコードと Cargo のビルド結果(target/)を専用のマシンに残し、次のジョブで使います。マシンをリセット を押したときと、イメージを更新したとき(少なくとも月に一度)も、マシンを作り直します。
自分で立てたランナーと同じく、同じアカウントのジョブどうしはこのディスクを共有します。リポジトリやブランチのあいだも分けたいときは、「毎回クリーン」をオンにします。
新しい VM
次のジョブは、ほかのジョブを動かしていない新しい VM で動き、終わればディスクごと消します。
- 「毎回クリーン」がオンのときの、すべてのジョブ
- 書き込み権限のない人のコード(フォークからのプルリクエストなど)
- 専用のマシンがすべて使用中のときのジョブ
チームの実行とは、コードがそのリポジトリ自身のもので、実行を始めた人が write・maintain・admin のどれかの権限を持つものです。それ以外は外部のコードとして扱います。フォークからのプルリクエスト、フォークのコードから始まった pull_request_target や workflow_run、書き込み権限のない人の issue_comment です。プライベートリポジトリでもパブリックリポジトリでも同じ決まりです。外部のジョブはキャッシュを読めますが、書き換えられません。それでも専用のマシンに届いたジョブはステップの前に失敗させ、マシンをリセットします。
VM のまわり
- ランナー 1つにジョブ 1つ。ランナーは、ジョブ 1つのためにその都度登録します。ジョブのあとに登録が残ったランナーは削除します。
- 外からは接続できない。インターネットからジョブの VM へは接続できません。
- コードは読めない。Skipbox のアプリにリポジトリの中身を読む権限はありません。コードは、ジョブが自分の VM の中でチェックアウトします。
- ほかの会社は使わない。専用のマシンで、ほかの組織のジョブが動くことはありません。
どのランナーでも同じく、ジョブの VM にはワークフローのシークレットとそのジョブ用の GitHub のトークンが入ります。ジョブには必要なシークレットだけを渡してください。くわしくはジョブの分離のしくみにあります。
GitHub ホストランナーと比べた費用
セルフホストランナーの分数を GitHub は請求しません。Skipbox のランナーもセルフホストランナーです。
| 月の実行時間(4 vCPU) | GitHub | Skipbox S | 毎月の差額 |
|---|---|---|---|
| 10,000分 | 参考値:2026年11月10日の為替レート・1ドル=158.22円。米ドルの料金を、このレートで円に換算した概算です。 | 6,000 円 | 参考値:2026年11月10日の為替レート・1ドル=158.22円。米ドルの料金を、このレートで円に換算した概算です。 |
| 20,000分 | 参考値:2026年11月10日の為替レート・1ドル=158.22円。米ドルの料金を、このレートで円に換算した概算です。 | 6,000 円 | 参考値:2026年11月10日の為替レート・1ドル=158.22円。米ドルの料金を、このレートで円に換算した概算です。 |
| 30,000分 | 参考値:2026年11月10日の為替レート・1ドル=158.22円。米ドルの料金を、このレートで円に換算した概算です。 | 6,000 円 | 参考値:2026年11月10日の為替レート・1ドル=158.22円。米ドルの料金を、このレートで円に換算した概算です。 |
| 常時稼働 | 参考値:2026年11月10日の為替レート・1ドル=158.22円。米ドルの料金を、このレートで円に換算した概算です。 | 6,000 円 | 参考値:2026年11月10日の為替レート・1ドル=158.22円。米ドルの料金を、このレートで円に換算した概算です。 |
GitHub の額は、GitHub Team に含まれる無料分を引いたあとの請求です。自分の分数はトップページの料金計算で出せます。ログインは要りません。
移行は runs-on を 1行書き換えるだけ
jobs:
test:
runs-on: skipbox # ubuntu-latest や self-hosted から書き換える
steps:
- uses: actions/checkout@v4
- run: npm ci && npm test
- Skipbox に GitHub でログインする
- Skipbox の GitHub アプリを入れて、使うリポジトリを選ぶ
runs-onを書き換えて push する
すべてのジョブを新しい VM で動かすなら、「プランと請求」で 毎回クリーン をオンにします。
まずプライベートリポジトリのジョブで試す
カード不要で、7日間かジョブの合計 3,000分まで無料です。ジョブを 1つ runs-on: skipbox に替えて、これから守りを固めるはずだったランナーを立てずに済ませてください。
よくある質問
GitHub Actions のセルフホストランナーの立て方は? セキュリティの注意点は?
リポジトリか組織の Settings の Actions → Runners で発行されるトークン(1時間で失効)を使い、マシンにランナーのアプリを入れて登録し、サービスとして起動します。注意点は、マシンが前のジョブのファイル、プロセス、認証情報を持ち越すことと、フォークからのプルリクエストがそのマシンに届くことです。Skipbox なら立てる作業も対策も要らず、runs-on を skipbox に書き換えるだけです。
セルフホストランナーはプライベートリポジトリなら安全?
そのままでは安全とは言えません。GitHub のドキュメントは、プライベートリポジトリでも、フォークしてプルリクエストを出せる人(ふつうは読み取り権限のある人)がランナーの環境を侵害でき、シークレットや GITHUB_TOKEN に届くと注意しています。Skipbox は、マシンをアカウント専用にし、ジョブごとに認証情報を消し、ランナーをジョブ 1つだけに登録し、書き込み権限のない人のコードを新しい VM で動かします。
ジョブごとに新しい VM で動かすには?
自分で組むなら、ジョブごとにジャストインタイムのランナーを登録し、ほかのジョブを動かしていない VM で起動し、終わったら VM を消す仕組み、つまりオートスケーラーを作って運用します。Skipbox ではスイッチ 1つです。「毎回クリーン」をオンにすると、すべてのジョブが新しい VM で動き、終わればディスクごと消えます。
Skipbox はすべてのジョブを新しい VM で動かす?
「毎回クリーン」がオンなら、すべてのジョブが新しい VM で動きます。オフのときは、チームのジョブはアカウント専用のマシンで動き、Docker のレイヤーやパッケージのキャッシュを残したまま、ジョブのたびにランナーの認証情報、プロセス、コンテナ、認証情報のファイルを消します。書き込み権限のない人のコードと、専用のマシンがすべて使用中のときのジョブは、いつも新しい VM です。
フォークからのプルリクエストは、セルフホストランナーで動いてしまう?
自分で立てたランナーでは、リポジトリの設定がフォークのワークフローを許していれば動きます。GitHub は、そのコードが自分たちのインフラでそのまま実行されると警告しています。Skipbox では、フォークからのプルリクエストは専用のマシンでは動きません。新しい VM で動き、キャッシュは読めますが書き換えられません。
パブリックリポジトリでセルフホストランナーを使ってもいい?
GitHub は、パブリックリポジトリではセルフホストランナーをほぼ使うべきでないとしています。だれでもプルリクエストを出してマシンを侵害できるからです。Skipbox は、そのプルリクエストを専用のマシンに届かせないことで、パブリックリポジトリのジョブも動かします。書き込み権限のない人のコードは使い捨ての新しい VM で動き、専用のマシンで動くのはチームのコードだけです。
2026年11月14日 更新