
GitHub ActionsでCI/CDパイプラインを構築する際、APIキーやデプロイ用の認証情報、接続先ホスト名、環境ごとの設定値をワークフローファイル(.github/workflows/*.yml)に安全に組み込む手法は必須の知識です。
しかし、いざ設定しようとすると「secrets と vars はどう使い分ければよいのか」「環境変数 env とコンテキスト参照 ${{ ... }} の違いは何なのか」「Environment secretsによる本番デプロイ保護はどう設計すべきか」といった疑問に直面することが少なくありません。
この記事では、GitHub Actionsにおける「Secrets(暗号化シークレット)」「Variables(設定変数 vars)」「Environment Variables(env)」の役割の違いを比較表で明確に整理した上で、具体的な登録手順、ワークフロー内での安全な参照方法、48KB制限やログマスクの注意点までを詳しく解説します。
この記事で行うこと
secrets(暗号化機密情報)とvars(平文設定変数)の決定的な違いを理解します- GitHub Web UIおよびGitHub CLI(
gh secret/gh variable)での登録手順を学びます - ワークフローファイル内での参照記法(
${{ secrets.* }}/${{ vars.* }}/env:)を整理します - Repository(リポジトリ単位)と Environment(環境単位・承認制)のスコープ設計を把握します
- 自動生成される
GITHUB_TOKENのパーミッション制御(permissions:)と漏洩防止策を理解します
前提条件・対象読者
- 対象サービス:GitHub Actions(パブリック・プライベートリポジトリ問わず)
- 前提知識:YAML形式の基本的な読み書き、Git/GitHubの基本操作
- 必要な権限:対象リポジトリの管理者権限(Settingsへのアクセス権)
- 動作確認ツール:GitHub CLI(
gh --versionにて2.50以降推奨、最終確認:2026年11月)
1. 3つの変数管理の役割分担(secrets / vars / env)
GitHub Actionsには、データを渡すための仕組みが大きく3種類存在します。用途を誤るとセキュリティインシデントに直結するため、まずは違いを把握しておきましょう。
| 項目 | Secrets(暗号化シークレット) | Variables(設定変数 vars) | Workflow env(環境変数) |
|---|---|---|---|
| 格納先 | GitHubの暗号化データベース | GitHubの設定データベース | YAMLファイル内の env: ブロック |
| 暗号化 | ⭕ 強力に暗号化(閲覧不可) | ❌ 暗号化なし(平文) | ❌ リポジトリ内で平文公開 |
| ログの自動マスク | ⭕ 自動的に * で隠蔽 | ❌ 平文でそのまま出力 | ❌ 平文でそのまま出力 |
| 主な用途 | APIキー、アクセストークン、SSH鍵、本番DBパスワード | 接続先エンドポイントURL、ポート番号、デバッグフラグ | ジョブやステップ単位の一時的なローカル変数定義 |
| 参照構文 | ${{ secrets.MY_SECRET }} | ${{ vars.MY_VAR }} | $MY_ENV または ${{ env.MY_ENV }} |
| 最大サイズ | 48KB / 項目 | 48KB / 項目 | なし |
最も重要な原則は「外部に漏れては困る機密情報はすべて secrets に預け、エンドポイントなどの公開可能な設定値は vars に預ける」という点です。
2. Secrets(暗号化シークレット)の設定と使い方
APIキーやデプロイ先サーバーの認証トークンを登録し、ワークフローで安全に呼び出す手順です。
手順1:Web UIからSecretsを登録する
- GitHubのリポジトリページを開き、上部メニューの「Settings」タブをクリックします。
- 左サイドバーの「Security」セクションにある「Secrets and variables」を展開し、「Actions」を選択します。
- 「Secrets」タブが選択されていることを確認し、「New repository secret」ボタンをクリックします。
- 「Name」にシークレット名(例:
AWS_ACCESS_KEY_IDやSLACK_WEBHOOK_URL)を入力します。 - 「Secret」に実際のトークン文字列を貼り付け、「Add secret」をクリックします。
※命名規則:シークレット名には英数字とアンダースコア(_)のみ使用可能です。スペースやハイフンは使えません。また、GitHub予約語である GITHUB_ から始まる名前は登録できません。
手順2:GitHub CLI(gh)から登録する場合
コマンドラインから登録する場合は、以下のコマンドで設定できます。
# 対話形式で安全にシークレットを入力
gh secret set DEPLOY_API_KEY
# ファイルから直接登録(SSH秘密鍵などを登録する際に便利)
gh secret set SSH_PRIVATE_KEY < ~/.ssh/id_ed25519
手順3:ワークフロー内でSecretsを呼び出す
登録したSecretsは、ワークフローYAML内で ${{ secrets.<シークレット名> }} の形式で参照します。
name: Deploy Application
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Deploy to Cloud
env:
# Secretsをステップの環境変数にマッピング
API_KEY: ${{ secrets.DEPLOY_API_KEY }}
API_ENDPOINT: ${{ vars.API_BASE_URL }}
run: |
echo "Starting deployment to $API_ENDPOINT..."
curl -H "Authorization: Bearer $API_KEY" "$API_ENDPOINT/deploy"
3. Variables(vars:設定変数)の設定と使い方
「Configuration Variables(vars)」は、平文で扱える非機密情報を一元管理するための機能です。
手順1:Web UIからVariablesを登録する
- リポジトリの「Settings」→「Secrets and variables」→「Actions」を開きます。
- 「Variables」タブをクリックし、「New repository variable」をクリックします。
- 「Name」に変数名(例:
API_BASE_URLやNODE_ENV)を入力します。 - 「Value」に値(例:
https://api.example.com)を入力して保存します。
※GitHub CLIで登録する場合は gh variable set API_BASE_URL --body "https://api.example.com" を実行します。
手順2:ワークフロー内でVariablesを呼び出す
ワークフローファイル内では、${{ vars.<変数名> }} で呼び出します。
- name: Print Configuration
run: |
echo "Current Environment: ${{ vars.NODE_ENV }}"
echo "Connecting to: ${{ vars.API_BASE_URL }}"
YAMLファイルを直接書き換えずに、GitHubのWeb設定画面からURLやバージョン番号を差し替えられるため、開発環境(dev)やステージング(stg)で設定値を切り替える際に威力を発揮します。
4. スコープ設計:Repository vs Environment vs Organization
SecretsとVariablesは、適用するスコープ(範囲)によって3つの階層に分類されます。特に本番デプロイを伴うプロジェクトでは「Environment」の活用が不可欠です。
[スコープの階層と優先度]
1. Environment(環境単位:最優先・本番承認ゲート付き)
2. Repository(リポジトリ単位:標準)
3. Organization(組織単位:複数リポジトリで共通化)
1. Repository Secrets / Variables(標準)
対象リポジトリ内のすべてのワークフローからアクセスできます。単一のリポジトリで完結するプロジェクトではこれを基本とします。
2. Environment Secrets / Variables(本番デプロイ保護)
「Settings」→「Environments」で production や staging といった環境を作成し、その環境専用にSecretsを紐付けます。
- 承認機能(Required Reviewers):
production環境へのデプロイ時のみ、指定したレビュー担当者の手動承認が下りるまでワークフローを一時停止できます。 - ブランチ保護(Deployment branches):
mainブランチからの実行時のみproductionのシークレットへのアクセスを許可し、開発ブランチからの不正アクセスを防ぎます。
jobs:
production-deploy:
runs-on: ubuntu-latest
# 環境名を明示することで、その環境専用のSecretsが注入される
environment: production
steps:
- name: Deploy to Production
env:
PROD_DB_PASS: ${{ secrets.DATABASE_PASSWORD }}
run: ./deploy.sh
3. Organization Secrets / Variables(組織一括管理)
GitHub Organizationを利用している場合、複数リポジトリで共通利用するライセンスキーや監視ツールのトークンを組織レベルで1箇所に登録し、全リポジトリまたは指定リポジトリへ自動配布できます。
5. 自動生成される GITHUB_TOKEN とパーミッション制御
GitHub Actionsでは、外部からトークンを登録しなくても、実行ごとに一時的な認証トークン secrets.GITHUB_TOKEN が自動生成されます。
近年のGitHubではセキュリティ強化のため、リポジトリ作成時のデフォルト権限が「読み取り専用(Read-only)」になっています。ワークフローからコミットをプッシュしたり、リリースタグを作成したり、Pull Requestにコメントを書き込む場合は、ワークフロー内に permissions: ブロックを明示する必要があります。
name: Release Package
on:
push:
tags: [ 'v*' ]
# 必要な権限のみを最小限で付与する(最小権限の原則)
permissions:
contents: write # リリースの作成やコード変更の書き込み
pull-requests: read
issues: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create GitHub Release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: gh release create ${{ github.ref_name }} --generate-notes
6. 実務で守るべきセキュリティ注意点
1. ログの自動マスク機能に過信しない
GitHub Actionsは、${{ secrets.* }} に登録された文字列がログに出力されると、自動的に * に置き換えて隠蔽(マスク)してくれます。
しかし、以下のようなケースではマスクをすり抜けてログに平文が漏洩する危険があります。
- シークレット文字列を Base64 や URLエンコードして出力した場合
- シークレットを1文字ずつ分割して出力した場合
- 複数行のシークレットで特定の行が空行や短い記号のみだった場合
- 誤って
run: echo "KEY=${{ secrets.KEY }}"のように直接コマンド文字列へ埋め込み、シェルインジェクションやデバッグトレース(set -x)で展開された場合
機密情報は直接 run: の文字列内に展開せず、可能な限り env: ブロック経由で環境変数にマッピングして扱う設計を徹底してください。
2. ForkされたリポジトリからのPull Requestの挙動
公開リポジトリ(OSS)において、外部のコントリビューターがフォーク先から送ってきたPull Request(on: pull_request)では、安全のためリポジトリのSecretsは自動的に無効化(空文字)されます。悪意あるPRによってシークレットを外部サーバーへ送信される攻撃を防ぐための正常な防御機構です。
7. よくある質問(FAQ)
Q1. 登録したSecretの値を後から確認(表示)できますか?
いいえ、一度登録したSecretの値をGitHubの画面やAPIから確認することはできません。暗号化されて保存されるため、値を忘れた場合は新しい値で上書き(Update)して再設定する必要があります。
Q2. 複数のジョブ(Jobs)間でSecretsを共有できますか?
はい、同じワークフローファイル内であれば、各ジョブのステップから共通の ${{ secrets.* }} を参照できます。また、再利用可能ワークフロー(Reusable Workflows)を呼び出す場合は、呼び出し側で secrets: inherit と記述することで、親ワークフローのSecretsをそのまま子ワークフローへ引き継ぐことができます。
Q3. .env ファイルをGit管理せずにActionsへ渡すにはどうすればいいですか?
.env の中身全体を1つのSecret(例:DOTENV_FILE)として登録し、ワークフロー実行時に env: 経由で printenv コマンドを使ってファイルへ書き出す方法が安全で確実です。
- name: Create .env file safely
env:
DOTENV_CONTENT: ${{ secrets.DOTENV_FILE }}
run: |
printenv DOTENV_CONTENT > .env
echo "${{ secrets.DOTENV_FILE }}" のように直接展開すると、引用符や特殊文字が含まれていた場合に構文エラーやコマンドインジェクションの原因となるため、printenv を使うパターンをおすすめします。
まとめ
GitHub Actionsにおける変数の安全な設計は、CI/CDパイプラインのセキュリティと保守性を両立するための土台です。
- パスワードやトークンなどの機密情報は
secrets、URLや環境名などの設定値はvarsに分ける - 本番環境へのデプロイには
Environmentを設定し、承認フローとブランチ制限をかける GITHUB_TOKENはワークフローの先頭でpermissions:を明記して最小限の権限のみを付与する- 機密情報は
run:に直接展開せず、env:ブロックを介して環境変数として渡す
適切なスコープ設計を取り入れ、安全で堅牢な自動化パイプラインを運用してください。
本格的なサーバー運用ならVPSがおすすめ
自宅のPCで構築した環境をインターネット上に公開して本番運用するなら、初期費用無料で導入しやすい「さくらのVPS」などのクラウド環境が便利です。
PR
次に読むおすすめ記事
GitおよびGitHubの全体像や基本コマンド、チーム開発でのトラブル解決を体系的に学びたい方は、以下の完全ガイドもあわせて参考にしてください。

WSL2とDockerを使ったモダンな開発環境の構築手順については、以下の総合まとめ記事で解説しています。

