The Secure Guide to Managing GitLab SSH Keys

The Apono Team

July 8, 2025

The Secure Guide to Managing GitLab SSH Keys post thumbnail

SSH keys may be the riskiest credentials you’re not thinking about. In today’s DevOps pipelines, GitLab SSH keys silently facilitate critical operations—from pushing code to deploying infrastructure. 

Just because GitLab SSH keys are unassuming doesn’t mean you should ignore them. Unlike passwords, SSH keys don’t trigger alerts when reused, leaked, or silently exploited. Unfortunately, attackers know this, too. 88% of all web application attacks involved stolen credentials. Last year, 2.8 billion passwords appeared for sale on the dark web.

Whether you’re a developer committing code or a platform engineer automating CI/CD, poorly managed SSH keys open the door to unauthorized access and untraceable changes.

What are SSH keys, and why do they matter for GitLab?

SSH (Secure Shell) keys are a cryptographic authentication method for establishing secure, encrypted connections between systems. Instead of relying on usernames and passwords, SSH keys allow for more secure, automated authentication.

An SSH key pair consists of two parts:

  • A public key is shared and stored on the remote server (like GitLab).
  • A private key, which remains securely stored on the user’s machine. 

When you connect to GitLab, your private key proves your identity without ever sending a password over the network. SSH keys are commonly used to securely push and pull code from repositories, automate deployments, and enable CI/CD tools to access Git projects without manual credential handling. 

For developers and platform engineers, SSH keys reduce friction while maintaining security—but there’s a catch: SSH keys only work as intended if they’re managed properly. Poor SSH key hygiene (e.g., reusing keys, not rotating them, or storing them insecurely) opens the door to credential abuse and unauthorized code changes.

How an SSH Key Pair Works

Understanding Non-Human Identities (NHIs) in GitLab

While SSH keys are often associated with developers, many are used by non-human identities (NHIs), such as CI/CD tools and infrastructure bots. These machine identities require access to GitLab repositories to complete tasks like syncing code or running builds.

Managing these identities securely is part of machine identity management (MIM). Each NHI should have precisely scoped, temporary access, just like a human user. Poor oversight of NHI credentials, especially static SSH keys, can expose your pipelines to serious risks, such as unauthorized code changes or lateral movement within your infrastructure.

It’s not just a vague possibility—these attacks occur in real life. In 2023, Microsoft exposed a Shared Access Signature (SAS) token granting full access to 38TB of internal data, including personal chats and documents. The long-lived token, a form of NHI, lacked expiration and proper access scoping. Similarly, BeyondTrust suffered a breach in 2024 due to an overprivileged API key that enabled attackers to escalate privileges across systems via a chained vulnerability.

How to Use SSH Keys to Communicate with GitLab

To securely access GitLab repositories using SSH, you need to generate an SSH key pair, add the public key to GitLab, and configure your local environment. Below is a step-by-step guide to get you up and running.

How to Use SSH Keys

1. Generate an SSH Key Pair for Your GitLab Account

Use the following command to generate a new key pair:

ssh-keygen -t ed25519 -C “[email protected]

If ed25519 isn’t supported on your system, fallback to:

ssh-keygen -t rsa -b 4096 -C “[email protected]

When prompted:

  • File location: Press Enter to save it to the default location (~/.ssh/id_ed25519). If a key already exists at that location, this will overwrite it. Use a custom filename to avoid this if you’re managing multiple keys.
  • Passphrase: Choose a strong, unique passphrase for enhanced security.

This step creates two files:

  • id_ed25519 (private key – keep secure)
  • id_ed25519.pub (public key – safe to share)

Pro tip: Use a custom filename if managing multiple keys (e.g., id_gitlab).

2. Add Your Public Key to GitLab

Make sure you install xclip if you haven’t already (e.g., for Linux systems). 

Copy the public key to your clipboard:

cat ~/.ssh/id_ed25519.pub | pbcopy   # macOS
xclip -sel clip < ~/.ssh/id_ed25519.pub   # Linux
clip < ~/.ssh/id_ed25519.pub   # Windows (Git Bash)

In GitLab:

  1. Go to User SettingsSSH Keys.
  2. Paste the key into the Key field.
  3. Set an expiration date to enforce periodic key rotation.
  4. Click Add key.

Security tip: Set an expiry date for each SSH key, especially for contractors or ephemeral environments.

SSH Keys

3. Configure the SSH Agent

To avoid entering your passphrase each time, you can load your private key into the SSH agent.

eval “$(ssh-agent -s)”
ssh-add ~/.ssh/id_ed25519

If you’re using a custom filename or key path, specify it accordingly.

Troubleshooting: If ssh-add returns an error, ensure your private key file has the correct permissions (chmod 600 ~/.ssh/id_ed25519) and that the SSH agent is running.

4. Test Your SSH Connection to GitLab

Verify the setup with:

ssh -T [email protected]

You should see:

Welcome to GitLab, @yourusername!

If prompted to trust the GitLab server fingerprint, type yes. This step adds GitLab to your known_hosts file.

Common issues:

  • Permission denied: Double-check if the correct key is loaded (ssh-add -l).
  • Wrong key used: Force usage of the right identity by editing your ~/.ssh/config:

With these steps complete, your machine is securely configured to communicate with GitLab via SSH—ideal for Git operations, automation scripts, and CI/CD workflows. Next, let’s make sure your keys are properly secured and managed.

SSH Key Lifecycle

10 Best Practices for Securing GitLab SSH Keys

Using SSH keys with GitLab significantly enhances the security of your development workflows—but only if they’re managed properly. Here are ten best practices to ensure your SSH keys remain secure and effective.

1. Use Strong, Modern Key Types

Avoid outdated algorithms like DSA. Instead, generate keys with stronger encryption standards like:

ssh-keygen -t ed25519 -C “[email protected]

Or, if you need broader compatibility:

ssh-keygen -t rsa -b 4096 -C “[email protected]

The ed25519 type is preferred for its speed and security.

2. Protect Your Private Key with a Passphrase

Always add a strong, unique passphrase when generating your SSH key, which ensures that even if someone obtains your private key file, they still can’t use it without the passphrase.

To change or add a passphrase to an existing key, use:

ssh-keygen -p -f ~/.ssh/id_ed25519

For long-running sessions, tools like ssh-agent or gpg-agent can securely cache your passphrase in memory so you don’t have to re-enter it constantly. If the passphrase is forgotten, the key becomes unusable and must be regenerated.

3. Store Private Keys Securely

Never commit your private SSH key (id_ed25519 or id_rsa) to Git or store it in publicly accessible locations.

Use encrypted disk storage or a password manager that supports file attachments for backup—this applies not just to SSH keys, but also to secrets used in API security contexts.

Set correct file permissions:

chmod 600 ~/.ssh/id_ed25519

4. Use One Key Per Device

Generate a unique SSH key pair for each device you use to access GitLab. This step allows you to revoke a single key if the device is lost or compromised without affecting access from other systems.

GitLab allows you to associate multiple SSH keys with your account. Use unique names to keep track of each device and manage them independently.

5. Rotate Keys Periodically

Regularly rotate your SSH keys, particularly if they’ve been used for a long time or if you suspect they may have been exposed. It involves:

  • Removing the old public key from GitLab.
  • Generating a new pair.
  • Adding the new public key.

Consider automating SSH key rotation using a centralized access management platform like Apono, which can enforce short-lived access and eliminate the risks of stale credentials, especially in ephemeral or short-term environments.

6. Restrict SSH Key Usage

If you’re managing a shared GitLab instance or have admin rights:

  • Use GitLab deploy keys for CI/CD or automation tasks.
  • Grant keys only the access level they need (read-only vs. read/write).
  • If required, use GPG signing in addition to SSH for commit verification. To ensure commit authenticity, consider enabling GPG signing for commits alongside SSH-based repository access.

Keep in mind that deploy keys in GitLab are tied to individual projects and can be granted read-only or read/write permissions. Be cautious when enabling write access, especially for automation tasks. 

For CI/CD pipelines and automated processes, you’re not managing human users—you’re securing machine identities. These non-human identities often need access to multiple environments but pose risks if granted persistent, broad permissions. It is especially important when pipelines include tasks like testing, deployment, or code generation, which require secure, scoped access to your GitLab repo.

Managing SSH keys for NHIs requires automation, auditability, and temporary access control—capabilities built into platforms like Apono, which help enforce just-enough, time-bound permissions for both humans and machines.

What are non-human Identities

7. Monitor and Audit Key Usage

Regularly review the list of SSH keys in your GitLab account:

  • Navigate to User > Preferences > SSH Keys (depends on GitLab version/edition).
  • Check for unfamiliar keys or outdated entries.
  • Remove keys that are no longer in use.

GitLab’s audit events and API endpoints can help automate SSH key inventory and alerting. For a more comprehensive view across cloud infrastructure and CI/CD workflows, platforms like Apono offer centralized logging, real-time auditing, and granular insight into how SSH credentials are used, granted, and revoked. Take a leaf out of Okta’s book for what not to do—in 2023, the company experienced a breach through a compromised service account (a type of non-human identity), exposing sensitive customer data. 

In addition to routine audits, periodic penetration testing can help uncover misconfigured SSH key permissions and exposed keys.

8. Avoid Using SSH Keys on Shared Machines

Never store your private SSH key on a shared or public system. If you’re using such a machine, consider temporary access tokens or Git over HTTPS instead.

Use ssh-add -l to verify that your key is currently loaded into the agent. If you’re using a custom key path, don’t forget to specify it when adding the key.

9. Use an SSH Agent for Convenience and Security

An SSH agent lets you enter your passphrase once per session and keeps your key in memory, minimizing repeated exposure. On Windows, enable the agent via:

#Powershell
Set-Service -Name ssh-agent -StartupType Manual
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519

On macOS and Linux, use:

#Bash
eval “$(ssh-agent -s)”
ssh-add ~/.ssh/id_ed25519

10. Disable Inactive Accounts Promptly

If a contributor leaves your team, remove their SSH keys immediately from GitLab to prevent unauthorized user access. Integrate SSH key deactivation into your offboarding workflow using GitLab’s user management API. In enterprise settings, consider syncing GitLab with your access management platform (whether Apono or others) to automate removing access when HR systems disable a user.

Taking GitLab SSH Security Further with Apono

SSH keys are a foundational element in securing access to GitLab repositories. By replacing password-based logins with strong public-private key cryptography, SSH keys ensure that only verified users and systems can interact with your codebase. Whether you’re working on personal projects or managing enterprise-scale infrastructure, using SSH keys properly is essential for maintaining secure and efficient developer workflows.

In this guide, we’ve covered:

  • What SSH keys are and why they matter.
  • How to generate, configure, and use SSH keys with GitLab.
  • Troubleshooting tips and hardening best practices.

Apono automates and governs access to GitLab and other tools with Just-In-Time (JIT) workflows, ephemeral credentials, and auto-expiring permissions. Instead of long-lived keys sitting unused (and vulnerable), Apono grants precisely scoped access when needed, and revokes it when it’s not. This eliminates standing privileges, enforces least privilege, and shrinks your attack surface.

With Apono, you can:

  • Replace static SSH key management with dynamic, audited access.
  • Apono integrates with GitLab to govern access at the repository and deployment level—ideal for securing CI/CD pipelines, GitOps workflows, and service-to-repo automation. 
  • Automatically revoke access when it’s no longer needed—no manual cleanup required.
  • Users can request and receive SSH access directly from Slack, Teams, or the CLI—no tickets, no waiting, and full auditability.

Don’t let SSH keys become your weakest link. Pair them with Apono to automate access, enforce least privilege, and stay audit-ready at scale.Ready to eliminate standing access and secure GitLab at scale? Book a personalized Apono demo and see how JIT access can transform your security posture.

Related Posts

How a DevSecOps Initiative Could Have Prevented the IKEA Canada Privacy Breach post thumbnail

How a DevSecOps Initiative Could Have Prevented the IKEA Canada Privacy Breach

Earlier this week, IKEA Canada confirmed that an employee had accessed...

Ofir Stein

September 20, 2022

Top 5 AWS Permissions Management Traps DevOps Leaders Must Avoid post thumbnail

Top 5 AWS Permissions Management Traps DevOps Leaders Must Avoid

As born-in-the cloud organizations grow, natively managed Identity and...

Ofir Stein

September 20, 2022

How we passed our SOC2 compliance certification in just 6 weeks with Apono post thumbnail

How we passed our SOC2 compliance certification in just 6 weeks with Apono

We recently went through the SOC2 process and are happy to report that...

Ofir Stein

September 20, 2022