Git Course 0%

Tokens, SSH keys, security settings

Intermediate GitLab UI ≈ 8 min

What you will learn

  • Which GitLab credential to use for which job, and where each is created
  • How to check what you have and revoke what you do not need
  • Where a project keeps the secrets its pipeline uses

After this lesson you can

  • I can create the least powerful credential that does the job, and clean up the rest

Why this matters

Section 8 covered what tokens and keys are. This lesson is the map: which of GitLab's six credential types to reach for, and the exact page each one lives on. Getting this right is what separates "I made a token" from "I made a token that can only read one project and expires in ninety days".

The choice, in one table

Pick the least powerful thing that works. It is the whole skill.

You want to Use Created at
Push and pull over HTTPS as yourself Personal access token, write_repository Avatar → Edit profileAccess → Personal access tokens
Push and pull over SSH as yourself SSH key Avatar → Edit profileSSH Keys
Let a script or tool act on one project Project access token Project → SettingsAccess tokens
Let a script act across a group's projects Group access token Group → SettingsAccess tokens
Let a deploy system read the repository or registry Deploy token, or a read-only deploy key Project → SettingsRepository
Give a pipeline job a secret CI/CD variable, masked and protected Project → SettingsCI/CDVariables

Two rules follow from the table. Never use your personal token for automation: it carries all of your access, it dies when you leave, and its actions look like yours in the audit log. And never put a credential in the repository: that is what CI/CD variables exist for (lesson 8.6).

Personal credentials

Personal access tokens are yours and carry your permissions, limited by the scopes you tick. For Git over HTTPS, write_repository is enough; api is only needed by tools that read issues and merge requests, such as the VS Code and IntelliJ integrations. Set an expiry you can live with; GitLab emails you before a token expires, and that email is the only warning you get.

SSH keys live on the same profile menu, one public key per machine, optionally with an expiry (lesson 8.2).

The token value is shown once, at creation. If you did not copy it, revoke it and make another; there is no way to see it again.

Project and group access tokens

These belong to the project or the group rather than to a person, which is what makes them right for automation. Creating one gives you two choices beyond the scopes:

  • A role. The token cannot do more than that role could, so a token for reading issues should be a Guest or Reporter, not a Maintainer (lesson 9.3).
  • An expiry, which GitLab requires you to think about and which is the main defence against a forgotten credential.

Behind the scenes each one creates a bot user, which is why its activity appears in the project as a distinct name rather than as yours. Creating them needs the Maintainer or Owner role.

Deploy tokens and deploy keys

Both give a machine access to one project without a person's account.

Deploy token Deploy key
Is a username and password pair an SSH public key
Can read or write the repository, and read the registry read, or read and write, the repository
Cannot use the API use the API or the registry
Good for a server that pulls the code or an image a build machine you already manage by SSH

If you are choosing for a documentation build server that only needs to clone, a read-only deploy token or key is the correct answer and a personal token is not.

Secrets a pipeline needs

Settings → CI/CD → Variables holds values jobs read as environment variables. Three settings on each one matter:

Setting Effect
Masked The value is replaced with [MASKED] in job logs
Protected Only jobs on protected branches and tags can read it
Expanded / raw Whether $OTHER inside the value is substituted

Mask anything secret, and protect anything that can change the world: a deployment key, a publishing token. An unprotected variable is readable by any job on any branch, which means anyone who can push a branch can print it.

Reviewing what you have

Once every few months, or on the day someone leaves:

  1. Edit profile → Access → Personal access tokens: revoke what you no longer recognize, and note what expires soon.
  2. Edit profile → SSH Keys: remove keys for machines you no longer have.
  3. Edit profile → Authentication log: check where your account has been used from.
  4. Project Settings → Access tokens and Settings → Repository: revoke tokens and keys for retired systems.
  5. Project Settings → CI/CD → Variables: confirm the sensitive ones are masked and protected.
  6. Group or project Manage → Members: remove people who have left (lesson 9.3).

Revoking is instantaneous and reversible only by making a new credential, which is the right trade: a token you are unsure about should be revoked, not kept.

How to do it

Nothing here is a Git command, but two checks tell you which credential your clone is actually using:

Terminal
$ git remote -v
origin	git@gitlab.com:northwind-trails/trailguide.git (fetch)
origin	git@gitlab.com:northwind-trails/trailguide.git (push)

A git@ address uses your SSH key; an https:// address uses a token from the credential manager (lesson 8.4). To check which account your SSH key authenticates as:

Terminal
$ ssh -T git@gitlab.com

Common mistakes

  • A personal token used by a server. It leaves with you and it carries all your access.
  • api scope when write_repository would do. Scope is the blast radius.
  • No expiry. A credential nobody remembers is a credential nobody revokes.
  • An unmasked CI/CD variable, printed into a job log the first time someone debugs.
  • An unprotected variable holding a deployment secret, readable from any branch anyone can push.
  • Keeping tokens "in case". Revoke; making a new one takes a minute.

Try it yourself

Goal: audit your own credentials and replace one with something weaker.

  1. Open Edit profile → Access → Personal access tokens and list what you have, with scopes and expiry dates.
  2. Revoke anything you cannot explain in one sentence.
  3. On your practice project, open Settings → CI/CD → Variables and add a variable called DEMO_SECRET, masked and protected.
  4. Add a job to .gitlab-ci.yml that runs echo "$DEMO_SECRET", push it on a branch, and read the job log.
  5. Explain the result: the value is masked, and on an unprotected branch it is empty.

Expected result: the log shows [MASKED] rather than the value, and, because the variable is protected and your branch is not, the job prints nothing at all.

Show solution

Step 5 is the lesson. Protected is not about hiding the value in the log, which is what masked does; it is about which branches can read it at all. Together they mean a secret used for deployment cannot be exposed by anyone who can push a branch, which is the attack that catches teams out.

Check yourself

1. A build server needs to clone one project and nothing else. Which credential?
2. What does marking a CI/CD variable protected do?
3. You created a personal access token and closed the page without copying it. What now?

Key terms

Environment variable Pipeline Maintainer Project