Skip to content
Arbinel

Commit signing

Arbinel can sign the commits that the instance creates, such as merges, web edits and new repositories. Forgejo’s signing page describes GPG signing and every condition key.

Forgejo supports two signing formats, openpgp (GPG) and ssh, and the keys in [repository.signing] mean different things for each. This page uses SSH, because SSH needs no keyring and Arbinel’s account linking works with SSH signatures.

By default, FORMAT = openpgp and SIGNING_KEY = default. default means the key that Git is configured to use for the user that runs Forgejo. On most installations Git has no signing key configured, so commits are not signed, and the interface does not show why.

You need:

  • Git 2.34 or later and ssh-keygen from OpenSSH 8.2p1 or later on the server.
  • An account or organization that should appear as the signer, with an email address you control.
  1. Create a key pair for the instance, as the user that runs Forgejo. Use an ed25519 key without a passphrase. Security keys (-sk types) do not work.

    ssh-keygen -t ed25519 -N "" -C "instance signing" -f /var/lib/forgejo/signing/instance_ed25519

    This writes the private key instance_ed25519 and the public key instance_ed25519.pub. Git looks for the private key next to the public key, at the same path without .pub.

  2. Configure the signing section in app.ini.

    [repository.signing]
    FORMAT = ssh
    SIGNING_KEY = /var/lib/forgejo/signing/instance_ed25519.pub
    SIGNING_NAME = Example Forge
    SIGNING_EMAIL = example-forge@noreply.example.com
  3. Restart the instance. Arbinel reads the public key at startup and refuses to start if it cannot read or parse it.

  4. Check that the key is published at /api/v1/signing-key.ssh. To verify signatures outside the instance, users add this key to their Git allowedSignersFile.

Key Default Meaning with FORMAT = ssh
FORMAT openpgp Set to ssh.
SIGNING_KEY default Absolute path to the public key. default is not valid with SSH and prevents startup, because Arbinel reads it as a file name. none turns signing off.
SIGNING_NAME empty Name in the commits the instance signs. Arbinel also shows it in “This commit will be signed with key” notices. When empty, the notice shows [server] APP_NAME.
SIGNING_EMAIL empty Email in the commits the instance signs. Arbinel links the signature to the account that owns it, see below.
DEFAULT_TRUST_MODEL collaborator Trust model for new repositories. See trust models.

With GPG, SIGNING_NAME and SIGNING_EMAIL only apply when SIGNING_KEY is a key ID. With SIGNING_KEY = default, all three values come from Git’s configuration instead. With SSH they always apply, so set both.

INITIAL_COMMIT, CRUD_ACTIONS, WIKI and MERGES each take a comma-separated list of conditions. The instance signs only when every condition in the list is met, not only one of them.

Key Default Signs when
INITIAL_COMMIT always Always, for the first commit of a new repository.
CRUD_ACTIONS pubkey, twofa, parentsigned The user has a public key, uses two-factor authentication and the parent commit is signed.
WIKI never Never.
MERGES pubkey, twofa, basesigned, commitssigned The user has a public key and two-factor authentication, the base is signed and every commit in the branch is signed.

With these defaults, a web edit or merge by a user without two-factor authentication is not signed. Set a key to always to sign every time. always and never cannot be combined with other conditions.

[repository.signing]
CRUD_ACTIONS = always
MERGES = always

The trust model determines whether a verified signature shows as trusted, untrusted or unmatched. Repository owners select one under Settings → Signature trust model, and DEFAULT_TRUST_MODEL sets it for new repositories.

Model Trusted when
collaborator The signer is a collaborator of the repository, even when they are not the committer.
committer The signer is the committer. The instance becomes the committer of the commits it signs and credits the user in Co-authored-by: and Co-committed-by: trailers.
collaboratorcommitter The signer is a collaborator and the committer.

In Forgejo, a commit signed with the instance SSH key shows Signed by with the SIGNING_NAME, a placeholder avatar and no link. Arbinel looks up the account that owns SIGNING_EMAIL and credits the signature to it, so Signed by links to that account and shows its avatar.

  • The lookup uses activated email addresses and no-reply addresses. An organization’s no-reply address, <name>@<NO_REPLY_ADDRESS>, resolves to that organization, so you can credit signatures to an organization without giving it a mailbox.
  • The API still reports SIGNING_EMAIL as the signer’s email, not the account’s own address, which may be private.
  • Under the committer trust model the signature shows as trusted, because the signer and the committer are the same account. In Forgejo it shows as unmatched when SIGNING_EMAIL belongs to an account.
  • When the address belongs to no account, Arbinel shows the same placeholder as Forgejo.
  • Only SSH signatures made with the instance key are linked. GPG signatures are unchanged.