Why GitLab SSH key restrictions matter for self-managed instances
GitLab SSH key restrictions give administrators one enforced policy over the SSH keys that users add to a self-managed instance. Developers often push over SSH with keys they generated years ago, using whatever tool and default their workstation offered at the time. Some of those keys use algorithms the security team no longer accepts, and some are shorter than current guidance. Without a restriction, each developer's choice becomes the instance's effective policy, and the security team has no single setting to point to during a review. The admin setting lets you choose which key types users may register and the minimum length for each allowed type, so a weak key is refused when it is added, before an auditor finds it.
Teams usually need the restriction in three situations. The first is a FIPS-mode environment, where the cryptographic modules accept only certain key types and lengths, and the GitLab minimums must line up with what those modules allow. The second is an audit finding that names weak SSH keys or unrestricted key types on a system that holds source code. The third is regulated change management, where pushes and commits must trace to an accountable person through a key that meets the organization's standard. Confirm the exact FIPS requirements with your assessor and in the GitLab authentication documentation, since supported algorithms and minimums depend on your version and mode.
The setting has limits you need to plan around. It governs keys added after you enable it, so keys already on accounts may remain until users or administrators remove them. Confirm how your version treats existing keys before you announce the change. It also does not cover deploy keys or other non-user keys, which follow their own controls. Before you enable it, count the keys currently in use, identify which would fail the new policy, and give developers a clear cutoff date and steps to generate a compliant key. Test the change on a staging instance first so you can see how the rejection message looks to developers.
Which SSH key types to allow and which to forbid
Each key type carries a different risk, and the GitLab setting for it is a separate decision. Allow the preferred type first, set the FIPS-driven minimums for the types your regime requires, and forbid the types that should no longer appear on the instance.
ED25519 as the preferred type
Make ED25519 the type you tell engineers to generate and the first entry in your allowed list. It is compact, uses a modern curve and is well supported by current OpenSSH tooling. Before tightening the policy, confirm that every client that connects to GitLab over SSH supports it, including developer workstations, Windows agents and any CI systems that push or pull over SSH. Allow ED25519 first so new keys follow the preferred path.
RSA under FIPS mode
FIPS mode keeps RSA available but only at a minimum key length set by the standard your assessor applies. Set the GitLab RSA minimum to that value and no lower, because a lower setting lets staff register keys that a FIPS-enforced host will reject. Ask your assessor for the current minimum, since the values in FIPS guidance change over time. The minimum comes from your assessor, not from a number copied from a blog post.
ECDSA under FIPS mode
ECDSA is the other type FIPS mode allows, and it is permitted on approved curves only. Your GitLab setting needs both a minimum size and an agreed set of curves. A key that passes the length check can still fail on a host that rejects its curve, so test a sample key on a FIPS-enabled host before rollout. Ask your assessor which curves and sizes they accept in writing.
Forbid DSA entirely
DSA is deprecated and should be disallowed in the GitLab setting, so no DSA key can be registered on the instance. Once the setting is in place, find existing DSA keys on user accounts and remove them during your review. Also check deploy keys and service accounts, since automated users often keep old keys that no one remembers adding. Disallow DSA and treat any remaining DSA key as a finding.
Check existing keys before enforcing
A restriction on new keys does not by itself remove keys users already registered. Before enforcement, list the key types in use across accounts, notify the owners of any key that would fail the new policy, and set a removal date. Confirm in your GitLab version whether the policy is checked against existing keys or only at registration. The GitLab hardening guide covers the wider settings this change belongs with.
SSH key settings and when each fits
This table compares how each SSH key type should be set in the GitLab admin area for three scenarios: a general internal instance, a FIPS-mode environment and a strict policy that bans DSA. Read each row as the setting to apply to that key type, and confirm minimum lengths against the GitLab version you run. Changes in the admin area generally apply to newly added keys first, so review keys already on accounts separately.
| Key type | General internal instance | FIPS-mode environment | Strict policy, DSA banned |
|---|---|---|---|
| ED25519 | Allowed and preferred for new keys. Fixed key size, so no length setting applies. | Confirm that your FIPS-validated OpenSSL and GitLab build accept it before making it the default. | Allowed and preferred. Fixed key size, so no length setting applies. |
| ECDSA | Allowed with a minimum length you set in the admin area. | Allowed only at or above the minimum your FIPS policy requires. Confirm the floor for your version. | Allowed with the same minimum length used for general use. |
| RSA | Allowed with a minimum length that matches your internal key policy. | Allowed at or above the minimum FIPS mode requires. Confirm the floor for your version. | Allowed with a minimum length. Identify existing keys below it and plan their replacement. |
| DSA | Forbidden. Remove legacy DSA keys from user accounts. | Forbidden. | Forbidden. Audit existing DSA keys before enabling the ban. |
| Existing keys | Review keys already on accounts after changing the settings. | Audit stored keys against the minimums before the FIPS settings are enforced. | Run an audit for DSA and short keys before enforcement, and give users time to add replacements. |
How to apply the SSH key policy on a self-managed instance
This sequence takes a self-managed GitLab instance from an inventory of the SSH keys users already hold to a verified policy that allows ED25519 keys, forbids DSA and enforces minimum lengths for RSA and ECDSA. Each step ends with a check so the administrator knows the change is in place before developers are asked to act.
Inventory existing SSH keys by type and length
Start by listing the SSH keys already registered on the instance, grouped by algorithm and key length. The administrator with access to the database or the admin interface runs this review, and the output is a count of keys per type, with the users who own any DSA or short RSA keys. Confirm the exact method for your installed version in the GitLab documentation on SSH keys, since the available reports and API calls differ between releases. The step is complete when you have a written list that shows which users will be affected by a stricter policy.
Agree the policy with security and compliance
Bring the inventory to the security and compliance owners and agree the allowed key types and minimum lengths before anything changes in the admin settings. The policy should name ED25519 as the preferred type, state that DSA is forbidden, and set the RSA and ECDSA minimums that your regulator, auditor or internal standard requires, including any minimums that FIPS mode imposes if you run in that mode. Record the decision, the owner and the review date in your change record. The step is complete when the approved policy is written down and signed off by the people who will be asked about it later.
Set allowed key types and minimum lengths
In the Admin area, open the SSH key restriction settings for the instance and set the allowed key types and minimum key lengths to match the approved policy. Confirm the exact menu path and field names in the GitLab documentation for your installed version before you change anything, because they can move between releases. Save the change as an administrator and note the time and the person who made it. The step is complete when the saved settings display the values you approved, and a reviewer has checked them against the written policy.
Communicate the change with a key generation guide
Send developers a short notice that explains the new policy, the date it takes effect as set by your organization, and what to do if their current key no longer passes. Include a guide with the commands to generate an ED25519 key pair, add the public key to their profile and test an SSH connection to the instance. Name the support contact for users who need help. Some users will have keys that existed before the change, so state whether existing keys remain usable or must be replaced, and confirm that behavior on your installed version before you publish the notice. The step is complete when the notice is sent and the support queue is ready to receive questions.
Attempt to add a forbidden key
As a test user on a non-production account, try to add a DSA key to the profile. The instance should reject it with a message about the key type, and nothing should be stored. Then try an RSA key shorter than the minimum you set, and an ECDSA key below its minimum if your policy covers ECDSA. Record each attempt, the error text and the result. The step is complete when every forbidden or undersized key is refused and the test records show no stored key.
Add a compliant ED25519 key and confirm access
With the same test account, generate an ED25519 key on a workstation, add the public key to the profile and then clone a repository over SSH. The key should be accepted and the clone should succeed. Check the audit or activity record for the key addition if your version logs it. Confirm the exact steps in the GitLab documentation for your installed version. The step is complete when the compliant key is stored, usable for an SSH operation, and visible in the account's key list.
Review existing keys and record the outcome
After the policy is live, rerun the inventory from the first step and confirm that the remaining non-compliant keys are known, scheduled for replacement or removed under your agreed process. Keep the test results, the saved settings and the review output in the change record so an auditor can trace the decision from policy to enforcement. Repeat the review on a schedule your security owner sets. The step is complete when the change record shows the policy, the enforcement evidence and the follow-up owner for any remaining exceptions.
How FIPS mode changes the RSA and ECDSA minimums
A GitLab key policy is only as good as the host that has to accept the key. In a FIPS-enabled environment, the operating system's cryptographic module and OpenSSH decide which algorithms and key sizes can actually be used. An RSA or ECDSA minimum set in the GitLab SSH key settings that is lower than what the host accepts is harmless in one direction only. The more dangerous case is a policy that allows a key the FIPS build cannot use, because users will register it, the GitLab check will pass, and the login will fail at the server or at the Git client. Before you set any minimum, confirm with your OS vendor and your OpenSSH build which RSA sizes and ECDSA curves the FIPS mode permits, and align the GitLab values to that list rather than to a generic recommendation.
Treat the FIPS build as its own test target. Use a host that runs in FIPS mode, register a test key that meets the proposed GitLab policy, and push and pull over SSH from a client you would expect a developer or runner to use. Repeat the test for each key type you plan to allow, including ED25519 if your FIPS build supports it, and record the exact OpenSSH and client versions used. A key that is accepted by GitLab but rejected by the host will usually show up as a failed authentication, not as a policy error, so the test must go all the way through the clone or push. Also check any automation that generates keys, such as provisioning scripts, because a key created with a non-permitted algorithm will break that automation on FIPS hosts only.
Record the minimums you choose and the reason for each in your change record, and ask your auditor or compliance lead which control evidence they expect to see for this setting. Confirm the current FIPS minimums with your OS vendor and any applicable standard (rather than relying on figures from older guides), and repeat the end-to-end test after each OS, OpenSSH or GitLab upgrade, since either side can change what it accepts. Keep the FIPS and non-FIPS hosts on separate test lists so a policy that works on one does not get assumed to work on the other.
Security and operational risks to plan for
A key-type policy only governs the keys it is applied to, so the risks sit at the edges: keys created before the change, credentials that never pass through this setting, and the habits of people who generate keys. Work through these cards before you announce the policy, and confirm each item against your own instance and workstation standards.
Existing keys stay valid
A restriction on allowed key types and minimum lengths is generally enforced when a key is added. Keys already registered before the change, including old DSA or short RSA keys, may keep working after you save the setting. Export the full list of user SSH keys, identify the types and lengths that no longer meet policy, and decide whether to notify owners, set a deadline, or remove the keys. Confirm the exact enforcement behavior for your GitLab version in the SSH key settings documentation before you rely on it.
Deploy keys sit outside the policy
Deploy keys are attached to projects rather than to user accounts, so a user-level key type rule does not automatically govern them. Project deploy keys used by CI servers, mirrors and deployment hosts can remain DSA or short RSA keys after the policy is in place. Inventory deploy keys per project, check their types and lengths, and plan their rotation as a separate task. Confirm how your version treats deploy keys against the restriction before you assume coverage.
CI tokens bypass key rules
Pipelines authenticate to GitLab with job tokens, personal or project access tokens, and CI/CD variables that hold credentials for other systems. None of these are SSH keys, so a key type restriction does nothing to limit them. Review which jobs clone over SSH with keys stored in CI/CD variables, move those credentials to a secrets manager where possible, and set token expiry and scopes as part of the same review.
Workstation tools default to RSA
Many developer tools and older operating system images still generate RSA keys by default, and engineers may register a key from an existing file without checking its type. After you forbid DSA and set a minimum length, expect rejected uploads and support requests. Publish the approved ssh-keygen command for ED25519, document how to inspect a key's type and length, and test the procedure on the workstation images your teams actually use.
Rotation after a policy change
Changing the policy creates a rotation project that most teams underestimate. Each affected user must generate a new key, add it to GitLab, update local SSH configuration, and remove the old key, and any automation that uses the old key must be updated in the same window. Plan the cutover with the owners of build servers and scripts, keep a short overlap period if your change process allows it, and record who rotated what for later audit.
Audit logging of key additions
Key additions and removals should appear in your audit trail so that a new weak key or an unexpected key attached to a privileged account can be traced to a user and a time. Confirm which key events your GitLab edition records, where audit events are retained, and whether they reach your central log platform. Set a review routine that compares new keys against the approved types, and treat unexpected additions to administrator accounts as incidents.
Gradual rollout with the hardening guide
The GitLab hardening guide describes its recommendations as a work in progress that should be rolled out gradually. Apply the SSH key policy in a test instance first, then in production after notifying users, and avoid stacking it on other hardening changes in the same window. Record each change so that a broken login can be traced to a single setting, and review the guide again at each upgrade stop, since its recommendations may change.
Questions teams ask before changing SSH key policy
Can our own administrators change SSH key restrictions in GitLab?
Yes. Allowed SSH key types and minimum key lengths are an administrator setting on a self-managed GitLab instance, so a team with an admin account can change them without a partner. The harder work surrounds the setting: telling users which key types will be refused, getting each person to generate a compliant key, deciding what happens to legacy keys that would stop working, and confirming that automation still authenticates. Record that work in a change plan before you touch the setting. Confirm the exact menu path and field names for your GitLab version in the administration documentation, because labels can change between releases.
What makes an SSH key policy change take longer?
Four factors drive most of the effort: the number of users, the number of legacy keys already stored on accounts, whether FIPS mode is required, and how much automation still depends on old keys. Each additional user is another person to notify and another key to replace, so a few hundred accounts is a different project from a small engineering group. Legacy keys carry the most risk because they may belong to people who have left or to scripts nobody maintains, and each one needs an owner decision. FIPS requirements narrow the acceptable algorithms and lengths. Long-lived keys tied to backup jobs, mirroring or deployment tooling must move before enforcement. Count these four factors before you estimate duration.
Do we need a consultant to restrict SSH keys?
Not for the setting itself. A competent GitLab administrator can switch it on. A consultant adds the most value when the change touches many users, a regulated scope, or automation that nobody has inventoried. DeployOpen plans, implements, hardens and documents self-hosted platforms inside your own infrastructure, and most engagements are fixed-scope, with deliverables and timelines agreed in writing before work starts. A partner can run the key inventory, draft the user communication, test the policy on a non-production instance, and produce the change record and configuration documentation. DeployOpen prepares evidence for compliance assessments, but auditors and certification bodies issue the reports. Decide by comparing your team's capacity against the four effort factors.
What should we ask a partner for in a fixed-scope SSH key quote?
Ask for the written scope before the price. A useful quote names the instances covered, the method for inventorying existing keys, the allowed key types and length settings to be applied, and whether FIPS-related configuration is included. It should list the deliverables: the user communication draft, a migration plan for legacy keys and automation, test results from a non-production instance, a rollback step, and updated configuration documentation. Ask what happens if the inventory finds more legacy keys than expected, which items are one-time and which recur, such as periodic reviews, and who decides on exceptions. Request the timeline and its dependencies in writing. DeployOpen does not publish a price list, so a quote follows from that written scope.
Does an SSH key restriction also apply to deploy keys and GitLab Runners?
The setting governs SSH keys that users add to their own accounts, and that is the scope to plan around. Deploy keys are attached to projects or groups and have their own management paths, so they are a separate control, covered in the guidance on push rules and deploy keys. GitLab Runners normally authenticate with runner tokens rather than user SSH keys, so this setting does not secure them. Confirm in the documentation for your version whether any key type restriction reaches deploy keys before you assume it does. Write the answer into your control inventory, so a reviewer can see that each key class was checked.
Will tightening SSH key types break CI jobs or scripts?
It can. Pipelines and scripts that clone, push, pull or mirror over SSH will fail when their key is no longer accepted. Jobs that use HTTPS with tokens are unaffected by an SSH key policy, so the risk sits in SSH-based automation. The safe sequence is to find these uses first, usually by searching job definitions, scheduled tasks, mirror configurations and deployment scripts. Replace each key with one of an allowed type, test the job on a non-production instance, and only then enforce the policy. Expect at least some failures in automation that nobody documented, and assign an owner to each one before the change date.
How does FIPS mode change which SSH keys we must allow?
FIPS mode narrows the algorithms and minimum key lengths a system may use, so the allowed list in GitLab must match what your platform accepts. Confirm the exact FIPS requirements for your environment, along with the minimum lengths GitLab's hardening guidance describes, instead of relying on memory or older examples. Disallowing DSA is a sensible step under either policy. Test a FIPS-enabled build in staging, because a key that works on a standard instance may fail once stricter rules apply. Record which standard or internal policy drives each value, so the configuration can be explained during a compliance assessment.
Is an SSH key policy change a one-time cost or a recurring one?
Most of the cost is one-time: the inventory, the policy change, the user communication and the key migration. Recurring effort is smaller but real. New hires generate new keys, periodic reviews should check for legacy keys that reappear, and each GitLab upgrade should be checked against the setting, since menus and defaults can change. Upgrades also pass through required upgrade stops, so schedule the review in the same window. Ask a partner which items sit inside the fixed scope and which would move to a retainer. Retainers are available for ongoing support, upgrades and continuous testing.
Limits to confirm in your own environment
The SSH key setting is simple to switch on, but its effect depends on the installed release, the authentication path your users take and how the instance is delivered. Each card below is a question to answer against your own GitLab version and deployment before you treat the restriction as enforced.
Which key types the setting governs
Confirm, for the exact GitLab version you run, which key families the allowed-types and minimum-length settings apply to, and whether DSA is blocked outright or only through a zero-length or disabled entry. Test each type with a throwaway account: add the key in the user profile and confirm GitLab rejects it with the message you expect. Do not assume a setting written for one release behaves the same way in the next.
Interaction with SSH certificates
Ask whether your instance uses SSH certificates or any other key-based trust model that bypasses the per-user key upload path. A restriction on uploaded keys may not cover certificate authorities or deploy keys, which can leave a weaker key type reachable by another route. Record each path that grants SSH access and test it separately.
External authentication and key sources
Confirm how users reach the instance: LDAP, SAML, OAuth providers, Kerberos or smart cards each handle identity differently, and a federated login does not always mean the local key rules apply to every user. Check whether keys are managed in the directory or in GitLab, and who owns the policy in each place.
Behavior across required upgrade stops
Plan the restriction as part of each upgrade. Required upgrade stops at versions such as 18.2, 18.5 and 18.8 mean you may apply the change at a stop rather than in one jump, and existing keys that fall outside the new rule may need a plan before the setting takes effect. Confirm in the release notes how existing stored keys are treated after each stop.
Offline and air-gapped instances
Confirm whether your offline or air-gapped instance needs the same procedure, including any package or documentation access it depends on during rollout. Test the setting on an isolated staging copy, because connected-only checks may not reflect how the instance behaves without outbound access.
How to roll the policy out without locking out developers
The safest way to tighten SSH key rules is to stage the change so no developer finds out through a failed git push. Start by announcing the policy, naming the allowed key types and minimum lengths, and stating the date on which the restriction will be enforced. GitLab's hardening recommendations advise rolling out hardening settings gradually and note that the guidance is still being developed, so treat each setting as a step in a plan you run and review, not a single switch. Confirm in your GitLab version whether the restriction blocks new keys only or also rejects existing keys at the next use, because that answer determines how much notice people need.
Give developers the exact steps before the cutover. For most engineers, the instruction is to generate an ED25519 key with ssh-keygen -t ed25519 -C "your.name@example.com", add the public key from ~/.ssh/id_ed25519.pub to their GitLab profile, and confirm access with ssh -T git@your-gitlab-host. Ask people to keep the old key until the new one has pushed and pulled successfully, and to update any ~/.ssh/config entries that name the old key file. Run a short pilot with a small group of engineers first, and collect the errors they hit so the written guide answers the questions the pilot actually raised.
Before setting the cutover date, inventory the keys that will stop working. Filter existing keys by type and length, then decide what to do with each group: personal keys owned by active users, keys tied to blocked or departed accounts, and automation keys used by service accounts or build systems. Deploy keys attached to projects need their own review, since they sit outside personal profiles. Assign an owner to every non-personal key, and schedule its replacement before the date. The cutover should happen only when the remaining list is empty or each remaining entry has a named owner and a confirmed replacement.
How SSH key restrictions fit the wider GitLab hardening plan
Allowed SSH key types are one control in a chain, and they only protect what the other controls let through. A restriction that forbids weak key types limits how a credential can be built, but it does nothing about who is able to create an account in the first place. Sign-up and visibility settings decide who can register and what anonymous users can see, so the SSH key policy should be set alongside them. If self-registration is open, a valid key of an approved type still gives an outsider a foothold, so plan both settings in the same change window and review them together.
Key policy also interacts with administrator access and project-level credentials. A key tied to a full administrator is the highest-value credential on the instance, so pair the key rules with Admin Mode and a small number of full administrators. Deploy keys and push rules solve a different problem: they govern which machine identities can read or write a repository and which commits are accepted. Ask your team to inventory existing user keys and deploy keys before tightening the policy, because keys of a type you are about to forbid will stop working on the next push or pull, and some of them may belong to service accounts nobody currently owns.
Finally, treat runner isolation as the boundary for anything a CI job can reach. A job running on a shared runner that holds a deploy key or a copied private key can use it regardless of how strong that key is. Confirm which runners execute jobs for protected branches, which keys those jobs can read, and whether the runner fleet follows the same trust model as your key policy. Verify the setting with the current GitLab hardening documentation for your release, since guidance on this area is still being rolled out.
How DeployOpen works on this
DeployOpen plans, implements, hardens, documents and supports self-hosted GitLab inside your own infrastructure, including the SSH key settings covered here. The work starts with a written scope that names the key types, minimum lengths and the instance settings you need to change.
How we scope
- Confirm which Git clients, CI runners and automation accounts currently authenticate over SSH
- Record the key types and minimum lengths your security policy or FIPS requirement sets
- List the instances, edition and install method the changes must cover, including offline sites
- Agree the scope, deliverables and timeline in writing before any change is made
- Identify which existing keys will be rejected once the new rules apply and who must rotate them
How we build
- Set the allowed key types and minimum lengths in a staged, documented change
- Test a sample of developer and service keys against the new rules before enforcement
- Review the configuration against the GitLab hardening guidance and your internal baseline
- Check that Runner, mirror and deployment key workflows still authenticate after the change
- Keep a rollback path and record the configuration state before and after each step
How we hand over
- Deliver the final configuration with the reasoning for each key type and length choice
- Provide a runbook for key rotation requests, exception handling and user communication
- Document the verification steps so your team can repeat them after each GitLab upgrade
- Supply evidence of the settings in place for your change management or audit records
- Walk your administrators through the settings and the support path before closing the engagement
How we support
- Offer ongoing support and upgrades as a retainer after the fixed-scope work closes
- Recheck SSH key settings when you move to a new GitLab release that changes defaults
- Review new key policy requirements and update the configuration under the agreed scope
- Help your team respond to users whose keys are rejected after a policy tightening
- Confirm with your auditors or assessors which evidence they expect, since DeployOpen prepares evidence but does not issue assessments

