A community Dockerfile for running TriliumNext Notes on linux/riscv64 hardware (e.g. OrangePi RV2, StarFive VisionFive 2, Milk-V Pioneer, QEMU riscv64).
The official TriliumNext image does not publish a riscv64 manifest, and a straight cross-compilation fails due to several platform-specific issues described below. This Dockerfile works around all of them.
If you just want to run Trilium without building the image yourself:
docker pull 12345qwert123456/trilium-riscv64:latestThen run:
docker run -d \
--name trilium \
-p 8080:8080 \
-v ~/trilium-data:/home/node/trilium-data \
12345qwert123456/trilium-riscv64:latestAnd open http://localhost:8080 in your browser.
The build uses three stages:
- Clones the TriliumNext repository from GitHub
- Builds
better-sqlite3from source usingnode-gyp(C++ compilation) inside an isolated directory with--shamefully-hoist— this mirrors the approach used in the officialapps/server/docker/package.jsonand ensures the.nodebinary ends up at a predictable flat path - Compiles the TypeScript server to a single
main.cjsbundle via esbuild, which ships a prebuilt binary forlinux/riscv64and requires no cross-compilation - Copies server-side assets (EJS views, icons, DB initialisation SQL files)
The official AMD64 image is used only as a file source. Because this stage contains no RUN instructions, Docker never executes any AMD64 code — it only pulls the image layers. QEMU is not required.
This approach avoids two riscv64-specific issues:
- V8
kMaxBranchOffsetoverflow crashes that occur during Vite/Rollup bundling of large JavaScript - Missing prebuilt
lightningcssbinary forriscv64
A minimal alpine:3.21 image with nodejs and su-exec. The su-exec utility is used in the entrypoint instead of su -c, because Alpine does not ship PAM configuration and su fails silently inside a container.
| Requirement | Notes |
|---|---|
| Docker with Buildx | Standard Docker Engine ≥ 23 |
| riscv64 host or QEMU user-mode emulation | Only Stage 1 needs the target platform; Stage 2 pulls AMD64 layers without executing them |
| Internet access during build | Clones the repo and downloads APK packages |
Cross-building from x86-64: register
qemu-user-staticand build withdocker buildx build --platform linux/riscv64. Stage 2 pulls the AMD64 image natively without QEMU; only Stage 1 runs under emulation.
docker build -t trilium-riscv64 .To pin a specific TriliumNext version, edit the git clone line in the Dockerfile and the ghcr.io/triliumnext/trilium:main reference in Stage 2 to the same tag (e.g. v0.102.1).
docker run -d \
--name trilium \
-p 8080:8080 \
-v ~/trilium-data:/home/node/trilium-data \
trilium-riscv64services:
trilium:
image: trilium-riscv64
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- ./data:/home/node/trilium-data
environment:
- USER_UID=1000 # optional, match your host user
- USER_GID=1000| Variable | Default | Description |
|---|---|---|
TRILIUM_DATA_DIR |
/home/node/trilium-data |
Path where notes database and config are stored |
USER_UID |
1000 |
UID the server process runs as |
USER_GID |
1000 |
GID the server process runs as |
- OrangePi RV2 (Ky(R) X1: 8-core RISC-V) - TriliumNext v0.102.1, Node.js 22.x
- QEMU riscv64 (x86-64 host, Docker buildx)
- The frontend is always taken from
ghcr.io/triliumnext/trilium:main(the latest development build). If you need a stable release, replace both thegit cloneref and theFROM --platform=linux/amd64tag with the same version tag. - Desktop (Electron) mode is not supported — server mode only.
- The build takes a significant amount of time on native riscv64 hardware due to the C++ compilation of
better-sqlite3. Subsequent rebuilds are fast because the/nativestage is cached independently of source changes.
The main blockers for an official riscv64 image are:
- No
node:*-alpineimage for riscv64 — the official Node.js Docker Library does not publish Alpine variants for this architecture. Alpine's ownnodejspackage is used instead. - Frontend build fails on riscv64 — Vite/Rollup trigger a V8
kMaxBranchOffsetout-of-range error when bundling the large CKEditor payload;lightningcsshas no prebuilt binary for riscv64. better-sqlite3must be compiled from source — no prebuilt binary exists fornode-v127-linux-riscv64.
This Dockerfile solves all three without requiring QEMU at runtime.
This Dockerfile is released under the same license as TriliumNext: AGPL-3.0.