Skip to main content
NativeLink provides seamless integration with Bazel through the Remote Execution API, offering both remote caching and remote execution capabilities. With Local Remote Execution (LRE), you can achieve near-perfect cache hit rates across different repositories, developers, and CI environments.

Prerequisites

  • Bazel 6.0 or later
  • A running NativeLink instance (see Quickstart)
  • For LRE: Nix 2.19.0 or later with flakes enabled

Basic Remote Cache Configuration

To use NativeLink as a remote cache, add the following flags to your .bazelrc:
.bazelrc
# Enable remote caching
build --remote_cache=grpc://localhost:50051
build --remote_instance_name=main

# Optional: Use blake3 for faster hashing
startup --digest_function=blake3

Remote Execution Configuration

For remote execution, configure both the cache and executor endpoints:
.bazelrc
# Remote execution
build:remote --remote_executor=grpc://localhost:50052
build:remote --remote_cache=grpc://localhost:50051
build:remote --remote_instance_name=main

# Platform configuration
build:remote --remote_default_exec_properties=cpu_count=1
build:remote --platform_suffix=remote
Invoke builds with:
bazel build --config=remote //your/target

Local Remote Execution (LRE)

LRE provides hermetic, reproducible toolchains that work identically in local and remote execution environments.

Flake-side Setup

1

Add NativeLink to your flake inputs

Configure your flake.nix to use NativeLink’s nixpkgs:
flake.nix
inputs = {
  nixpkgs = {
    url = "github:nixos/nixpkgs";
    # Follow nativelink's nixpkgs for toolchain compatibility
    follows = "nativelink/nixpkgs";
  };
  nativelink = {
    # Keep this commit in sync with MODULE.bazel
    url = "github:TraceMachina/nativelink/64ed20a40964b8c606c7d65f76af840bcfc837fd";
  };
};
2

Import the LRE flake module

Add to your flake-parts imports:
imports = [
  inputs.nativelink.flakeModule
];
3

Configure the development shell

Add the LRE installation script to your devShell:
devShells.default = pkgs.mkShell {
  shellHook = ''
    # Generate lre.bazelrc for LRE toolchains
    ${config.lre.installationScript}
  '';
};
4

Configure LRE environment

Specify the LRE environment and optional prefix:
lre = {
  # Import the lre-cc environment
  inherit (lre-cc.meta) Env;

  # Optional: Require --config=lre to enable
  prefix = "lre";
};

Bazel-side Setup

1

Import the generated configuration

Add to your .bazelrc:
.bazelrc
# Generated by the LRE flake module
try-import %workspace%/lre.bazelrc
2

Add LRE module to MODULE.bazel

MODULE.bazel
bazel_dep(name = "local-remote-execution", version = "0")
git_override(
    module_name = "local-remote-execution",
    remote = "https://github.com/TraceMachina/nativelink",
    strip_prefix = "local-remote-execution",
    # Keep in sync with flake.nix
    commit = "64ed20a40964b8c606c7d65f76af840bcfc837fd",
)

Generated Configuration

When you enter the Nix environment, lre.bazelrc is generated with LRE toolchain paths:
lre.bazelrc
# Bazel-side configuration for LRE
build:lre --action_env=BAZEL_DO_NOT_DETECT_CPP_TOOLCHAIN=1
build:lre --define=EXECUTOR=remote
build:lre --extra_execution_platforms=@local-remote-execution//generated-cc/config:platform
build:lre --extra_toolchains=@local-remote-execution//generated-cc/config:cc-toolchain

Complete Configuration Example

Here’s a complete .bazelrc based on NativeLink’s own configuration:
# Use blake3 for faster digests
startup --digest_function=blake3

# Enable platform-specific config
common --enable_platform_specific_config

# Remote cache configuration
build --remote_cache=grpc://127.0.0.1:50051
build --remote_instance_name=main

# Strict action environment
build --incompatible_strict_action_env

# Test output
build --test_output=errors

Authentication

For production deployments with authentication:
Configure mutual TLS authentication:
.bazelrc
build --remote_cache=grpcs://cache.example.com:50051
build --tls_client_certificate=/path/to/client.crt
build --tls_client_key=/path/to/client.key
build --tls_authority=cache.example.com

Testing Your Configuration

1

Clean build

bazel clean
bazel build //...
2

Verify cache hits

Run the build again:
bazel clean
bazel build //...
Look for remote cache hit in the output:
INFO: 11 processes: 2 remote cache hit, 9 internal.
3

Test remote execution

With remote execution enabled:
bazel build --config=remote //...
Look for remote in the process output:
INFO: 11 processes: 9 internal, 2 remote.

Common Flags

FlagDescription
--remote_cacheRemote cache endpoint (grpc:// or grpcs://)
--remote_executorRemote execution endpoint
--remote_instance_nameInstance name for multi-tenant setups
--remote_default_exec_propertiesDefault execution properties (cpu_count, memory, etc.)
--digest_functionHash function (blake3 recommended)
--incompatible_strict_action_envPrevent PATH/LD_LIBRARY_PATH leakage
--platform_suffixSuffix for platform names

Troubleshooting

Cache misses between local and remote

Ensure toolchain paths match between local and remote execution. With LRE, verify the /nix/store/... paths in lre.bazelrc match the worker container.

Connection refused errors

Verify NativeLink is running and the endpoint is correct:
grpcurl -plaintext localhost:50051 list

Permission denied

Check authentication configuration and ensure credentials are valid.

Next Steps

Build docs developers (and LLMs) love