Advanced 10 min read

Self-Hosting

Run your own x402 facilitator with x402-rs

If you prefer full control over your infrastructure, you can run your own x402 facilitator using x402-rs.

Consider Self-Hosting If:

  • Custom logic - You need specialized behavior during x402 workflows
  • Regulatory compliance - Data residency requirements or audit trails that must stay on your infrastructure
  • Absolute control - You want complete ownership of the payment verification and settlement process
  • Blockchain proximity - You’re already running nodes or have deep integration with the target chain
  • Ops-ready - You’re comfortable managing gas bumps, stuck transactions, nonce coordination, and private key management yourself

Use FareSide Hosted If:

  • Avoid settlement complexity - We handle gas bumps, stuck transactions, nonce management, private key management and other operational headaches for you
  • Getting started - Focus on building your product, not payment infrastructure
  • Managed reliability - Want uptime guarantees and automatic failover
  • Advanced features - Need payment splits, webhooks, or cross-chain support (coming soon)

Prerequisites

  • Docker (recommended) or Rust toolchain (1.80+)
  • Access to RPC endpoints for your target networks
  • Private key for the facilitator wallet (for gas)
  • Server with reliable uptime

Quick Start with Docker

Prebuilt Docker images are available from:

  • GitHub Container Registry: ghcr.io/x402-rs/x402-facilitator

1. Create Environment File

Create a .env file with your configuration:

# Server
HOST=0.0.0.0
PORT=8080

# Signer configuration
SIGNER_TYPE=private-key
EVM_PRIVATE_KEY=0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef
SOLANA_PRIVATE_KEY=6ASf5EcmmEHTgDJ4X4ZT5vT6iHVJBXPg5AN5YoTCpGWt

# RPC endpoints (only networks you configure will be supported)
RPC_URL_BASE_SEPOLIA=https://sepolia.base.org
RPC_URL_BASE=https://mainnet.base.org
RPC_URL_SOLANA=https://api.mainnet-beta.solana.com

# Logging
RUST_LOG=info

2. Run the Container

docker run --env-file .env -p 8080:8080 ghcr.io/x402-rs/x402-facilitator

3. Verify It’s Running

curl http://localhost:8080/health

Configuration Reference

The facilitator is configured entirely through environment variables:

VariableRequiredDescription
HOSTNoHTTP host to bind to (default: 0.0.0.0)
PORTNoHTTP server port (default: 8080)
SIGNER_TYPEYesType of signer, only private-key supported
EVM_PRIVATE_KEYYes*Private key in hex for EVM networks
SOLANA_PRIVATE_KEYYes*Private key for Solana networks
RUST_LOGNoLogging level (info, debug, trace)

*At least one private key is required depending on which networks you support.

RPC Endpoints

The networks you support are determined by which RPC URLs you provide:

NetworkEnvironment Variable
Base Sepolia (testnet)RPC_URL_BASE_SEPOLIA
Base MainnetRPC_URL_BASE
Solana MainnetRPC_URL_SOLANA
Solana DevnetRPC_URL_SOLANA_DEVNET
Polygon MainnetRPC_URL_POLYGON
Polygon Amoy (testnet)RPC_URL_POLYGON_AMOY
Avalanche MainnetRPC_URL_AVALANCHE
Avalanche Fuji (testnet)RPC_URL_AVALANCHE_FUJI
Sei MainnetRPC_URL_SEI
Sei TestnetRPC_URL_SEI_TESTNET

If an RPC URL for a network is missing, that network will not be available.

Building from Source

If you prefer to build locally:

# Clone the repository
git clone https://github.com/x402-rs/x402-rs.git
cd x402-rs

# Build and run
cargo build --release
cargo run --release

Or build your own Docker image:

docker build -t x402-rs .
docker run --env-file .env -p 8080:8080 x402-rs

Docker Compose

For production deployments:

version: '3.8'
services:
  facilitator:
    image: ghcr.io/x402-rs/x402-facilitator
    ports:
      - "8080:8080"
    env_file:
      - .env
    restart: unless-stopped

Connecting Your Services

Point your middleware to your self-hosted facilitator:

TypeScript (x402-hono)

import { Hono } from "hono";
import { serve } from "@hono/node-server";
import { paymentMiddleware } from "x402-hono";

const app = new Hono();

// Configure the payment middleware with your self-hosted facilitator
app.use(paymentMiddleware(
  "0xYourAddress", // your receiving wallet address
  {  // Route configurations for protected endpoints
    "/weather": {
      price: "$0.001",
      network: "base-sepolia",
      config: {
        description: "Access to weather data",
      }
    }
  },
  {
    url: "http://your-facilitator:8080/", // Your self-hosted facilitator
  }
));

// Implement your route
app.get("/weather", (c) => {
  return c.json({
    report: {
      weather: "sunny",
      temperature: 70,
    }
  });
});

serve({
  fetch: app.fetch,
  port: 3000
});

Rust (x402-axum)

use x402_axum::X402Middleware;

// Point to your self-hosted facilitator
let x402 = X402Middleware::try_from("http://your-facilitator:8080/").unwrap();

Production Considerations

High Availability

For production, run multiple facilitator instances behind a load balancer:

# docker-compose.prod.yml
version: '3.8'
services:
  facilitator-1:
    image: ghcr.io/x402-rs/x402-facilitator
    env_file: .env.instance1  # Unique private key

  facilitator-2:
    image: ghcr.io/x402-rs/x402-facilitator
    env_file: .env.instance2  # Different private key

  nginx:
    image: nginx
    ports:
      - "8080:80"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
Each instance must have its own private key

Sharing a private key across multiple facilitator instances will cause nonce collisions and transaction failures. Each instance needs a unique EVM_PRIVATE_KEY and SOLANA_PRIVATE_KEY, and each wallet must be funded with gas tokens.

Each facilitator instance needs its own funded wallet:

  • Generate separate keys for each instance
  • Fund each wallet with gas tokens on all supported networks
  • Monitor gas balances across all wallets
  • Consider using a key management service for rotation

RPC providers often have rate limits. For high-availability deployments:

  • Carefully distribute RPC endpoints across instances to spread the load
  • Use different RPC providers for different instances
# .env.instance1
RPC_URL_BASE=https://base-mainnet.g.alchemy.com/v2/KEY_1

# .env.instance2
RPC_URL_BASE=https://base.llamarpc.com

Security

  • Minimize wallet balances - Don’t keep large amounts of gas funds in facilitator wallets. Top up regularly as they deplete rather than pre-funding with large amounts
  • Never expose private keys in logs or error messages
  • Use HTTPS in production (terminate at load balancer)
  • Firewall the facilitator to only accept traffic from your services
  • Rotate keys periodically

Logs

Enable detailed logging via environment variable:

RUST_LOG=debug

Observability

The facilitator emits OpenTelemetry-compatible traces and metrics. To enable:

# For Honeycomb
OTEL_EXPORTER_OTLP_ENDPOINT=https://api.honeycomb.io:443
OTEL_EXPORTER_OTLP_HEADERS=x-honeycomb-team=your_api_key,x-honeycomb-dataset=x402-rs
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf

The service automatically detects and initializes exporters if OTEL_EXPORTER_OTLP_* variables are provided.

Comparison: Self-Hosted vs FareSide

AspectSelf-HostedFareSide
Setup timeHoursMinutes
Settlement opsGas bumps, nonces, stuck txs - all yoursHandled for you
Private key managementGenerate, secure, rotate, fund multiple walletsNot your problem
RPC managementRate limits, failover, multiple providersManaged
High availabilityComplex (unique keys per instance, RPC planning)Built-in
Cost modelFixed (servers + gas + ops time)Per transaction
UptimeYour responsibility99.9% SLA
Payment routingDIYIncluded
SupportCommunityDirect

Migration

From FareSide to Self-Hosted

  1. Set up your facilitator
  2. Test with a staging environment
  3. Update middleware configuration
  4. Monitor for issues

From Self-Hosted to FareSide

  1. Join the waitlist
  2. Get your API key
  3. Update middleware to use FareSide URL
  4. Decommission your facilitator

Resources