When GitLab says your SSH key has expired, it usually means the public key registered to your GitLab account has passed its expiration date. Your local private-key file may still be readable; GitLab is simply no longer accepting that registered key for Git operations.
The usual fix is to add a valid public key, make sure your SSH client uses its matching private key, and test authentication before retrying Git.
First, check which key is affected
Open the SSH Keys section of your GitLab profile or user settings and check the key’s status and expiration date. Also check whether you already have another valid key registered to the account you need. You may not need to generate a new pair if an existing identity is appropriate.
To inspect local SSH files and the fingerprint of a public key, run:
ls -la ~/.ssh
ssh-keygen -lf ~/.ssh/id_ed25519.pub
Change the filename if your key uses a different name. Public keys typically end in .pub; the similarly named file without that suffix is the private key. Keep that private file secret.
Create a replacement key if needed
Using a separate filename helps avoid overwriting a key that may still be used for another account or service:
ssh-keygen -t ed25519 -C "you@example.com" -f ~/.ssh/id_ed25519_gitlab
Replace the comment with a label that helps you identify the key. Set a passphrase when prompted if it fits your workflow.
This creates two files:
-
~/.ssh/id_ed25519_gitlab— the private key; do not share it. -
~/.ssh/id_ed25519_gitlab.pub— the public key; this is the one you can register with GitLab.
Print the public key so you can copy it:
cat ~/.ssh/id_ed25519_gitlab.pub
In GitLab’s SSH Keys settings, paste the complete output into the key field, give it a recognizable title, and set an expiration date that follows your organization’s policy. If you use a self-managed GitLab instance, use its hostname and check with its administrator about any additional rules.
Never paste or upload the private key. The public key is safe to register; the private key proves possession of that identity.
Tell SSH to use the replacement
If the new key is not your default SSH identity, configure the GitLab host in ~/.ssh/config:
Host gitlab.com
HostName gitlab.com
User git
IdentityFile ~/.ssh/id_ed25519_gitlab
IdentitiesOnly yes
For a self-managed instance, replace gitlab.com with that instance’s hostname. If you use a custom host alias, make sure the alias matches the host in your Git remote.
A different client or environment may use a different key. For example, a desktop Git client, a container, another computer, or a CI job might not use the identity configured for your interactive terminal.
Test authentication before retrying Git
For GitLab.com, test the connection with:
ssh -T git@gitlab.com
For a self-managed instance, substitute its hostname. On a first connection, SSH may ask you to confirm the server’s host key. Verify its fingerprint through a trusted source before accepting it.
A successful test should identify the GitLab account that accepted the key. GitLab may also say that shell access is not provided; that message can still mean SSH authentication succeeded.
If the test works, retry the failed clone, pull, or push. If Git still cannot access the repository, confirm that the authenticated account has permission and that the remote points to the intended project:
git remote -v
A Git-over-SSH remote commonly looks like git@gitlab.com:group/project.git. Check that it names the expected host and repository.
If the error persists
Check these items in order:
- The replacement public key is listed on the GitLab account you intend to use and has not expired.
- Your SSH configuration points to the matching private key, and the
IdentityFilepath is correct. - The Git remote uses the host you tested. A successful test against GitLab.com does not validate a different self-managed instance.
- Your client is offering the identity you expect. For more detail, try
ssh -vT git@gitlab.comand look for lines showing which identity files are offered. Review verbose output before sharing it, since it can contain information about your local setup. - If automation is involved, update the private-key secret and the corresponding public-key or deploy-key configuration. Keep private key material in the system’s protected secret storage; don’t commit it or print it in logs.
What “expired” does—and doesn’t—mean
An ordinary OpenSSH key pair does not have a built-in expiration date. In this GitLab error, expiration usually applies to the public key’s registration with GitLab. A local private-key file can remain readable even though GitLab no longer accepts its registered public key.
That differs from an SSH user certificate, which can have its own validity period. It also differs from a generic Permission denied (publickey) error, which can happen when the wrong key, account, or host is being used.
You generally don’t need to delete an expired entry before adding a replacement. First verify that the replacement works everywhere it is needed. Then remove the old GitLab entry if it is no longer needed. Removing a key from GitLab revokes access through that account; deleting a local file alone does not revoke a public key that remains registered.
The key distinction is simple: GitLab’s expiration applies to the key it trusts, not necessarily to the private-key file on your machine. Register the right public key, configure the matching private key in each environment, and test the exact GitLab host before returning to your Git operation.
I originally published a more detailed version of this guide on the SSHFlow blog.
I'm also building SSHFlow — an SSH client where every server gets its own workspace for terminals, SFTP, code, and databases.
Top comments (0)