NativeLink
Getting Started

Setup

Install NativeLink and point your build system at it in under 10 minutes.

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, Reclient, Pants, Goma, or CMake via recc. For the Docker path, Docker 24+. For the Nix path, a recent Nix install with flakes enabled.

The fastest way is the prebuilt container image. It runs anywhere Docker runs and ships with a tested configuration.

# Grab a known-good basic configuration
curl -O https://raw.githubusercontent.com/TraceMachina/nativelink/v1.3.2/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.3.2 config

The server is now listening on localhost:50051.

curl -O https://raw.githubusercontent.com/TraceMachina/nativelink/main/nativelink-config/examples/basic_cas.json5

nix run github:TraceMachina/nativelink ./basic_cas.json5

Slower than the prebuilt image because it builds from source, but works on macOS (Apple Silicon and Intel) and any Linux with Nix. Also the only path that supports Apple Silicon natively at the moment.

Invoke-WebRequest `
  -Uri "https://raw.githubusercontent.com/TraceMachina/nativelink/v1.3.2/nativelink-config/examples/basic_cas.json5" `
  -OutFile "basic_cas.json5"

docker run `
  -v ${PWD}/basic_cas.json5:/config `
  -p 50051:50051 `
  ghcr.io/tracemachina/nativelink:v1.3.2 config

Native Windows support is x86_64 only. ARM64 Windows users should use WSL2 with the Linux instructions above.

Verify it's running

In another terminal:

curl -v http://localhost:50051/

You should see a gRPC server responding. 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_executor=grpc://localhost:50051
build --remote_instance_name=main

Or pass them per invocation:

bazel build //... \
  --remote_cache=grpc://localhost:50051 \
  --remote_executor=grpc://localhost:50051

Run any build target. Subsequent rebuilds of unchanged targets should report (remote cache hit) in the action log.

In your project root, add .buckconfig:

[buck2_re_client]
engine_address = grpc://localhost:50051
action_cache_address = grpc://localhost:50051
cas_address = grpc://localhost:50051
instance_name = main

Then run with --remote_cache:

buck2 build //... --remote-cache

Set the environment variables Reclient reads:

export RBE_service=localhost:50051
export RBE_instance=main
export RBE_service_no_security=true   # only for local TLS-free dev

reproxy &
rewrapper -- <your-compile-command>

The Chromium build is the canonical Reclient consumer; see Deployment → Chromium for a full example.

In pants.toml:

[GLOBAL]
remote_cache_read = true
remote_cache_write = true
remote_store_address = "grpc://localhost:50051"
remote_instance_name = "main"

Then run any goal as usual; Pants will route through the cache.

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.json

If you see hits — you're done. If not, jump to the troubleshooting section below.

Troubleshooting

What's next

You have a local cache running. The natural next steps: