「コードレビューを通ったPlaybookがどの環境に入っているのかが、いつも把握できていない」
Ansibleでサーバー構成を自動化した後に訪れるのが、この「実行管理」の課題です。どれほど精密なPlaybookを書いても、実行タイミングや担当者の手作業に依存していると、環境のズレ・適用漏れ・「どのバージョンが本番に入っているか分からない」問題が繰り返し発生します。
この記事では、AnsibleをGitHub Actionsのワークフローに組み込んで「gitのPushを契機にLinuxサーバーへ自動デプロイする」仕組みを解説します。SSHキーのSecrets管理・known_hostsの安全な設定・ワークフローファイルの設計から、ステージング/本番の環境別デプロイ設計まで、実際のコードで説明します。
実行環境: Rocky Linux 9.4(管理対象ノード)、Ansible 2.16、GitHub Actions(ubuntu-24.04)
この記事のポイント
・GitHubリポジトリへのPushを契機にAnsibleを自動実行できる
・SSHキーはBase64エンコードしてGitHub Secretsで安全に管理する
・GitHub-hostedとself-hostedランナーの選定が設計の核心
・GitHub Environmentsでstaging→production承認フローを実現できる
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
手動実行が抱える限界と自動化の必要性
Ansibleは「コードとして管理できる構成管理ツール」ですが、実行タイミングを人手に委ねていると次の問題が発生します。・Gitにマージされた変更が本番に反映されないまま放置される
・誰がいつどの環境に対して実行したのかがログに残らない
・「実行忘れ」による本番/ステージング環境のズレが蓄積する
・複数のPlaybookを順序どおりに実行する手順が属人管理になる
GitHub ActionsにAnsibleの実行を委ねることで、これらをまとめて解消できます。Pushのたびに自動実行・ログ記録・成否通知まで一貫して管理できる状態が作れます。
「Playbookを書くことがゴールではなく、それが確実に適用されることがゴール」という観点で、CI/CDへの組み込みはAnsible活用の自然な次のステップです。
GitHub ActionsとAnsibleの連携設計(全体像)
GitHub ActionsからAnsibleを実行する構成は、大きく2つのパターンがあります。1. パターンA:GitHub-hostedランナー
GitHubが提供するクラウド上のランナー(ubuntu-24.04等)にAnsibleをインストールし、外部のLinuxサーバーへSSH越しにPlaybookを実行します。GitHub Push │ ▼ GitHub-hostedランナー(ubuntu-24.04) │ pip install ansible-core │ SSH鍵をSecretsから展開 ▼ SSH(port 22) │ ▼ 管理対象ノード(Rocky Linux 9.4) Playbookによる構成変更
・デメリット: SSH接続元がGitHubのIP帯になる。ファイアウォールをGitHub MetaのIPレンジに開放する必要がある。
2. パターンB:self-hostedランナー
自社のコントロールノード(Ansibleをインストール済みのLinuxサーバー)にGitHub Actionsランナーを設置します。GitHub Push │ ▼ 自社コントロールノード(GitHub Actionsランナー兼Ansibleコントロール) │ 既存のAnsible環境をそのまま使用 ▼ SSH(内部ネットワーク) │ ▼ 管理対象ノード(Rocky Linux 9.4)
・デメリット: ランナー自体の管理が追加で発生する。
プライベートクラウド・プライベートVPC環境ではパターンBが現実的です。管理対象ノードがパブリッククラウド上にあり外部SSH可能ならパターンAがシンプルです。
SSHキーをGitHub Secretsで安全に管理する手順
GitHub ActionsからSSHでAnsible管理対象ノードへ接続するには、SSH秘密鍵をワークフローに安全に渡す必要があります。1. Ansible専用のSSHキーペアを生成する
管理対象ノードへの接続に使うSSHキーは、個人鍵と分けて「Ansible CI/CD専用」で生成することを強く推奨します。鍵を分けることで、ローテーション・無効化の影響範囲を限定できます。# Ansible GitHub Actions用のSSHキーペアを生成(パスフレーズなし・ed25519推奨) $ ssh-keygen -t ed25519 -C "ansible-github-actions" -f ~/.ssh/id_ansible_gha -N "" Generating public/private ed25519 key pair. Your identification has been saved in /home/ops/.ssh/id_ansible_gha Your public key has been saved in /home/ops/.ssh/id_ansible_gha.pub The key fingerprint is: SHA256:xE7T9mKrD2qNpLb3cFvH8sWo6iYjAeZu1XnR4gTd0kM ansible-github-actions
# 管理対象ノードへ公開鍵を配布 $ ssh-copy-id -i ~/.ssh/id_ansible_gha.pub ansible-user@192.0.2.10 /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/home/ops/.ssh/id_ansible_gha.pub" /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s) Number of key(s) added: 1
2. 秘密鍵をBase64エンコードしてGitHub Secretsに登録する
秘密鍵をそのままGitHub Secretsに貼り付けると、改行が失われて正しく展開できない場合があります。Base64エンコードして1行にまとめるのが確実な方法です。# 秘密鍵をBase64エンコード(改行なしで出力) $ base64 -w 0 ~/.ssh/id_ansible_gha LS0tLS1CRUdJTiBPUEVOU1NIIFBSSVZBVEUgS0VZLS0tLS0KYjNCbGJuTnphQzFyWlhrdGRqRUFBQUFBQ...(省略)
GitHub Actionsワークフローファイルの設計と書き方
リポジトリのルートに `.github/workflows/deploy.yml` を作成します。name: Ansible Deploy on: push: branches: - main jobs: deploy: runs-on: ubuntu-24.04 steps: - name: Checkout repository uses: actions/checkout@v4 - name: Install Ansible run: | pip install --quiet "ansible-core==2.16.*" - name: Setup SSH key env: SSH_PRIVATE_KEY: ${{ secrets.ANSIBLE_SSH_KEY }} run: | mkdir -p ~/.ssh chmod 700 ~/.ssh echo "$SSH_PRIVATE_KEY" | base64 -d > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 - name: Setup known_hosts run: | ssh-keyscan -H "${{ secrets.TARGET_HOST }}" >> ~/.ssh/known_hosts - name: Run Ansible Playbook run: | ansible-playbook \ -i inventory/production.ini \ -u ansible-user \ --private-key ~/.ssh/id_ed25519 \ site.yml
PLAY [webservers] ************************************************************** TASK [Gathering Facts] ********************************************************* ok: [192.0.2.10] TASK [nginx : Install nginx] *************************************************** ok: [192.0.2.10] TASK [nginx : Deploy nginx config] ********************************************* changed: [192.0.2.10] RUNNING HANDLER [nginx : restart nginx] **************************************** changed: [192.0.2.10] PLAY RECAP ********************************************************************* 192.0.2.10 : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
GitHub-hostedランナーとself-hostedランナーの使い分け
どちらを選ぶかは以下の基準で判断します。| 判断軸 | GitHub-hosted | self-hosted |
|---|---|---|
| 管理対象ノードの場所 | パブリッククラウド・外部SSH可能 | オンプレミス・プライベートVPC |
| SSH接続元IP | GitHubのIPレンジ(変動あり) | 固定IP(自社サーバー) |
| ランナー管理コスト | 不要 | 自社で管理が必要 |
| Ansible環境 | 毎回pip installで用意 | 既存環境をそのまま利用 |
# Rocky Linux 9.4 上でのself-hostedランナーセットアップ例 $ mkdir actions-runner && cd actions-runner $ curl -o actions-runner-linux-x64-2.319.1.tar.gz -L \ https://github.com/actions/runner/releases/download/v2.319.1/actions-runner-linux-x64-2.319.1.tar.gz $ tar xzf ./actions-runner-linux-x64-2.319.1.tar.gz $ ./config.sh --url https://github.com/ORG/REPO --token AXXXXXXX $ sudo ./svc.sh install $ sudo ./svc.sh start # サービス状態を確認 $ sudo ./svc.sh status * actions.runner.ORG-REPO.hostname.service - GitHub Actions Runner (ORG-REPO.hostname) Loaded: loaded (/etc/systemd/system/actions.runner.ORG-REPO.hostname.service; enabled) Active: active (running)
jobs: deploy: runs-on: self-hosted
Ansible実践ハンズオンの詳細を見る >>
ステージング・本番を分けた環境別デプロイ設計
mainブランチへのPushでステージングに自動デプロイし、本番への反映はタグ付きリリース+手動承認を必要とする設計が現場でよく使われます。name: Ansible Deploy on: push: branches: - main # ステージングへ自動デプロイ tags: - 'v*' # 本番へのデプロイ(タグ付きリリース) jobs: deploy-staging: if: github.ref_type == 'branch' runs-on: ubuntu-24.04 environment: staging steps: - uses: actions/checkout@v4 - name: Setup SSH key env: SSH_PRIVATE_KEY: ${{ secrets.ANSIBLE_SSH_KEY }} run: | mkdir -p ~/.ssh && chmod 700 ~/.ssh echo "$SSH_PRIVATE_KEY" | base64 -d > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 ssh-keyscan -H "${{ secrets.STAGING_HOST }}" >> ~/.ssh/known_hosts - name: Install Ansible run: pip install --quiet "ansible-core==2.16.*" - name: Deploy to staging run: | ansible-playbook -i inventory/staging.ini -u ansible-user \ --private-key ~/.ssh/id_ed25519 site.yml deploy-production: if: github.ref_type == 'tag' runs-on: ubuntu-24.04 environment: production # GitHub Environmentsで手動承認を設定 steps: - uses: actions/checkout@v4 - name: Setup SSH key env: SSH_PRIVATE_KEY: ${{ secrets.ANSIBLE_SSH_KEY }} run: | mkdir -p ~/.ssh && chmod 700 ~/.ssh echo "$SSH_PRIVATE_KEY" | base64 -d > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 ssh-keyscan -H "${{ secrets.PRODUCTION_HOST }}" >> ~/.ssh/known_hosts - name: Install Ansible run: pip install --quiet "ansible-core==2.16.*" - name: Deploy to production run: | ansible-playbook -i inventory/production.ini -u ansible-user \ --private-key ~/.ssh/id_ed25519 site.yml
よくあるエラーと対処法
【エラー1】Host key verification failed.
known_hostsにホストが登録されていない場合に発生します。`ssh-keyscan` のステップがSSH接続より前に配置されているか確認します。UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Host key verification failed.", "unreachable": true}
【エラー2】Permission denied (publickey)
秘密鍵のデコードに失敗しているか、公開鍵が管理対象ノードの `~/.ssh/authorized_keys` に入っていない場合に発生します。# ローカルでBase64デコードを検証(先頭行の確認) $ cat ~/.ssh/id_ansible_gha | base64 -w 0 | base64 -d | head -1 -----BEGIN OPENSSH PRIVATE KEY-----
【エラー3】Could not connect to target host
ファイアウォールでSSH(port 22)が遮断されている場合に発生します。パターンA(GitHub-hostedランナー)の場合、GitHub MetaのIPレンジ(`curl https://api.github.com/meta` で取得可能)を許可リストに追加します。パターンB(self-hostedランナー)への切り替えも有効な対処です。本記事のまとめ
| やりたいこと | 設計ポイント |
|---|---|
| GitHub Pushで自動デプロイ | on.push.branches でブランチを指定する |
| SSH秘密鍵の安全な受け渡し | base64エンコードしてGitHub Secretsに登録する |
| known_hostsの事前設定 | ssh-keyscan をSSH接続より前のステップで実行する |
| ステージング/本番の分離 | branchとtagでjobを分け、GitHub Environmentsで制御する |
| 外部アクセス不要の構成 | self-hostedランナーをコントロールノードに設置する |
| 本番デプロイの承認制御 | GitHub EnvironmentsのRequired reviewers機能を使う |
Ansible実践ハンズオンの詳細を見る >>
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:AnsibleのマルチステージInventory設計|staging・productionのgroup_vars分離とホストパターンによる環境切り替え実践
- この記事の属するカテゴリ:Ansibleへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます