实现 CI/CD 环境下的 SSH 免密登录,主要涉及以下几个步骤:

1. 生成 SSH 密钥对 (在 CI/CD 系统或安全的环境中生成)

位置: 密钥对的生成应在安全的、可控的环境中进行,通常在 CI/CD 系统自身或者一个安全的管理机器上。不要在开发人员的本地机器上生成用于生产环境的密钥,因为私钥的安全性至关重要。

命令: 使用 ssh-keygen 命令生成密钥对。与普通 SSH 免密登录类似,但需要考虑密钥的存放和管理。

ssh-keygen -t rsa -b 4096 -N "" -f ./id_rsa_deploy

-t rsa: 指定密钥类型为 RSA (也可以选择 ed25519,更安全高效)。
-b 4096: 指定密钥长度为 4096 位 (RSA 密钥推荐 4096 位或以上,提高安全性)。
-N "": 设置为空密码短语 (passphrase)。在 CI/CD 自动化场景中,通常不设置 passphrase,因为自动化脚本无法交互式输入 passphrase。但请权衡安全性,如果你的 CI/CD 系统可以安全地管理 passphrase,设置 passphrase 会更安全。 如果选择不使用 passphrase,务必更加小心地保护私钥。
-f ./id_rsa_deploy: 指定私钥文件名为 id_rsa_deploy,并保存在当前目录。你可以自定义文件名和路径。
执行该命令后,会生成两个文件:

id_rsa_deploy (私钥): 极其重要,必须妥善保管,不要泄露。 这是 CI/CD 系统用来进行 SSH 认证的凭证。
id_rsa_deploy.pub (公钥): 需要部署到目标服务器。

2. 在 CI/CD 系统中安全存储私钥

不要硬编码在代码中: 绝对不要将私钥直接硬编码在 CI/CD 配置文件、脚本或者源代码仓库中。这是非常不安全的行为。

使用 CI/CD 系统的 Secrets 管理功能: 绝大多数现代 CI/CD 系统 (例如 Jenkins, GitLab CI, GitHub Actions, Azure DevOps Pipelines, CircleCI 等) 都提供了安全的 Secrets 或 Credentials 管理功能。你应该使用这些功能来存储私钥。

环境变量: 某些系统允许将 Secrets 设置为环境变量,在 CI/CD 任务运行时注入。但环境变量有时可能存在泄露风险 (例如日志输出)。
Secret Files: 更安全的方式是将私钥作为 Secret 文件上传到 CI/CD 系统,在任务运行时,CI/CD 系统会将私钥文件安全地挂载到任务运行环境中。
示例 (以 GitLab CI 为例):

在 GitLab CI 中,你可以在 "Settings" -> "CI/CD" -> "Variables" 中添加一个类型为 "File" 的变量,变量名为 DEPLOY_PRIVATE_KEY,并将 id_rsa_deploy 私钥文件的内容粘贴到 "Value" 字段中。

3. 分发公钥到目标部署机器

公钥需要被添加到所有目标部署机器的 ~/.ssh/authorized_keys 文件中。有多种方式可以实现:

手动复制 (适用于少量服务器,初始化配置): 最简单的方式是手动 SSH 登录到每台目标服务器,创建 .ssh 目录 (如果不存在),并将公钥内容追加到 ~/.ssh/authorized_keys 文件中,并设置正确的权限 (chmod 700 ~/.ssh, chmod 600 ~/.ssh/authorized_keys)。

4. 在 CI/CD Pipeline 中使用私钥进行 SSH 连接

在 CI/CD 管道的部署任务中,需要使用之前存储在 Secrets 中的私钥进行 SSH 连接。具体的实现方式取决于你使用的 CI/CD 系统和部署工具。

脚本方式 (例如 Shell 脚本): 在 CI/CD 任务中执行 Shell 脚本,使用 ssh 命令进行连接。

示例 (GitLab CI .gitlab-ci.yml 文件):

deploy_job:
  stage: deploy
  image: alpine/ssh  # 包含 ssh 命令的 Docker 镜像
  variables:
    DEPLOY_SERVER_IP: "your_deploy_server_ip"
    DEPLOY_USER: "deploy_user"
    DEPLOY_PATH: "/path/to/deploy/directory"
  script:
    - mkdir -p ~/.ssh
    - echo "$DEPLOY_PRIVATE_KEY" > ~/.ssh/id_rsa  # 将 Secret 变量写入私钥文件
    - chmod 600 ~/.ssh/id_rsa
    - ssh -o StrictHostKeyChecking=no -i ~/.ssh/id_rsa $DEPLOY_USER@$DEPLOY_SERVER_IP "
        cd $DEPLOY_PATH &&
        git pull origin main &&
        # 执行部署命令,例如重启服务等
        echo 'Deployment successful!'
      "
  environment:
    name: production