Help us learn about your current experience with the documentation. Take the survey.

在 GitLab CI/CD 中使用 SSH 密钥

  • Tier: Free, Premium, Ultimate
  • Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated

GitLab 在构建环境(GitLab Runner 运行的环境)中没有内置的 SSH 密钥管理支持。

当您需要以下操作时,请使用 SSH 密钥:

  • 检出内部子模块。
  • 使用包管理器下载私有包。例如 Bundler。
  • 将应用程序部署到您自己的服务器或 Heroku 等平台。
  • 从构建环境执行 SSH 命令到远程服务器。
  • 将文件从构建环境同步到远程服务器。

最广泛支持的方法是通过扩展 .gitlab-ci.yml 将 SSH 密钥注入到构建环境中,这是一种适用于任何类型 executor(如 Docker 或 shell)的解决方案。

创建和使用 SSH 密钥

要在 GitLab CI/CD 中创建和使用 SSH 密钥:

  1. 使用 ssh-keygen 在本地 创建新的 SSH 密钥对
  2. 将私钥作为 文件类型 CI/CD 变量 添加到您的项目中。变量值必须以换行符(LF 字符)结尾。要添加换行符,在保存 SSH 密钥到 CI/CD 设置之前,在最后一行末尾按 EnterReturn
  3. 在作业中运行 ssh-agent,它会加载私钥。
  4. 将公钥复制到您要访问的服务器上(通常在 ~/.ssh/authorized_keys 中)。 如果您要访问私有 GitLab 仓库,还需要将公钥添加为 部署密钥

在以下示例中,ssh-add - 命令不会在作业日志中显示 $SSH_PRIVATE_KEY 的值,但如果您启用了 调试日志,它可能会被暴露。您可能还想检查 流水线的可见性

使用 Docker executor 时的 SSH 密钥

当您的 CI/CD 作业在 Docker 容器内运行(意味着环境是隔离的)并且您想要将代码部署到私有服务器时,您需要一种访问方式。在这种情况下,您可以使用 SSH 密钥对。

  1. 您首先必须创建一个 SSH 密钥对。更多信息请遵循 生成 SSH 密钥 的说明。 不要 为 SSH 密钥添加密码短语,否则 before_script 会提示输入密码。

  2. 创建一个新的 文件类型 CI/CD 变量

    • Key 字段中,输入 SSH_PRIVATE_KEY
    • Value 字段中,粘贴您之前创建的密钥对中的私钥内容。 确保文件以换行符结尾。要添加换行符,在保存更改之前,在 SSH 密钥的最后一行末尾按 EnterReturn
  3. 使用 before_script 操作修改您的 .gitlab-ci.yml。在以下示例中,假设使用基于 Debian 的镜像。根据需要编辑:

    before_script:
      ##
      ## 如果尚未安装 ssh-agent,请安装它,Docker 需要它。
      ##(如果您使用基于 RPM 的镜像,请将 apt-get 更改为 yum)
      ##
      - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
    
      ##
      ## 在构建环境中运行 ssh-agent
      ##
      - eval $(ssh-agent -s)
    
      ##
      ## 给予正确的权限,否则 ssh-add 将拒绝添加文件
      ## 将存储在 SSH_PRIVATE_KEY 文件类型 CI/CD 变量中的 SSH 密钥添加到代理存储
      ##
      - chmod 400 "$SSH_PRIVATE_KEY"
      - ssh-add "$SSH_PRIVATE_KEY"
    
      ##
      ## 创建 SSH 目录并给予正确的权限
      ##
      - mkdir -p ~/.ssh
      - chmod 700 ~/.ssh
    
      ##
      ## 可选,如果您将使用任何 Git 命令,设置用户名和
      ## 邮箱。
      ##
      # - git config --global user.email "user@example.com"
      # - git config --global user.name "User name"

    before_script 可以设置为默认值或每个作业单独设置。

  4. 确保私有服务器的 SSH 主机密钥已验证

  5. 最后一步,将您在第一步中创建的公钥添加到您希望从构建环境访问的服务中。如果您要访问私有 GitLab 仓库,必须将其添加为 部署密钥

就是这样!您现在可以在构建环境中访问私有服务器或仓库了。

使用 Shell executor 时的 SSH 密钥

如果您使用的是 Shell executor 而不是 Docker,设置 SSH 密钥会更简单。

您可以从安装 GitLab Runner 的机器上生成 SSH 密钥,并使用该密钥运行此机器上的所有项目。

  1. 首先,登录到运行您的作业的服务器。

  2. 然后,从终端,以 gitlab-runner 用户身份登录:

    sudo su - gitlab-runner
  3. 按照 生成 SSH 密钥 的说明生成 SSH 密钥对。 不要 为 SSH 密钥添加密码短语,否则 before_script 会提示输入密码。

  4. 最后一步,将您之前创建的公钥添加到您希望从构建环境访问的服务中。 如果您要访问私有 GitLab 仓库,必须将其添加为 部署密钥

生成密钥后,尝试登录到远程服务器以接受指纹:

ssh example.com

对于访问 GitLab.com 上的仓库,您将使用 git@gitlab.com

验证 SSH 主机密钥

检查私有服务器自身的公钥是一个好习惯,以确保您没有成为中间人攻击的目标。如果发生任何可疑情况,您会注意到,因为作业会失败(当公钥不匹配时 SSH 连接失败)。

要查找您服务器的主机密钥,从可信网络(最好是私有服务器本身)运行 ssh-keyscan 命令:

## 使用域名
ssh-keyscan example.com

## 或使用 IP
ssh-keyscan 10.0.2.2

创建一个新的 文件类型 CI/CD 变量,将 SSH_KNOWN_HOSTS 作为 “Key”,将 ssh-keyscan 的输出作为 “Value”。确保文件以换行符结尾。要添加换行符,在保存更改之前,在 SSH 密钥的最后一行末尾按 EnterReturn

如果您必须连接到多个服务器,所有服务器主机密钥必须收集在变量的 Value 中,每行一个密钥。

使用文件类型 CI/CD 变量而不是直接在 .gitlab-ci.yml 中使用 ssh-keyscan,好处是如果主机域名因某种原因更改,您不必更改 .gitlab-ci.yml。此外,值是由您预定义的,这意味着如果主机密钥突然更改,CI/CD 作业不会失败,所以服务器或网络有问题。

现在 SSH_KNOWN_HOSTS 变量已创建,除了 .gitlab-ci.yml 的内容,您还必须添加:

before_script:
  ##
  ## 假设您创建了 SSH_KNOWN_HOSTS 文件类型 CI/CD 变量,取消注释以下两行。
  ##
  - cp "$SSH_KNOWN_HOSTS" ~/.ssh/known_hosts
  - chmod 644 ~/.ssh/known_hosts

  ##
  ## 或者,使用 ssh-keyscan 扫描您私有服务器的密钥。
  ## 将 example.com 替换为您的私有服务器域名。如果您有多个要连接的服务器,请重复该命令。
  ## 包含 -t 标志来指定密钥类型。
  ##
  # - ssh-keyscan -t rsa,ed25519 example.com >> ~/.ssh/known_hosts
  # - chmod 644 ~/.ssh/known_hosts

  ##
  ## 您可以选择禁用主机密钥检查。请注意,通过添加此选项,您容易受到中间人攻击。
  ## 警告:仅与 Docker executor 一起使用,如果您与 shell 一起使用,您将覆盖用户的 SSH 配置。
  ##
  # - '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" >> ~/.ssh/config'

不使用文件类型 CI/CD 变量使用 SSH 密钥

如果您不想使用文件类型 CI/CD 变量,SSH 项目示例 展示了另一种方法。此方法使用常规 CI/CD 变量而不是之前推荐的文件类型变量。

故障排除

Error loading key "/builds/path/SSH_PRIVATE_KEY": error in libcrypto 消息

如果 SSH 密钥有格式错误,可能会返回此消息。

当将 SSH 密钥保存为 文件类型 CI/CD 变量 时,值必须以换行符(LF 字符)结尾。要添加换行符,在保存变量之前,在 SSH 密钥的 -----END OPENSSH PRIVATE KEY----- 行末尾按 EnterReturn