Short answer: Go to User settings → Account → Two-factor authentication and register an authenticator app, a WebAuthn security key, or both. Save the recovery codes — GitLab shows them once. Then handle the part that actually matters for developers: personal access tokens, SSH keys and CI variables all authenticate without 2FA, so they need auditing separately.
Why a code host is a high-value target
Source code is the obvious answer, and it is the least of it.
Repositories routinely contain credentials — database strings, API keys, cloud secrets — committed by accident and left in history. CI/CD pipelines hold deployment credentials by design. And a GitLab account with write access can push code that runs on production.
That is the supply-chain risk: an attacker does not need to breach your servers if they can commit to the pipeline that deploys to them. This has happened to real organisations, and it starts with one developer’s account.
If you self-host GitLab, the instance itself is also infrastructure worth defending, and so is the server behind it — see 2FA on cPanel and web hosting.
Step 1: Register your first method
- Sign in and click your avatar → Edit profile (or User settings).
- Open Account in the left menu.
- Find Two-factor authentication and click Enable two-factor authentication.
- Scan the QR code with your authenticator app and enter the six-digit code, plus your password.
Any standard TOTP app works — Google Authenticator, Aegis, 2FAS, Microsoft Authenticator, or a password manager. If the QR will not scan, GitLab shows the key for manual entry.
Do not screenshot the QR code — see what’s inside a 2FA QR code.
Step 2: Add a WebAuthn security key
GitLab supports WebAuthn devices — hardware security keys and platform passkeys. Register one, ideally two.
The advantage over TOTP is phishing resistance: the credential is bound to your GitLab instance’s domain, so a lookalike login page cannot use it. Developers are specifically targeted with convincing fake login pages and malicious “collaboration” invitations, so this matters. See hardware security keys, which key to buy and phishing-resistant MFA.
Step 3: Save the recovery codes
GitLab generates ten recovery codes at setup and displays them once. Download them and store them offline — not in a repository, which is an easy mistake to make when everything else lives in Git.
See where to store backup codes safely. If you are self-hosting, note that an administrator can disable 2FA for a user via the Rails console — useful, and also a reason admin accounts need strong protection of their own.
Step 4: Fix Git operations
Once 2FA is on, your account password no longer works for Git over HTTPS. You need one of:
- SSH keys — the cleanest option. Generate a key per machine, add the public key under User settings → SSH Keys, and set an expiry date. Protect the private key with a passphrase.
- Personal access tokens — used in place of a password for HTTPS. Scope them narrowly and set expiry.
Both bypass 2FA entirely by design, which brings us to the part that matters most.
Step 5: The credential audit
This is where developer accounts are actually compromised — not at the login screen.
- Personal access tokens — review the list, revoke anything you cannot account for, scope the rest to the minimum (read_repository rather than api, where possible), and set expiry dates. A token with api scope can do almost anything your account can.
- SSH keys — remove keys for machines you no longer use. An old laptop’s key is a live credential.
- Project and group access tokens — same treatment, and easy to forget because they are not on your profile page.
- CI/CD variables — mark secrets as masked and protected. Unmasked variables leak into job logs, which are frequently more visible than people assume.
- Deploy keys and deploy tokens — audit per project.
- Runners — if you self-host runners, they hold job credentials. Do not run untrusted merge request pipelines on privileged runners.
- Secrets in Git history — enable secret detection scanning. Remember that removing a secret in a new commit does not remove it from history; rotate the credential instead.
The same principle applies at Atlassian, Cloudflare and AWS: token systems run parallel to your login, and 2FA does not touch them.
Step 6: For group and instance administrators
- Enforce 2FA for all group members — Group settings → General → Permissions, with a grace period.
- Self-managed instances can require 2FA globally in Admin Area → Settings → General → Sign-in restrictions.
- Set token expiry policies at group or instance level.
- Require signed commits and protected branches for anything that deploys.
- Review members and remove departed contributors. See 2FA for small teams.
- Enable audit events so unusual activity leaves a trail.
Frequently asked questions
Does GitLab require 2FA?
GitLab.com does not universally mandate it for all users, though groups and self-managed instances can enforce it. Enable it regardless — and note GitHub does require it for code contributors, per our GitHub guide.
Will 2FA break my CI pipelines?
No. Pipelines authenticate with tokens and job credentials, not your login. That is convenient and exactly why token hygiene matters.
What if I lose my phone and my recovery codes?
On GitLab.com, support with identity verification. On self-managed, an administrator can disable 2FA through the Rails console. See recovering accounts after losing your 2FA phone.
Why is my code rejected?
Clock drift on your phone, or — on self-managed instances — server clock drift. Both ends must agree on the time. See why 2FA codes get rejected.
Can I use the same authenticator entry for GitLab and GitHub?
They are separate accounts with separate secrets, so two entries in the same app. Label them clearly.
Should I use SSH or a personal access token?
SSH keys for interactive development on machines you control; scoped tokens for automation and CI. Set expiry on both.
The bottom line
Register an authenticator app and a security key, save the ten recovery codes somewhere that is not a repository, and then do the audit that actually protects you: scoped tokens with expiry, SSH keys pruned, CI variables masked, and secrets rotated rather than deleted from history. For developers, the login is rarely the way in.
Rest of the toolchain: GitHub, Atlassian and AWS root MFA.