Skip to content

feat: add Linux arm64 AppImage support for SBC users (Pi, Orange Pi, etc.)#3441

Open
toastmanAu wants to merge 1 commit into
nervosnetwork:developfrom
toastmanAu:feat/linux-arm64-appimage
Open

feat: add Linux arm64 AppImage support for SBC users (Pi, Orange Pi, etc.)#3441
toastmanAu wants to merge 1 commit into
nervosnetwork:developfrom
toastmanAu:feat/linux-arm64-appimage

Conversation

@toastmanAu

Copy link
Copy Markdown

Add Linux arm64 (aarch64) AppImage support

Summary

This PR adds support for building Neuron as a Linux arm64 AppImage, targeting Raspberry Pi 4/5, Orange Pi, ROCK series boards and other aarch64 single-board computers running Linux — which are popular in the CKB node-running community.

A working Neuron-v0.204.0-arm64.AppImage (192 MB, verified ELF aarch64) was built successfully on an Orange Pi 5 (aarch64, Ubuntu 22.04) using the changes in this PR.


Changes

1. scripts/download-ckb.sh — add download_linux_aarch64()

Added a new function that downloads the aarch64-unknown-linux-gnu CKB binary (which already exists in every CKB release) and saves it as bin/linux/ckb-arm64:

function download_linux_aarch64() {
  CKB_FILENAME="ckb_${CKB_VERSION}_aarch64-unknown-linux-gnu"
  cd $ROOT_DIR/packages/neuron-wallet/bin/linux
  curl -O -L "${GITHUB_RELEASE_URL}/${CKB_VERSION}/${CKB_FILENAME}.tar.gz"
  tar xvzf ${CKB_FILENAME}.tar.gz
  cp ${CKB_FILENAME}/ckb ./ckb-arm64
  rm -rf $CKB_FILENAME ${CKB_FILENAME}.tar.gz
}

Also added a linux-arm64 case to the switch:

linux-arm64) download_linux_aarch64; download_linux_light;;

Note on ckb-light-client: No arm64 Linux release exists in the ckb-light-client repo yet. The x86_64 binary is currently used for both architectures. A separate issue/PR to the ckb-light-client repo would complete that gap.

2. packages/neuron-wallet/electron-builder.yml — add arm64 target + extraFile

linux:
  extraFiles:
    - from: "bin/linux/ckb"
      to: "bin/ckb"
    - from: "bin/linux/ckb-arm64"   # ← new
      to: "bin/ckb-arm64"
    # ... rest unchanged
  target:
    - target: AppImage
      arch:
        - x64
        - arm64    # ← new

3. package.yml (GitHub Actions) — add arm64 Linux runner

To build the arm64 AppImage in CI, add an ubuntu-24.04-arm runner to the matrix:

jobs:
  default:
    strategy:
      matrix:
        node: [22]
        os:
          - macos-latest
          - ubuntu-latest
          - ubuntu-24.04-arm   # ← new: GitHub's hosted arm64 runner
          - windows-latest

And add a conditional upload step:

- name: Upload Neuron Linux arm64
  if: runner.os == 'Linux' && runner.arch == 'ARM64'
  uses: actions/upload-artifact@v4
  with:
    name: Neuron-Linux-arm64
    path: release/Neuron-*-arm64.AppImage

Build instructions (manual, on arm64 Linux)

# Prerequisites
sudo apt-get install -y libudev-dev libusb-1.0-0-dev fuse libfuse2 rpm python3-setuptools

# Clone and install
git clone https://github.com/nervosnetwork/neuron.git
cd neuron
yarn global add lerna
CI=false yarn
yarn build
./scripts/copy-ui-files.sh

# Download CKB binaries (both x64 and arm64)
./scripts/download-ckb.sh linux

# Build AppImage for arm64
cd packages/neuron-wallet
npx electron-builder --linux --arm64 --config.npmRebuild=false

Output: release/Neuron-v{version}-arm64.AppImage

Flags explained:

  • --linux --arm64: target platform and architecture
  • --config.npmRebuild=false: skip native module rebuild (avoids cross-compilation issues when building arm64 on an arm64 host where modules are already built for the right arch)

Tested on

Device OS Result
Orange Pi 5 (RK3588S) Ubuntu 22.04 arm64 Neuron-v0.204.0-arm64.AppImage built, 192 MB

The resulting AppImage is a valid ELF aarch64 executable:

ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked,
interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, stripped

Why this matters

Single-board computers (Raspberry Pi 4/5, Orange Pi, Rock Pi, etc.) are widely used to run CKB full nodes — they're low-power, always-on, and affordable. Many CKB community members running nodes on these devices also want to use Neuron as their wallet but currently have no official binary. An arm64 AppImage closes that gap with a single self-contained download.

@toastmanAu

Copy link
Copy Markdown
Author

Testing Results — Tested on arm64 hardware

Orange Pi 5 (RK3588, aarch64) — Ubuntu 22.04

AppImage launches and renders correctly

Screenshot of welcome screen (running on Pi 5):

Full UI renders, wallet import/create options visible, app functional

Log output confirms:

  • App starts successfully
  • Connects to local CKB node (http://127.0.0.1:8114)
  • Mainnet genesis hash verified
  • ckb-arm64 bundled binary is genuine aarch64 ELF ✅

Known Issues / Notes

1. Auto-updater 404 (expected)

Error: Cannot find latest-linux-arm64.yml in the latest release artifacts

The updater looks for latest-linux-arm64.yml on the official GitHub release. This will 404 until this PR is merged and a new release is cut. Not a blocker — expected behaviour for a draft PR.

2. libz.so missing on minimal systems
The AppImage runtime requires the unversioned libz.so symlink. On some minimal arm64 systems it may only have libz.so.1. Fix:

sudo apt install zlib1g-dev

Or: sudo ln -sf /lib/aarch64-linux-gnu/libz.so.1 /lib/aarch64-linux-gnu/libz.so

3. GPU / SwiftShader fallback
On BSP 5.10 kernels (Rockchip SBCs), libGL: failed to load driver: rockchip causes the GPU process to fail and Electron falls back to software rendering (SwiftShader). The app still works correctly — just falls back to CPU rendering. This is a BSP driver limitation, not an Electron or Neuron issue. On mainline kernels with Panfrost or Mesa this is not an issue.


Tested build: Neuron-v0.204.0-arm64.AppImage (192MB, ELF aarch64, built on Orange Pi 5)

@toastmanAu

Copy link
Copy Markdown
Author

Bumping this for visibility — happy to address any feedback or adjust the implementation if needed.

For context on the broader motivation: we've been building community tooling to lower the barrier for ARM-based node deployment on the Nervos network (Orange Pi, Raspberry Pi, etc.), and just filed a related request on the Fiber repo (nervosnetwork/fiber#1186) for aarch64 prebuilt binaries there too.

Neuron arm64 support would complete the picture for users wanting a full desktop wallet experience on these devices. Would love to know if this is something the team would consider merging, or if there are concerns we can address.

@chenyukang

Copy link
Copy Markdown
Contributor

Thanks @toastmanAu!
Sorry for the delay, we will review this PR in coming days.

Comment thread scripts/download-ckb.sh

curl -O -L "${GITHUB_RELEASE_URL}/${CKB_VERSION}/${CKB_FILENAME}.tar.gz"
tar xvzf ${CKB_FILENAME}.tar.gz
cp ${CKB_FILENAME}/ckb ./ckb-arm64

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds bin/linux/ckb-arm64 as an unconditional Linux extraFile and also asks electron-builder to build both x64 and arm64 from the same Linux packaging config.

In the current workflows, Linux packaging package.yml and package_for_test.yml calls ./scripts/download-ckb.sh without arguments, which only prepares the x64 bin/linux/ckb path. So the existing x64 Linux packaging path can fail because bin/linux/ckb-arm64 is missing.

Even when an arm64 AppImage is built manually, the app would still launch packaged bin/ckb here

const ckbBinary = (): string => {
const binary = app.isPackaged ? path.resolve(ckbPath(), './ckb') : path.resolve(ckbPath(), `./${platform()}`, './ckb')
switch (platform()) {
case 'win':
return binary + '.exe'
case 'mac':
if (app.isPackaged) {
return binary
}
return `${binary}-${process.arch === 'arm64' ? 'arm64' : 'x64'}`
default:
return binary
}
}
, so bundling the arm64 node as bin/ckb-arm64 does not make the full node use it.

I think the cleaner fix is to keep the packaged runtime path architecture-neutral: always bundle exactly one CKB binary as bin/ckb. Then make the build input architecture-specific: download-ckb.sh linux prepares the x64 binary as bin/linux/ckb, and download-ckb.sh linux-arm64 prepares the arm64 binary as the same bin/linux/ckb path. The release/test scripts can then add explicit linux-arm64 cases that run electron-builder --linux --arm64. This avoids breaking the existing x64 packaging path and keeps the runtime lookup unchanged.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe like this:

diff --git a/packages/neuron-wallet/electron-builder.yml b/packages/neuron-wallet/electron-builder.yml
index 55aa42bc..4e7e6dda 100644
--- a/packages/neuron-wallet/electron-builder.yml
+++ b/packages/neuron-wallet/electron-builder.yml
@@ -88,10 +88,6 @@ linux:
   extraFiles:
     - from: "bin/linux/ckb"
       to: "bin/ckb"
-      filter: "**/*"
-    - from: "bin/linux/ckb-arm64"
-      to: "bin/ckb-arm64"
-      filter: "**/*"
     - from: "bin/linux/ckb-light-client"
       to: "bin/ckb-light-client"
     - from: "light/ckb_light_testnet.toml"
@@ -99,7 +95,4 @@ linux:
     - from: "light/ckb_light_mainnet.toml"
       to: "light/ckb_light_mainnet.toml"
   target:
-    - target: AppImage
-      arch:
-        - x64
-        - arm64
+    - AppImage
diff --git a/scripts/download-ckb.sh b/scripts/download-ckb.sh
index 7710c9a9..e635479f 100755
--- a/scripts/download-ckb.sh
+++ b/scripts/download-ckb.sh
@@ -66,7 +66,7 @@ function download_linux_aarch64() {
 
   curl -O -L "${GITHUB_RELEASE_URL}/${CKB_VERSION}/${CKB_FILENAME}.tar.gz"
   tar xvzf ${CKB_FILENAME}.tar.gz
-  cp ${CKB_FILENAME}/ckb ./ckb-arm64
+  cp ${CKB_FILENAME}/ckb ./ckb
   rm -rf $CKB_FILENAME
   rm ${CKB_FILENAME}.tar.gz
 }
@@ -111,7 +111,7 @@ function download_windows_light() {
 
 case $1 in
   mac)    download_macos; download_macos_light;;
-  linux)  download_linux; download_linux_aarch64; download_linux_light;;
+  linux)  download_linux; download_linux_light;;
   linux-arm64) download_linux_aarch64; download_linux_light;;
   win)    download_windows; download_windows_light;;
   *)
diff --git a/scripts/package-for-test.sh b/scripts/package-for-test.sh
index 34415589..e4401c3f 100755
--- a/scripts/package-for-test.sh
+++ b/scripts/package-for-test.sh
@@ -11,6 +11,9 @@ function package() {
         linux)
         electron-builder --linux -p never
         ;;
+        linux-arm64)
+        electron-builder --linux --arm64 -p never
+        ;;
         *)
         electron-builder -mwl -p never
         ;;
diff --git a/scripts/release.sh b/scripts/release.sh
index 4ce8ca38..27479dbc 100755
--- a/scripts/release.sh
+++ b/scripts/release.sh
@@ -11,6 +11,9 @@ function release() {
         linux)
         electron-builder --linux -p always
         ;;
+        linux-arm64)
+        electron-builder --linux --arm64 -p always
+        ;;
         *)
         electron-builder -mwl -p always
         ;;

Comment thread ARM64_PR.md
linux-arm64) download_linux_aarch64; download_linux_light;;
```

> **Note on `ckb-light-client`**: No arm64 Linux release exists in the `ckb-light-client` repo yet. The x86_64 binary is currently used for both architectures. A separate issue/PR to the `ckb-light-client` repo would complete that gap.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add a fix to support arm64 Linux release for ckb-light-client.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh, we already had this nervosnetwork/ckb-light-client#265, it's still in rc stage.

@eval-exec eval-exec Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once ckb-light-client is updated, I'll release another release build that includes aarch64 support.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants