doc/ci/jobs/ssh_keys.md
{{< details >}}
{{< /details >}}
GitLab does not have built-in support for managing SSH keys in a build environment (where the GitLab Runner runs).
Use SSH keys when you want to:
The most widely supported method is to inject an SSH key into the build environment by extending
.gitlab-ci.yml. This approach works with any type of executor,
such as Docker or shell.
[!note] When using SSH keys in CI/CD, store private keys securely and avoid reusing personal SSH keys for automated jobs. Rotate keys regularly to reduce the risk of unauthorized access.
To create and use an SSH key in GitLab CI/CD:
SSH_PRIVATE_KEY.ssh-agent in the job, which loads
the private key.~/.ssh/authorized_keys).
If you are accessing a private GitLab repository, you also need to add the public key as
a deploy key.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
debug logging. You might also want to
check the visibility of your pipelines.
To add an SSH key to your project, add the key as a file type CI/CD variable:
Set Visibility to Visible.
[!note] The visibility setting must be Visible because SSH keys contain whitespace characters, and Masked or Masked and hidden variables cannot contain whitespace characters. Never run a command like
catorteeon the variable because the SSH key is not masked if it appears in the job log.
In the Key text box, enter the name of the variable. For example, SSH_PRIVATE_KEY.
In the Value text box, paste the private key content.
The value must end with a newline (LF character).
To add a newline, press <kbd>Enter</kbd> or <kbd>Return</kbd> at the end of the last line
before saving.
If you do not want to use a file type CI/CD variable, see the example SSH Project. This method uses a regular CI/CD variable instead of a file type variable. Generally, file type variables are preferred because they preserve multiline formatting and reduce the risk of formatting-related errors.
When your CI/CD jobs run in Docker containers, the environment is isolated. To deploy your code to a private server, you can use an SSH key pair.
Generate a new SSH key pair.
Do not add a passphrase to the SSH key, or the before_script will prompt for it.
Add the private key as a file type CI/CD variable named SSH_PRIVATE_KEY.
Modify your .gitlab-ci.yml with a before_script action. The following example assumes a
Debian-based image and that the job runs in a container with permission to install packages.
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)
##
## 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
##
- chmod 400 "$SSH_PRIVATE_KEY"
- ssh-add "$SSH_PRIVATE_KEY"
##
## Create the SSH directory and give it the right permissions
##
- mkdir -p ~/.ssh
- chmod 700 ~/.ssh
##
## Optionally, if you use Git commands, set the user name and email.
##
# - git config --global user.email "[email protected]"
# - git config --global user.name "User name"
The before_script can be set as a default
or per-job.
Make sure the private server's SSH host keys are verified.
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 inside the build environment. If you are accessing a private GitLab repository you must add it as a deploy key.
That's it! You can now have access to private servers or repositories in your build environment.
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.
First, sign in to the server that runs your jobs.
Then, from the terminal, sign in as the gitlab-runner user:
sudo su - gitlab-runner
Generate a new SSH key pair.
Do not add a passphrase to the SSH key, or the before_script will
prompt for it.
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 inside the build environment. If you are accessing a private GitLab repository you must add it as a deploy key.
After generating the key, try to sign in to the remote server to accept the fingerprint:
ssh example.com
For accessing repositories on GitLab.com, you would use [email protected].
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):
## Use the domain name
ssh-keyscan example.com
## Or use an IP
ssh-keyscan 10.0.2.2
Add the hosts to your project as a file type CI/CD variable, except:
SSH_KNOWN_HOSTS as the Key.ssh-keyscan as the Value.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.
[!note] By using a file type CI/CD variable instead of
ssh-keyscandirectly inside.gitlab-ci.yml, it has the benefit that you don't have to change.gitlab-ci.ymlif 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.Do not run
ssh-keyscandirectly in a CI/CD job, as it is a security risk vulnerable to machine-in-the-middle attacks.
Now that the SSH_KNOWN_HOSTS variable is created, in addition to the
content of .gitlab-ci.yml, you must add:
before_script:
##
## Assuming you created the SSH_KNOWN_HOSTS file type CI/CD variable:
##
- cp "$SSH_KNOWN_HOSTS" ~/.ssh/known_hosts
- chmod 644 ~/.ssh/known_hosts
... error in libcryptoYou might get the following error when you load an SSH key in a CI/CD job:
Error loading key "/builds/path/SSH_PRIVATE_KEY": error in libcrypto
This issue can happen when the SSH key value does not end with a newline (LF character).
To resolve this issue, edit the
file type CI/CD variable
and press <kbd>Enter</kbd> or <kbd>Return</kbd> at the end of the -----END OPENSSH PRIVATE KEY-----
line of the SSH key before saving the variable.
... value cannot contain...You might get an error when you save an SSH key as a CI/CD variable:
Unable to create masked variable because: The value cannot contain the
following characters: whitespace characters.
This issue occurs when the variable Visibility is set to Masked or Masked and hidden. Masked variables must be a single line with no spaces, but SSH keys contain whitespace characters that are incompatible with masking.
To resolve this issue, set Visibility to Visible when you add the SSH key as a file type variable. File type variables are not exposed in job logs, which provides an additional layer of protection for the key value.