GitHub ActionsをRaspberry Piのセルフホストランナーへ切り替えた

CI の実行先を 1 行変えた後、checkジョブは Raspberry Pi 上で 114 秒かけて完走しました。GitHub 側が記録したランナー名はpi-hermes-hibanasです。18 ステップはすべて成功しています。
2026 年 9 月 30 日、hibanas.net の CI を GitHub-hosted のubuntu-latestから、手元の ARM64 セルフホストランナーへ切り替えました。私は AI エージェントへ仕事を任せるほど、実行場所を曖昧にしない方がよいと考えています。ジョブ名が同じでも、ホストが変われば更新、ディスク、秘密情報の扱いが変わるためです。
前回完了時から変わったこと
| 時点 | runs-on | 実行場所の管理 |
|---|---|---|
| 前回完了時 | ubuntu-latest | GitHub-hostedの一時VMです |
| 今回完了後 | [self-hosted, linux, arm64, hibanas] | 自分で管理するRaspberry Piです |
変更は.github/workflows/ci.ymlの 1 行だけです。PR #131 は 1 追加、1 削除で、2026 年 9 月 30 日 1 時 56 分に main へ入りました。その後の push ジョブで、実行先と完走を確認しました。
読み飛ばせる章: すでにセルフホストランナーを登録済みなら、「4ラベルで1台へ絞る」から読めます。ランナーの新規登録手順は扱いません。
なぜ実行先をラベルで固定したのか
セルフホストランナーは、GitHub-hosted ランナーと違ってジョブごとのクリーンな VM ではありません。OS と導入ソフトの更新も利用者側の責任です。既存のマシンを使える一方で、前のジョブが残したファイルやキャッシュも管理対象になります。
だから、単にself-hostedだけを指定しませんでした。OS、CPU アーキテクチャ、用途の 4 条件をすべて満たすランナーへ絞っています。GitHub の仕様では、配列に並べたラベルは累積条件です。1 つでも合わないランナーは候補になりません。
[push / pull request]
│
▼
[GitHub Actions: check]
│ runs-onの4条件
├─ self-hosted
├─ linux
├─ arm64
└─ hibanas
│
▼
[pi-hermes-hibanas]
│
├─ pnpm install
├─ frontmatter / textlint
├─ Astro build
└─ smoke test
個人的には、hibanasという用途ラベルが重要です。linuxとarm64だけでは、同じ構成の別ランナーへ記事サイトのジョブを流せます。用途を 1 語加えると、ハードウェア条件と運用上の所有範囲を分けられます。
用語をそろえる
| 用語 | この回での意味 |
|---|---|
| GitHub-hostedランナー | GitHubが用意し、ジョブごとに新しいVMで動く実行環境です |
| セルフホストランナー | 利用者が用意して管理するGitHub Actionsの実行環境です |
runs-on | ジョブを受け取れるランナーの条件を書くYAMLキーです |
| デフォルトラベル | self-hosted、OS、CPU構成など、登録時に付くラベルです |
| カスタムラベル | 用途や機材を区別するために利用者が付けるラベルです |
| ARM64 | 今回のRaspberry Piが使う64ビットARMアーキテクチャです |
4ラベルで1台へ絞る
main に入った本番 YAML では、checkジョブの実行先を次のように指定しています。
jobs:
check:
runs-on: [self-hosted, linux, arm64, hibanas]
実際のコミット差分を確認しました。
git show --stat --oneline 5445e3273e847f4f963c4b50159d7160e5ddf1dc
5445e32 ci: run check job on Pi self-hosted runner (#131)
.github/workflows/ci.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
差分はubuntu-latestを 4 ラベルの配列へ置き換えただけです。checkout、Node 22、pnpm、Astro build などの手順は変えていません。移行時に実行先と処理内容を同時に変えると、失敗原因を分けにくくなるためです。
GitHubが記録した実行先を確認する
ワークフローが緑色でも、想定した機材で動いたとは限りません。実行結果の job API から、ランナー名とラベルを読みます。
gh api repos/dicekanbe/hibanas-net/actions/jobs/109519562376 \
--jq '{name,status,conclusion,runner_name,labels,started_at,completed_at}'
{
"completed_at": "2026-09-29T17:00:19Z",
"conclusion": "success",
"labels": ["self-hosted", "linux", "arm64", "hibanas"],
"name": "check",
"runner_name": "pi-hermes-hibanas",
"started_at": "2026-09-29T16:58:25Z",
"status": "completed"
}
開始から完了までは 114 秒です。runner_nameと 4 ラベルが、YAML の狙いと一致しました。時刻は GitHub API が返した UTC です。
次に、同じコミットの run を確認しました。
gh run list --repo dicekanbe/hibanas-net \
--commit 5445e3273e847f4f963c4b50159d7160e5ddf1dc \
--json databaseId,status,conclusion,url
[
{
"conclusion": "success",
"databaseId": 36601441959,
"status": "completed",
"url": "https://github.com/dicekanbe/hibanas-net/actions/runs/36601441959"
},
{
"conclusion": "success",
"databaseId": 36601361058,
"status": "completed",
"url": "https://github.com/dicekanbe/hibanas-net/actions/runs/36601361058"
}
]
同じ merge commit に 2 件の push run があり、どちらも成功しています。少なくとも切り替え直後の 1 回だけ偶然通った状態ではありません。
緑になった後も残る管理
今回わかったのは、ARM64 の Raspberry Pi で現在の CI が通ることです。将来のすべての実行を保証する結果ではありません。
セルフホストランナーでは、次の項目をこちらで持ちます。
- OS と導入ソフトを更新します
- ジョブ間で残る作業ファイルとキャッシュを掃除します
- 空き容量と停止状態を監視します
- workflow へ渡す権限と秘密情報を絞ります
- 外部から来る PR で任意コードを動かす範囲を決めます
特に公開リポジトリでは、未信頼の PR コードを常設機で動かす設計を軽く扱えません。GitHub もセルフホストランナーを使う公開リポジトリへの注意を示しています。CI が通ることと、安全に常用できることは別です。
よくあるエラー
| 症状 | 確認する場所 | 対応 |
|---|---|---|
ジョブがQueuedのままです | runs-onとランナー側のラベルです | 大文字小文字を含め、4ラベルがすべて一致するか確認します |
| 別の機材で動きます | job APIのrunner_nameです | 用途ラベルを追加し、候補を分けます |
| Nodeのセットアップで止まります | Setup Nodeステップです | ARM64とNode 22に対応するランナー環境か確認します |
| 何回か通った後に失敗します | ディスク使用量とtool cacheです | 作業ディレクトリとキャッシュの増加を計測します |
| PRだけ危険な処理を実行します | workflowのtriggerと権限です | 未信頼コードへ秘密情報や常設機の権限を渡さない設計にします |
| 緑だが実行先が不明です | job APIのrunner_nameとlabelsです | runの色だけで判断せず、実行先も記録します |
今回の到達点
1 行の変更で、hibanas.net のcheckジョブは Raspberry Pi へ移りました。ラベルだけでなく、job API でpi-hermes-hibanasを確認し、18 ステップの成功まで追えています。
私なら次は、成功率より先にディスク残量とキャッシュ増加を測ります。セルフホスト化の価値は、自分の機材で動いた瞬間ではなく、翌週も同じ条件で動かせるかに出るからです。
一次情報
| 出典 | 確認した内容 |
|---|---|
| PR #131 | runs-onを1行変更したPRとmerge commitです |
| GitHub Actions run 36601441959 | 切り替え後のpushジョブが成功した実行記録です |
| GitHub Docs: Using self-hosted runners in a workflow | デフォルトラベル、カスタムラベル、累積条件を確認しました |
| GitHub Docs: Self-hosted runners | 更新責任、費用、ジョブごとにクリーンではない点を確認しました |
| GitHub Docs: Secure use reference | 最小権限、秘密情報、未信頼入力の扱いを確認しました |
