プロジェクトの背景
最近のプロジェクトで、オンプレミス環境でWindows Server上で動作するシステムを担当しました。
リポジトリは 1 つですが、以下の 2つの環境 へデプロイする必要がありました。
- Staging(stg)
- Production(prod)
求められた要件は以下の通りです。
- 明確で管理しやすい Continuous Deployment(CD)
- 安定したデプロイ
- サーバーのため、負荷は最小限にしたい
- オンプレミス環境で、外部からのポート開放が難しい
検討したデプロイ方法
1. 手動スクリプト(PowerShell / Batch)
- スクリプトを作成してサーバー上で手動実行
- 長期的な運用には不向き
- 人為的ミスが起きやすい
- CD の仕組みとして弱い
2. Ansible
- 理論的には非常に良い構成
- SSH が必要
- Windows Server + オンプレミス環境
- ネットワークやセキュリティポリシーの都合で SSH ポートを開けない
→ 不採用
3. GitHub Actions(クラウドランナー)
- CI/CD としては非常に便利
- オンプレミスサーバーへ SSH 接続できない
- 外部からの inbound 接続ができない
→ 現実的ではない
本質的な課題
これらの案には共通の問題がありました。
オンプレミス + Windows Server + inbound ポートを開けない
つまり、
- GitHub からデプロイをトリガーしたい
- しかし 外部からサーバーへ接続したくない
という状況です。
最終的な解決策:GitHub Actions Self-Hosted Runner
最終的に選択したのが、GitHub Actions Self-Hosted Runner です。
Runner を アプリケーションと同じサーバー上に直接インストール しました。
この構成を選んだ理由
- inbound ポートを開ける必要がない
- Runner が GitHub に対して自発的にポーリングする
- CD は軽い処理のみ(pull / build / service restart)
- サーバーでも負荷が小さい
- GitHub の公式ドキュメントがある
重要なポイントは次の通りです。
GitHub がサーバーに接続するのではなく、
サーバーが GitHub に接続しに行く
Production で Self-Hosted Runner を使う際の注意点
1. Default label を削除しないと本番に誤デプロイされる
Self-hosted runner には、デフォルトで以下の label が付与されます。
self-hosted
windows
x64
これらを削除・管理しないまま、次のように記述すると:
runs-on: self-hosted
- Production runner が空いている
- GitHub Actions のキューが空
という条件下で、本番環境で job が実行されてしまう可能性があります。
これは非常に危険です。
推奨対応:
-
runs-on: self-hostedを使わない
インストルージでdefault label 削除
./config.cmd --url https://github.com/xxx --token xxx --no-default-labels --labels production
- 環境ごとに専用 label を作成する
stagingproduction
- workflow で明示的に指定する
runs-on: production
2. Production Runner は常時起動しない
Runner は 本番サーバー上で直接動作 するため:
- 24 時間起動しっぱなしにしない
- デプロイ時のみ Windows Service を起動
- デプロイ完了後は停止
これにより: - 意図しないデプロイを防止
- 誤操作時の影響を最小化
- 本番サーバーの安定性向上
Runner の管理は以下で可能です。 - Windows Services
- PowerShell(
Start-Service,Stop-Service)
3. Production は必ず Manual Approval を入れる
Production 環境は commit トリガーで自動デプロイすべきではありません。
GitHub Actions の Environments を使うことで、
Manual Approval を簡単に設定できます。
-
productionenvironment を作成 - Required reviewers を有効化
- approve されるまで job は実行されない
environment:
name: production
これにより:
- 誤デプロイ防止
- 人による最終確認(Human Gate)
- オンプレミス環境に適した運用
が可能になります。
4. Workflow YAML で Production Runner を変更できないようにする
もう一つのリスクは、
workflow YAML を修正して
production runner に向けてしまうこと
対策案:
- Husky を使った pre-commit hook
- 以下をチェック:
- workflow 内に
runner-prodが含まれていないか -
main/releaseブランチ以外は禁止
これにより:
- workflow 内に
- 人為的ミスの防止
- デプロイフローの強制
- Production の安全性向上
まとめ
理想的な環境であれば、
クラウド、SSH、Ansible などを使う選択肢もあります。
しかし、Windows Server + オンプレミス環境 では:
GitHub Actions Self-Hosted Runner は
現実的でシンプル、かつ効果的な解決策
ただし、安全に運用するためには:
- Runner label の厳密な管理
- Runner service の制御
- Manual approval の導入
- Git レベルでのガードレール
が不可欠です。
「一番きれいな設計」よりも、
「現実の制約下で正しく動く設計」が重要だと感じました。