如何在Ubuntu上使用ssh-add永久添加私钥?

631

我有一把私钥,用密码保护,用于通过SSH访问服务器。

我有两台Linux(Ubuntu 10.04)机器,它们的ssh-add命令行为不同。

在其中一台机器上,一旦我使用“ssh-add .ssh/identity”并输入密码,密钥就会被永久添加,即每次我关闭计算机并再次登录时,密钥已经添加。

在另一台机器上,我必须每次登录时都添加密钥。

据我所记,我在两台机器上都做了同样的事情。唯一的区别是密钥是在被永久添加的那台机器上创建的。

有人知道如何在另一台机器上永久添加密钥吗?


1
代理应该是临时的;但是可能你在其中一台机器的~/.bashrc或其他地方有ssh-add命令。 - mirek
这个命令对我有效:ssh-add --apple-use-keychain ~/.ssh/id_rsa - Vansuita Jr.
这是适用于Ubuntu 22.04.2的解决方案。重新启动后无需密码。`cp key.pub ~/.sshcp key ~/.sshchmod 600 ~/.ssh/key.pubchmod 600 ~/.ssh/key` - oginski
13个回答

912

一个解决方案是通过将关键文件添加到您的~/.ssh/config文件中,强制使它们永久保存。

IdentityFile ~/.ssh/gitHubKey
IdentityFile ~/.ssh/id_rsa_buhlServer

如果您在~/.ssh目录中没有'config'文件,则应创建一个。它不需要root权限,所以只需执行以下操作:

nano ~/.ssh/config

根据您的需求输入上述行,为此工作,文件需要具有chmod 600权限。 您可以使用命令 chmod 600 ~/.ssh/config 进行操作。

如果您希望计算机上的所有用户都使用该密钥,则将这些行放入/etc/ssh/ssh_config文件中,将密钥放在所有人都可以访问的文件夹中。

此外,如果您想将密钥设置为特定主机,则可以在您的〜/ .ssh / config中执行以下操作:

Host github.com
    User git
    IdentityFile ~/.ssh/githubKey

当你有多个身份时,这种方法的优点在于服务器不会因为你先尝试错误的身份而拒绝你。只有特定的身份会被尝试。


103
配置文件的权限应该是600。chmod 600 config - generalopinion
11
我必须为每个推送、拉取或克隆操作输入我的密码,我该如何避免这种情况? - Asaf
9
请使用ssh-add ~/.ssh/gitHubKey代替,这将记住您的密钥密码。我提出的解决方案是在重新启动后永久设置它。 - daminetreg
47
这个答案非常好,以至于ssh-add命令不应该存在。当你可以永久编辑配置文件时,为什么还要使用一个“临时”解决问题的命令,这个命令可能会突然崩溃呢? - RussellStewart
6
这个解决方案没有使用ssh-agent。-有什么区别吗?是的,您无法通过代理转发来传递身份验证信息。 - Robert Siemer
显示剩余13条评论

173

在 macOS 10.10 上,我通过在 ssh-add 命令中使用 -K 标志解决了那个问题:

ssh-add -K ~/.ssh/your_private_key

对于 macOS 10.12 及更高版本,您还需要按照此处描述的方法编辑您的 ssh 配置文件:https://github.com/jirsbek/SSH-keys-in-macOS-Sierra-keychain

2023 年更新

在较新版本的 macOS 中,您需要使用 --apple-use-keychain 标志代替 -K,因为 -K 已被弃用:

ssh-add --apple-use-keychain ~/.ssh/your_private_key

4
这是一个更好的答案,适用于那些想要永久设置它的人。 - punkrockpolly
14
因此,这一部分内容是指:“在Mac OSX(10.10)上”…… - Andrew K.
5
这对我来说不起作用(在OSX 10.12.4上)。 - abc123
2
根据 macOS High Sierra 上的 man ssh-addssh-add -K 将把密语保存到钥匙串中,在重启后,只需使用 ssh-add -A,无需输入您的密语。 - DawnSong
6
OP明确寻求Ubuntu的帮助,但这篇帖子掩盖了他的需求。请问将此移至Mac专用线程是否过于迂腐?(那需要额外花费吗?:*) - Vincent Buscarello
显示剩余8条评论

131

9
我认为这种方法比我提出的解决方案更好,因为ssh-add使用身份验证代理可以记住受保护的私钥的密码,这样您就不必每次尝试进行身份验证时都要输入密码。您提出的解决方案的另一个优势是,如果您有许多密钥,ssh客户端不会提供与您尝试连接的服务器无关的密钥,它将仅提供适用于此服务器的密钥,而不会因尝试ssh/config中列出的所有密钥而导致服务器拒绝连接,因为已达到MaxAuthTries的限制。 - daminetreg
1
感谢@daminetreg。我的特定问题是需要在开发机器上访问gitosis,而不需要将我的私钥传输到它上面。这个解决方案(以及将ForwardAgent yes添加到我的.ssh/config中)非常好地解决了这个问题。事实证明,它只需要ssh-add &>/dev/null,因为ssh-add的默认行为似乎是添加它在您的.ssh文件夹中找到的密钥。 - Aaron
1
我的理解是Mac OS中有一个-K开关:https://dev59.com/wHI-5IYBdhLWcg3wVWvv - Nicu Tofan
3
@TNick -K 命令可以将密钥添加到 macOS 的钥匙串中,这些密钥可用于身份验证外部服务器。该问题的发布者通过 SSH 隧道连接到远程服务器。但实际上仍然只是连接到远程服务器。 A-[SSH 隧道]->B 我所处的情况是我在远程服务器上,但希望身份验证使用我本地系统中的凭据。 A <-[身份验证]-**B**-[连接]->C 因此,-K 命令并没有实际帮助我的情况,但对于另一个问题来说是个好解决方案。 - Aaron
Linux或Ubuntu的等效命令是什么?我收到“未知选项--K”(我承认我甚至不确定为什么需要这样做...) - Charlie Parker

59

只需添加钥匙链,就像在Ubuntu快速提示中引用的那样:https://help.ubuntu.com/community/QuickTips

什么是Keychain

使用keychain管理ssh密钥,而不是经常启动ssh-agent和ssh-add。要安装keychain,可以点击此处,也可以使用Synaptic进行操作或从命令行使用apt-get命令。

命令行

另一种安装该文件的方法是打开终端(应用程序->附件->终端)并输入:

sudo apt-get install keychain

编辑文件

接下来,您应该将以下行添加到${HOME}/.bashrc或/etc/bash.bashrc中:

keychain id_rsa id_dsa
. ~/.keychain/`uname -n`-sh

1
第二个命令究竟是做什么的,纯属好奇?这只是为当前用户打开权限吗? - Vincent Buscarello
2
这个 .source 的别名。 - Brad Solomon
2
id_dsa是什么?我在这个页面上搜索了一下,只在这个答案和另一个中看到了提到它,但在原始问题中没有。这只是像id_rsa一样的另一个密钥吗,因为正在设置2个密钥? - therobyouknow
当使用这种方法时,在打开第一个终端时,会要求输入我的密码短语。 - therobyouknow
3
我想知道钥匙串是否保存了SSH密钥的密码,它是如何保存的?这些密码保存在哪里? - Sudhir Singh Khanger
显示剩余3条评论

24
我在Ubuntu 16.04上遇到了同样的问题:有些密钥被永久添加,而其他密钥则需要在每个会话中执行ssh-add。我发现那些被永久添加的密钥在~/.ssh中既有私钥又有公钥,而那些在每个会话中被忘记的密钥只有私钥在~/.ssh目录中。因此解决方法很简单:在执行ssh-add之前,你应该将私钥和公钥一起复制到~/.ssh中。
附言:据我从Gnome Wiki所理解的,我的方法要归功于gnome-keyring工具,这是Gnome桌面环境的一部分。因此,我的方法可能只适用于使用Gnome或基于Gnome的桌面环境。

8
被低估的回答。在搜寻了两个小时后,这个回答解决了我的问题,而且没有需要额外的脚本或软件包。 - etagenklo
太棒了!做得好,真是个伟大的侦探工作。我觉得我自己不会想到这一点。 - nicorellius
1
对我来说,这也是解决方案!您不需要任何其他软件、安装或配置。只需将两个密钥放入即可。 - Andreas
虽然这可能有效,但我建议将公钥和私钥放在同一个地方是一个非常糟糕的主意 - 这就像把钥匙留在车里。 - Oly Dungey
1
这对我有用。@OliverDungey 我同意也不同意。归根结底,除非您将私钥存储在计算机之外(例如闪存驱动器),因为它在您的目录中,另一个sudo用户/ root可以使用find命令访问文件,无论它在哪里。如果您是系统上唯一的用户并且有强密码,我认为这不构成风险。 - Charles Ludlow
这在我的Ubuntu 20.04和22.04上运行良好。太棒了! - Sasquatch

20

我尝试了@Aaron的解决方案,但对我来说并没有完全起作用,因为每次在终端中打开一个新标签页时,它都会重新添加我的密钥。所以我稍作修改(请注意,我的大多数密钥也受到密码保护,因此我不能只将输出发送到/dev/null):

added_keys=`ssh-add -l`

if [ ! $(echo $added_keys | grep -o -e my_key) ]; then
    ssh-add "$HOME/.ssh/my_key"
fi
这将检查ssh-add -l的输出(列出已添加的所有密钥),以查找特定密钥,如果未找到,则使用ssh-add添加。现在,当我打开终端时,第一次被要求输入私钥密码,直到我重新启动计算机(或注销 - 我还没有检查)之前不再需要输入密码。由于我有很多密钥,我将ssh-add -l的输出存储在一个变量中以提高性能(至少我认为它可以提高性能 :))。注意:我使用的是Linux,此代码已放置在我的~/.bashrc文件中 - 如果您使用的是Mac OS X,则应将其添加到.zshrc.profile。编辑:正如评论中@Aaron指出的那样,.zshrc文件用于zsh shell - 因此,如果您没有使用它(如果您不确定,则大多数情况下,您正在使用bash),则此代码应放置在.bashrc文件中。

3
.zshrc 是用于 zsh shell,我使用它代替 bash。如果你在 Mac OS X 上使用的是默认的 bash,那么对应的文件名也是 .bashrc - Aaron
1
在Linux机器上,使用Bash时,ssh-add -l不会输出密钥文件名。因此,在执行完ssh-add -l命令后,可以使用返回码echo $?来决定是否添加密钥。 - Bharat G

14
在我的情况下,解决方案是:

配置文件的权限应为600。 chmod 600 config

如上所述评论中由generalopinion提到,
无需更改配置文件的内容。

在Linux Mint 17.1上对我来说不够用。 - Benares
我认为600没有意义。man ssh告诉我们,~/.ssh/config文件是用户可读/写的,而其他人无法写入。 - DawnSong
600 对于用户来说是只读和只写的。 - Enthusiasmus

6

我使用两个id_rsa密钥来运行Ubuntu系统,一个用于个人,另一个用于工作。

ssh-add指令会记住一个密钥(个人密钥),但每次都会忘记公司的那个密钥。

通过比较这两个密钥的差异,我发现我的个人密钥权限为400,而公司的密钥权限为600。其中公司密钥有u+w权限。

将公司密钥的用户写入权限去掉(设置为u-w或设置为400)即可解决我的问题。现在ssh-add能够记住这两个密钥了。


4

对于使用Fish shell的人,您可以使用以下函数,然后在~ / .config / fish / config.fish~ / .config / fish / conf.d / loadsshkeys.fish中的单独配置文件中调用它。它将加载所有以id_rsa开头的密钥到ssh-agent中。

# Load all ssh keys that start with "id_rsa"
function loadsshkeys
  set added_keys (ssh-add -l)
   for key in (find ~/.ssh/ -not -name "*.pub" -a -iname "id_rsa*")
    if test ! (echo $added_keys | grep -o -e $key)
      ssh-add "$key"
    end
  end
end

# Call the function to run it.
loadsshkeys

如果你想在打开终端时自动启动ssh-agent,可以使用danhper/fish-ssh-agent来实现。


1
谢谢,仓库链接似乎现在重定向到https://github.com/danhper/fish-ssh-agent。 - Elijah Lynn
谢谢@ElijahLynn!我编辑了我的回答并更新了存储库链接。 - frederickjh

4
在“~/.bashrc”中添加以下行解决了我的问题。我正在使用Ubuntu 14.04桌面版。
eval `gnome-keyring-daemon --start`
USERNAME="reynold"
export SSH_AUTH_SOCK="$(ls /run/user/$(id -u $USERNAME)/keyring*/ssh|head -1)"
export SSH_AGENT_PID="$(pgrep gnome-keyring)"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接