Quickstart
Install NativeLink and point your build system at it in under 10 minutes.
Before you start
Nothing beyond a build system that speaks the Remote Execution API.
This guide takes you from zero to your first cached build. Pick the installation method that matches your platform, then wire your build system to the running cluster.
Prerequisites
You need a build tool that speaks the Remote Execution API: Bazel, Buck2, Siso, Pants, Goma, or CMake via recc. For the Docker path, Docker. For the Nix path, a recent Nix install with flakes enabled.
Install NativeLink
The fastest way is the prebuilt container image. It runs anywhere Docker runs; the configuration it needs is a single JSON5 file from the repository.
# Grab a known-good basic configuration
curl -O https://raw.githubusercontent.com/TraceMachina/nativelink/v1.6.5/nativelink-config/examples/basic_cas.json5
# Run the official image
docker run \
-v $(pwd)/basic_cas.json5:/config \
-p 50051:50051 \
ghcr.io/tracemachina/nativelink:v1.6.5 configThe image is multi-arch: x86_64 and ARM64 both run natively (use
v1.6.0 or later; earlier tags are x86_64-only). The server is now
listening on localhost:50051.
Verify it's running
In another terminal:
curl -v http://localhost:50051/You should see the connection open and an HTTP response come back. The
status will be an error, since / is not a gRPC route; the exact body
doesn't matter, the connection succeeding does.
Point your build system at it
Add to your .bazelrc:
build --remote_cache=grpc://localhost:50051
build --remote_instance_name=mainOr pass them per invocation:
bazel build //... \
--remote_cache=grpc://localhost:50051 \
--remote_instance_name=mainRun any build target. Subsequent rebuilds of unchanged targets should
report a remote cache hit count in the final processes: summary line.
Leave --remote_executor off for now: the container image holds only the
NativeLink binary, no shell or compilers, so actions sent to its worker
cannot run. Remote execution sets up workers with a
toolchain.
Confirm cache hits
Re-run your build a second time without changing any source files. Every action should land in the cache and report a hit. With Bazel:
bazel build //... \
--remote_cache=grpc://localhost:50051 \
--execution_log_json_file=/tmp/exec.json
# Count the cache hits vs misses
grep -c '"remoteCacheHit": true' /tmp/exec.jsonIf you see hits, you're done. If not, jump to the troubleshooting section below.
Troubleshooting
Connection refused
The NativeLink server isn't listening on the port your client is
pointing at. Confirm with lsof -i :50051 (macOS / Linux) or
netstat -ano | findstr 50051 (Windows). Check the Docker container is
still running with docker ps.
Cache writes succeed, reads always miss
Most often this means two clients are using different instance_name
values or different toolchain configurations. Compare the
--remote_instance_name flag (Bazel) or the equivalent in your build
system across the two invocations. Toolchain mismatches surface as
action hashes that never collide.
Permission denied on /config in Docker
SELinux-enforcing distributions (Fedora, RHEL) require an explicit
:Z label on the mounted volume:
-v $(pwd)/basic_cas.json5:/config:Z.
FAQ
A server that starts and a build that succeeds are not evidence that anything was cached. This is the line to read, and what it means when it says zero.
SidewaysConfigurationWhat is in that JSON5 file, and how to grow it from a single node to a fleet.
SidewaysArchitectureWhat each piece of the cluster is responsible for, and why the split is drawn where it is.