DESIGN / CODE / INFRA / AI

解説

GitHub ActionsのSecretsとVariablesはどう分ける?デプロイ設定を安全に管理する

GitHub ActionsのSecrets・Variables・envの役割を整理。登録範囲の違い、値を表示しない未設定チェック、設定が反映されないときの確認手順をサンプル付きで紹介するよ。

GitHub ActionsのSecretsとVariablesはどう分ける?デプロイ設定を安全に管理する

GitHub Actionsでデプロイを設定すると、「接続先のURLもSecretsに入れる?」「Variablesに鍵を書いても同じ?」と迷うことがあるよね。

まずは、秘密にする必要がある値をSecrets、公開されても困らない設定値をVariablesに分けよう。そのうえで、どの範囲に登録し、workflowからどう読み込むかをそろえると、設定ミスを探しやすくなるよ。

Secrets・Variables・envは役割が違う

仕組み 主な用途 workflowでの参照例
Secrets SSH秘密鍵、APIキー、パスワードなど ${{ secrets.DEPLOY_SSH_KEY }}
Variables 公開サイトのURL、ビルド対象名など、秘密ではない設定 ${{ vars.SITE_URL }}
env jobやstepで使う環境変数に値を渡す Bashでは$SITE_URL

SecretsとVariablesは登録先、envは実行時の受け渡し方、と分けて考えると整理しやすいね。envに書いたから秘密になるわけではないよ。値をworkflowへ直接書けば、その値はリポジトリのファイルに残る。

Variablesは機密情報の保管先ではなく、Secretsのようなログの自動マスクを前提にしない。公開URLでも社内の構成が分かる値など、公開したくない事情があればSecrets側へ分けよう。

公開設定はVariables、認証情報はSecretsに登録し、必要なstepのenvへ渡す関係図

設定の保管先と、runnerで使う環境変数を分けて描いた整理図。値の暗号化方式や通信経路そのものを表した図ではないよ。

まずはRepositoryから設定する

リポジトリの Settings → Secrets and variables → Actions を開くと、SecretsとVariablesのタブがある。

今回の例では、SecretsにDEPLOY_SSH_KEY、VariablesにSITE_URLを登録する。URLの例はhttps://example.com。鍵には実際の接続で使う秘密鍵を登録するけれど、記事やIssue、workflowの本文には貼らないでね。

SecretsにはOrganization、Repository、Environmentという登録範囲がある。最初はRepositoryに集めると場所を把握しやすい。ステージングと本番で鍵を分けたい場合は、Environmentを使い、job側のenvironmentと対応させよう。

同じ名前のSecretが複数の範囲にあると、EnvironmentがRepositoryより優先される。Repository側の鍵を更新したのに古い鍵が使われるときは、同名のEnvironment secretが残っていないか確認したいね。Environmentの保護ルールや利用可能な機能は、契約・リポジトリの公開範囲にもよるので、使う前に自分の条件で確認しよう。

envに渡して、値を出さずに未設定を検出する

以下は、登録した値をstepの環境変数として受け取り、設定があるか確認する小さな例だよ。SITE_URLはVariables、DEPLOY_SSH_KEYはSecretsに登録してから使う。

name: Check deploy configuration

on:
  workflow_dispatch:

permissions:
  contents: read

jobs:
  check:
    runs-on: ubuntu-24.04
    steps:
      - name: Check required configuration
        shell: bash
        env:
          SITE_URL: ${{ vars.SITE_URL }}
          DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
        run: |
          set -euo pipefail
          test -n "$SITE_URL" || {
            echo 'SITE_URL is not configured'
            exit 1
          }
          test -n "$DEPLOY_SSH_KEY" || {
            echo 'DEPLOY_SSH_KEY is not configured'
            exit 1
          }
          echo 'Required configuration is present'

Secretが未設定なら、${{ secrets.DEPLOY_SSH_KEY }}の参照結果は空文字列になる。そこで、値そのものではなく「空ではないか」を調べる形にしているよ。

このサンプルは設定の存在を確かめるところまで。鍵の形式、接続先のホスト鍵、接続権限、デプロイ先の応答は別に検証する。実際のSSH接続では、ホスト鍵の照合を省略せず、使用する鍵やポートも確認しよう。

サンプルで確かめたこと

上のYAMLを読み取り、Bash部分を構文確認したうえで、環境変数を空にした場合と、架空のテスト文字列を渡した場合を実行した。両方未設定、URLだけ設定、鍵だけ設定では終了コード1。両方を設定した場合だけ終了コード0になり、渡したテスト文字列は標準出力・標準エラーに出なかったよ。

同じYAMLはダウンロード用サンプルでも用意している。手元のBash確認と、GitHub上でSecretを注入して実行することは別の確認なので、自分のリポジトリでも手動実行して確かめよう。

ログに出さないことも設計に含める

GitHubはSecretsをログでマスクするけれど、値を加工した結果や、想定外の出力まで常に隠れると考えないようにしよう。

  • echo "$DEPLOY_SSH_KEY"で値を表示して確認しない。
  • envやprintenvで環境変数を丸ごと出力しない。
  • set -xで秘密値を含むコマンドをトレースしない。
  • コマンドライン引数へ秘密値を直接渡すより、そのツールが対応する環境変数・標準入力などを使う。
  • 鍵ファイルが必要なら権限を絞り、使い終えた一時ファイルを削除する。

問題を調べるときは、変数名、登録範囲、未設定かどうか、接続のどの段階で止まったかを記録すると、値を見せずに切り分けられるよ。認証情報が漏れた可能性がある場合は、ログから隠すだけでなく、発行元で失効・交換まで行おう。

「登録したのに使えない」ときの確認順

確認すること 見直す場所
名前・参照先が一致している? secrets.DEPLOY_SSH_KEYとvars.SITE_URLの取り違え、綴り
同名の古いSecretがある? Organization・Repository・Environmentの登録範囲
対象Environmentを指定した? jobのenvironmentとEnvironment secrets
どのイベントで動いた? forkからのpull request、Dependabot等のSecret提供条件
workflowを呼び出している? 再利用可能workflowへのSecretsの受け渡し
登録後の実行を確認した? 新しいrunでの注入と、失敗したstep

通常、forkからのpull requestには、GITHUB_TOKENを除くSecretsは渡されない。Dependabotを起点とする実行や再利用可能workflowにも、それぞれ提供・引き継ぎの条件がある。空だったからといって、鍵をYAMLへ直書きして回避しないでね。

また、Secretsをif:の条件式から直接参照することはできない。必要なら公式資料に沿って環境変数へ渡して条件を組むか、上の例のようにstep内で未設定を確認する方法を選ぼう。

設定を変えたら、新しい実行で確かめよう

Organization・Repository secretsはworkflowがキューに入るとき、Environment secretsはそのEnvironmentを使うjobの開始時に読み取られる。値を登録・更新したら、新しい手動実行で結果を確認すると状況を整理しやすいね。

最後は「Secretの登録ができた」だけで終わらず、設定確認、接続、デプロイ、公開先の応答まで順番に確認しよう。Git管理対象から外しただけのファイルの扱いは、.gitignoreと追跡済みファイルの違いも参考にしてね。Docker側の設定が反映されない場合は、Composeの.envとenv_fileの違いと分けて確認すると、原因を追いやすくなるよ。

参考・出典

みんなのコメント 0

感想や、試してみたことを聞かせてね。コメント・返信は承認後に公開されます。

最初のコメントをどうぞ。