Skip to content

Signed Runner Commits

Jump to forgejo-runner

If using the base Forgejo runner image of Debian Bullseye you need to upgrade git from backports channel to obtain commit.gpgsign ability, or just upgrade the whole build environment image. The simplest way is to update config.yml for your Forgejo runner and inside the labels field swap the runners container image. I set mine to use Ubuntu 22.04 for some of the extra packages included in the base image, and git will be current enough for the features I require.

labels: [ "docker:docker://gitea/runner-images:ubuntu-22.04" ]

How its configured

Whenever a forgejo runner pushes code to a remote repository on my behalf I want the action to still be from my account, just a separate author so I can determine what I have personally pushed and what was an action on my behalf.

Features of this setup: - Forgejo runner bot will use a unique SSH key pair to sign commits - Commits have a separate author name but share one account - Build pipeline will fail if either parties key pairs change

Signing Commit Messages

First step is to add a NON password protected public key to Codeberg, and verify the key by signing a message with your private key and submitting it back to Codeberg. Do this from the web UI under your user account Settings. Once your key is verified test your SSH connection to Codeberg.

ssh -i ~/.ssh/private_key -T git@codeberg.org

Configure Git

You don't have to use the --global flag if you are configuring this on a local system with git already setup. I'm using this in an isolated runner environment that are destroyed each run.

git config --global user.email your_username@noreply.codeberg.org
git config --global user.name your_username
git config --global commit.gpgsign true
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/public_key

At this point you could clone, sign your commits, and push as you'd expect... So it should be easy to reproduce that in a git action workflow?

HA!

Forgejo Runners | you even known_host?

I squashed 53 commits of frustration to finally run down where these issues were coming from. Using trusty ssh -vvv flags and breaking the mkdocs deploy script apart, I have arrived at the solution.

I like to write my actions out manually rather than relying on 3rd party workflows. This makes sure I'm 100% aware of what is happening in the code and when. You do loose a lot of the already worked out error handling and niceties of a predefined workflow.

known_hosts

You will need to add Codeberg's public key to your known_hosts file otherwise the SSH connection will fail until you pass both StrictHostKeyChecking no and UserKnownHostsFile /dev/null to SSH. The better solution is you use ssh-keyscan and add the public key for Codeberg proactively.

This little bit took a lot of reading docs and blog posts to find the correct solution.

ssh-keyscan codeberg.org >> ~/.ssh/known_hosts

SSH config

echo "${{ secrets.SSH_CONFIG }}" > ~/.ssh/config

I am using secrets to write a formatted config file that makes sure the correct SSH key is used with git. Can we take a moment to appreciate formatted secrets ♥️ It solves basic file creation in most cases rather than cating text to a buffer cat <<'EOF' > config.file and hoping the format is correct.

This is all that's required for a basic SSH config file but if you use multiple git accounts feel free to customize to suite your needs.

Host codeberg.org
    IdentityFile ~/.ssh/private_key

Solution

jobs:
  gitSign:
    runs-on: docker
    steps:
      - name: Setup SSH
        run: |
          if [ ! -d ~/.ssh ]; then
            mkdir ~/.ssh
          fi
          echo "${{ secrets.SSH_CONFIG }}" > ~/.ssh/config
          ssh-keyscan codeberg.org >> ~/.ssh/known_hosts
          echo "${{ secrets.PRIV_SSH_KEY }}" > ~/.ssh/private_key
          echo "${{ secrets.PUB_SSH_KEY }}" > ~/.ssh/public_key.pub
          chmod 700 ~/.ssh/
          chmod 600 ~/.ssh/*
          chmod 644 -f ~/.ssh/*.pub ~/.ssh/config ~/.ssh/known_hosts
          ssh -vvv -i ~/.ssh/private_key -T git@codeberg.org

      - name: Configure git and clone repos
        run: |
          git config --global user.email noflcl@noreply.codeberg.org
          git config --global user.name noflcl
          git config --global commit.gpgsign true
          git config --global gpg.format ssh
          git config --global user.signingkey ~/.ssh/autobot.pub
          git clone git@codeberg.org:your_username/git_repo.git