Permission denied (publickey).

ちくしょう!台無しにしやがった!お前はいつもそうだ。このエラーはお前の人生そのものだ。お前はいつも失敗ばかりだ。

個人用(YotioSoft)と研究室用の2つのGitHubアカウントを併用しているという話はこの前も書きましたが、複数のGitHubアカウントを併用していると何が面倒かって、アカウントの切り替えです。
今まではsshでの管理が面倒だったのでhttpsでのパスワード認証に逃げていたのですが、今年の8月13日からGitHubがパスワード認証を禁止、ssh認証の利用を余儀なくされました。自分みたいによく理解しないままssh認証でアカウントを併用しようとすると、すぐにPermission deniedが頻出します。つまり、正しくユーザ認証できてないよということです。

今回は、ようやくgitでのsshの正しい利用方法を(たぶん)覚えたので、その方法を忘備録として書いておきます。これで忌まわしきPermission deniedともおさらばです。

現状

sshの鍵を登録し、~/.ssh/configにも鍵の場所とか書いたにもかかわらずPermission deniedされる。

ゴール

Permission deniedされなければなんでもいい。簡単にGitHubアカウントの切り替えができたらなおよし。

解決策

~/.ssh/configにアカウントの設定を書き込んでおき、リポジトリごとにURLを設定しておく。GitHub前提で話していますが、他のGitサーバでも同様の手順で可能かと思います。
その方法について順を追って説明します。

1. OpenSSHをインストールする

OpenSSHは既に導入済みなのでどうやって導入したかは覚えてない(おい)ですが、Windowsならgit for WindowsをインストールしたときにOpenSSHも付いてきた気がします。
コマンドプロンプトに

> ssh-V

と打って、OpenSSHのバージョンが出ればインストール済みです。

mac OSは基本的に標準搭載です。
Linuxはディストリビューションによっては別途インストールが必要かもしれません。

2. .sshディレクトリの作成

Windowsの場合

C:\Users\[ユーザ名]の下に.sshというディレクトリがあるか確認。なければエクスプローラかなにかで作成します。

macOS / Linuxの場合

ホームディレクトリ(~)の下に.sshというディレクトリがあるか確認。なければmkdirで作成します。

3. 鍵の作成&登録

sshキーを作成します。

Windowsの場合

ssh-keygenも使えますが、WindowsではいつもPuTTYgenというツールで作成しています。
SnapCrab_PuTTY Key Generator_2021-12-14_21-50-45_No-00
「Generate」をクリックした後、適当にカーソルをぐるぐる回すと鍵が生成されます。

SnapCrab_PuTTY Key Generator_2021-12-14_21-43-12_No-00
作成した秘密鍵は「Conversions」→「Export OpenSSH Key」の順で保存。C:\Users\[ユーザ名]\.ssh内に任意の名前で保存します。
SnapCrab_NoName_2021-12-14_22-34-49_No-00
「Public key for pasting in to OpenSSH authorized_keys file:」の下に表示されている”ssh-rsa”から始まる文字列が公開鍵で、こちらはGitHubに登録します。
SnapCrab_NoName_2021-12-14_21-52-8_No-00

macOS / Linuxの場合

ssh-keygenを使います。なければ要インストールです。

$ ssh-keygen

保存先ファイルパスを特別に指定しなければ、秘密鍵(拡張子なし)と公開鍵(.pub)は~/.sshの下に保存されます。ただし、既存の鍵とファイル名がかぶらないよう要注意です。

公開鍵はcatコマンドなどで開き、

$ cat ~/ssh/○○.pub

その内容をコピペしてGitHubに登録します。

4. configファイルの作成

.ssh内にconfigというファイルを作成し(既にあればそのまま)、エディタで開きます。
そして作成した鍵を以下のようにして追記し保存します。

Host 接続名
    HostName github.com
    User git
    Port 22
    IdentityFile 秘密鍵のファイルパス
    TCPKeepAlive yes
    IdentitiesOnly yes

秘密鍵のファイルパスは絶対パスじゃないと上手く行かないので注意。

例えばこんな感じに。(3.で.sshに秘密鍵をid_rsa_yotiosoftとして保存した場合)

Host GitHub-YotioSoft
    HostName github.com
    User git
    Port 22
    IdentityFile C:\Users\[ユーザ名]\.ssh\id_rsa_yotiosoft
    TCPKeepAlive yes
    IdentitiesOnly yes

5. 以降、同様の手順で他のアカウントのsshキーも作成&登録

新しく秘密鍵を作ったら、どんどんconfigに追記していきます。

例)研究室用アカウント(秘密鍵:id_rsa_labo)を登録

Host GitHub-YotioSoft
    HostName github.com
    User git
    Port 22
    IdentityFile C:\Users\[ユーザ名]\.ssh\id_rsa_yotiosoft
    TCPKeepAlive yes
    IdentitiesOnly yes

Host GitHub-Labo
    HostName github.com
    User git
    Port 22
    IdentityFile C:\Users\[ユーザ名]\.ssh\id_rsa_labo
    TCPKeepAlive yes
    IdentitiesOnly yes

※2022/02/21:TCPKeepAlive yesIdentitiesOnly yesを追記

6. gitのremote先のURLを設定

$ git initした直後に$ git remote add origin [リモートリポジトリのパス]でリモートリポジトリとやり取りできるようになりますが、このとき、リモートリポジトリのURLを

[接続名]:[接続先GitHubアカウント名]/[リモートリポジトリの名前].git

とすると、先程./ssh/configに登録した鍵情報が利用できるようになります。

例)

  • 秘密鍵:.ssh/configGitHub-YotioSoftとして登録したもの(id_rsa_yotiosoft
  • GitHubアカウント名:YotioSoft
  • 接続先リポジトリ名:blog.git
GitHub-YotioSoft:YotioSoft/blog.git

ですので、gitのリモートリポジトリとして登録する際は

$ git remote add origin GitHub-YotioSoft:YotioSoft/blog.git

としてやることでssh接続でGitHubとやり取りできるようになります。

また、もう一つの別のアカウント(先程GitHub-Laboとして登録)のリモートリポジトリに接続する際も、例えば

$ git remote add origin GitHub-Labo:[研究室用アカウント名]/[研究室用リモートリポジトリ名].git

としてやれば、いちいちユーザを切り替えることなくリポジトリごとに別々のアカウントのリモートリポジトリに接続できます。

リポジトリごとにアカウントが切り替わるので、これでこの前みたいにユーザを間違えて意図しないアカウントでcommitしちゃってうわああああ!!!みたいな失敗が起こることもありません。

おわりに

バイバイPermission denied!
これで夜もぐっすり眠れそう。