add arm build support

Signed-off-by: Ronni Skansing <rskansing@gmail.com>
This commit is contained in:
Ronni Skansing
2026-01-19 18:15:32 +01:00
parent dee61c2633
commit 504e7cc6e6
3 changed files with 144 additions and 51 deletions

View File

@@ -17,7 +17,12 @@ jobs:
with: with:
fetch-depth: 1 fetch-depth: 1
- name: Set up Docker - name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: linux/amd64,linux/arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry - name: Log in to GitHub Container Registry
@@ -49,16 +54,32 @@ jobs:
mkdir -p backend/frontend/build mkdir -p backend/frontend/build
cp -r frontend/build/* backend/frontend/build/ cp -r frontend/build/* backend/frontend/build/
- name: Build single binary with all features - name: Build binaries for multiple architectures
run: | run: |
mkdir -p build/amd64 build/arm64
# build amd64 binary
sudo docker run --rm \ sudo docker run --rm \
-v "$(pwd)":/app \ -v "$(pwd)":/app \
-w /app/backend \ -w /app/backend \
-e CGO_ENABLED=1 \ -e CGO_ENABLED=1 \
-e GOOS=linux \
-e GOARCH=amd64 \
golang:1.25.1 \ golang:1.25.1 \
go build -trimpath \ go build -trimpath \
-ldflags='-X github.com/phishingclub/phishingclub/version.hash=ph${{ steps.get_version.outputs.HASH }} -X github.com/phishingclub/phishingclub/version.version=${{ steps.get_version.outputs.VERSION }}' \ -ldflags='-X github.com/phishingclub/phishingclub/version.hash=ph${{ steps.get_version.outputs.HASH }} -X github.com/phishingclub/phishingclub/version.version=${{ steps.get_version.outputs.VERSION }}' \
-tags production -o ../build/phishingclub main.go -tags production -o ../build/amd64/phishingclub main.go
# build arm64 binary
sudo docker run --rm \
-v "$(pwd)":/app \
-w /app/backend \
-e CGO_ENABLED=1 \
-e GOOS=linux \
-e GOARCH=arm64 \
-e CC=aarch64-linux-gnu-gcc \
golang:1.25.1 \
bash -c "apt-get update && apt-get install -y gcc-aarch64-linux-gnu && go build -trimpath -ldflags='-X github.com/phishingclub/phishingclub/version.hash=ph${{ steps.get_version.outputs.HASH }} -X github.com/phishingclub/phishingclub/version.version=${{ steps.get_version.outputs.VERSION }}' -tags production -o ../build/arm64/phishingclub main.go"
- name: Fix build directory permissions - name: Fix build directory permissions
run: | run: |
@@ -66,49 +87,60 @@ jobs:
chmod 755 build/ chmod 755 build/
ls -la build/ ls -la build/
- name: Sign binary with Ed25519 - name: Sign binaries with Ed25519
run: | run: |
# Create directory for keys # create directory for keys
mkdir -p /tmp/keys mkdir -p /tmp/keys
chmod 700 /tmp/keys chmod 700 /tmp/keys
# Save both private keys from GitHub secrets # save both private keys from github secrets
echo "${{ secrets.SIGNKEY_1 }}" > /tmp/keys/private1.pem echo "${{ secrets.SIGNKEY_1 }}" > /tmp/keys/private1.pem
echo "${{ secrets.SIGNKEY_2 }}" > /tmp/keys/private2.pem echo "${{ secrets.SIGNKEY_2 }}" > /tmp/keys/private2.pem
chmod 600 /tmp/keys/private1.pem chmod 600 /tmp/keys/private1.pem
chmod 600 /tmp/keys/private2.pem chmod 600 /tmp/keys/private2.pem
# Sign binary with primary key (Key 1) # sign amd64 binary with primary key (key 1)
openssl pkeyutl -sign -inkey /tmp/keys/private1.pem \ openssl pkeyutl -sign -inkey /tmp/keys/private1.pem \
-rawin -in build/phishingclub \ -rawin -in build/amd64/phishingclub \
-out build/phishingclub.sig -out build/amd64/phishingclub.sig
# Clean up keys # sign arm64 binary with primary key (key 1)
openssl pkeyutl -sign -inkey /tmp/keys/private1.pem \
-rawin -in build/arm64/phishingclub \
-out build/arm64/phishingclub.sig
# clean up keys
rm -rf /tmp/keys rm -rf /tmp/keys
- name: Create compressed package with signature - name: Create compressed packages with signatures
run: | run: |
mkdir -p packages mkdir -p packages
# Package binary with signature # package amd64 binary with signature
tar -czf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}.tar.gz \ tar -czf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_amd64.tar.gz \
-C build \ -C build/amd64 \
phishingclub \ phishingclub \
phishingclub.sig phishingclub.sig
- name: Build and push release Docker image # package arm64 binary with signature
tar -czf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_arm64.tar.gz \
-C build/arm64 \
phishingclub \
phishingclub.sig
- name: Build and push multi-arch Docker image
uses: docker/build-push-action@v5 uses: docker/build-push-action@v5
with: with:
context: . context: .
file: ./Dockerfile.release file: ./Dockerfile.release
push: true push: true
platforms: linux/amd64 platforms: linux/amd64,linux/arm64
tags: | tags: |
ghcr.io/${{ github.repository }}:latest ghcr.io/${{ github.repository }}:latest
ghcr.io/${{ github.repository }}:${{ steps.get_version.outputs.VERSION }} ghcr.io/${{ github.repository }}:${{ steps.get_version.outputs.VERSION }}
labels: | labels: |
org.opencontainers.image.title=PhishingClub ${{ steps.get_version.outputs.VERSION }} org.opencontainers.image.title=PhishingClub ${{ steps.get_version.outputs.VERSION }}
org.opencontainers.image.description=PhishingClub production release image (linux/amd64). Built from tag ${{ steps.get_version.outputs.TAG }}. org.opencontainers.image.description=PhishingClub production release image (linux/amd64, linux/arm64). Built from tag ${{ steps.get_version.outputs.TAG }}.
org.opencontainers.image.url=${{ github.server_url }}/${{ github.repository }} org.opencontainers.image.url=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.version=${{ steps.get_version.outputs.VERSION }} org.opencontainers.image.version=${{ steps.get_version.outputs.VERSION }}
@@ -152,7 +184,8 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: | run: |
gh release create ${{ steps.get_version.outputs.TAG }} \ gh release create ${{ steps.get_version.outputs.TAG }} \
./packages/phishingclub_${{ steps.get_version.outputs.VERSION }}.tar.gz \ ./packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_amd64.tar.gz \
./packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_arm64.tar.gz \
--title "PhishingClub ${{ steps.get_version.outputs.TAG }}" \ --title "PhishingClub ${{ steps.get_version.outputs.TAG }}" \
--notes "${{ steps.get_release_notes.outputs.NOTES }}" --notes "${{ steps.get_release_notes.outputs.NOTES }}"

View File

@@ -18,7 +18,12 @@ jobs:
with: with:
fetch-depth: 1 fetch-depth: 1
- name: Set up Docker - name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: linux/amd64,linux/arm64
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry - name: Log in to GitHub Container Registry
@@ -49,16 +54,32 @@ jobs:
mkdir -p backend/frontend/build mkdir -p backend/frontend/build
cp -r frontend/build/* backend/frontend/build/ cp -r frontend/build/* backend/frontend/build/
- name: Build binary - name: Build binaries for multiple architectures
run: | run: |
mkdir -p build/amd64 build/arm64
# build amd64 binary
sudo docker run --rm \ sudo docker run --rm \
-v "$(pwd)":/app \ -v "$(pwd)":/app \
-w /app/backend \ -w /app/backend \
-e CGO_ENABLED=1 \ -e CGO_ENABLED=1 \
-e GOOS=linux \
-e GOARCH=amd64 \
golang:1.25.1 \ golang:1.25.1 \
go build -trimpath \ go build -trimpath \
-ldflags='-X github.com/phishingclub/phishingclub/version.hash=ph${{ steps.get_version.outputs.HASH }} -X github.com/phishingclub/phishingclub/version.version=${{ steps.get_version.outputs.VERSION }}' \ -ldflags='-X github.com/phishingclub/phishingclub/version.hash=ph${{ steps.get_version.outputs.HASH }} -X github.com/phishingclub/phishingclub/version.version=${{ steps.get_version.outputs.VERSION }}' \
-tags production -o ../build/phishingclub main.go -tags production -o ../build/amd64/phishingclub main.go
# build arm64 binary
sudo docker run --rm \
-v "$(pwd)":/app \
-w /app/backend \
-e CGO_ENABLED=1 \
-e GOOS=linux \
-e GOARCH=arm64 \
-e CC=aarch64-linux-gnu-gcc \
golang:1.25.1 \
bash -c "apt-get update && apt-get install -y gcc-aarch64-linux-gnu && go build -trimpath -ldflags='-X github.com/phishingclub/phishingclub/version.hash=ph${{ steps.get_version.outputs.HASH }} -X github.com/phishingclub/phishingclub/version.version=${{ steps.get_version.outputs.VERSION }}' -tags production -o ../build/arm64/phishingclub main.go"
- name: Fix build directory permissions - name: Fix build directory permissions
run: | run: |
@@ -71,20 +92,25 @@ jobs:
if [ -n "${{ secrets.SIGNKEY_1 }}" ]; then if [ -n "${{ secrets.SIGNKEY_1 }}" ]; then
echo "Testing binary signing..." echo "Testing binary signing..."
# Create directory for keys # create directory for keys
mkdir -p /tmp/keys mkdir -p /tmp/keys
chmod 700 /tmp/keys chmod 700 /tmp/keys
# Save private key from GitHub secrets # save private key from github secrets
echo "${{ secrets.SIGNKEY_1 }}" > /tmp/keys/private1.pem echo "${{ secrets.SIGNKEY_1 }}" > /tmp/keys/private1.pem
chmod 600 /tmp/keys/private1.pem chmod 600 /tmp/keys/private1.pem
# Sign binary with primary key # sign amd64 binary with primary key
openssl pkeyutl -sign -inkey /tmp/keys/private1.pem \ openssl pkeyutl -sign -inkey /tmp/keys/private1.pem \
-rawin -in build/phishingclub \ -rawin -in build/amd64/phishingclub \
-out build/phishingclub.sig -out build/amd64/phishingclub.sig
# Clean up keys # sign arm64 binary with primary key
openssl pkeyutl -sign -inkey /tmp/keys/private1.pem \
-rawin -in build/arm64/phishingclub \
-out build/arm64/phishingclub.sig
# clean up keys
rm -rf /tmp/keys rm -rf /tmp/keys
echo "✅ Binary signing test successful" echo "✅ Binary signing test successful"
@@ -96,32 +122,46 @@ jobs:
run: | run: |
mkdir -p packages mkdir -p packages
# Test packaging # test packaging for amd64
if [ -f build/phishingclub.sig ]; then if [ -f build/amd64/phishingclub.sig ]; then
tar -czf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}.tar.gz \ tar -czf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_amd64.tar.gz \
-C build \ -C build/amd64 \
phishingclub \ phishingclub \
phishingclub.sig phishingclub.sig
echo "✅ Package created with signature" echo "✅ AMD64 package created with signature"
else else
tar -czf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}.tar.gz \ tar -czf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_amd64.tar.gz \
-C build \ -C build/amd64 \
phishingclub phishingclub
echo "✅ Package created without signature" echo "✅ AMD64 package created without signature"
fi fi
- name: Build and push test Docker image # test packaging for arm64
if [ -f build/arm64/phishingclub.sig ]; then
tar -czf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_arm64.tar.gz \
-C build/arm64 \
phishingclub \
phishingclub.sig
echo "✅ ARM64 package created with signature"
else
tar -czf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_arm64.tar.gz \
-C build/arm64 \
phishingclub
echo "✅ ARM64 package created without signature"
fi
- name: Build and push test multi-arch Docker image
uses: docker/build-push-action@v5 uses: docker/build-push-action@v5
with: with:
context: . context: .
file: ./Dockerfile.release file: ./Dockerfile.release
push: true push: true
platforms: linux/amd64 platforms: linux/amd64,linux/arm64
tags: | tags: |
ghcr.io/${{ github.repository }}:test-latest ghcr.io/${{ github.repository }}:test-latest
labels: | labels: |
org.opencontainers.image.title=PhishingClub-Test ${{ steps.get_version.outputs.VERSION }} org.opencontainers.image.title=PhishingClub-Test ${{ steps.get_version.outputs.VERSION }}
org.opencontainers.image.description=PhishingClub test build image (linux/amd64). Not for production deployment. org.opencontainers.image.description=PhishingClub test build image (linux/amd64, linux/arm64). Not for production deployment.
org.opencontainers.image.url=${{ github.server_url }}/${{ github.repository }} org.opencontainers.image.url=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }} org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
org.opencontainers.image.version=${{ steps.get_version.outputs.VERSION }} org.opencontainers.image.version=${{ steps.get_version.outputs.VERSION }}
@@ -131,24 +171,43 @@ jobs:
- name: Verify build artifacts - name: Verify build artifacts
run: | run: |
echo "=== Build Summary ===" echo "=== Build Summary ==="
echo "Binary size: $(du -h build/phishingclub | cut -f1)" echo ""
echo "Binary info:" echo "AMD64 Binary size: $(du -h build/amd64/phishingclub | cut -f1)"
file build/phishingclub echo "AMD64 Binary info:"
file build/amd64/phishingclub
if [ -f build/phishingclub.sig ]; then if [ -f build/amd64/phishingclub.sig ]; then
echo "Signature size: $(du -h build/phishingclub.sig | cut -f1)" echo "AMD64 Signature size: $(du -h build/amd64/phishingclub.sig | cut -f1)"
fi fi
echo "Package size: $(du -h packages/phishingclub_${{ steps.get_version.outputs.VERSION }}.tar.gz | cut -f1)" echo ""
echo "Package contents:" echo "ARM64 Binary size: $(du -h build/arm64/phishingclub | cut -f1)"
tar -tzf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}.tar.gz echo "ARM64 Binary info:"
file build/arm64/phishingclub
if [ -f build/arm64/phishingclub.sig ]; then
echo "ARM64 Signature size: $(du -h build/arm64/phishingclub.sig | cut -f1)"
fi
echo ""
echo "AMD64 Package size: $(du -h packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_amd64.tar.gz | cut -f1)"
echo "AMD64 Package contents:"
tar -tzf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_amd64.tar.gz
echo ""
echo "ARM64 Package size: $(du -h packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_arm64.tar.gz | cut -f1)"
echo "ARM64 Package contents:"
tar -tzf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_arm64.tar.gz
- name: Upload build artifacts (for review) - name: Upload build artifacts (for review)
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: phishingclub-test-build-${{ steps.get_version.outputs.HASH }} name: phishingclub-test-build-${{ steps.get_version.outputs.HASH }}
path: | path: |
build/phishingclub build/amd64/phishingclub
build/phishingclub.sig build/amd64/phishingclub.sig
packages/phishingclub_${{ steps.get_version.outputs.VERSION }}.tar.gz build/arm64/phishingclub
build/arm64/phishingclub.sig
packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_amd64.tar.gz
packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_arm64.tar.gz
retention-days: 2 retention-days: 2

View File

@@ -12,8 +12,9 @@ RUN groupadd -g 1000 appuser && \
# set working directory # set working directory
WORKDIR /app WORKDIR /app
# copy the binary from build context # copy the binary from build context based on target architecture
COPY build/phishingclub /app/phishingclub ARG TARGETARCH
COPY build/${TARGETARCH}/phishingclub /app/phishingclub
# make binary executable and set ownership # make binary executable and set ownership
RUN chmod +x /app/phishingclub && \ RUN chmod +x /app/phishingclub && \