Skip to content

GetDutchie/nx-cache-server-src

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

34 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Nx Custom Remote Cache Server

Release

A lightweight, high-performance Nx cache server that bridges Nx CLI clients with cloud storage providers for caching build artifacts. Built in Rust with a focus on maximum performance and minimal memory usage - less than 4MB during regular operation! 🚀

Features

  • AWS S3 Integration: Direct streaming integration with AWS S3 and S3-compatible services
  • Memory Efficient: Direct streaming with less than 4MB RAM usage during typical operation
  • High Performance: Built with Rust and Axum for maximum throughput
  • Zero Dependencies: Self-contained single executable with no external dependencies required
  • Nx API Compliant: Full implementation of the Nx custom remote cache OpenAPI specification
  • Security First: Bearer token authentication with constant-time comparison
  • Self-Hosted & Private: Full control over your data with zero telemetry

Quick Start

Prerequisites

Access to AWS S3 (or S3-compatible service like MinIO)

Installation

Step 1: Download the binary

Go to Releases page and download the binary for your operating system.

Alternatively, use command line tools:

# Using curl
curl -L https://github.com/nxcite/nx-cache-server/releases/download/<VERSION>/nx-cache-aws-<VERSION>-<PLATFORM> -o nx-cache-aws

# Using wget
wget https://github.com/nxcite/nx-cache-server/releases/download/<VERSION>/nx-cache-aws-<VERSION>-<PLATFORM> -O nx-cache-aws

# Replace:
#  <VERSION> with the version tag (e.g., v1.2.0)
#  <PLATFORM> with your platform (e.g., linux-x86_64, macos-arm64, macos-x86_64, windows-x86_64.exe).

Step 2: Make executable (Linux/macOS only)

chmod +x nx-cache-aws

Step 3: Configure the server

The server supports configuration via environment variables, command-line arguments, or both.

Option A: Environment Variables (Recommended)
# Required
export S3_BUCKET_NAME="your-s3-bucket-name"
export SERVICE_ACCESS_TOKEN="your-bearer-token"

# AWS Credentials (optional - auto-discovered from IAM roles, config files, SSO if not provided)
export AWS_ACCESS_KEY_ID="your-aws-access-key-id"
export AWS_SECRET_ACCESS_KEY="your-aws-secret-access-key"
export AWS_SESSION_TOKEN="your-session-token"  # If you are using temporary credentials

# AWS Region (optional - auto-discovered from AWS config, EC2/ECS metadata if not provided)
export AWS_REGION="us-west-2"

# Optional
export S3_ENDPOINT_URL="your-s3-endpoint-url"   # For S3-compatible services like MinIO
export S3_TIMEOUT="30"                          # S3 operation timeout in seconds (default: 30)
export PORT="3000"                              # Server port (default: 3000)
export BIND_ADDRESS="0.0.0.0"                   # IP to bind to (default: 0.0.0.0). Use "::" for IPv6/dual-stack
Option B: Command Line Arguments
./nx-cache-aws \
  --region "your-aws-region" \
  --access-key-id "your-aws-access-key-id" \
  --secret-access-key "your-aws-secret-access-key" \
  --bucket-name "your-s3-bucket-name" \
  --session-token "your-session-token" \
  --endpoint-url "your-s3-endpoint-url" \
  --service-access-token "your-bearer-token" \
  --timeout-seconds 30 \
  --port 3000 \
  --bind-address 0.0.0.0
Option C: Mixed Configuration

You can also combine both methods. Command line arguments will override environment variables:

# Set common config via environment
export AWS_REGION="us-west-2"
export S3_BUCKET_NAME="my-cache-bucket"
export SERVICE_ACCESS_TOKEN="my-secure-token"

# Specify other values via CLI
./nx-cache-aws --port 8080

Note: AWS credentials and region are optional when running on AWS infrastructure (EC2, ECS, Lambda) or when AWS config files are present. The server will auto-discover them from your environment.

Step 4: Run the server

./nx-cache-aws

Step 5 (optional): Verify the service is up and running

curl http://localhost:3000/health

You should receive an "OK" response.

Client Configuration

To configure your Nx workspace to use this cache server, set the following environment variables:

# Point Nx to your cache server
export NX_SELF_HOSTED_REMOTE_CACHE_SERVER="http://localhost:3000"

# Authentication token (must match SERVICE_ACCESS_TOKEN from server config)
export NX_SELF_HOSTED_REMOTE_CACHE_ACCESS_TOKEN="your-bearer-token"

# Optional: Disable TLS certificate validation (e.g. for development/testing environment)
export NODE_TLS_REJECT_UNAUTHORIZED="0"

Once configured, Nx will automatically use your cache server for storing and retrieving build artifacts.

For more details, see the Nx documentation.

Observability & Diagnosability

This fork's operating rule: RUST_LOG=nx_cache_server=info must be sufficient to fully diagnose any 4xx/5xx response, without ever needing debug logging. This matters because enabling debug logging on the whole AWS SDK (RUST_LOG=debug) generates enough volume to rotate out of a small log window in a couple of minutes on a busy cache server - exactly what happened during an incident that motivated this section.

At INFO level you get:

  • One access-log line per request (method, path, status, duration_ms, and bytes when a Content-Length is set) - so you can always tell whether/when/how a request finished.
  • One structured error line per failure, carrying operation (head/get/put/multipart-create/multipart-part/multipart-complete/multipart-abort), the cache object hash, and the AWS SDK's own request id(s) plus the full error detail - enough to open an AWS support case or match logs to an S3-side incident without re-running anything at debug.
  • Client-side aborts are logged at WARN, not ERROR, and answered with 400 Bad Request instead of 500. A client disconnecting or resetting mid-upload is not a server failure and must not page anyone or count toward server error budgets.

Run with, e.g.:

export RUST_LOG="nx_cache_server=info"

Uploads: Multipart Streaming & S3 Lifecycle Cleanup

PUT bodies are streamed to S3 in ~8MiB chunks. Small bodies use a single PutObject; anything larger uses S3 multipart upload (CreateMultipartUpload / UploadPart / CompleteMultipartUpload), so the server never buffers more than roughly one part of a (potentially multi-GB) build artifact in memory at a time. If any part fails to upload (including the client disconnecting mid-stream), the in-progress multipart upload is aborted via AbortMultipartUpload.

Recommended: because a process crash, network partition, or bug could in principle still leave an incomplete multipart upload behind (incomplete parts are billed S3 storage with no object to show for it), add an S3 Lifecycle rule to the cache bucket that expires incomplete multipart uploads after a few days, e.g.:

{
  "Rules": [
    {
      "ID": "abort-incomplete-multipart-uploads",
      "Status": "Enabled",
      "AbortIncompleteMultipartUpload": { "DaysAfterInitiation": 3 }
    }
  ]
}

This makes cleanup self-healing even in failure modes the server-side abort can't reach (e.g. the process being killed before it runs).


Stay Updated. Watch this repository to get notified about new releases

image image

About

A light, fast and open-source cache server for Nx. Written in Rust

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages

  • Rust 100.0%