GitHubのSSH接続:鍵の作り方と登録、HTTPSとの違い

公開 書いた人 大林 諒

「SSHでcloneしてください」と制作会社に言われて手が止まったり、Permission denied (publickey) が出て先へ進めなかったりする話です。SSHは、パソコンとサーバーが鍵で本人確認をして、暗号化したまま通信する接続の方法です。サンプル料理教室の代表のパソコンで鍵を作り、GitHubに登録し、リポジトリのURLを切り替えるまでを、実際に動かした表示つきで書きます。読み終わると、SSHが要るかどうかを判断でき、鍵まわりのエラーも自分で直せます。

この記事の内容
  1. 先に答えると
  2. HTTPS・gh auth login・SSHの違い
  3. 鍵を作る
  4. GitHubに公開鍵を登録する
  5. 接続を確かめる
  6. リポジトリのURLを切り替える
  7. パスフレーズと、Macのキーチェーン
  8. 複数のアカウントで鍵を使い分ける
  9. known_hostsとHost key verification failed
  10. GitLabでも鍵は同じ
  11. 鍵を漏らしたとき
  12. できないことと、その代わり
  13. よく詰まるところ
  14. 次に読む

先に答えると

GitHubとの接続は、まず gh auth login で足ります。SSHが要るのは、制作会社にSSHを指定されたときと、社内のルールやサーバーの都合でHTTPSを使えないときくらいです。使うなら、ssh-keygen で鍵を作り、GitHubの「SSH and GPG keys」に公開鍵を登録し、ssh -T git@github.com で確かめます。

  • 鍵は2つで1組です。.pub の付く公開鍵だけをGitHubに渡します
  • .pub の付かない秘密鍵は、誰にも送りません。AIとのやり取りにも貼りません
  • URLは https://github.com/... から git@github.com:... に変えます
  • 鍵を漏らしたら、GitHubから削除して作り直します
  • GitLabも鍵の作り方は同じで、登録する場所だけが違います

HTTPS・gh auth login・SSHの違い

GitHubに本人だと示す手段は3通りあります。リポジトリ(ファイルと履歴を入れる箱)を受け取るcloneと、変更を送るpushで使います。

gh auth loginHTTPSとトークンSSH鍵
設定の手間少ない。ブラウザで承認するだけ中くらい。トークンを作り、期限が来たら作り直す最初だけ多い。鍵を作って登録する
URLの形https://github.com/sample-cooking/website.git同じgit@github.com:sample-cooking/website.git
パソコンに保管されるものトークンをパソコンの保管庫に自分で入れたトークン(資格情報の保管の設定による)秘密鍵のファイル
GitHubに登録するものなし(承認だけ)なし(GitHubで発行)公開鍵
社内のネットワークHTTPSなので通りやすい同じ22番ポートが止められていることがある
向いている人ほとんどの人特定のリポジトリだけ権限を渡したい人制作会社の指示がSSHの人、よく触る開発者

トークンは、パスワードの代わりに使う長い文字列です。ポートはパソコンの通信の出入り口の番号で、SSHは22番を使います。SSHにしても、できることがアカウントの権限より増えることはありません。

gh auth login の手順は「Gitのインストールと初期設定:MacとWindows、名前とメールと認証」と「GitHub CLIの使い方:ghでできることと、gitとの違い」にあります。そこでHTTPSの代わりに SSH を選ぶと、gh が手元の鍵を探し、無ければ鍵の作成と登録まで案内します。自分の手で作る場合が、次の節です。

SSHでは、秘密鍵は手元に残し、公開鍵だけをGitHubに登録して本人確認する
SSHでは、秘密鍵は手元に残し、公開鍵だけをGitHubに登録して本人確認する

鍵を作る

鍵は ssh-keygen で作ります。ここでは練習用のフォルダ keys の中に作るので、-f で置き場所を指定しています。本番では -f を外すと保存先を聞かれ、そのままEnterで ~/.ssh/id_ed25519 に入ります。~ はホームフォルダです。

$ ssh-keygen -t ed25519 -C "daihyo@sample-cooking.example" -f keys/id_ed25519
Generating public/private ed25519 key pair.
Enter passphrase for "keys/id_ed25519" (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in keys/id_ed25519
Your public key has been saved in keys/id_ed25519.pub
The key fingerprint is:
SHA256:xxxxxxxx daihyo@sample-cooking.example

(指紋の値は伏せ、続いて出る模様の図は省きました。)

-t ed25519 は鍵の種類、-C は後で見分けるための目印です。パスフレーズは鍵を守る合言葉で、打っても画面に何も出ません。指紋(fingerprint)は鍵を短くした識別番号で、GitHubの一覧と見比べるときに使います。

できたファイルは2つです。

$ stat -f "%Sp %N" keys/id_ed25519 keys/id_ed25519.pub
-rw------- keys/id_ed25519
-rw-r--r-- keys/id_ed25519.pub
ファイル中身扱い
id_ed25519秘密鍵。本人だと証明する側パソコンから出さない。自分だけが読める状態で保存される
id_ed25519.pub公開鍵。証明を確かめる側GitHubに登録する。制作会社に渡すのもこちら

比喩で言えば、公開鍵は錠前で、秘密鍵はそれを開ける鍵です。錠前はどこに取り付けても困りませんが、鍵を渡すと開けられます。公開鍵の中身は ssh-ed25519 xxxxxxxx daihyo@sample-cooking.example のような1行です。

すでに同じ名前の鍵があると、次のように聞かれます。

Generating public/private ed25519 key pair.
keys/id_ed25519 already exists.
Overwrite (y/n)? n

ここで y を押すと古い鍵が消え、その鍵でつないでいた先に入れなくなります。迷ったら n で止め、別の名前で作ります。

GitHubに公開鍵を登録する

  1. Macのターミナルで pbcopy < ~/.ssh/id_ed25519.pub と打ち、公開鍵をコピーします(Windowsは clip < ~/.ssh/id_ed25519.pub。PowerShellで失敗するときは cat ~/.ssh/id_ed25519.pub | clip)。
  2. GitHubの右上のアイコンから「Settings」を開きます。
  3. 左の一覧の「Access」にある「SSH and GPG keys」を開きます。
  4. 「New SSH key」を押します。
  5. 「Title」に「代表のMacBook」のように分かる名前を入れます。
  6. 種類は認証用(Authentication)を選びます。
  7. 「Key」に貼り付けます。
  8. 「Add SSH key」を押します。確認を求められたら、パスワードなどで本人確認をします。

貼るのは .pub の中身です。.pub の付かないファイルをコピーしていないか、手順1で確かめます。

GitHubの New SSH key で、名前と公開鍵を入れて Add SSH key を押す画面
GitHubの New SSH key で、名前と公開鍵を入れて Add SSH key を押す画面

接続を確かめる

ターミナルで ssh -T git@github.com と打ちます。初めての接続では、相手が本物のGitHubかを聞かれます。GitHub公式の説明では、次の文が出ます。

The authenticity of host 'github.com (IP ADDRESS)' can't be established.
ED25519 key fingerprint is SHA256:xxxxxxxx.
Are you sure you want to continue connecting (yes/no)?

GitHub Docsの「GitHub’s SSH key fingerprints」のページにある値と一致するときだけ yes と答えます。一致しなければ接続しません。成功すると次の文が出ます。

Hi USERNAME! You've successfully authenticated, but GitHub does not provide shell access.

「shell access(サーバーの操作)は提供していない」と書かれていますが、これで成功です。GitHubはサーバーにログインさせる用途ではないので、この文で正常に終わります。USERNAME のところに自分のユーザー名が出ているかを見ます。

リポジトリのURLを切り替える

すでにHTTPSで受け取っているリポジトリは、git remote set-url で送り先の書き方を変えます。ファイルも履歴も変わりません。cloneし直す必要もありません。

$ git remote -v
origin	https://github.com/sample-cooking/website.git (fetch)
origin	https://github.com/sample-cooking/website.git (push)

$ git remote set-url origin git@github.com:sample-cooking/website.git

$ git remote -v
origin	git@github.com:sample-cooking/website.git (fetch)
origin	git@github.com:sample-cooking/website.git (push)

origin は送り先につけた呼び名です。HTTPSに戻すときは、同じコマンドで元のURLを入れます。これから受け取るリポジトリなら、リポジトリのページの「Code」ボタンで「SSH」を選んだURLを git clone に渡します。

リポジトリの Code を開き、SSH を選ぶと出る接続用のURLの場所
リポジトリの Code を開き、SSH を選ぶと出る接続用のURLの場所

パスフレーズと、Macのキーチェーン

パスフレーズを付けておくと、秘密鍵のファイルを取られてもすぐには使えません。その代わり、使うたびに入力を求められます。この手間を減らすのが ssh-agent(解いた鍵を預かる常駐の仕組み)と、Macのキーチェーン(パスワードの保管庫)です。

GitHub公式のMacの手順は次のとおりです。

  1. eval "$(ssh-agent -s)" で ssh-agent を起動します。
  2. ~/.ssh/config を開きます。無ければ作ります。
  3. 次の4行を書きます。パスフレーズを付けていない鍵なら UseKeychain の行は要りません。
Host github.com
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_ed25519
  1. ssh-add --apple-use-keychain ~/.ssh/id_ed25519 で鍵を預け、パスフレーズをキーチェーンに入れます。

Windowsは、管理者のPowerShellで ssh-agent のサービスを起動してから ssh-add を使います。手順はGitHub Docsの「Generating a new SSH key and adding it to the ssh-agent」にあります。

あとからパスフレーズを付ける、変えるときは鍵を作り直さずに済みます。

$ ssh-keygen -p -f keys/id_ed25519
Enter old passphrase: 
Key has comment 'daihyo@sample-cooking.example'
Enter new passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved with the new passphrase.

複数のアカウントで鍵を使い分ける

1つのアカウントでいくつものOrganization(GitHub上の会社のアカウント)に招待してもらえるので、ふつうはアカウントも鍵も1つで足ります。使い分けが要るのは、外注エンジニアBのように1台のパソコンでアカウントを2つ持つ人です。

同じ公開鍵は2つのアカウントに登録できません(Key is already in use になります)。アカウントごとに鍵を作り、~/.ssh/config に別名を書きます。

Host github.com
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519
  IdentitiesOnly yes

Host github-sample
  HostName github.com
  User git
  IdentityFile ~/.ssh/id_ed25519_sample
  IdentitiesOnly yes

Host が別名、HostName が本当の接続先、IdentityFile が使う秘密鍵です。IdentitiesOnly yes は、指定した鍵だけを使う指定です。ssh -G を使うと、接続せずに設定の読まれ方を確かめられます。ここは練習用のファイルなので -F config で指定しています。~/.ssh/config なら -F は要りません。

$ ssh -G -F config github-sample | grep -E '^(hostname|user|identityfile) '
user git
hostname github.com
identityfile ~/.ssh/id_ed25519_sample

リポジトリのURLのほうも、別名に書き換えます。

$ git remote set-url origin git@github-sample:sample-cooking/website.git

$ git remote -v
origin	git@github-sample:sample-cooking/website.git (fetch)
origin	git@github-sample:sample-cooking/website.git (push)

接続の確認は ssh -T git@github-sample で、出た文のユーザー名が2つ目のアカウントなら合っています。別名が2つ以上になると設定のミスが増えるので、そもそも2つ目のアカウントを持たずに済まないかを先に考えます。

known_hostsとHost key verification failed

SSHは、一度つないだ相手の鍵を ~/.ssh/known_hosts に控えておき、次からその控えと比べます。なりすましを防ぐ仕組みです。比べて合わないと、次のように止まります。

Host key verification failed.

GitHub公式が挙げる原因は2つで、相手が鍵を変えたか、別のサーバーにつながっているかです。前者の実例が2023年3月24日で、GitHubがRSAという種類の鍵を作り替え、WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! という警告が出るようになりました。

直し方の順番は次のとおりです。警告を消すことだけを考えて、確かめずに yes を押さないでください。別のサーバーだった場合、その相手に接続してしまいます。

  1. GitHub Blog に鍵の変更の告知があるかを見ます。
  2. GitHub Docsの「GitHub’s SSH key fingerprints」のページを開きます。
  3. 控えの古い行を ssh-keygen -R github.com で消します。
  4. ssh -T git@github.com で接続します。
  5. 出た指紋が公式のページの値と一致するときだけ yes と答えます。

公式の値を見つけられないときは接続せず、社内のIT担当かGitHubのサポートに相談します。手順3を練習用のファイルで動かすと、次の表示になります。元の内容は .old の付くファイルに残ります(本番では -f は要りません)。

$ ssh-keygen -R github.com -f known_hosts
known_hosts updated.
Original contents retained as known_hosts.old

(先頭に出る、見つかった行番号の1行は省きました。)

GitLabでも鍵は同じ

鍵の作り方は同じです。違うのは登録の場所と確認の文です。

GitHubGitLab
登録の場所「Settings」→「SSH and GPG keys」→「New SSH key」アイコン→「Edit profile」→「Access」→「SSH keys」→「Add new key」
確認のコマンドssh -T git@github.comssh -T git@gitlab.com
成功の文Hi USERNAME! ...Welcome to GitLab, <username>!

鍵を漏らしたとき

秘密鍵をチャットに貼った、パソコンをなくした、リポジトリに入れてしまった、というときは、順番を守ります。やることは「APIキーやパスワードをGitHubにpushしてしまったときの対応」と同じで、履歴を消すより先に止めます。

  1. GitHubの「SSH and GPG keys」を開きます。
  2. その鍵の「Delete」を押します。これで、その鍵ではつながらなくなります。
  3. 別の名前で鍵を作り直します。
  4. 新しい公開鍵を登録します。

同じ公開鍵を制作会社のサーバーなど他の場所にも登録しているなら、そこからも消します。見覚えのない鍵が一覧に並んでいたら、すぐ消してGitHub Supportに連絡します。公式はこれを安全上の問題の兆候として扱っています。パスフレーズを付けていても、取られた鍵は使い続けません。

できないことと、その代わり

できないことその代わり
秘密鍵を忘れた・消したあとに取り戻すGitHubには公開鍵しかない。作り直して登録し直す
鍵1つで2つのアカウントに登録するアカウントごとに鍵を作り、~/.ssh/config で分ける
22番ポートが止められた環境でそのまま使うssh.github.com の443番ポートへ向ける(次の節)。HTTPSに戻してもよい
外注に鍵を共有して権限を渡す相手のアカウントを招待する。「GitHubの権限と2段階認証:共同作業者・Organization・非公開リポジトリ」へ
1年使っていない鍵を使い続けるGitHubが約1年使われていない鍵を自動で消す。もう一度登録する

よく詰まるところ

症状原因直し方
Permission denied (publickey)鍵が読み込まれていない、GitHubに未登録、sudo を付けて別ユーザーで実行しているeval "$(ssh-agent -s)" のあと ssh-add -l -E sha256 で指紋を見て、「SSH and GPG keys」の一覧と比べる。無ければ登録する。sudo は付けない
Permission denied で、接続先が ユーザー名@github.com接続するユーザーは必ず gitgit@github.com にする
名前を変えた鍵が使われない既定の名前以外は自動で読まれないssh-add 鍵のパス、または ~/.ssh/config の IdentityFile に書く
Key is already in useその公開鍵が別のアカウントかリポジトリに登録されているそちらから外す。外せないなら鍵を作り直す
UNPROTECTED PRIVATE KEY FILE! bad permissions秘密鍵が他のユーザーにも読める状態chmod 600 ~/.ssh/id_ed25519
Host key verification failed控えの鍵と相手の鍵が違う上の節の順で公式の値と比べる
connect to host github.com port 22 で止まる社内のネットワークが22番を止めているssh -T -p 443 git@ssh.github.com を試し、通るなら ~/.ssh/config に書く
Could not read from remote repository.SSHの接続に失敗すると、Gitがこの文を足すその上の行にあるSSHのエラーを見る。この文が本体ではない

最後の行は、接続先を差し替えて失敗させると次のように出ます。原因の行はこの上に出ます。

fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

22番ポートを避ける設定は次のとおりです。初回は鍵の確認が改めて出ることがあります。指紋が公式の値と一致するなら yes で進みます。

Host github.com
  Hostname ssh.github.com
  Port 443
  User git

実際に運用していると、AIに「SSHが通らない」と相談するときに鍵のファイルごと貼りたくなる場面があります。エラーの文と ssh-add -l -E sha256 の指紋だけで足ります。秘密鍵の中身は貼らないでください。

次に読む

SSHを使わずに済ませる手順は「Gitのインストールと初期設定:MacとWindows、名前とメールと認証」と「GitHub CLIの使い方:ghでできることと、gitとの違い」にあります。鍵が漏れたあとの対応は「APIキーやパスワードをGitHubにpushしてしまったときの対応」、外注に権限を渡すときは「GitHubの権限と2段階認証:共同作業者・Organization・非公開リポジトリ」を開きます。

あわせて読む