Sign commits published to GitLab
Published on September 3rd, 2026Actions used
fetch:templatepublish:gitlab
For more information on these actions and others visit /create/actions in your Roadie application.
Overview
By default the commits that publish:gitlab makes are unsigned. You can have
them signed with a PGP key by storing the private key in Roadie as a secret and
setting signCommit: true on the action.
Once GitLab can match the signature to a key on a user's profile, it shows the commit as Verified.
Generate a signing key
The key must be RSA and must have no passphrase. Other key types are not
supported — see Supported keys below. Note that recent
versions of gpg create an ed25519 key unless you ask for RSA explicitly:
gpg --batch --passphrase '' --quick-generate-key "Scaffolder <[email protected]>" rsa4096 sign never
Check what you got. You are looking for rsa4096 on the sec line:
gpg --list-secret-keys --keyid-format=long [email protected]
Then export both halves:
gpg --armor --export-secret-keys [email protected] > private.asc
gpg --armor --export [email protected] > public.asc
Add the private key to Roadie
Go to https://<tenant-name>.roadie.so/administration/settings/secret and paste
the contents of private.asc into GITLAB_COMMIT_SIGNING_KEY.
The value spans multiple lines. The field expands into a text area when you
paste a multi-line value, and the line breaks matter — a key whose line breaks
have been lost cannot be read. Paste the whole block, including the
-----BEGIN PGP PRIVATE KEY BLOCK----- and -----END PGP PRIVATE KEY BLOCK-----
lines.
Choose Save and Restart. The key is not picked up until the backend has restarted.
If your GitLab integration was configured before commit signing was available, open your GitLab settings in Roadie and save them once. This refreshes the stored integration configuration so it includes the signing key.
Add the public key to GitLab
In GitLab, go to Preferences → GPG Keys and add the contents of
public.asc.
Two things have to line up or GitLab will show the commit as Unverified even though the signature itself is good:
- the email you pass as
gitAuthorEmailmust be one of the user IDs on the key - that email must be added and verified on the GitLab account
Template
You can create a template with this content or import from here .
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: gitlab-signed-commit
title: GitLab repo with a PGP signed commit
description: Publishes a repo to GitLab and signs the initial commit.
spec:
owner: group:default/engineering
type: service
parameters:
- title: Where to publish
required:
- repoUrl
properties:
repoUrl:
title: Repository location
type: string
ui:field: RepoUrlPicker
ui:options:
allowedHosts:
- gitlab.com
- title: Commit identity
required:
- gitAuthorName
- gitAuthorEmail
properties:
gitAuthorName:
title: Commit author name
type: string
default: Roadie Scaffolder
gitAuthorEmail:
title: Commit author email
type: string
description: Must match a user ID on the signing key
steps:
- id: fetch-skeleton
name: Fetch skeleton
action: fetch:template
input:
url: ./skeleton
values:
gitAuthorName: ${{ parameters.gitAuthorName }}
gitAuthorEmail: ${{ parameters.gitAuthorEmail }}
- id: publish
name: Publish to GitLab
action: publish:gitlab
input:
repoUrl: ${{ parameters.repoUrl }}
repoVisibility: private
defaultBranch: main
gitCommitMessage: Initial commit from the Roadie scaffolder
gitAuthorName: ${{ parameters.gitAuthorName }}
gitAuthorEmail: ${{ parameters.gitAuthorEmail }}
signCommit: true
output:
links:
- title: Repository
url: ${{ steps['publish'].output.remoteUrl }}
- title: Signed commit
url: ${{ steps['publish'].output.remoteUrl }}/-/commit/${{ steps['publish'].output.commitHash }}
In the Owner field of the repository picker, use the GitLab namespace path —
your username or a group path, such as my-group. It is not your display name.
Check the result
Open the commit in GitLab and look for the Verified badge. You can also check the signature from a clone:
git log --show-signature -1
gpg: Good signature means the commit was signed with your key.
Supported keys
Commit signing is done in the scaffolder itself rather than by shelling out to
gpg, and the library used supports a narrow set of keys:
| Key | Supported |
|---|---|
| RSA, no passphrase | Yes |
| RSA, passphrase protected | No |
| ed25519, ECDSA and other ECC | No |
An unsupported key is only detected when a template runs, so it is worth confirming the key type when you generate it.
Troubleshooting
| Symptom | Cause |
|---|---|
Signing commits is enabled but no signing key is provided | GITLAB_COMMIT_SIGNING_KEY is not set, or the backend has not restarted since it was saved |
| The step fails while reading the key | The key is not RSA, is passphrase protected, or lost its line breaks when it was pasted |
git log --show-signature shows a good signature but GitLab says Unverified | The public key is not on the GitLab profile, or gitAuthorEmail is not a verified email and a user ID on the key |
| Commits are unsigned and no error is reported | The key could not be read at all. Check the task log for a message about the signing key |
The namespace ... is not found | The Owner field holds a display name rather than a GitLab namespace path |
A failed signing step happens after the GitLab project has been created, so a failed run can leave an empty project behind. Delete it before retrying with the same name.