2021-03-11 19:13:27 +05:30
---
stage: Verify
2023-05-27 22:25:52 +05:30
group: Pipeline Security
2022-11-25 23:54:43 +05:30
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
2021-03-11 19:13:27 +05:30
type: tutorial
---
2021-09-30 23:02:18 +05:30
# Using SSH keys with GitLab CI/CD **(FREE)**
2021-03-11 19:13:27 +05:30
GitLab currently doesn't have built-in support for managing SSH keys in a build
environment (where the GitLab Runner runs).
2022-11-25 23:54:43 +05:30
Use SSH keys when you want to:
2021-03-11 19:13:27 +05:30
2022-11-25 23:54:43 +05:30
- Check out internal submodules.
- Download private packages using your package manager. For example, Bundler.
- Deploy your application to your own server or, for example, Heroku.
- Execute SSH commands from the build environment to a remote server.
- Rsync files from the build environment to a remote server.
2021-03-11 19:13:27 +05:30
If anything of the above rings a bell, then you most likely need an SSH key.
The most widely supported method is to inject an SSH key into your build
2021-10-27 15:23:28 +05:30
environment by extending your `.gitlab-ci.yml` , and it's a solution that works
2021-03-11 19:13:27 +05:30
with any type of [executor ](https://docs.gitlab.com/runner/executors/ )
2021-10-27 15:23:28 +05:30
(like Docker or shell, for example).
2021-03-11 19:13:27 +05:30
## How it works
1. Create a new SSH key pair locally with [`ssh-keygen` ](https://linux.die.net/man/1/ssh-keygen )
2023-04-23 21:23:45 +05:30
1. Add the private key as a [file type CI/CD variable ](../variables/index.md#use-file-type-cicd-variables ) to
2021-03-11 19:13:27 +05:30
your project
1. Run the [`ssh-agent` ](https://linux.die.net/man/1/ssh-agent ) during job to load
the private key.
1. Copy the public key to the servers you want to have access to (usually in
2021-04-17 20:07:23 +05:30
`~/.ssh/authorized_keys` ) or add it as a [deploy key ](../../user/project/deploy_keys/index.md )
2021-03-11 19:13:27 +05:30
if you are accessing a private GitLab repository.
2021-04-29 21:17:54 +05:30
In the following example, the `ssh-add -` command does not display the value of
`$SSH_PRIVATE_KEY` in the job log, though it could be exposed if you enable
2023-03-17 16:20:25 +05:30
[debug logging ](../variables/index.md#enable-debug-logging ). You might also want to
2021-09-30 23:02:18 +05:30
check the [visibility of your pipelines ](../pipelines/settings.md#change-which-users-can-view-your-pipelines ).
2021-03-11 19:13:27 +05:30
## SSH keys when using the Docker executor
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
2021-11-18 22:05:49 +05:30
to access it. In this case, you can use an SSH key pair.
2021-03-11 19:13:27 +05:30
2021-11-18 22:05:49 +05:30
1. You first must create an SSH key pair. For more information, follow
2022-06-21 17:19:12 +05:30
the instructions to [generate an SSH key ](../../user/ssh.md#generate-an-ssh-key-pair ).
2021-03-11 19:13:27 +05:30
**Do not** add a passphrase to the SSH key, or the `before_script` will
prompt for it.
2023-04-23 21:23:45 +05:30
1. Create a new [file type CI/CD variable ](../variables/index.md ).
2021-03-11 19:13:27 +05:30
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:
```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)
##
- 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
##
## Run ssh-agent (inside the build environment)
##
- eval $(ssh-agent -s)
##
2023-04-23 21:23:45 +05:30
## Give the right permissions, otherwise ssh-add will refuse to add files
## Add the SSH key stored in SSH_PRIVATE_KEY file type CI/CD variable to the agent store
2021-03-11 19:13:27 +05:30
##
2023-04-23 21:23:45 +05:30
- chmod 400 "$SSH_PRIVATE_KEY"
- ssh-add "$SSH_PRIVATE_KEY"
2021-03-11 19:13:27 +05:30
##
## 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"
```
2021-09-30 23:02:18 +05:30
The [`before_script` ](../yaml/index.md#before_script ) can be set globally
2021-03-11 19:13:27 +05:30
or per-job.
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
2023-04-23 21:23:45 +05:30
step to the services that you want to have an access to from inside the build
2021-11-18 22:05:49 +05:30
environment. If you are accessing a private GitLab repository you must add
2021-04-17 20:07:23 +05:30
it as a [deploy key ](../../user/project/deploy_keys/index.md ).
2021-03-11 19:13:27 +05:30
That's it! You can now have access to private servers or repositories in your
build environment.
## SSH keys when using the Shell executor
If you are using the Shell executor and not Docker, it is easier to set up an
SSH key.
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.
2022-11-25 23:54:43 +05:30
1. First, sign in to the server that runs your jobs.
2021-03-11 19:13:27 +05:30
2022-11-25 23:54:43 +05:30
1. Then, from the terminal, sign in as the `gitlab-runner` user:
2021-03-11 19:13:27 +05:30
```shell
sudo su - gitlab-runner
```
1. Generate the SSH key pair as described in the instructions to
2022-06-21 17:19:12 +05:30
[generate an SSH key ](../../user/ssh.md#generate-an-ssh-key-pair ).
2021-03-11 19:13:27 +05:30
**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
2023-04-23 21:23:45 +05:30
services that you want to have an access to from inside the build environment.
2021-11-18 22:05:49 +05:30
If you are accessing a private GitLab repository you must add it as a
2021-04-17 20:07:23 +05:30
[deploy key ](../../user/project/deploy_keys/index.md ).
2021-03-11 19:13:27 +05:30
After generating the key, try to sign in to the remote server to accept the
fingerprint:
```shell
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. If anything
suspicious happens, you notice it because the job fails (the SSH
connection fails when the public keys don't 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):
```shell
## Use the domain name
ssh-keyscan example.com
## Or use an IP
ssh-keyscan 1.2.3.4
```
2023-04-23 21:23:45 +05:30
Create a new [file type CI/CD variable ](../variables/index.md#use-file-type-cicd-variables )
with `SSH_KNOWN_HOSTS` as "Key", and as a "Value" add the output of `ssh-keyscan` .
2021-03-11 19:13:27 +05:30
2021-11-18 22:05:49 +05:30
If you must connect to multiple servers, all the server host keys
must be collected in the **Value** of the variable, one key per line.
2021-03-11 19:13:27 +05:30
NOTE:
2023-04-23 21:23:45 +05:30
By using a file type CI/CD variable instead of `ssh-keyscan` directly inside
2021-03-11 19:13:27 +05:30
`.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 doesn't fail,
so 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 )
2021-11-18 22:05:49 +05:30
above, you must add:
2021-03-11 19:13:27 +05:30
```yaml
before_script:
##
2023-04-23 21:23:45 +05:30
## Assuming you created the SSH_KNOWN_HOSTS file type CI/CD variable, uncomment the
2021-03-11 19:13:27 +05:30
## following two lines.
##
2023-04-23 21:23:45 +05:30
- cp "$SSH_KNOWN_HOSTS" ~/.ssh/known_hosts
2021-03-11 19:13:27 +05:30
- 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
## you are susceptible to man-in-the-middle attacks.
## 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'
```
## Example project
We have set up an [Example SSH Project ](https://gitlab.com/gitlab-examples/ssh-private-key/ ) for your convenience
that runs on [GitLab.com ](https://gitlab.com ) using our publicly available
2021-09-30 23:02:18 +05:30
[shared runners ](../runners/index.md ).
2021-03-11 19:13:27 +05:30
2021-11-18 22:05:49 +05:30
Want to hack on it? Fork it, commit, and push your changes. In a few
2021-03-11 19:13:27 +05:30
moments the changes is picked by a public runner and the job starts.