diff --git a/.github/workflows/RELEASE_SIGNING.md b/.github/workflows/RELEASE_SIGNING.md
new file mode 100644
index 0000000000..43e854c250
--- /dev/null
+++ b/.github/workflows/RELEASE_SIGNING.md
@@ -0,0 +1,140 @@
+# Release Signing Setup
+
+This document explains how release signing is implemented for bera-geth, including PGP signing for binaries and Cosign signing for Docker images.
+
+## Overview
+
+The bera-geth release process includes cryptographic signing for all release artifacts:
+- **Binary releases**: Signed with PGP/GPG
+- **Docker images**: Signed with Cosign (keyless signing via OIDC)
+
+## Configuration
+
+### Prerequisites for Release Managers
+
+#### PGP Signing Setup
+
+1. **Create the `LINUX_SIGNING_KEY` secret in GitHub**:
+ ```bash
+ # Export your PGP private key
+ gpg --export-secret-keys --armor YOUR_KEY_ID > private.key
+
+ # Base64 encode it
+ cat private.key | base64 -w 0
+
+ # Copy the output and add it as the LINUX_SIGNING_KEY secret in GitHub repository settings
+ ```
+
+2. **Ensure the public key matches**: The public key at `.github/workflows/release.asc` should correspond to the private key used for signing.
+
+#### Cosign Setup
+
+Cosign uses keyless signing (no secret required). The workflow uses GitHub's OIDC provider to sign images, which means:
+- No private keys to manage
+- Signatures are tied to the GitHub Actions workflow identity
+- Full transparency via Rekor transparency log
+
+## Release Process
+
+### Triggering a Release
+
+Releases are triggered by:
+- Pushing a tag matching `v1.*` (e.g., `v1.0.0`, `v1.0.0-rc1`)
+- The workflow will automatically create a draft release with all signed artifacts
+
+### What Gets Signed
+
+1. **Binary Archives**:
+ - `bera-geth-linux-amd64-*.tar.gz` → `bera-geth-linux-amd64-*.tar.gz.asc`
+ - `bera-geth-linux-arm64-*.tar.gz` → `bera-geth-linux-arm64-*.tar.gz.asc`
+ - `bera-geth-alltools-linux-amd64-*.tar.gz` → `bera-geth-alltools-linux-amd64-*.tar.gz.asc`
+ - `bera-geth-alltools-linux-arm64-*.tar.gz` → `bera-geth-alltools-linux-arm64-*.tar.gz.asc`
+
+2. **Docker Images**:
+ - Multi-arch images at `ghcr.io/berachain/bera-geth:VERSION`
+ - Signed with Cosign using keyless signing
+
+## Verification Instructions
+
+### Verifying Binary Signatures
+
+Users can verify the PGP signatures of release binaries:
+
+```bash
+# Download and import the public key
+curl -sSL https://raw.githubusercontent.com/berachain/bera-geth/main/.github/workflows/release.asc | gpg --import
+
+# Download a release archive and its signature
+wget https://github.com/berachain/bera-geth/releases/download/v1.0.0/bera-geth-linux-amd64-v1.0.0.tar.gz
+wget https://github.com/berachain/bera-geth/releases/download/v1.0.0/bera-geth-linux-amd64-v1.0.0.tar.gz.asc
+
+# Verify the signature
+gpg --verify bera-geth-linux-amd64-v1.0.0.tar.gz.asc bera-geth-linux-amd64-v1.0.0.tar.gz
+```
+
+Expected output:
+```
+gpg: Signature made [date] using RSA key ID [key-id]
+gpg: Good signature from "bera-geth-linux-signing-key"
+```
+
+### Verifying Docker Images
+
+Docker images are signed with Cosign and can be verified:
+
+```bash
+# Install cosign if not already installed
+brew install cosign # macOS
+# or see https://docs.sigstore.dev/cosign/installation/
+
+# Verify a specific version
+cosign verify ghcr.io/berachain/bera-geth:v1.0.0
+
+# Verify the latest image
+cosign verify ghcr.io/berachain/bera-geth:latest
+```
+
+The verification will show:
+- The GitHub Actions workflow that created the image
+- The commit SHA
+- The OIDC issuer (GitHub)
+
+## Security Considerations
+
+1. **PGP Key Security**:
+ - The PGP private key should be kept secure and only accessible to authorized release managers
+ - Regularly rotate keys and update the public key in the repository
+ - Use a strong passphrase for the private key
+
+2. **Cosign Keyless Signing**:
+ - Signatures are tied to the GitHub Actions workflow identity
+ - Verification includes checking the workflow that signed the image
+ - All signatures are recorded in the Rekor transparency log
+
+3. **Best Practices**:
+ - Always verify signatures before using release artifacts in production
+ - Check that the signing workflow matches the official repository
+ - Monitor the repository for any changes to signing keys or workflows
+
+## Troubleshooting
+
+### PGP Signing Issues
+
+If PGP signing fails:
+1. Check that the `LINUX_SIGNING_KEY` secret is properly set
+2. Verify the key hasn't expired: `gpg --list-secret-keys`
+3. Ensure the base64 encoding was done correctly
+
+### Cosign Signing Issues
+
+If Cosign signing fails:
+1. Ensure the workflow has `id-token: write` permission
+2. Check that the Docker image was successfully pushed before signing
+3. Verify the image tag/digest is correct
+
+### Release Draft Issues
+
+If the release draft fails:
+1. Ensure all artifacts were successfully uploaded
+2. Check that the tag follows the correct format (`v1.*`)
+3. Verify the workflow has `contents: write` permission
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index a72296e184..e2275f10e3 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -38,6 +38,36 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
+ - name: Install Cosign
+ uses: sigstore/cosign-installer@v3
+
- name: Build and push multi-arch images to GHCR
run: |
go run build/ci.go dockerx -platform linux/amd64,linux/arm64 -hub ghcr.io/berachain/bera-geth -upload
+
+ - name: Get image digest and version
+ id: image_info
+ run: |
+ # Extract version information
+ if [[ "${{ github.ref }}" == refs/tags/* ]]; then
+ VERSION="${{ github.ref_name }}"
+ elif [[ "${{ github.ref }}" == refs/heads/main ]]; then
+ VERSION="latest"
+ else
+ VERSION="branch-${GITHUB_REF##*/}"
+ fi
+
+ # Get the digest of the pushed image
+ DIGEST=$(docker buildx imagetools inspect ghcr.io/berachain/bera-geth:${VERSION} --format "{{.Manifest.Digest}}")
+ echo "digest=${DIGEST}" >> $GITHUB_OUTPUT
+ echo "version=${VERSION}" >> $GITHUB_OUTPUT
+
+ - name: Sign Docker images with Cosign
+ env:
+ COSIGN_EXPERIMENTAL: true
+ run: |
+ # Sign the multi-arch manifest by digest
+ cosign sign --yes ghcr.io/berachain/bera-geth@${{ steps.image_info.outputs.digest }}
+
+ # Also sign the tagged version
+ cosign sign --yes ghcr.io/berachain/bera-geth:${{ steps.image_info.outputs.version }}
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index aa8892b4fd..053a628294 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -39,14 +39,18 @@ jobs:
- name: Create archive (amd64)
run: |
- go run build/ci.go archive -arch amd64 -type tar
+ go run build/ci.go archive -arch amd64 -type tar -signer LINUX_SIGNING_KEY
+ env:
+ LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
- name: Upload artifacts (amd64)
uses: actions/upload-artifact@v4
with:
name: bera-geth-linux-amd64-archives
path: |
bera-geth-linux-amd64-*.tar.gz
+ bera-geth-linux-amd64-*.tar.gz.asc
bera-geth-alltools-linux-amd64-*.tar.gz
+ bera-geth-alltools-linux-amd64-*.tar.gz.asc
- name: Cleanup bin
run: rm -f build/bin/*
@@ -74,19 +78,23 @@ jobs:
- name: Create archive (arm64)
run: |
- go run build/ci.go archive -arch arm64 -type tar
+ go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY
+ env:
+ LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
- name: Upload artifacts (arm64)
uses: actions/upload-artifact@v4
with:
name: bera-geth-linux-arm64-archives
path: |
bera-geth-linux-arm64-*.tar.gz
+ bera-geth-linux-arm64-*.tar.gz.asc
bera-geth-alltools-linux-arm64-*.tar.gz
+ bera-geth-alltools-linux-arm64-*.tar.gz.asc
- name: Cleanup bin
run: rm -fr build/bin/*
draft-release:
- name: Draft Release
+ name: Draft Release
needs: [extract-version, linux-intel, linux-arm]
runs-on: ubuntu-latest
env:
@@ -176,15 +184,32 @@ jobs:
## Binaries
- | System | Architecture | Binary | Notes |
- |:---:|:---:|:---:|:---|
- |
| amd64 | [GETH_AMD64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_AMD64_PLACEHOLDER) | Most Linux systems |
- |
| arm64 | [GETH_ARM64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ARM64_PLACEHOLDER) | 64-bit ARM systems |
- |
| amd64 | [GETH_ALLTOOLS_AMD64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ALLTOOLS_AMD64_PLACEHOLDER) | All tools bundle (amd64) |
- |
| arm64 | [GETH_ALLTOOLS_ARM64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ALLTOOLS_ARM64_PLACEHOLDER) | All tools bundle (arm64) |
+ | System | Architecture | Binary | PGP Signature | Notes |
+ |:---:|:---:|:---:|:---:|:---|
+ |
| amd64 | [GETH_AMD64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_AMD64_PLACEHOLDER) | [Signature](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_AMD64_PLACEHOLDER.asc) | Most Linux systems |
+ |
| arm64 | [GETH_ARM64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ARM64_PLACEHOLDER) | [Signature](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ARM64_PLACEHOLDER.asc) | 64-bit ARM systems |
+ |
| amd64 | [GETH_ALLTOOLS_AMD64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ALLTOOLS_AMD64_PLACEHOLDER) | [Signature](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ALLTOOLS_AMD64_PLACEHOLDER.asc) | All tools bundle (amd64) |
+ |
| arm64 | [GETH_ALLTOOLS_ARM64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ALLTOOLS_ARM64_PLACEHOLDER) | [Signature](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ALLTOOLS_ARM64_PLACEHOLDER.asc) | All tools bundle (arm64) |
| **System** | **Option** | - | **Resource** |
|
| Docker | | [ghcr.io/berachain/bera-geth](https://ghcr.io/berachain/bera-geth) |
+ ### Verifying Binary Signatures
+
+ All release binaries are signed with PGP. To verify:
+
+ 1. Download the [public key](https://raw.githubusercontent.com/${{ github.repository }}/master/.github/workflows/release.asc)
+ 2. Import the key: `gpg --import release.asc`
+ 3. Verify the signature: `gpg --verify .asc `
+
+ ### Docker Images
+
+ Docker images are available at `ghcr.io/berachain/bera-geth` and are signed with [Cosign](https://github.com/sigstore/cosign).
+
+ To verify Docker images:
+ ```bash
+ cosign verify ghcr.io/berachain/bera-geth:RELEASE_TAG_PLACEHOLDER
+ ```
+
### Installation
The archives contain the geth binary and license file. Extract and run: