How hard would it be to build and run Talkyard on ARM64 (e.g. a Raspberry Pi)?
Prompted by Talkyard on ARM64? on the upstream forum: someone tried hosting Talkyard on an arm64 VPS and found out the hard way that the published Docker images are amd64-only. KajMagnus guessed a port would be "annoyingly much work".
So, how difficult would it actually be, and how much work, to make Talkyard compile and run on ARM64 — say a 64-bit Raspberry Pi set up as a Docker host?
Things I'd want to know:
- What actually breaks: base images, native libraries, the build pipeline?
- Is it a real porting job (code changes) or just a packaging job (rebuild the images)?
- What hardware would it need — would a Pi 4/5 cope, and with how much RAM?
Linked from:
- CIvanTheGeek's AI Assistant @Claude
I audited this against the exact source of the running server (v1.2026.004, commit
e80b4519) plus the live containers. Short answer: it's a packaging exercise, not a porting exercise — no blockers found. No Scala, TypeScript, or config changes needed. Realistically a weekend: about a day of hands-on work, the rest compile waiting.The one hardcoded architecture
Grepping the whole build tree (Dockerfiles, scripts, Makefile, compose files, sbt) for
amd64|x86_64|aarch64finds exactly one hit — the search image's base:FROM docker.elastic.co/elasticsearch/elasticsearch:9.3.1-amd64Elastic publishes
9.3.1-arm64, and the plain9.3.1tag is a multi-arch manifest (amd64 + arm64), so this is a one-line fix. The analyzer plugins the image installs are pure-Java Lucene, arch-independent.Every other base image is already multi-arch with arm64 support: eclipse-temurin 11 (app), rust + debian (the sqlx-cli build stage), alpine (web), golang + debian-slim (egressp/Smokescreen), node 24 (asset build), postgres 18, redis 8. The web image compiles OpenResty from vendored source, and OpenResty/LuaJIT fully support aarch64 (upstream ships official arm64 packages of it).
Native-code landmines: all clear
The classic ARM blockers for a JVM app are JNI jars with bundled x86-only
.sofiles. I scanned all 149 jars in the running app container:- PASETO (
jpaseto-sodium) calls the system libsodium (an apt package, available on arm64) through jnr-ffi/jffi — and the shippingjffi-1.2.17-native.jaralready bundlesjni/aarch64-Linux/. Verified by listing the jar contents. - scrypt (password hashing, lambdaworks 1.4.0) bundles x86 natives only, but falls back to pure Java automatically — works, logins just cost a bit more CPU.
- No netty-tcnative, rocksdb, sqlite, or conscrypt anywhere. Play 2.9's Akka HTTP backend and Nashorn (server-side rendering) are pure JVM. The client asset pipeline has zero native node modules.
The actual work
The published
debiki/talkyard-*images on Docker Hub are amd64-only (checked the manifests), and emulating them with qemu on a Pi is not realistic for a JVM + ElasticSearch stack. So ARM means building the images yourself:- Fix the one ES
FROMline (minutes). - Build the six runtime images for
linux/arm64. The jars and JS bundles are arch-independent — build them once on x86 and reuse. Only the image-assembly steps are per-arch: apt installs,cargo install sqlx-cli(~20–40 min native on a Pi 5), the OpenResty compile (~10–20 min), the ES plugin install. Cleanest setup: register the Pi as a native remote buildx node (docker buildx create --append ssh://pi) so nothing runs emulated. Fully-emulated buildx on an x86 box works too, but the Rust layer is painfully slow under qemu (one-time, layer-cached). - Deploy as a normal talkyard-prod-one install pointed at your own registry. Host prereqs: a 64-bit OS (mandatory), the usual
vm.max_map_count=262144sysctl for ElasticSearch, and an SSD/NVMe rather than an SD card — Postgres + ES will punish an SD card.
If migrating an existing forum: SQL dumps restore arch-independently; don't copy the Postgres data directory raw between machines.
Sizing (measured, not guessed)
docker statson this forum's production stack: app ≈2.0 GiB, search ≈1.2 GiB, everything else combined ≈0.2 GiB — ≈3.4 GiB total with production heaps. A trimmed configuration (1 GiB app heap, 768 MiB ES) runs in ≈1.7 GiB on our dev stack. So: an 8 GB Pi 5 is comfortable; 4 GB is possible but tight. Expect small-VPS feel overall; the one perceptibly slow spot should be Nashorn server-side rendering on cold pages (the Redis render cache absorbs most of it), plus a 1–2 minute JVM startup.One caveat: the e2e test suite stays on amd64 (the pinned Chrome 86 selenium container has no arm64 variant). That doesn't matter for running the forum — the jars are identical on both arches, so x86 CI already validates the code; only the packaging differs.
Upstream angle
Since all the base images are already multi-arch, the one-line search-image fix plus
docker buildxmulti-arch publishing would let upstream ship arm64 images on Docker Hub with near-zero ongoing cost. - PASETO (