SSHでGitHub/GitLab等にアクセスしたとき、「Permission denied (publickey)」エラーで止まった経験はエンジニアなら一度は通る道です。
$ git clone git@github.com:user/repo.git Cloning into 'repo'... git@github.com: Permission denied (publickey). fatal: Could not read from remote repository. Please make sure you have the correct access rights and the repository exists.
原因はSSH公開鍵認証の設定ミスがほとんどですが、具体的にはSSH鍵の生成忘れ・GitHub未登録・ssh-agent起動失敗・SSH config設定・Windows特有のOpenSSH問題・複数アカウント混在など、10以上のパターンがあります。
この記事では、Permission denied (publickey)エラーの原因10パターンを最速診断フローから徹底解説。macOS/Windows/WSL/Linux別のセットアップ、1Password SSH Agent活用、複数鍵の使い分け、CI環境でのdeploy key設定、insteadOfによるURL自動書き換えまで網羅し、一度読めば二度と詰まらない完全ガイドに仕上げました。
この記事で学べること
- 60秒で動ける診断フローと10原因パターン早見表
- ed25519鍵の生成(2026年現在のベストプラクティス、RSAは非推奨)
- GitHub/GitLab/Bitbucket/Azure DevOps別の公開鍵登録手順
- ssh-agentの起動+OS別自動化(macOS Keychain/WSL/Windows)
- SSH config で複数アカウント/鍵を使い分け
- 1Password SSH Agent・Bitwarden・KeePassXC連携(モダン運用)
ssh -vT git@github.comのverbose診断の読み方- CI環境(GitHub Actions/CircleCI)でのdeploy key設定
insteadOfでHTTPSとSSHを透過的に切り替える運用
【最速60秒】診断フロー
エラー解決の成否は原因の正確な特定で決まります。以下の3コマンドで9割の原因が切り分けられます。
# ■ 20秒:SSH鍵の存在確認 ls -al ~/.ssh # id_ed25519.pub / id_rsa.pub があれば鍵は存在 # なければ「鍵未作成」確定 → ed25519で新規作成へ # ■ 40秒:SSH接続テスト(verbose) ssh -vT git@github.com # 最後の数行を見ると原因がほぼ分かる: # "Offering public key:" → 鍵は送っている # "Authentications that can continue: publickey" → 鍵が拒否された # "no such identity" → 鍵がagentに読み込まれてない # "Permission denied (publickey)" → GitHub側に未登録 # ■ 60秒:リモートURL方式確認 git remote -v # git@github.com:... → SSH方式(このエラー対象) # https://github.com/... → HTTPS方式(別のエラー)
ポイント:ssh -vT git@github.comの出力が最も情報量が多いです。「Offering public key: /path/to/id_xxx」という行が出ているかどうかで、鍵が送られているか/そもそも鍵を見つけていないかが一瞬で判別できます。
原因10パターン早見表
STEP 1:SSH鍵を生成する(ed25519推奨)
2026年現在の推奨はed25519(楕円曲線暗号、高速&安全)。RSAは鍵サイズ4096bit以上が必須で古い環境以外では使う理由がありません。GitHubもed25519を推奨しています。
# ed25519(推奨) ssh-keygen -t ed25519 -C "your_email@example.com" # 出力例: # Generating public/private ed25519 key pair. # Enter file in which to save the key (~/.ssh/id_ed25519): [Enter] # Enter passphrase (empty for no passphrase): [推奨: 設定] # Enter same passphrase again: [Enter] # 古い環境でRSAが必要なら4096bit必須 ssh-keygen -t rsa -b 4096 -C "your_email@example.com" # 確認 ls -la ~/.ssh/ # id_ed25519 ← 秘密鍵(絶対に外部へ出さない) # id_ed25519.pub ← 公開鍵(GitHub等に登録する方)
パスフレーズは設定すべき?
- 推奨:設定する。秘密鍵ファイルが流出しても二次防壁になる
- 毎回入力が面倒ならssh-agent+macOS Keychain/1Password SSH Agentで自動入力化できる
- CI用deploy keyは逆にパスフレーズ無しが一般的(自動実行のため)
重要:秘密鍵(id_ed25519/id_rsa)は絶対にコミットやアップロードしないこと。GitHubに.pubではなく秘密鍵をアップロードすると即座に漏洩します。万が一コミットしてしまった場合は履歴の機密情報を完全削除する方法で緊急対応を。
STEP 2:公開鍵を各サービスに登録
GitHub
# 公開鍵をクリップボードにコピー # macOS pbcopy < ~/.ssh/id_ed25519.pub # Linux xclip -selection clipboard < ~/.ssh/id_ed25519.pub # Windows(Git Bash) cat ~/.ssh/id_ed25519.pub | clip # または表示してコピー cat ~/.ssh/id_ed25519.pub
GitHubでの公開鍵登録
- GitHub右上アイコン → Settings
- 左メニュー → SSH and GPG keys
- New SSH key をクリック
- Title: 識別しやすい名前(例: “MacBook Pro 2026″)
- Key type: Authentication Key
- Key: 公開鍵内容を貼り付け → Add SSH key
GitLab/Bitbucket/Azure DevOps
他サービスでの登録場所
- GitLab:右上アイコン → Preferences → SSH Keys
- Bitbucket:Profile → Personal settings → SSH keys
- Azure DevOps:User settings → SSH public keys
- GitHub Enterprise:GitHubと同じUI(URL違い)
接続テスト
# GitHub ssh -T git@github.com # 成功例: Hi username! You've successfully authenticated... # GitLab ssh -T git@gitlab.com # Bitbucket ssh -T git@bitbucket.org # Azure DevOps ssh -T git@ssh.dev.azure.com
STEP 3:ssh-agentに鍵を登録する
ssh-agentは秘密鍵をメモリに保持する仕組み。パスフレーズ付き鍵の場合、毎回入力する手間を省けます。OS別に起動方法と自動化設定が異なります。
# ssh-agent 起動(Linux/Git Bash) eval "$(ssh-agent -s)" # 鍵をロード ssh-add ~/.ssh/id_ed25519 # ロード済み鍵の確認 ssh-add -l # 全鍵を削除 ssh-add -D # 鍵を一時期間だけロード(1時間=3600秒) ssh-add -t 3600 ~/.ssh/id_ed25519
macOS:Keychainで自動化
# ~/.ssh/config に追加 cat >> ~/.ssh/config << "EOF" Host * AddKeysToAgent yes UseKeychain yes IdentityFile ~/.ssh/id_ed25519 EOF # Keychainに鍵を追加(パスフレーズはKeychainに保存) ssh-add --apple-use-keychain ~/.ssh/id_ed25519 # 以降、再起動後も自動でssh-agentが使える
Linux/WSL:systemdまたは.bashrcで自動起動
# ~/.config/systemd/user/ssh-agent.service mkdir -p ~/.config/systemd/user/ cat > ~/.config/systemd/user/ssh-agent.service << "EOF" [Unit] Description=SSH key agent [Service] Type=simple Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK [Install] WantedBy=default.target EOF systemctl --user enable --now ssh-agent # 環境変数を.bashrcに echo 'export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"' >> ~/.bashrc
Windows:OpenSSH Authentication Agent
# PowerShellを管理者権限で起動 # OpenSSH Authentication Agentサービスを自動起動に Set-Service -Name ssh-agent -StartupType Automatic Start-Service ssh-agent # 鍵をロード(PowerShell) ssh-add $env:USERPROFILE\.ssh\id_ed25519 # Git for Windows のGit Bashは別のssh-agent実装を使う場合あり # 統一するなら GIT_SSH 環境変数で OpenSSH を指定 $env:GIT_SSH = "C:\Windows\System32\OpenSSH\ssh.exe"
Windows注意:Git for Windowsに同梱のOpenSSHと、Windows 10/11公式のOpenSSHは別実装で、それぞれ別のssh-agentを使う場合があります。両方起動していると「鍵はロードしたのに認識されない」事態に。どちらを使うかをwhere sshで確認し、片方に統一するのが無難。
SSH configで複数アカウント/鍵を使い分ける
「個人用と会社用のGitHubを切り替えたい」「非標準の鍵ファイル名を使いたい」といった場合は~/.ssh/configで設定します。Host aliasを使えば透過的に切り替えられるのでおすすめ。
# ~/.ssh/config cat > ~/.ssh/config << "EOF" # 個人アカウント(デフォルト) Host github.com HostName github.com User git IdentityFile ~/.ssh/id_ed25519_personal AddKeysToAgent yes # 会社アカウント(ホスト名を別名に) Host github-work HostName github.com User git IdentityFile ~/.ssh/id_ed25519_work AddKeysToAgent yes # プライベートGitHub Enterprise Host github-enterprise HostName github.enterprise.example.com User git IdentityFile ~/.ssh/id_ed25519_ent Port 22 EOF # 権限設定 chmod 600 ~/.ssh/config
# 会社のrepo(github-work alias使用) git clone git@github-work:company/repo.git # → ssh configで id_ed25519_work が使われる # 個人のrepo(通常のgithub.com) git clone git@github.com:personal/repo.git # → id_ed25519_personal が使われる # 既存remote URLを alias に変更 git remote set-url origin git@github-work:company/repo.git # ユーザー名/メールもrepoごとに変える cd company-repo git config user.name "Work Taro" git config user.email "taro@company.com"
ポイント:SSH configのHost aliasは複数アカウント運用の鉄板解。「git@github-work」「git@github-personal」のようにエイリアス名でcloneすれば、自動的に正しい鍵が使われます。git config user.emailもrepoごとに変えれば、commit authorも正しく分離できます。
モダン運用:1Password SSH Agent活用
2022年以降、1Passwordに内蔵されたSSH Agent機能がSSH鍵管理のゴールドスタンダードになりつつあります。パスフレーズ管理・バイオメトリクス認証・複数デバイス同期を全部任せられる優れもの。
# 1Password v8+ の Developer設定で SSH Agent を有効化 # 鍵を1Passwordに保存(アプリ内で新規作成 or 既存鍵インポート) # ~/.ssh/config に以下を追加 cat >> ~/.ssh/config << "EOF" Host github.com IdentityAgent "~/Library/Group Containers/2BUA8C4S2C.com.1password/t/agent.sock" IdentityFile ~/.ssh/id_ed25519_1password.pub IdentitiesOnly yes EOF # Windowsの場合のパス: # IdentityAgent \\.\pipe\openssh-ssh-agent # 接続時にTouch ID/Windows Hello等で認証される ssh -T git@github.com
1Password SSH Agent の利点
- 秘密鍵は1Password内で暗号化保存、ディスクに平文なし
- Touch ID / Face IDで毎回の認証(強固)
- 複数デバイスで同じ鍵を同期(1Password Families/Businessで自動)
- SSH config書き換えで既存ssh-agentをそのまま置換可能
- GitコミットへのSSH署名にも使える
ポイント:1Passwordを使わない場合でも、Bitwarden(SSH Agent機能は限定的)やKeePassXC(エージェント機能あり)など類似の選択肢があります。パスフレーズを何度も入力する時代は終わりつつあるので、ツール投資の価値は大きいです。
ssh -vT出力の読み方
verboseログは膨大に見えますが、見るべき行は限られています。次の行を順に確認すれば原因が特定できます。
$ ssh -vT git@github.com # 1. 使おうとしているconfig debug1: Reading configuration data /Users/user/.ssh/config # → このconfigパスを使っている # 2. 接続先とポート debug1: Connecting to github.com [140.82.x.x] port 22. # 3. 試す鍵の順序 debug1: Will attempt key: /Users/user/.ssh/id_ed25519 ED25519 debug1: Offering public key: /Users/user/.ssh/id_ed25519 ED25519 # → この鍵を送っている # 4. サーバーの応答 debug1: Authentications that can continue: publickey # → GitHubが鍵を受け取ったが認証失敗(未登録か別ユーザーの鍵) # 5. 最終結果 git@github.com: Permission denied (publickey).
CI環境(GitHub Actions/CircleCI)でのSSH認証
CI環境はユーザーセッションが無いため、Deploy keyやmachine user、Secrets経由での鍵設定が必要です。ローカルでは動くのにCIだけPermission deniedになるケースで参照してください。
GitHub Deploy Key(リポジトリごと)
# 専用の鍵ペアをCI用に生成 ssh-keygen -t ed25519 -f ~/.ssh/deploy_key -N "" # 公開鍵をGitHubのリポジトリに登録 # Settings → Deploy keys → Add deploy key # Title: "CI Deploy Key" # Key: 公開鍵内容を貼り付け # Allow write access: 必要なら有効化 # 秘密鍵をCI環境のSecretに登録 cat ~/.ssh/deploy_key # → GitHub Actions: Settings → Secrets → DEPLOY_KEY
GitHub Actions で使う
name: Deploy
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: webfactory/ssh-agent@v0.9.0
with:
ssh-private-key: ${{ secrets.DEPLOY_KEY }}
- uses: actions/checkout@v4
with:
ssh-key: ${{ secrets.DEPLOY_KEY }}
GitLab CI/CircleCIでも同様のパターン
CI環境のSSH設定
- GitLab CI:
SSH_PRIVATE_KEYをVariablesに登録→before_scriptでssh-agent起動 - CircleCI:SSH keys設定からUpload、
add_ssh_keysステップで有効化 - Jenkins:Credentials pluginでSSH鍵管理
- AWS CodeBuild:Systems Manager Parameter Storeで鍵保存
insteadOfでHTTPSとSSHを透過的に切り替える
「チームではHTTPS URLがREADMEに記載されている」「でも自分はSSHで認証したい」という場合、Git設定のurl.insteadOfで自動的に書き換えられます。
# 設定:HTTPSをSSHに書き換え git config --global url."git@github.com:".insteadOf "https://github.com/" # これで https://github.com/user/repo.git を渡しても # 内部的に git@github.com:user/repo.git として扱われる # 確認 git clone https://github.com/user/repo.git # → 実際はSSH接続(認証にSSH鍵が使われる) # 逆方向(SSH→HTTPS)も可能 git config --global url."https://github.com/".insteadOf "git@github.com:"
ポイント:insteadOfはURLプレフィックスを自動書き換えする機能。CI環境でHTTPSが必須だが個人はSSHを使いたい、というケースで便利。会社・個人でGit設定を分けるなら、リポジトリ別.gitconfig-workにincludeIfで読み込ませるテクニックもあります。
実践シナリオ
シナリオ① 新規マシンで初めてGitHubにSSH接続
# 鍵生成 ssh-keygen -t ed25519 -C "your_email@example.com" # agent起動+ロード eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_ed25519 # 公開鍵コピー → GitHub Settings → SSH keys で登録 cat ~/.ssh/id_ed25519.pub | pbcopy # macOS # 接続テスト ssh -T git@github.com
シナリオ② 個人と会社のアカウントを切り替える
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_work -C "work@company.com" # ~/.ssh/configに会社用Host追加(本文参照) # 会社GitHub で公開鍵登録 # 会社repoをclone git clone git@github-work:company/repo.git cd repo git config user.email "work@company.com"
シナリオ③ CI環境でPermission denied
# CI専用鍵を生成(パスフレーズなし) ssh-keygen -t ed25519 -f /tmp/deploy_key -N "" # 公開鍵 → GitHub repo Settings → Deploy keys # 秘密鍵 → GitHub Actions Secrets (DEPLOY_KEY) # workflow YAML で webfactory/ssh-agent アクション使用
シナリオ④ WSLでSSH鍵が認識されない
# WSLに入る wsl # WSL内で鍵生成 ssh-keygen -t ed25519 -C "your_email@example.com" # ~/.ssh の権限確認 chmod 700 ~/.ssh chmod 600 ~/.ssh/id_ed25519 # GitHub登録後 → 接続テスト ssh -T git@github.com
やってはいけない落とし穴
秘密鍵ファイルをコミット
.gitignore未設定のディレクトリで誤って~/.ssh/をコピーして秘密鍵(id_ed25519)をコミットすると即座に漏洩します。発覚したら鍵を破棄→新規作成→GitHubで旧鍵削除+履歴から削除(履歴の機密情報削除参照)。
権限が緩い鍵ファイルを使う
id_ed25519の権限が644等で緩いと「Permissions too open」警告+認証失敗。chmod 600 ~/.ssh/id_ed25519+chmod 700 ~/.sshで必ず厳格化してください。
Windows OpenSSHとGit for Windows混在
Windows 10/11に標準搭載のOpenSSHと、Git for Windowsに同梱のOpenSSHは別実装でssh-agentも別。両方起動すると鍵の参照が混乱します。where sshで確認し、一方をGIT_SSH環境変数で明示的に使うのが推奨。
ssh-agent を毎回手動起動
ターミナル起動ごとにeval $(ssh-agent -s)を打つのは非効率。macOSはKeychain+AddKeysToAgent、Linuxはsystemd user service、Windowsはサービス自動起動と、OS別の自動化を必ず設定しましょう。
RSAで鍵長短い(1024bit等)
古いRSA鍵(1024bit)はすでにセキュリティ的に危険で、GitHub他多くのサービスで拒否されます。RSAを使うなら4096bit以上が必須、現代的にはed25519が第一選択。古い鍵を使い続けているなら今すぐed25519に置き換えを。
organizationのSSO認可を忘れる
GitHub EnterpriseやSSO有効なorganizationでは、公開鍵を登録しただけでは組織リポジトリにアクセスできません。SSH keys設定画面の“Authorize” ボタンでSSO有効化を忘れずに(鍵ごとに必要)。
よくある質問
git remote -vで確認し、SSHに切り替え:git remote set-url origin git@github.com:user/repo.git。~/.ssh/configでHost aliasを定義するのが王道。git@github-work:company/repo.gitのようにaliasでcloneすれば自動切替です。詳細は本記事の該当セクション参照。-v付きで走らせ、どのタイミングで認証失敗するか特定を。~/.sshをシンボリックリンクで繋ぐか、1Password SSH Agentをnamed pipe経由でWSL接続も可能。関連記事
- 【Git】「does not appear to be a git repository」エラーの原因と解決方法 — SSH認証OKでもrepo未登録の場合
- 【Git】「failed to push some refs to」エラーの原因と対処法 — push失敗の総合ガイド
- 【Git】pushしようとしたら”non-fast-forward”で拒否されたときの解決方法 — 別系統のpushエラー
- 【Git】履歴に含まれる機密情報を完全に削除する方法 — 鍵誤コミット時の緊急対応
- 【Git】originとupstreamの違いと使い分け完全ガイド — リモート設定の基礎
- 【Git】リモートブランチを確認する方法 — 接続確認
- 【Git】pushを取り消す方法 — 誤push時の対処
- 【Git】よく使うgitコマンドまとめ — 日常コマンドの早見表
まとめ
- 診断は
ssh -vT git@github.comで最速(verboseログの「Offering」「no such identity」を見る) - 鍵はed25519が推奨(RSAは非推奨、古い環境のみ4096bit)
- 公開鍵はGitHub Settings → SSH and GPG keys で登録、接続テストは
ssh -T - ssh-agent+OS別自動化(macOS Keychain/Linux systemd/Windowsサービス)
- 複数アカウントは
~/.ssh/configでHost alias - モダン運用:1Password SSH Agentでパスフレーズ管理+バイオメトリクス
- CI環境はDeploy key+Secretsで、webfactory/ssh-agent等のアクションで有効化
- HTTPS/SSH混在は
url.insteadOfで透過的に書き換え
Permission denied (publickey)は一見難しそうですが、診断→10パターンのどれかを特定→対処の流れで多くは数分で解決します。ed25519鍵の生成+GitHub登録+ssh-agent自動化+SSH config整備を一度やっておけば、以降は安定運用できます。モダン運用として1Password SSH Agentの導入、CI環境のDeploy key設定まで押さえれば、SSH認証で二度と詰まることはありません。このエラーに出会ったら、本記事をブックマークして診断フローから確実に原因を特定していきましょう。

