feat: add ARM (aarch64) platform support - #94
Conversation
…support Add per-architecture overrides in deps_manifest.toml so Firecracker and kernel dependencies can use different versions and download URLs on ARM platforms without changing the x86_64 defaults. - Firecracker: ARM uses official GitHub release (v1.15.1) while x86_64 continues using the R2-hosted patched version (1.15.1-patch-v1). - Kernel: ARM uses a separate vmlinux-6.1.175-arm64 artifact. The actual ARM kernel must be compiled and provided separately because the R2 bucket does not currently carry an aarch64 kernel. - deps.rs: both ensure_firecracker() and ensure_kernel() now check for arch-specific manifest overrides before falling back to defaults. - cfg.rs: ManifestDownload gains version_for_host_arch() so resolved paths stay consistent with the arch-aware download logic. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
openEuler (ID=openEuler or ID=openeuler in /etc/os-release) is a glibc-based RPM-family distribution. Like centos/rhel/tencentos, it falls back to the Ubuntu 22.04 overlaybd package which bundles its own shared libraries. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…86_64 The CAPABILITY_RUNNER was hardcoded to CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER, which prevented the custom test runner from being applied on aarch64 hosts. Now it is computed dynamically: uname -m → triple → uppercased env var. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Dockerfile.agentenv now accepts an optional pre-built kernel via deploy/docker/kernel/vmlinux.bin for aarch64 builds where the R2 kernel download is not available. - When the kernel file is present, it is placed at the expected path so --setup-only skips the download. When absent (x86_64), behavior is unchanged. - Gateway and scheduler Dockerfiles are already ARM-ready via CGO_ENABLED=0 cross-compilation and multi-arch base images. ARM build procedure: 1. cp arch/arm64/boot/Image deploy/docker/kernel/vmlinux.bin 2. docker build --platform linux/arm64 -f deploy/docker/Dockerfile.agentenv . Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…roach
Switch Firecracker and kernel sources from R2/GitHub-official to
kvcache-ai/firecracker fork which provides both x86_64 and aarch64
binaries from a single URL template. This eliminates the need for
per-architecture manifest overrides and removes the Docker kernel
injection mechanism.
Key changes:
- deps_manifest.toml: use kvcache-ai/firecracker for both Firecracker
and kernel, leveraging {arch} in the URL template.
- deps.rs + cfg.rs: remove arch-override HashMap/struct/helper, back
to simple version resolution.
- Dockerfile.agentenv: remove kernel injection (no longer needed since
kvcache-ai/firecracker provides ARM kernel binaries).
Our unique additions beyond PR kvcache-ai#86:
- Makefile: dynamic target triple detection for capability runner
- overlaybd.rs: openEuler in RPM-family OS fallback list
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The deb.debian.org source times out during ARM Docker builds in certain network environments. Switch to mirrors.aliyun.com before apt-get in both envd-builder and ext4-builder stages. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
proxy.golang.org is unreachable in certain network environments. Set GOPROXY to https://goproxy.cn for the envd go build step. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
TARGETPLATFORM was not resolving correctly to linux/arm64, causing busybox to be pulled as amd64 and failing with exec format error. Use BUILDPLATFORM (like envd-builder and ext4-builder stages) so the image architecture matches the build host. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
busybox:1.37.0-musl does not have an arm64 manifest, causing exec format error on ARM builds. Switch to busybox:1.37.0 (glibc) which has full multi-arch support including linux/arm64. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Both busybox:1.37.0 and alpine:3.21 fail with 'exec format error' at container init on this ARM host, while golang and debian stages work. Switch rootfs base to debian:bookworm-slim with busybox installed via apt to match the working ext4-builder environment. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The busybox image cannot exec /bin/sh on this ARM host, but its layers contain a valid arm64 busybox with runsv+svlogd. Use a dedicated FROM stage to pull the image, then COPY --from to extract the binary into the debian-based rootfs stage which CAN execute. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The detect_distro function in packages.rs did not recognize openEuler, causing --setup-only to fail with 'unsupported Linux distribution'. Map openeuler/openEuler to the CentOS distro variant (RPM family). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Covers source-build installation on ARM servers including: - Ubuntu/Debian and openEuler/CentOS/RHEL dependencies - ARM tools drive compilation - Configuration for ARM (ublk disable, MMIO boot args) - Offline dependency installation - Common troubleshooting Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Mention aarch64 in prerequisites - Add Option C for ARM source build in Quick Start - Link to ARM Quick Start guide in deployment section Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
🔍 OpenCodeReview found 2 issue(s) in this PR.
|
| let kernel_url = resolve_url( | ||
| kernel_url_template, | ||
| &[("version", kernel_version), ("arch", arch)], | ||
| ); |
There was a problem hiding this comment.
[bug · medium]
The downloaded kernel is now architecture-specific, but resolved_kernel_image_path() still caches it under kernel/<version>/vmlinux.bin, and the preceding existence check reuses that file unconditionally. If the same dependency directory is reused by x86_64 and aarch64 setups (for example, a shared cache), the second setup will silently use the kernel for the wrong architecture. Include arch in the managed kernel cache path (or otherwise record and validate the cached artifact's architecture) before accepting the existing file.
| # BUSYBOX_IMAGE BusyBox image copied into the guest tools rootfs. | ||
|
|
||
| ARG BUSYBOX_IMAGE=busybox:1.37.0-musl | ||
| ARG BUSYBOX_IMAGE=busybox:1.37.0 |
There was a problem hiding this comment.
[maintainability · medium]
BUSYBOX_IMAGE remains documented as an overridable build argument, but the new extraction stage hard-codes busybox:1.37.0-musl, so supplying --build-arg BUSYBOX_IMAGE=... silently has no effect. Reference this argument in the busybox-bin stage (and keep its default aligned with the required musl variant) or remove the advertised argument.
| # Extract the full busybox binary (with runsv + svlogd) from the official | ||
| # multi-arch image. We cannot RUN inside this image on this host (exec format | ||
| # error), but COPY --from works because it only reads image layers. | ||
| FROM --platform=$BUILDPLATFORM busybox:1.37.0-musl AS busybox-bin |
There was a problem hiding this comment.
[bug · high]
This selects the BusyBox binary for the builder host, not for the guest target. During an amd64→arm64 (or arm64→amd64) build, envd is compiled for TARGETARCH, but the tools drive receives a host-architecture BusyBox; the build-time --list checks pass precisely because it is host-native, while /init will later fail to execute it in the guest. The extraction stage must select TARGETPLATFORM (and the validation approach must not rely on running a target binary without emulation).
Suggestion:
| FROM --platform=$BUILDPLATFORM busybox:1.37.0-musl AS busybox-bin | |
| FROM --platform=${TARGETPLATFORM} ${BUSYBOX_IMAGE} AS busybox-bin |
- Include arch in resolved_kernel_image_path() to prevent wrong-arch
kernel reuse when deps are shared across architectures.
- Reference ${BUSYBOX_IMAGE} in busybox-bin FROM stage so the build
arg takes effect instead of being silently ignored.
- Use TARGETPLATFORM instead of BUILDPLATFORM for busybox-bin so the
guest binary matches the target architecture during cross-compilation.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
| .join(arch) | ||
| .join("vmlinux.bin") |
There was a problem hiding this comment.
[test · medium]
This changes the managed kernel path to include the architecture, but the existing managed_dependency_paths_remain_implicit_and_resolve_from_deps_path test in this file still expects kernel/kernel-test/vmlinux.bin. The test will now fail on every supported host. Update its expected path to include std::env::consts::ARCH (and ideally add coverage confirming the architecture-specific layout).
| # because it only reads image layers. | ||
| FROM --platform=${TARGETPLATFORM} ${BUSYBOX_IMAGE} AS busybox-bin | ||
|
|
||
| FROM --platform=$BUILDPLATFORM debian:${DEBIAN_VERSION}-slim AS rootfs |
There was a problem hiding this comment.
[bug · high]
This makes the rootfs stage use the host architecture while /usr/local/bin/busybox-full is copied for TARGETPLATFORM. Later, the stage executes that target binary with busybox --list, so a cross-platform build (for example, arm64 on amd64) fails with exec format error. Keep this stage on ${TARGETPLATFORM} so BuildKit can apply target-platform emulation, or avoid executing the copied target binary in a build-platform stage and validate its applets by another architecture-independent mechanism.
Suggestion:
| FROM --platform=$BUILDPLATFORM debian:${DEBIAN_VERSION}-slim AS rootfs | |
| FROM --platform=${TARGETPLATFORM} debian:${DEBIAN_VERSION}-slim AS rootfs |
What
Add ARM (aarch64) platform support for AgentENV, enabling source-build installation on ARM servers including AWS Graviton, Ampere Altra, and Kunpeng (openEuler).
Why
AgentENV currently only supports x86_64. ARM servers are increasingly common in cloud and enterprise deployments, and openEuler is widely used on Kunpeng hardware. This PR makes AgentENV installable from source on aarch64.
Related issue
Closes #63
Scope and non-goals
Included:
Excluded:
Design and behavior changes
Compatibility and operations
Validation
Commands and results:
Risks and reviewer notes