Easy verified commits in GitHub Actions with no GPG hassles
Unsigned commits look suspicious. GitHub shows "Verified" badges on signed commits, proving they're authentic. Signing commits with GPG within CI is tricky. Signing commits with SSH is much simpler.
This action makes it trivial.
Add this to your workflow (e.g., .github/workflows/release.yml
):
steps:
- uses: actions/checkout@v4 # Must come first!
- uses: photostructure/git-ssh-signing-action@v1
with:
ssh-signing-key: ${{ secrets.SSH_SIGNING_KEY }}
git-user-name: ${{ secrets.GIT_USER_NAME }}
git-user-email: ${{ secrets.GIT_USER_EMAIL }}
Important: This action must be placed after actions/checkout
because it configures git locally by default.
Input | Required | Default | Description |
---|---|---|---|
ssh-signing-key |
✅ | - | SSH private key for signing |
git-user-name |
✅ | - | Git user name |
git-user-email |
✅ | - | Git user email |
ssh-key-path |
~/.ssh/signing_key |
Where to store the key | |
git-commit-gpgsign |
true |
Sign all commits | |
git-tag-gpgsign |
true |
Sign all tags | |
git-push-gpgsign |
if-asked |
Sign pushes | |
git-config-scope |
local |
Use global to configure git globally |
If you need the action to work before checkout or across multiple repositories:
steps:
- uses: photostructure/git-ssh-signing-action@v1
with:
ssh-signing-key: ${{ secrets.SSH_SIGNING_KEY }}
git-user-name: ${{ secrets.GIT_USER_NAME }}
git-user-email: ${{ secrets.GIT_USER_EMAIL }}
git-config-scope: global # Works anywhere in workflow
# Generate Ed25519 key (recommended)
# -N "" creates a passwordless key (required for CI)
# -C must match the GitHub username that will own this key
ssh-keygen -t ed25519 -f ~/.ssh/signing-key -N "" -C "yourproject-bot"
# Copy public key for next step
cat ~/.ssh/signing-key.pub
- Sign in as your machine user account (if using one)
- Go to Settings → SSH and GPG keys
- Click New SSH key
- Critical: For "Key type", select "Signing Key" (
⚠️ NOT "Authentication Key") - Title:
Repository Release Signing Key
- Key: Paste the contents from
cat ~/.ssh/signing-key.pub
- Click Add SSH key
# Copy private key to clipboard (macOS)
cat ~/.ssh/signing-key | pbcopy
# Copy private key to clipboard (Linux)
cat ~/.ssh/signing-key | xclip -selection clipboard
Repository → Settings → Secrets → Actions:
SSH_SIGNING_KEY
= private key (paste from clipboard)GIT_USER_NAME
= machine user's GitHub username (e.g.,yourproject-bot
)GIT_USER_EMAIL
= machine user's email
rm ~/.ssh/signing-key ~/.ssh/signing-key.pub
Done! Your commits will now be verified.
Use a machine user account (commonly called a "bot account") for production.
Why not use your personal account?
- Security: If CI credentials leak, only the machine user is compromised, not your personal account
- Persistence: When team members leave, automation continues working
- Audit trail: Clear distinction between human and automated commits
- Access control: Machine user permissions can be limited to specific repositories
Steps to set up a machine user:
-
Create Machine User Account
- Sign up at github.com/join as
yourproject-bot
- Use a real email (needed for collaborator invite)
- Enable 2FA (required by many orgs)
- Sign up at github.com/join as
-
Add Machine User as Collaborator
- Repository Settings → Collaborators → Add people
- Grant write access (needed for pushes)
- Machine user must accept invite via email
-
Generate Machine User's Key
# IMPORTANT: -C must match your machine user's GitHub username exactly ssh-keygen -t ed25519 -f ~/.ssh/machine-user-signing -N "" -C "yourproject-bot" # Display the public key (you'll need this for GitHub) cat ~/.ssh/machine-user-signing.pub
Use this key in your secrets instead.
Problem | Solution |
---|---|
Commits show "Unverified" | Add key as "Signing Key" not "Authentication Key" |
Permission denied | Give bot write access to repository |
Key load failed | Check secret has complete private key |
- Runners:
ubuntu-latest
ormacos-latest
(Windows runners not supported) - Git: 2.34+ (for SSH signing)
- Note: Your dev machine can be Windows, but the workflow must run on Linux/macOS
MIT © PhotoStructure