起因
由于换新的服务器,之前搭建的 Gogs 也是旧版本(一直懒得升级),于是就重新拉取了docker 镜像,搭建服务的过程一切都顺利。在配置系统时,看见启用两步验证,手机也刚好安装了 Google Authenticator,结果悲剧了迁出代码的时候需要加上临时凭证,感觉一下子就麻烦了起来(通过 https 的方式接取推送代码)。
想了一想,能不能鱼和熊掌兼得,既有 Web 安全登录,又可以顺利拉取推送代码(这是刚需,不然玩个寂寞)。于是就和标题里面的 Permission denied
展开搏斗(主要是自己技术不精)。
使用 docker 搭建 Gogs,请参阅:Docker for Gogs
场景还原
我使用的是 win10 系统,安装了 git,使用的 shell 是 git-bash
。
首先,使用 ED25519 算法生成的公私钥文件(名为 gogs
的私钥,gogs.pub
的公钥)。
ssh-keygen -t ed25519 -f gogs -C "your@email.com"
其次,按照文档说明在站点的个人设置里配置好了公钥。并在系统盘,用户目录下, 配置了%userprofile%/.ssh/config
文件,添加了如下配置:
Host gogs
Hostname 10.0.0.10
User git
Port 10022
IdentityFile ~/.ssh/gogs
IdentitiesOnly yes
关于配置选项请参阅:list of client coinfiguration-options
.ssh
目录主要存储 ssh 服务相关文件,config
文件是用来配置经常访问的主机连接信息(如 IP 地址、用户名、私钥)。使用
config
文件的好处是,平时我们使用 ssh 连接远程主机时通常使用下面两种命令:
密码形式
ssh git@10.0.0.10 -p 10022 # 回车后会提示输入密码
密钥文件形式
ssh -i ~/.ssh/gogs git@10.0.010 -p 10022
上面的命令每次输入,就会变得繁琐,然而配置
config
文件后,命令就可以简化为:ssh gogs # 语法: ssh <host>
接下来,尝试使用 git bash
尝试推送代码,结果就报了 Permission denied
错误。
原因及解决方案
经过一番搜索后,得出结论:问题是出在 ssh-agent 身上。
ssh-agent 是客户端 ssh 的默认代理,其作用是管理私钥,负责 ssh 连接的整个认证过程(本质就是一个验证身份的程序)。
关于
ssh-agent
的详细解释,请参阅:ssh-agent 详解
为什么这样说呢?因为在使用 ssh-keygen
时如果一路回车下去,命令最终会生成如 id_xxx
的公私钥文件(xxx 指的是算法),这些文件通常会作为 ssh-agent 的默认文件。这样的公私钥也不会有问题,问题是我自定义了公私钥文件名称。
这里摘自 ssh-agent 文档:在 Linux 系统下,ssh-agent
通常会在登录系统时自动配置并运行。默认会使用用户目录下 .ssh
目录中的私钥文件,在简单模式下,只会加载 ~/.ssh/id_rsa
, .ssh/id_dsa
, ~/.ssh/id_ecdsa
, ~/.ssh/id_ed25519
, and ~/.ssh/identity
等文件。如果要使用其它文件私钥文件,需要使用 ssh-add
添加。
这也就解释了,为什么名 gogs
私钥文件一直没有起作用的原因。
接下来,只需要添加 gogs
私钥文件给 ssh-agent
就好了:
ssh-add ~/.ssh/gogs
如果执行 ssh-add 命令时出现
Could not open a connection to your authentication agent
错误,请尝试运行命令(这个在 ssh-agent 里也有提到):eval `ssh-agent`
再次尝试推送,就可以了。
总结
解决方案主要参考了 Github Error: Permission denied (publickey) 的文档,其中最主要部分是如何查找错误,其主要命令如下:
ssh -vT git@10.0.0.10 -p 10022
参数 -T
是调试命令,-v
则是输出详情,结合起来就可以看到连接远程主机的整个过程,以及过程中尝试查找的私钥文件,最后选择了哪个私钥文件与远程主机交互。
下面是 Github 文档里的输出示例,其中最后的 -1
代表没有找到此文件。
$ ssh -vT git@github.com
> ...
> debug1: identity file /Users/you/.ssh/id_rsa type -1
> debug1: identity file /Users/you/.ssh/id_rsa-cert type -1
> debug1: identity file /Users/you/.ssh/id_dsa type -1
> debug1: identity file /Users/you/.ssh/id_dsa-cert type -1
> ...
> debug1: Authentications that can continue: publickey
> debug1: Next authentication method: publickey
> debug1: Trying private key: /Users/you/.ssh/id_rsa
> debug1: Trying private key: /Users/you/.ssh/id_dsa
> debug1: No more authentication methods to try.
> Permission denied (publickey).
运行这个命令来验证我们的私钥是否被加载。私钥没有被正确加载就是 Permission denied (publickey)
错误的一个最大的原因。
本文由 waynelone 创作,采用 知识共享署名4.0 国际许可协议进行许可。
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。