Deploy Github Pages With GPG Signing
December 18, 2024 · 5 min read · Page View:
DALL 3 prompt: Git commit with GPG signature --ar 16:9
If you have any questions, feel free to comment below.
I have been busy migrating my blog this week. Coincidentally, I learned that there may be cases of commit forgery on GitHub. Therefore, for security reasons, I added a GPG signature. However, when deploying Hugo, I encountered many problems regarding whether GPG signatures can also be used. Fortunately, I finally solved them.
If you don’t know what GPG is, you can read GPG 101.
How to Deploy Github Pages With Gpg Signing and Verify #
There are two main ways to deploy:
- Push all source files to GitHub directly, then use the relevant action to complete the entire deployment process.
- Isolate the blog source files from the built files, push the source files to the private repository of GitHub each time, and then set up the relevant workflow in the private repository to push to the public static repository.
To ensure greater security, I chose the second method, deploying Hugo in the workflow of GitHub Pages, and using the actions-gh-pages
action. However, due to various reasons, the author of this action does not want to add the GPG signature feature. Therefore, we have to solve the problem ourselves.
Import GPG Key #
First, I found a workflow for importing GPG keys on GitHub. After reading the documentation, my own workflow is as follows:
- name: Import GPG key # import the gpg key to the github action
uses: crazy-max/ghaction-import-gpg@v6 # repository https://github.com/crazy-max/ghaction-import-gpg
with: # I use the subkey to sign the commit, if you use the primary key, you can refer to his repository docs.
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} # the secret gpg subkey
passphrase: ${{ secrets.PASSPHRASE }} # the passphrase of the gpg subkey
git_user_signingkey: true
git_commit_gpgsign: true
fingerprint: ${{ secrets.FINGERPRINT }} # the fingerprint of the public subkey you use
If you only use the primary secret key of GPG, you do not need to add the fingerprint, and I generated a dedicated subkey for signing for security reasons. Therefore, you need to specify the fingerprint of the public key of the subkey. Note that the fingerprint should be entered without spaces; otherwise, it will report an error 67108933 Not implemented <GPG Agent>
. I added this note to the corresponding issue.
Don’t forget to fill in the corresponding secret variables and values in the repository.
Deploy #
Since the author does not plan to add GPG signature, we need to clone the project and modify it ourselves. Usually, the -S
option is used in the commit to specify the use of GPG signature. Therefore, I found the corresponding function in the commit and added the corresponding -S
option.
Note that the modified workflow you created cannot be used directly. The author’s instructions are as follows:
This action and my other actions do not provide the branch execution. I add the lib/index.js for only each release commit. After releasing, I delete it.
Therefore, we still need to publish a version ourselves. Run ./release.sh
directly in the project, and publish the version you wrote. After that, you can reference your version in the workflow, and my workflow is as follows:
- name: Deploy Web
uses: timerring/[email protected] # this is adjusted action from peaceiris/actions-gh-pages, you can use it directly.
with:
personal_token: ${{ secrets.PERSONAL_TOKEN }} # the personal token of the github action
external_repository: your_username/your_repository # your target repository
publish_branch: main # the branch you want to deploy
publish_dir: ./public # the directory you want to deploy
user_name: ${{ secrets.USER_NAME }} # the name of the github action
user_email: ${{ secrets.USER_EMAIL }} # the email of the github action # ATTENTION: please add your github verified email
commit_message: ${{ github.event.head_commit.message }}
Note that please ensure that you add the email verified by GitHub; otherwise, the default parameter ${process.env.GITHUB_ACTOR}@users.noreply.github.com
will only generate [email protected]
, not [email protected]
. This is a historical issue with GitHub, details can be found here. However, your private key does not contain this UUID, so it cannot be verified by GPG. (Even if you add this UID to the keys, since the user email has not been verified by GitHub, it will only display unverified
in the end.)
In short, if your GitHub account was created after July 18, 2017, then your GitHub email address is
[email protected]
, not the default[email protected]
. In this case, you need to specify theuser_email
parameter and fill in the email address you have verified.
Finally, after pushing to the blogsource
repository, the workflow will automatically deploy to the blog
repository, and the commit will be signed with GPG and display verified
!
You can check my result here, every commit pushed from the blogsource
repository will be signed with GPG and display verified
.
Appendix #
If you also need my hugo deployment method, you can directly use the action version I modified and released, repository address timerring/actions-gh-pages, refer to my complete workflow yaml, and don’t forget to fill in the corresponding secret variables and values:
name: deploy
on:
push:
branches:
- main
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
submodules: true
fetch-depth: 0
ref: main
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: "0.108.0"
extended: true
- name: Build Web
run: hugo --minify
- name: Import GPG key # import the gpg key to the github action
uses: crazy-max/ghaction-import-gpg@v6 # repository https://github.com/crazy-max/ghaction-import-gpg
with: # I use the subkey to sign the commit, if you use the primary key, you can refer to his repository docs.
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} # the secret gpg subkey
passphrase: ${{ secrets.PASSPHRASE }} # the passphrase of the gpg subkey
git_user_signingkey: true
git_commit_gpgsign: true
fingerprint: ${{ secrets.FINGERPRINT }} # the fingerprint of the public subkey you use
- name: Deploy Web
uses: timerring/[email protected] # this is adjusted action from peaceiris/actions-gh-pages, you can use it directly.
with:
personal_token: ${{ secrets.PERSONAL_TOKEN }} # the personal token of the github action
external_repository: your_username/your_repository # your target repository
publish_branch: main # the branch you want to deploy
publish_dir: ./public # the directory you want to deploy
user_name: ${{ secrets.USER_NAME }} # the name of the github action
user_email: ${{ secrets.USER_EMAIL }} # the email of the github action # ATTENTION: please add your github verified email
commit_message: ${{ github.event.head_commit.message }}
Related readings
If you find this blog useful and want to support my blog, need my skill for something, or have a coffee chat with me, feel free to: