diff --git a/.drone.yml b/.drone.yml
deleted file mode 100644
index ef030c3f870760ebcafdeb06cac850106ef25b60..0000000000000000000000000000000000000000
--- a/.drone.yml
+++ /dev/null
@@ -1,276 +0,0 @@
----
-kind: pipeline
-name: amd64
-
-platform:
-  os: linux
-  arch: amd64
-
-steps:
-- name: build
-  image: rancher/dapper:v0.4.2
-  commands:
-  - dapper ci
-  #- dapper e2e-test
-  volumes:
-  - name: docker
-    path: /var/run/docker.sock
-
-- name: github_binary_release
-  image: plugins/github-release
-  settings:
-    api_key:
-      from_secret: github_token
-    prerelease: true
-    checksum:
-    - sha256
-    checksum_file: CHECKSUMsum-amd64.txt
-    checksum_flatten: true
-    files:
-    - "dist/artifacts/*"
-  when:
-    instance:
-    - drone-publish.rancher.io
-    event:
-    - tag
-
-- name: docker-publish
-  image: plugins/docker
-  settings:
-    dockerfile: package/Dockerfile
-    password:
-      from_secret: docker_password
-    repo: "rancher/local-path-provisioner"
-    tag: "${DRONE_BRANCH}-head-amd64"
-    username:
-      from_secret: docker_username
-  when:
-    instance:
-    - drone-publish.rancher.io
-    event:
-    - push
-
-- name: docker-tagged-publish
-  image: plugins/docker
-  settings:
-    dockerfile: package/Dockerfile
-    password:
-      from_secret: docker_password
-    repo: "rancher/local-path-provisioner"
-    tag: "${DRONE_TAG}-amd64"
-    username:
-      from_secret: docker_username
-  when:
-    instance:
-    - drone-publish.rancher.io
-    event:
-    - tag
-
-volumes:
-- name: docker
-  host:
-    path: /var/run/docker.sock
-
----
-kind: pipeline
-name: arm64
-
-platform:
-  os: linux
-  arch: arm64
-
-steps:
-- name: build
-  image: rancher/dapper:v0.4.2
-  commands:
-  - dapper ci
-#  - dapper e2e-test
-  volumes:
-  - name: docker
-    path: /var/run/docker.sock
-
-- name: github_binary_release
-  image: plugins/github-release
-  settings:
-    api_key:
-      from_secret: github_token
-    prerelease: true
-    checksum:
-    - sha256
-    checksum_file: CHECKSUMsum-arm64.txt
-    checksum_flatten: true
-    files:
-    - "dist/artifacts/*"
-  when:
-    instance:
-    - drone-publish.rancher.io
-    event:
-    - tag
-
-- name: docker-publish
-  image: plugins/docker
-  settings:
-    dockerfile: package/Dockerfile
-    password:
-      from_secret: docker_password
-    repo: "rancher/local-path-provisioner"
-    tag: "${DRONE_BRANCH}-head-arm64"
-    username:
-      from_secret: docker_username
-  when:
-    instance:
-    - drone-publish.rancher.io
-    event:
-    - push
-
-- name: docker-tagged-publish
-  image: plugins/docker
-  settings:
-    dockerfile: package/Dockerfile
-    password:
-      from_secret: docker_password
-    repo: "rancher/local-path-provisioner"
-    tag: "${DRONE_TAG}-arm64"
-    username:
-      from_secret: docker_username
-  when:
-    instance:
-    - drone-publish.rancher.io
-    event:
-    - tag
-
-volumes:
-- name: docker
-  host:
-    path: /var/run/docker.sock
-
----
-kind: pipeline
-name: arm
-
-platform:
-  os: linux
-  arch: arm
-
-# ad-hoc fix:
-# disable the use of upstream images https://github.com/rancherlabs/eio/issues/1493
-clone:
-  disable: true
-
-steps:
-- name: clone
-  image: drone/git:linux-arm
-- name: build
-  image: rancher/dapper:v0.4.2
-  commands:
-  - dapper ci
-  volumes:
-  - name: docker
-    path: /var/run/docker.sock
-
-- name: github_binary_release
-  image: plugins/github-release:linux-arm
-  settings:
-    api_key:
-      from_secret: github_token
-    prerelease: true
-    checksum:
-    - sha256
-    checksum_file: CHECKSUMsum-arm.txt
-    checksum_flatten: true
-    files:
-    - "dist/artifacts/*"
-  when:
-    instance:
-    - drone-publish.rancher.io
-    event:
-    - tag
-
-- name: docker-publish
-  image: plugins/docker:linux-arm
-  settings:
-    dockerfile: package/Dockerfile
-    password:
-      from_secret: docker_password
-    repo: "rancher/local-path-provisioner"
-    tag: "${DRONE_BRANCH}-head-arm"
-    username:
-      from_secret: docker_username
-  when:
-    instance:
-    - drone-publish.rancher.io
-    event:
-    - push
-
-- name: docker-tagged-publish
-  image: plugins/docker:linux-arm
-  settings:
-    dockerfile: package/Dockerfile
-    password:
-      from_secret: docker_password
-    repo: "rancher/local-path-provisioner"
-    tag: "${DRONE_TAG}-arm"
-    username:
-      from_secret: docker_username
-  when:
-    instance:
-    - drone-publish.rancher.io
-    event:
-    - tag
-
-volumes:
-- name: docker
-  host:
-    path: /var/run/docker.sock
-
----
-kind: pipeline
-name: manifest
-
-platform:
-  os: linux
-  arch: amd64
-
-steps:
-- name: manifest
-  image: plugins/manifest:1.0.2
-  settings:
-    username:
-      from_secret: docker_username
-    password:
-      from_secret: docker_password
-    platforms:
-      - linux/amd64
-      - linux/arm64
-      - linux/arm
-    target: "rancher/local-path-provisioner:${DRONE_BRANCH}-head"
-    template: "rancher/local-path-provisioner:${DRONE_BRANCH}-head-ARCH"
-  when:
-    instance:
-    - drone-publish.rancher.io
-    event:
-    - push
-
-- name: manifest-tag
-  image: plugins/manifest:1.0.2
-  settings:
-    username:
-      from_secret: docker_username
-    password:
-      from_secret: docker_password
-    platforms:
-      - linux/amd64
-      - linux/arm64
-      - linux/arm
-    target: "rancher/local-path-provisioner:${DRONE_TAG}"
-    template: "rancher/local-path-provisioner:${DRONE_TAG}-ARCH"
-  when:
-    instance:
-    - drone-publish.rancher.io
-    event:
-    - tag
-
-depends_on:
-- amd64
-- arm64
-- arm
diff --git a/.github/stale.yaml b/.github/stale.yaml
deleted file mode 100644
index b3589df531c84d514a55300655e84521a8915da0..0000000000000000000000000000000000000000
--- a/.github/stale.yaml
+++ /dev/null
@@ -1,63 +0,0 @@
-# Configuration for probot-stale - https://github.com/probot/stale
-
-# Number of days of inactivity before an Issue or Pull Request becomes stale
-daysUntilStale: 60
-
-# Number of days of inactivity before an Issue or Pull Request with the stale label is closed.
-# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
-daysUntilClose: 7
-
-# Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled)
-onlyLabels: []
-
-# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
-exemptLabels:
-  - bug
-  - doc
-  - enhancement
-  - good first issue
-  - help wanted
-  - question
-
-# Set to true to ignore issues in a project (defaults to false)
-exemptProjects: true
-
-# Set to true to ignore issues in a milestone (defaults to false)
-exemptMilestones: true
-
-# Set to true to ignore issues with an assignee (defaults to false)
-exemptAssignees: true
-
-# Label to use when marking as stale
-staleLabel: wontfix
-
-# Comment to post when marking as stale. Set to `false` to disable
-markComment: >
-  This issue has been automatically marked as stale because it has not had
-  recent activity. It will be closed if no further activity occurs. Thank you
-  for your contributions.
-# Comment to post when removing the stale label.
-# unmarkComment: >
-#   Your comment here.
-
-# Comment to post when closing a stale Issue or Pull Request.
-# closeComment: >
-#   Your comment here.
-
-# Limit the number of actions per hour, from 1-30. Default is 30
-limitPerRun: 30
-
-# Limit to only `issues` or `pulls`
-# only: issues
-
-# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
-# pulls:
-#   daysUntilStale: 30
-#   markComment: >
-#     This pull request has been automatically marked as stale because it has not had
-#     recent activity. It will be closed if no further activity occurs. Thank you
-#     for your contributions.
-
-# issues:
-#   exemptLabels:
-#     - confirmed
\ No newline at end of file
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000000000000000000000000000000000000..199d675b3bdef2baa5fd59173dcf1b2fbc4f44b9
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,90 @@
+name: build
+on:
+  push:
+    branches:
+    - master
+    - v*
+    tags:
+    - v*
+  pull_request:
+jobs:
+  build:
+    name: Build Binaries
+    runs-on: ubuntu-latest
+    steps:
+    - name: Checkout Codes
+      uses: actions/checkout@v4
+
+    # Build binaries
+    - name: Run CI
+      run: make ci
+
+    # Run e2e test
+    #- name: Run E2e Test
+    #  run: make e2e-test
+
+    # Upload binaries
+    - name: Upload Binaries
+      uses: actions/upload-artifact@v4
+      with:
+        name: binaries_artifact
+        path: ./bin/*
+
+  build_push_image:
+    name: Build and Push Images
+    runs-on: ubuntu-latest
+    needs: build
+    if: ${{ startsWith(github.ref, 'refs/heads/') || startsWith(github.ref, 'refs/tags/') }}
+    steps:
+    - name: Checkout Codes
+      uses: actions/checkout@v4
+
+    - name: Download Binaries
+      uses: actions/download-artifact@v4
+      with:
+        name: binaries_artifact
+        path: ./bin/
+
+    - name: Add Executable Permission
+      run: |
+        chmod +x ./bin/*
+
+    - name: Copy bin Folder to package Folder
+      run: |
+        cp -r ./bin ./package/
+
+    # For multi-platform support
+    - name: Set up QEMU
+      uses: docker/setup-qemu-action@v3
+    - name: Set up Docker Buildx
+      uses: docker/setup-buildx-action@v3
+
+    - name: Declare Branch
+      run: |
+        echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> "$GITHUB_ENV"
+    - name: Login to Docker Hub
+      uses: docker/login-action@v3
+      with:
+        username: ${{ secrets.DOCKER_USERNAME }}
+        password: ${{ secrets.DOCKER_PASSWORD }}
+
+    # rancher/local-path-provisioner image
+    - name: docker-publish
+      if: ${{ startsWith(github.ref, 'refs/heads/') }}
+      uses: docker/build-push-action@v5
+      with:
+        context: ./
+        push: true
+        platforms: linux/amd64,linux/arm64
+        tags: rancher/local-path-provisioner:${{ env.branch }}-head
+        file: package/Dockerfile
+
+    - name: docker-publish-with-tag
+      if: ${{ startsWith(github.ref, 'refs/tags/') }}
+      uses: docker/build-push-action@v5
+      with:
+        context: ./
+        push: true
+        platforms: linux/amd64,linux/arm64
+        tags: rancher/local-path-provisioner:${{ github.ref_name }}
+        file: package/Dockerfile
diff --git a/.github/workflows/stale.yaml b/.github/workflows/stale.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..aa1f4f27c50190810706d016b2b71c0aaf916c99
--- /dev/null
+++ b/.github/workflows/stale.yaml
@@ -0,0 +1,28 @@
+name: 'Close stale issues and PRs'
+
+on:
+  workflow_call:
+  workflow_dispatch:
+  schedule:
+  - cron: '30 1 * * *'
+
+jobs:
+  stale:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/stale@v4
+      with:
+        stale-issue-message: 'This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.'
+        stale-pr-message: 'This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.'
+        close-issue-message: 'This issue was closed because it has been stalled for 5 days with no activity.'
+        close-pr-message: 'This PR was closed because it has been stalled for 10 days with no activity.'
+        days-before-stale: 60
+        days-before-pr-stale: 45
+        days-before-close: 5
+        days-before-pr-close: 10
+        stale-issue-label: 'stale'
+        stale-pr-label: 'stale'
+        exempt-all-assignees: true
+        exempt-issue-labels: 'bug,doc,enhancement,good first issue,help wanted,question'
+        exempt-draft-pr: true
+        exempt-all-milestones: true
diff --git a/Dockerfile.dapper b/Dockerfile.dapper
index 90d0ec2b3075d46b1df8a0ed763eff97837152fc..497b2cd1714aa16cd79829b715a00be040912977 100644
--- a/Dockerfile.dapper
+++ b/Dockerfile.dapper
@@ -14,6 +14,13 @@ RUN if [ "${ARCH}" == "amd64" ]; then \
         curl -sL "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv4.2.0/kustomize_v4.2.0_linux_${ARCH}.tar.gz" | tar -zxv -C /usr/local/bin; \
     fi
 
+RUN curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.55.2
+
+# The docker version in dapper is too old to have buildx. Install it manually.
+RUN wget https://github.com/docker/buildx/releases/download/v0.13.1/buildx-v0.13.1.linux-${ARCH} && \
+    chmod +x buildx-v0.13.1.linux-${ARCH} && \
+    mv buildx-v0.13.1.linux-${ARCH} /usr/local/bin/buildx
+
 ENV DAPPER_ENV REPO TAG DRONE_TAG
 ENV DAPPER_SOURCE /go/src/github.com/rancher/local-path-provisioner/
 ENV DAPPER_OUTPUT ./bin ./dist
diff --git a/package/Dockerfile b/package/Dockerfile
index 4a3a66c0574c1c59a4c3a0f953b6fc3d4425f27a..3ce3b261fe9a929d5f32661a91dd87927e022c7d 100644
--- a/package/Dockerfile
+++ b/package/Dockerfile
@@ -1,7 +1,17 @@
+# syntax=docker/dockerfile:1.7.0
+
 FROM alpine
 
+ARG TARGETPLATFORM
+RUN if [ "$TARGETPLATFORM" != "linux/amd64" ] && [ "$TARGETPLATFORM" != "linux/arm64" ]; then \
+    echo "Error: Unsupported TARGETPLATFORM: $TARGETPLATFORM" && \
+    exit 1; \
+    fi
+
+ENV ARCH ${TARGETPLATFORM#linux/}
+
 RUN apk update
 RUN apk upgrade --no-cache busybox zlib
 
-COPY bin/local-path-provisioner /usr/bin/
+COPY bin/local-path-provisioner-${ARCH} /usr/bin/local-path-provisioner
 CMD ["local-path-provisioner"]
diff --git a/scripts/build b/scripts/build
index 5d5218fb033956563e5284aa1387791dcccaa83f..89f03a663d779ce7ba799eb56cf8aad38f418752 100755
--- a/scripts/build
+++ b/scripts/build
@@ -10,7 +10,8 @@ if [ "$(uname)" = "Linux" ]; then
     OTHER_LINKFLAGS="-extldflags -static -s -w"
 fi
 LINKFLAGS="-X main.VERSION=$VERSION"
-CGO_ENABLED=0 go build -ldflags "$LINKFLAGS $OTHER_LINKFLAGS" -o bin/local-path-provisioner
+CGO_ENABLED=0 GOARCH=amd64 go build -ldflags "$LINKFLAGS $OTHER_LINKFLAGS" -o bin/local-path-provisioner-amd64
+CGO_ENABLED=0 GOARCH=arm64 go build -ldflags "$LINKFLAGS $OTHER_LINKFLAGS" -o bin/local-path-provisioner-arm64
 if [ "$CROSS" = "true" ] && [ "$ARCH" = "amd64" ]; then
     GOOS=darwin go build -ldflags "$LINKFLAGS" -o bin/local-path-provisioner-darwin
     GOOS=windows go build -ldflags "$LINKFLAGS" -o bin/local-path-provisioner-windows
diff --git a/scripts/package b/scripts/package
index ea6f5f3f3a052d0c33cd9e0fb60bf3d0f937313d..e006b2e1cf8b87e723e1c869cb7d7987370b4002 100755
--- a/scripts/package
+++ b/scripts/package
@@ -6,7 +6,7 @@ source $(dirname $0)/version
 cd $(dirname $0)/..
 
 mkdir -p dist/artifacts
-cp bin/local-path-provisioner dist/artifacts/local-path-provisioner${SUFFIX}
+cp bin/local-path-provisioner* dist/artifacts/
 
 IMAGE=${REPO}/local-path-provisioner:${TAG}
 DOCKERFILE=package/Dockerfile
@@ -14,7 +14,7 @@ if [ -e ${DOCKERFILE}.${ARCH} ]; then
     DOCKERFILE=${DOCKERFILE}.${ARCH}
 fi
 
-docker build -f ${DOCKERFILE} -t ${IMAGE} .
+buildx build --load -t ${IMAGE} -f ${DOCKERFILE} .
 echo Built ${IMAGE}
 
 echo ${IMAGE} > ./bin/latest_image