README.md 8.1 KB
Newer Older
1 2
---
last_updated: 2017-12-13
M
Marcia Ramos 已提交
3
type: tutorial
4 5 6
---

# Using SSH keys with GitLab CI/CD
7

8
GitLab currently doesn't have built-in support for managing SSH keys in a build
9
environment (where the GitLab Runner runs).
10 11 12

The SSH keys can be useful when:

13
1. You want to checkout internal submodules
14 15 16 17
1. You want to download private packages using your package manager (e.g., Bundler)
1. You want to deploy your application to your own server, or, for example, Heroku
1. You want to execute SSH commands from the build environment to a remote server
1. You want to rsync files from the build environment to a remote server
18

19
If anything of the above rings a bell, then you most likely need an SSH key.
20

21
The most widely supported method is to inject an SSH key into your build
22 23 24 25 26 27
environment by extending your `.gitlab-ci.yml`, and it's a solution which works
with any type of [executor](https://docs.gitlab.com/runner/executors/)
(Docker, shell, etc.).

## How it works

28
1. Create a new SSH key pair locally with [`ssh-keygen`](https://linux.die.net/man/1/ssh-keygen)
29
1. Add the private key as a [variable](../variables/README.md) to
30
   your project
31
1. Run the [`ssh-agent`](https://linux.die.net/man/1/ssh-agent) during job to load
32 33 34 35 36 37
   the private key.
1. Copy the public key to the servers you want to have access to (usually in
   `~/.ssh/authorized_keys`) or add it as a [deploy key](../../ssh/README.md#deploy-keys)
   if you are accessing a private GitLab repository.

NOTE: **Note:**
38 39
The private key will not be displayed in the job log, unless you enable
[debug logging](../variables/README.md#debug-logging). You might also want to
40
check the [visibility of your pipelines](../pipelines/settings.md#visibility-of-pipelines).
41 42

## SSH keys when using the Docker executor
43

44 45 46 47 48 49
When your CI/CD jobs run inside Docker containers (meaning the environment is
contained) and you want to deploy your code in a private server, you need a way
to access it. This is where an SSH key pair comes in handy.

1. You will first need to create an SSH key pair. For more information, follow
   the instructions to [generate an SSH key](../../ssh/README.md#generating-a-new-ssh-key-pair).
50
   **Do not** add a passphrase to the SSH key, or the `before_script` will
51 52
   prompt for it.

53
1. Create a new [variable](../variables/README.md#gitlab-cicd-environment-variables).
54 55 56 57 58 59
   As **Key** enter the name `SSH_PRIVATE_KEY` and in the **Value** field paste
   the content of your _private_ key that you created earlier.

1. Modify your `.gitlab-ci.yml` with a `before_script` action. In the following
   example, a Debian based image is assumed. Edit to your needs:

M
Marcel Amirault 已提交
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
   ```yaml
   before_script:
     ##
     ## Install ssh-agent if not already installed, it is required by Docker.
     ## (change apt-get to yum if you use an RPM-based image)
     ##
     - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'

     ##
     ## Run ssh-agent (inside the build environment)
     ##
     - eval $(ssh-agent -s)

     ##
     ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
     ## We're using tr to fix line endings which makes ed25519 keys work
     ## without extra base64 encoding.
     ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556
     ##
79
     - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
M
Marcel Amirault 已提交
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97

     ##
     ## Create the SSH directory and give it the right permissions
     ##
     - mkdir -p ~/.ssh
     - chmod 700 ~/.ssh

     ##
     ## Optionally, if you will be using any Git commands, set the user name and
     ## and email.
     ##
     #- git config --global user.email "user@example.com"
     #- git config --global user.name "User name"
   ```

   NOTE: **Note:**
   The [`before_script`](../yaml/README.md#before_script-and-after_script) can be set globally
   or per-job.
98 99 100 101 102 103 104

1. Make sure the private server's [SSH host keys are verified](#verifying-the-ssh-host-keys).

1. As a final step, add the _public_ key from the one you created in the first
   step to the services that you want to have an access to from within the build
   environment. If you are accessing a private GitLab repository you need to add
   it as a [deploy key](../../ssh/README.md#deploy-keys).
105

106 107
That's it! You can now have access to private servers or repositories in your
build environment.
108

109
## SSH keys when using the Shell executor
110

111 112
If you are using the Shell executor and not Docker, it is easier to set up an
SSH key.
113

114 115
You can generate the SSH key from the machine that GitLab Runner is installed
on, and use that key for all projects that are run on this machine.
116

117
1. First, log in to the server that runs your jobs.
118

119
1. Then, from the terminal, log in as the `gitlab-runner` user:
120

121
   ```shell
M
Marcel Amirault 已提交
122 123
   sudo su - gitlab-runner
   ```
124

125 126 127 128 129 130 131 132 133
1. Generate the SSH key pair as described in the instructions to
   [generate an SSH key](../../ssh/README.md#generating-a-new-ssh-key-pair).
   **Do not** add a passphrase to the SSH key, or the `before_script` will
   prompt for it.

1. As a final step, add the _public_ key from the one you created earlier to the
   services that you want to have an access to from within the build environment.
   If you are accessing a private GitLab repository you need to add it as a
   [deploy key](../../ssh/README.md#deploy-keys).
134

135
Once done, try to log in to the remote server in order to accept the fingerprint:
136

137
```shell
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
ssh example.com
```

For accessing repositories on GitLab.com, you would use `git@gitlab.com`.

## Verifying the SSH host keys

It is a good practice to check the private server's own public key to make sure
you are not being targeted by a man-in-the-middle attack. In case anything
suspicious happens, you will notice it since the job would fail (the SSH
connection would fail if the public keys would not match).

To find out the host keys of your server, run the `ssh-keyscan` command from a
trusted network (ideally, from the private server itself):

153
```shell
154 155 156 157 158
## Use the domain name
ssh-keyscan example.com

## Or use an IP
ssh-keyscan 1.2.3.4
159 160
```

161
Create a new [variable](../variables/README.md#gitlab-cicd-environment-variables) with
162 163 164 165 166 167 168
`SSH_KNOWN_HOSTS` as "Key", and as a "Value" add the output of `ssh-keyscan`.

NOTE: **Note:**
If you need to connect to multiple servers, all the server host keys
need to be collected in the **Value** of the variable, one key per line.

TIP: **Tip:**
169
By using a variable instead of `ssh-keyscan` directly inside
170 171 172 173 174 175 176 177 178
`.gitlab-ci.yml`, it has the benefit that you don't have to change `.gitlab-ci.yml`
if the host domain name changes for some reason. Also, the values are predefined
by you, meaning that if the host keys suddenly change, the CI/CD job will fail,
and you'll know there's something wrong with the server or the network.

Now that the `SSH_KNOWN_HOSTS` variable is created, in addition to the
[content of `.gitlab-ci.yml`](#ssh-keys-when-using-the-docker-executor)
above, here's what more you need to add:

179
```yaml
180 181 182 183 184
before_script:
  ##
  ## Assuming you created the SSH_KNOWN_HOSTS variable, uncomment the
  ## following two lines.
  ##
185
  - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
186 187 188 189 190 191 192 193 194 195 196 197
  - chmod 644 ~/.ssh/known_hosts

  ##
  ## Alternatively, use ssh-keyscan to scan the keys of your private server.
  ## Replace example.com with your private server's domain name. Repeat that
  ## command if you have more than one server to connect to.
  ##
  #- ssh-keyscan example.com >> ~/.ssh/known_hosts
  #- chmod 644 ~/.ssh/known_hosts

  ##
  ## You can optionally disable host key checking. Be aware that by adding that
V
Ville Skyttä 已提交
198
  ## you are susceptible to man-in-the-middle attacks.
199 200 201 202 203
  ## WARNING: Use this only with the Docker executor, if you use it with shell
  ## you will overwrite your user's SSH config.
  ##
  #- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
```
204

205 206
## Example project

207
We have set up an [Example SSH Project](https://gitlab.com/gitlab-examples/ssh-private-key/) for your convenience
208 209 210 211
that runs on [GitLab.com](https://gitlab.com) using our publicly available
[shared runners](../runners/README.md).

Want to hack on it? Simply fork it, commit and push your changes. Within a few
212
moments the changes will be picked by a public runner and the job will begin.