From 504e7cc6e69501d2300aac6945fd08352ef342eb Mon Sep 17 00:00:00 2001 From: Ronni Skansing Date: Mon, 19 Jan 2026 18:15:32 +0100 Subject: [PATCH] add arm build support Signed-off-by: Ronni Skansing --- .github/workflows/release.yml | 69 +++++++++++++----- .github/workflows/test-build.yml | 121 +++++++++++++++++++++++-------- Dockerfile.release | 5 +- 3 files changed, 144 insertions(+), 51 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c03c95f..318d958 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -17,7 +17,12 @@ jobs: with: 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 - name: Log in to GitHub Container Registry @@ -49,16 +54,32 @@ jobs: mkdir -p backend/frontend/build cp -r frontend/build/* backend/frontend/build/ - - name: Build single binary with all features + - name: Build binaries for multiple architectures run: | + mkdir -p build/amd64 build/arm64 + + # build amd64 binary sudo docker run --rm \ -v "$(pwd)":/app \ -w /app/backend \ -e CGO_ENABLED=1 \ + -e GOOS=linux \ + -e GOARCH=amd64 \ golang:1.25.1 \ 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/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 run: | @@ -66,49 +87,60 @@ jobs: chmod 755 build/ ls -la build/ - - name: Sign binary with Ed25519 + - name: Sign binaries with Ed25519 run: | - # Create directory for keys + # create directory for keys mkdir -p /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_2 }}" > /tmp/keys/private2.pem chmod 600 /tmp/keys/private1.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 \ - -rawin -in build/phishingclub \ - -out build/phishingclub.sig + -rawin -in build/amd64/phishingclub \ + -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 - - name: Create compressed package with signature + - name: Create compressed packages with signatures run: | mkdir -p packages - # Package binary with signature - tar -czf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}.tar.gz \ - -C build \ + # package amd64 binary with signature + tar -czf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_amd64.tar.gz \ + -C build/amd64 \ phishingclub \ 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 with: context: . file: ./Dockerfile.release push: true - platforms: linux/amd64 + platforms: linux/amd64,linux/arm64 tags: | ghcr.io/${{ github.repository }}:latest ghcr.io/${{ github.repository }}:${{ steps.get_version.outputs.VERSION }} labels: | 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.source=${{ github.server_url }}/${{ github.repository }} org.opencontainers.image.version=${{ steps.get_version.outputs.VERSION }} @@ -152,7 +184,8 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | 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 }}" \ --notes "${{ steps.get_release_notes.outputs.NOTES }}" diff --git a/.github/workflows/test-build.yml b/.github/workflows/test-build.yml index 4923f0e..dbe81c1 100644 --- a/.github/workflows/test-build.yml +++ b/.github/workflows/test-build.yml @@ -18,7 +18,12 @@ jobs: with: 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 - name: Log in to GitHub Container Registry @@ -49,16 +54,32 @@ jobs: mkdir -p backend/frontend/build cp -r frontend/build/* backend/frontend/build/ - - name: Build binary + - name: Build binaries for multiple architectures run: | + mkdir -p build/amd64 build/arm64 + + # build amd64 binary sudo docker run --rm \ -v "$(pwd)":/app \ -w /app/backend \ -e CGO_ENABLED=1 \ + -e GOOS=linux \ + -e GOARCH=amd64 \ golang:1.25.1 \ 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/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 run: | @@ -71,20 +92,25 @@ jobs: if [ -n "${{ secrets.SIGNKEY_1 }}" ]; then echo "Testing binary signing..." - # Create directory for keys + # create directory for keys mkdir -p /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 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 \ - -rawin -in build/phishingclub \ - -out build/phishingclub.sig + -rawin -in build/amd64/phishingclub \ + -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 echo "✅ Binary signing test successful" @@ -96,32 +122,46 @@ jobs: run: | mkdir -p packages - # Test packaging - if [ -f build/phishingclub.sig ]; then - tar -czf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}.tar.gz \ - -C build \ + # test packaging for amd64 + if [ -f build/amd64/phishingclub.sig ]; then + tar -czf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_amd64.tar.gz \ + -C build/amd64 \ phishingclub \ phishingclub.sig - echo "✅ Package created with signature" + echo "✅ AMD64 package created with signature" else - tar -czf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}.tar.gz \ - -C build \ + tar -czf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}_linux_amd64.tar.gz \ + -C build/amd64 \ phishingclub - echo "✅ Package created without signature" + echo "✅ AMD64 package created without signature" 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 with: context: . file: ./Dockerfile.release push: true - platforms: linux/amd64 + platforms: linux/amd64,linux/arm64 tags: | ghcr.io/${{ github.repository }}:test-latest labels: | 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.source=${{ github.server_url }}/${{ github.repository }} org.opencontainers.image.version=${{ steps.get_version.outputs.VERSION }} @@ -131,24 +171,43 @@ jobs: - name: Verify build artifacts run: | echo "=== Build Summary ===" - echo "Binary size: $(du -h build/phishingclub | cut -f1)" - echo "Binary info:" - file build/phishingclub + echo "" + echo "AMD64 Binary size: $(du -h build/amd64/phishingclub | cut -f1)" + echo "AMD64 Binary info:" + file build/amd64/phishingclub - if [ -f build/phishingclub.sig ]; then - echo "Signature size: $(du -h build/phishingclub.sig | cut -f1)" + if [ -f build/amd64/phishingclub.sig ]; then + echo "AMD64 Signature size: $(du -h build/amd64/phishingclub.sig | cut -f1)" fi - echo "Package size: $(du -h packages/phishingclub_${{ steps.get_version.outputs.VERSION }}.tar.gz | cut -f1)" - echo "Package contents:" - tar -tzf packages/phishingclub_${{ steps.get_version.outputs.VERSION }}.tar.gz + echo "" + echo "ARM64 Binary size: $(du -h build/arm64/phishingclub | cut -f1)" + 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) uses: actions/upload-artifact@v4 with: name: phishingclub-test-build-${{ steps.get_version.outputs.HASH }} path: | - build/phishingclub - build/phishingclub.sig - packages/phishingclub_${{ steps.get_version.outputs.VERSION }}.tar.gz + build/amd64/phishingclub + build/amd64/phishingclub.sig + 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 diff --git a/Dockerfile.release b/Dockerfile.release index 70936d9..3ee0950 100644 --- a/Dockerfile.release +++ b/Dockerfile.release @@ -12,8 +12,9 @@ RUN groupadd -g 1000 appuser && \ # set working directory WORKDIR /app -# copy the binary from build context -COPY build/phishingclub /app/phishingclub +# copy the binary from build context based on target architecture +ARG TARGETARCH +COPY build/${TARGETARCH}/phishingclub /app/phishingclub # make binary executable and set ownership RUN chmod +x /app/phishingclub && \