Skip to content
 
 

Latest commit

 

History

15,666 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ferrum Edge

Ferrum Edge

A high-performance edge proxy built in Rust

CI Coverage Release License Docker Pulls

Overview

Ferrum Edge is a lightweight, extensible edge proxy designed for modern microservice architectures. It provides dynamic routing, multi-protocol support, a robust plugin system, and multiple deployment topologies — from single-node file-based setups to distributed Control Plane / Data Plane architectures.

Key highlights:

  • Multi-protocol: HTTP/1.1, HTTP/2, HTTP/3 (QUIC), WebSocket, gRPC, raw TCP/UDP with TLS/DTLS
  • Built-in plugin system: Authentication, authorization, OPA policy decisions, adaptive concurrency, WAF content threat detection, OpenAPI contract validation, rate limiting, fault injection, compression, response security headers, SSE stream handling, transformation, response mocking, spec exposure, serverless functions, AI/LLM-specific plugins (including AI federation for multi-provider routing), MCP / Agent Tool Gateway routing, A2A agent gateway observability/policy, load testing, API chargeback, and observability
  • Eight operating modes: Database, File, Control Plane, Data Plane, Mesh, Injector, Node Agent, and Migrate
  • Lock-free hot path: All request-path reads use ArcSwap or DashMap — no mutexes on the proxy path
  • Zero-downtime config reloads: Atomic config swap via DB polling (database/cp), CP push (dp), or SIGHUP (file mode, and mesh with a local file/xDS config source — other modes log and ignore SIGHUP)
  • Service mesh: Six topologies (sidecar, ambient, Experimental node waypoint, service waypoint, east-west gateway, egress), native MeshSubscribe, xDS ADS, or localized file config consumption, SPIFFE identity, HBONE, transparent DNS proxy, mesh authorization, REGISTRY_ONLY outbound policy, and Istio/GAMMA RED metrics. See docs/mesh.md
  • Runtime observability: JWT-gated /metrics/runtime JSON snapshot with system/process state, HTTP status windows, error classes, DNS outcomes, backend pool churn, TCP resets, log counters, and overload state
  • Operable alerts: the ferrum-gateway chart ships Prometheus alerts and Grafana dashboards, and every alert links a first-response procedure in docs/runbooks/gateway.md
  • Kubernetes mesh translation: Gateway API and Istio VirtualService route splits, Istio AuthorizationPolicy/RequestAuthentication/PeerAuthentication, and sidecar injection webhook

For the full feature list, see FEATURES.md.

Operating Modes

Mode Env Var Description Admin API Proxy
Database FERRUM_MODE=database Single-instance, DB-backed (PostgreSQL/MySQL/SQLite/MongoDB) Read/Write Yes
File FERRUM_MODE=file Single-instance, YAML/JSON config, SIGHUP reload Read-only Yes
Control Plane FERRUM_MODE=cp Centralized config authority, gRPC distribution to DPs Read/Write No
Data Plane FERRUM_MODE=dp Horizontally scalable traffic processing nodes Read-only Yes
Mesh FERRUM_MODE=mesh Service-mesh data plane consuming native MeshSubscribe, xDS ADS, or a localized config file with six topologies Read-only Yes
Injector FERRUM_MODE=injector Kubernetes admission webhook that injects Ferrum mesh sidecars/init capture No No
Node Agent FERRUM_MODE=node_agent Per-node eBPF capture manager for ambient mesh; no proxy listeners. See docs/node_agent.md Optional (read-only) No
Migrate FERRUM_MODE=migrate Runs DB schema migrations then exits (explicit CLI / external K8s Job; not a Helm chart mode) No No

See docs/cp_dp_mode.md for distributed deployment details. On Kubernetes, map each mode to its chart or external contract in docs/kubernetes_deployment.md.

Prerequisites

  • Rust toolchain — latest stable (the repo pins channel = "stable" via rust-toolchain.toml; rustup will auto-install on first cargo invocation). CI runs clippy with -D warnings against the current stable, so local toolchains MUST be at parity.
  • protoc (Protocol Buffers compiler) for gRPC code generation — install protobuf-compiler or set PROTOC to the executable path
  • Database (optional): PostgreSQL, MySQL, SQLite, or MongoDB (for database and CP modes)

Installation

From Source

git clone https://github.com/ferrum-edge/ferrum-edge.git
cd ferrum-edge
cargo build --release

# Install to PATH
sudo cp target/release/ferrum-edge /usr/local/bin/
ferrum-edge version

Pre-built Binaries

Download from GitHub Releases for Linux x86_64/ARM64 and macOS x86_64/ARM64. Releases ship raw platform binaries plus adjacent .sha256 checksum files (for example ferrum-edge-linux-x86_64 and ferrum-edge-linux-x86_64.sha256).

Pin an explicit release tag in download URLs. Ferrum's moving latest tag is published as a prerelease, while GitHub's /releases/latest redirect and the releases/latest API endpoint skip prereleases. Use /releases/download/<tag>/… or gh release download <tag> instead. Pick the current immutable vX.Y.Z semver tag from the Releases page, and do not pin production to the mutable latest prerelease.

# Example: Linux x86_64
set -euo pipefail
TAG=<published-tag>  # from GitHub Releases / container registry (not a chart default)
BASE="https://github.com/ferrum-edge/ferrum-edge/releases/download/${TAG}"
curl -fsSLO "${BASE}/ferrum-edge-linux-x86_64"
curl -fsSLO "${BASE}/ferrum-edge-linux-x86_64.sha256"
sha256sum -c ferrum-edge-linux-x86_64.sha256
chmod +x ferrum-edge-linux-x86_64
sudo install -m 0755 ferrum-edge-linux-x86_64 /usr/local/bin/ferrum-edge
ferrum-edge version

Published Linux GNU artifacts (ferrum-edge-linux-x86_64, ferrum-cni-linux-x86_64, and the ARM64 pair) are dynamically linked against glibc. The declared runtime floor is GLIBC_2.34 (RHEL 9 / Rocky Linux 9 / AlmaLinux 9, which also covers Ubuntu 22.04 and Debian 12). The x86_64 GNU binaries are built in a digest-pinned AlmaLinux 8.10 sysroot (glibc 2.28) by the same job that checksums and uploads them, and that job ABI-scans and smoke-tests the exact staged bytes before publishing them, so the released artifact is the artifact that was verified. ARM64 GNU artifacts come from the isolated Cross build, already target an older glibc, and are re-checked as published. Beyond glibc, the remaining dynamic libraries are libgcc_s.so.1 and, when the Kafka stack does not static-link zlib, libz.so.1. Any GNU artifact whose GLIBC version-need records exceed 2.34, whose DT_NEEDED set is outside that allowlist, whose e_machine does not match the advertised *-x86_64 / *-aarch64 architecture, or that embeds a DT_RPATH / DT_RUNPATH, fails the release.

Docker

docker pull ghcr.io/ferrum-edge/ferrum-edge:latest

docker run -d --name ferrum-edge \
  -p 8000:8000 \
  -e FERRUM_MODE=database \
  -e FERRUM_DB_TYPE=sqlite \
  -e FERRUM_DB_URL="sqlite:////data/ferrum.db?mode=rwc" \
  -e FERRUM_ADMIN_JWT_SECRET="please-change-me-to-a-32+character-secret" \
  -e FERRUM_ADMIN_BIND_ADDRESS=127.0.0.1 \
  -v ferrum_data:/data \
  ghcr.io/ferrum-edge/ferrum-edge:latest

Admin API exposure. The admin API is a management plane. Both admin listeners (HTTP and HTTPS) bind to loopback (127.0.0.1) by default, so the example does not publish port 9000 and admin is not reachable from the network. In the writable database/cp modes the gateway refuses to start if the plaintext admin listener is bound to a non-loopback address (0.0.0.0, a public IP, or a private/VPC interface IP) with no FERRUM_ADMIN_ALLOWED_CIDRS allowlist. To make admin reachable from outside the container you must set FERRUM_ADMIN_BIND_ADDRESS=0.0.0.0 (or ::) — loopback alone is not reachable through a published port. Then either: (a) serve it over TLS (FERRUM_ADMIN_TLS_CERT_PATH/FERRUM_ADMIN_TLS_KEY_PATH, publish 9443, set FERRUM_ADMIN_HTTP_PORT=0 to disable plaintext) and/or set FERRUM_ADMIN_ALLOWED_CIDRS; or (b) for throwaway local testing only, set FERRUM_ALLOW_INSECURE_ADMIN_HTTP=true and publish 127.0.0.1:9000:9000.

See docs/docker.md for Docker Compose examples and production deployment.

Getting Started

File Mode (quickest start)

# Using the CLI (recommended)
ferrum-edge run --spec tests/config.yaml -v

# Using environment variables
FERRUM_MODE=file \
FERRUM_FILE_CONFIG_PATH=tests/config.yaml \
FERRUM_LOG_LEVEL=info \
cargo run --release -- run

With smart defaults, if ./ferrum.conf and ./resources.yaml exist in the current directory:

ferrum-edge run

See docs/cli.md for the full CLI reference.

Database Mode (SQLite)

FERRUM_MODE=database \
FERRUM_DB_TYPE=sqlite \
FERRUM_DB_URL="sqlite://ferrum.db?mode=rwc" \
FERRUM_ADMIN_JWT_SECRET="change-me-dev-admin-secret-min-32-chars" \
FERRUM_ADMIN_BIND_ADDRESS=127.0.0.1 \
FERRUM_LOG_LEVEL=info \
cargo run --release -- run

Database Mode (PostgreSQL)

FERRUM_MODE=database \
FERRUM_DB_TYPE=postgres \
FERRUM_DB_URL="postgres://user:pass@localhost/ferrum" \
FERRUM_ADMIN_JWT_SECRET="change-me-dev-admin-secret-min-32-chars" \
FERRUM_ADMIN_BIND_ADDRESS=127.0.0.1 \
cargo run --release -- run

Database Mode (MongoDB)

FERRUM_MODE=database \
FERRUM_DB_TYPE=mongodb \
FERRUM_DB_URL="mongodb://user:pass@localhost:27017/ferrum?authSource=admin" \
FERRUM_MONGO_DATABASE=ferrum \
FERRUM_ADMIN_JWT_SECRET="change-me-dev-admin-secret-min-32-chars" \
FERRUM_ADMIN_BIND_ADDRESS=127.0.0.1 \
cargo run --release -- run

Control Plane + Data Plane (local development)

The CP→DP gRPC channel carries Data Plane authentication JWTs and the full gateway configuration, so it is TLS-first and secure-by-default: the CP refuses to bind a plaintext gRPC listener on a non-loopback address, and the DP refuses a non-loopback http:// CP URL, unless TLS is configured (or plaintext is explicitly permitted — see below). The loopback quickstart below runs as-is; any networked deployment must use TLS.

# Control Plane (loopback + plaintext — local development only; secrets must be 32+ chars)
FERRUM_MODE=cp \
FERRUM_DB_TYPE=sqlite \
FERRUM_DB_URL="sqlite://ferrum.db?mode=rwc" \
FERRUM_ADMIN_JWT_SECRET="change-me-dev-admin-secret-min-32-chars" \
FERRUM_CP_GRPC_LISTEN_ADDR="127.0.0.1:50051" \
FERRUM_CP_DP_GRPC_JWT_SECRET="change-me-dev-cp-dp-secret-min-32-chars" \
cargo run --release -- run

# Data Plane (single CP, loopback — local development only)
FERRUM_MODE=dp \
FERRUM_DP_CP_GRPC_URLS="http://localhost:50051" \
FERRUM_CP_DP_GRPC_JWT_SECRET="change-me-dev-cp-dp-secret-min-32-chars" \
cargo run --release -- run

# Data Plane (multi-CP failover over TLS — production shape)
FERRUM_MODE=dp \
FERRUM_DP_CP_GRPC_URLS="https://cp1:50051,https://cp2:50051,https://cp3:50051" \
FERRUM_DP_GRPC_TLS_CA_CERT_PATH="/certs/ca.pem" \
FERRUM_CP_DP_GRPC_JWT_SECRET="change-me-dev-cp-dp-secret-min-32-chars" \
cargo run --release -- run

For production CP/DP with TLS/mTLS, see docs/cp_dp_mode.md. To intentionally run plaintext config sync on a networked address (trusted network, with compensating controls), set FERRUM_CP_DP_GRPC_ALLOW_PLAINTEXT=true on both the CP and the DP. For multi-region high availability, see docs/multi_region_ha.md.

Default Ports

Port Protocol Purpose
8000 HTTP Proxy traffic
8443 HTTPS Proxy traffic (TLS)
9000 HTTP Admin API
9443 HTTPS Admin API (TLS)
50051 gRPC Control Plane → Data Plane sync

All ports are configurable via environment variables (FERRUM_PROXY_HTTP_PORT, FERRUM_PROXY_HTTPS_PORT, FERRUM_ADMIN_HTTP_PORT, FERRUM_ADMIN_HTTPS_PORT, FERRUM_CP_GRPC_LISTEN_ADDR). Set any plaintext port to 0 to disable its listener entirely for TLS-only deployments.

Configuration

Ferrum Edge is configured through environment variables, with an optional ferrum.conf file for defaults. Environment variables take precedence.

Essential Variables

Variable Required Default Description
FERRUM_MODE Yes database, file, cp, dp, mesh, injector, node_agent, migrate
FERRUM_LOG_LEVEL No warn error, warn, info, debug, trace
FERRUM_LOG_BUFFER_CAPACITY No 4096 Per-sink hard record limit; aggregate bytes are separately bounded by FERRUM_LOG_BUFFER_BYTES
FERRUM_PROXY_HTTP_PORT No 8000 HTTP proxy port (0 = disabled)
FERRUM_PROXY_HTTPS_PORT No 8443 HTTPS proxy port
FERRUM_ACCEPT_THREADS No 0 (auto-detect) Parallel accept loops on duplicated fds of one exclusive listen socket (0 = CPU cores; Unix only, non-Unix falls back to one loop)
FERRUM_ADMIN_HTTP_PORT No 9000 Admin API HTTP port (0 = disabled)
FERRUM_ADMIN_JWT_SECRET DB/CP HS256 secret for Admin API (min 32 chars)
FERRUM_DB_TYPE DB/CP postgres, mysql, sqlite, mongodb
FERRUM_DB_URL DB/CP Database connection string
FERRUM_FILE_CONFIG_PATH File mode Path to YAML/JSON config file

For the full list of 300+ environment variables, see docs/configuration.md.

Operational note: all logging flows through bounded non-blocking writers (fixed record and byte admission → dedicated background threads → stdout/stderr), so log calls never block request-processing threads. Keep application logs on stdout/stderr by default. In containers, let the container runtime or platform collect and rotate the stream. On VMs, prefer running Ferrum Edge under systemd or another supervisor and let journald, rsyslog, logrotate, or a host log agent handle retention and rotation. Only add application-level file logging if you have a specific requirement for local log files. Under extreme throughput, size FERRUM_LOG_BUFFER_CAPACITY and FERRUM_LOG_BUFFER_BYTES together; increasing the record limit alone cannot increase admission when the byte budget is already full. New events are dropped and counted when either bound is reached so collector backpressure cannot stall the gateway.

File Mode Config Format

version: "1"
proxies:
  - id: "my-api"
    listen_path: "/api/v1"
    backend_scheme: http
    backend_host: "backend-service"
    backend_port: 3000
    strip_listen_path: true

consumers:
  - id: "user-1"
    username: "alice"
    credentials:
      keyauth:
        - key: "alice-api-key"
    acl_groups:
      - "engineering"

plugin_configs:
  - id: "log-plugin"
    plugin_name: "stdout_logging"
    config: {}
    scope: global
    enabled: true

See docs/configuration.md for stream proxy config, service discovery, and the ferrum.conf reference.

Admin API

JWT-protected REST API for managing proxies, consumers, plugins, and upstreams at runtime.

The examples below use http://localhost:9000, matching the local quick-start (admin bound to loopback, plaintext). In production, serve the admin API over HTTPS (FERRUM_ADMIN_TLS_CERT_PATH/FERRUM_ADMIN_TLS_KEY_PATH, then https://host:9443) and disable plaintext with FERRUM_ADMIN_HTTP_PORT=0, or restrict callers with FERRUM_ADMIN_ALLOWED_CIDRS. Bearer tokens sent over plaintext http:// traverse the network in the clear. In database/cp modes the gateway refuses to start a public plaintext admin listener without an allowlist (see docs/configuration.md).

# Liveness probe (no auth) — always {"status":"ok"}
curl http://localhost:9000/live

# Readiness/health (no auth returns status+ready; full diagnostics need auth)
curl http://localhost:9000/health

# List proxies
curl -H "Authorization: Bearer $TOKEN" http://localhost:9000/proxies

# Create a proxy
curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"listen_path": "/api", "backend_scheme": "http", "backend_host": "backend", "backend_port": 3000}' \
  http://localhost:9000/proxies

# Backup / Restore
curl -H "Authorization: Bearer $TOKEN" http://localhost:9000/backup > backup.json
curl -X POST -H "Authorization: Bearer $TOKEN" -d @backup.json "http://localhost:9000/restore?confirm=true"

Submit an OpenAPI/Swagger spec to atomically provision a proxy, upstream, and plugins in one call — see docs/api_specs.md.

See docs/admin_api.md for the full endpoint reference, and openapi.yaml for the OpenAPI specification.

Plugin System

Ferrum ships a large built-in plugin set for request preflight, authentication, authorization and backend admission, request/response transformation, AI/agent gateway policy, protocol bridging, stream/WebSocket/UDP handling, and observability. Plugins execute in a deterministic priority pipeline (lower priority runs first) and are protocol-aware, so the gateway skips plugins that do not apply to the current protocol.

The canonical plugin registry and ordering live outside the README to avoid drift: see docs/plugins.md for detailed configuration of each plugin, and docs/plugin_execution_order.md for the full execution order and protocol support matrix.

AI / LLM Plugins

Plugins for AI and agent gateway use cases — transcript audit, cost visibility, budget enforcement, semantic policy, request policy, PII protection, output guardrails, prompt compression, streaming and non-streaming provider routing, MCP tool routing, and response caching:

  • ai_token_metrics — Extract token usage from LLM responses for observability only (SSE metrics require explicit buffered opt-in)
  • ai_request_guard — Enforce model whitelists, token limits, and request policy
  • ai_rate_limiter — Enforce token budgets with pre-request reservation and response reconciliation (HTTP-only; native gRPC is unsupported) (supports centralized Redis mode; compatible with any RESP-protocol server: Redis, Valkey, DragonflyDB, KeyDB, Garnet)
  • ai_prompt_shield — Scan for PII and reject, redact, or warn
  • ai_prompt_compressor — Bounded model-free compression for admitted OpenAI Chat/Text Completions requests (no external models or services); preserves matching-backtick code, URLs, Unicode numbers, common identifiers, and negations, with bounded fail-safe preserve_tag marker cleanup
  • ai_semantic_firewall — Semantic prompt/response firewall for prompt injection, jailbreaks, data exfiltration intent, tool abuse, and topic allow/deny policy
  • ai_semantic_cache — LLM response caching with normalized exact-match keys, optional embedding-based semantic similarity, and local or Redis exact-response storage
  • ai_response_guard — Output-side content guardrails: PII detection, blocked phrases, response format validation, and descriptor-based native gRPC response inspection for explicitly enrolled methods
  • ai_tool_governor — Deterministic allow/deny/redact/approval policy for AI tool/function calls by name, arguments, JSON Schema, regex, risk, and identity; screens request tool definitions, buffered and streaming response tool calls (held until cleared, then released or cut), and optional MCP/A2A methods, with an optional approval webhook
  • ai_transcript_audit — Controlled AI payload capture for compliance: redacted request/response excerpts, canonical hashes, model/provider, token/guardrail/tool/cache metadata, sampling, and async batched HTTP export; never blocks the hot path unless configured fail-closed
  • ai_stream_router — Streaming counterpart to ai_federation: claims "stream": true OpenAI Chat Completions, route-overrides to the matched provider, and normalizes provider-native SSE (e.g. Anthropic) to OpenAI chat.completion.chunk SSE without buffering
  • ai_federation — HTTP-only AI gateway routing final transformed Chat Completions JSON to supported providers with bounded responses, replay-safe fallback, strict endpoint policy, and provider-native tool/content normalization; the opt-in streaming block adds a non-buffering path that commits ONE provider pre-first-byte and relays OpenAI-contract provider SSE incrementally (fallback only before commit, never a spliced second provider), while ineligible providers and disabled streaming keep returning 501
  • mcp_gateway — MCP / Agent Tool Gateway for HTTP JSON-RPC MCP traffic: transparent proxying, aggregate discovery, namespaced tool/resource/prompt routing, session mediation, tool argument validation, and mcp.* metadata for downstream Ferrum plugins
  • a2a_gateway — Transparent Agent-to-Agent gateway for HTTP/HTTPS JSON-RPC, HTTP+JSON/REST, and gRPC/grpcs traffic: method detection, lightweight method policy, HTTP Agent Card URL rewriting, streaming-safe pass-through, and a2a.* metadata

Auto-detects OpenAI, Anthropic, Google Gemini, Cohere, Mistral, and AWS Bedrock response formats. See docs/plugins.md for configuration and a composition example.

Centralized Rate Limiting

rate_limiting and ai_rate_limiter support centralized mode via sync_mode: "redis" for coordinated limits across multiple gateway instances. When the centralized store cannot be consulted, redis_failure_policy decides: fail_closed (default) refuses, local_fallback explicitly opts into per-process budgets. Redis Cluster is not supported and is screened at connect — see docs/plugins.md. ws_rate_limiting also supports sync_mode: "redis", but only to externalize per-connection frame counters under a per-plugin/gateway-instance Redis namespace — budgets are not shared across instances or portable across reconnects/rebuilds. Compatible with any RESP-protocol server (Redis, Valkey, DragonflyDB, KeyDB, Garnet). Redis TLS uses gateway-level FERRUM_TLS_CA_BUNDLE_PATH and FERRUM_TLS_NO_VERIFY settings.

Custom Plugins

Drop-in custom plugins via custom_plugins/ directory — auto-discovered at build time. Custom plugins can declare their own database migrations via plugin_migrations() for creating and managing private tables, tracked independently from core migrations. See CUSTOM_PLUGINS.md.

Routing

  • Longest prefix match on listen_path with unique path enforcement
  • Host-based routing with exact and wildcard prefix support (*.example.com)
  • Host-only routing — omit listen_path on HTTP proxies to match any path under the specified hosts
  • Regex routes with auto-anchored full-path matching (prefix with ~)
  • Method filtering via allowed_methods per-proxy (405 on mismatch)
  • Path forwarding: strip_listen_path (default: true; no-op on host-only proxies), optional backend_path prefix

See docs/routing.md for detailed routing behavior.

Protocol-Specific Proxying

Protocol Config Notes
HTTP/1.1 backend_scheme: http / https Default, with connection pooling
HTTP/2 ALPN-negotiated on https Automatic via pool_enable_http2: true; startup capability classification decides when the direct H2 pool is used; body-size limits are enforced in-path on that pool
HTTP/3 backend_scheme: https Startup capability classification probes HTTPS backends for H3 support and plain HTTP traffic uses QUIC automatically when supported
WebSocket Runtime-detected from Upgrade: websocket (H1.1) or :protocol=websocket Extended CONNECT (H2 RFC 8441, H3 RFC 9220) on any HTTP-family proxy backend_scheme: httpws:// upstream; httpswss://. Same plugin pipeline across all three frontends; H3 sessions controlled by FERRUM_HTTP3_WEBSOCKET_ENABLED (default on)
gRPC Runtime-detected from content-type: application/grpc* on any HTTP-family proxy HTTP/2 with trailer support on both http (h2c) and https (ALPN) schemes
TCP backend_scheme: tcp / tcps Dedicated-port stream proxy (plaintext or TLS)
UDP backend_scheme: udp / dtls Datagram proxy with session tracking (plaintext or DTLS)

See docs/tcp_udp_proxy.md for TCP/UDP/DTLS proxy configuration.

Load Balancing & Resilience

  • Six algorithms: Round Robin, Weighted Round Robin, Least Connections, Least Latency, Consistent Hashing, Random
  • Health checks: Active probes (HTTP, TCP SYN, UDP) and passive monitoring
  • Circuit breaker: Three-state pattern (Closed/Open/Half-Open)
  • Retry: Connection and HTTP-level retries with fixed/exponential backoff
  • Service discovery: DNS-SD, Kubernetes, and Consul providers
  • Config caching: All modes maintain in-memory config cache for resilience during source outages
  • DP stale-config fence: In dp mode, a data plane serves its last applied CP snapshot during outages, but when every control plane is unreachable and that snapshot ages past FERRUM_DP_CONFIG_MAX_STALE_SECONDS (default 3600), the pod becomes unready and, by default (FERRUM_DP_CONFIG_STALE_ACTION=fail_closed), refuses new traffic on every protocol while existing connections drain. Partial CP loss and successful failover do not trigger the fence. See docs/cp_dp_mode.md
  • Startup failover: FERRUM_DB_CONFIG_BACKUP_PATH for DB outage recovery in Kubernetes
  • Multi-URL failover: FERRUM_DB_FAILOVER_URLS for database high availability

See docs/load_balancing.md, docs/retry.md, and docs/error_classification.md.

Connection Pooling

Lock-free connection reuse with per-proxy pool keys and HTTP/2 flow control tuning. Hybrid configuration with global defaults and per-proxy overrides. Startup pool warmup pre-establishes backend connections after DNS warmup to eliminate first-request cold-start latency.

See docs/connection_pooling.md for sizing guidance, pool warmup, and configuration.

Security

TLS

  • Frontend TLS/mTLS: Proxy and admin HTTPS with optional client certificate verification — docs/frontend_tls.md
  • Backend mTLS: Per-proxy client certificates for backend authentication — docs/backend_mtls.md
  • Database TLS: PostgreSQL and MySQL TLS/mTLS connections — docs/database_tls.md
  • TLS hardening: Configurable cipher suites, key exchange groups, and protocol versions — docs/frontend_tls.md

Client IP Resolution

Secure originating IP detection via trusted proxy configuration with X-Forwarded-For right-to-left walk. See docs/client_ip_resolution.md.

DNS

In-memory async DNS cache with startup warmup, stale-while-revalidate, per-proxy TTL overrides, and static overrides. See docs/dns_resolver.md.

Performance

Historical small-payload multi-protocol benchmark results from tests/performance/multi_protocol/ (local macOS Apple Silicon run, 200 concurrent, 10s, 64-byte payload; run date not recorded in this summary):

Protocol Gateway RPS Gw P50 Gw P99 Direct RPS Direct P50 Direct P99 Overhead
HTTP/1.1 102,183 1.89ms 3.85ms 209,910 939μs 1.81ms ~51%
HTTP/1.1+TLS 101,317 1.90ms 3.84ms 209,361 941μs 1.81ms ~52%
HTTP/2 108,138 1.67ms 6.38ms 355,544 486μs 1.53ms ~70%
HTTP/3 (QUIC) 53,085 3.51ms 5.87ms 83,592 2.38ms 2.80ms ~37%
gRPC 68,352 2.53ms 12.02ms 205,927 821μs 3.15ms ~67%
WebSocket 103,830 1.88ms 3.15ms 207,507 952μs 1.72ms ~50%
TCP 108,841 1.83ms 2.59ms 214,113 928μs 1.65ms ~49%
TCP+TLS 107,340 1.84ms 2.68ms 207,103 949μs 1.78ms ~48%
UDP 82,042 2.46ms 2.93ms 276,526 682μs 1.27ms ~70%
UDP+DTLS 76,107 2.61ms 3.69ms 101,839 1.96ms 2.47ms ~25%

Adaptive buffer sizing (enabled by default) dynamically tunes TCP/WebSocket tunnel copy buffers and UDP batch limits per proxy based on observed traffic patterns. Small-message proxies get smaller buffers (saves memory), bulk transfer proxies get larger buffers (reduces syscalls). See FERRUM_ADAPTIVE_BUFFER_* env vars for tuning.

Linux socket tuning: (TCP_FASTOPEN, IP_BIND_ADDRESS_NO_PORT), thread-local Date header caching, lazy timeout initialization, frequency-aware router cache eviction (Count-Min Sketch), RED-style adaptive load shedding, and a cacheability predictor for the response cache plugin. See FEATURES.md for details.

For current suite methodology and dated result tables, see tests/performance/ and tests/performance/multi_protocol/README.md.

Production tuning

File descriptor limit. On Unix, Ferrum Edge calls setrlimit(RLIMIT_NOFILE, rlim_cur=rlim_max) once at startup, raising the soft cap to whatever the hard cap allows. The call never asks for privileges the process does not already have, so a sandboxed/seccomp-restricted run is a silent no-op rather than a failure. The hard cap must be set externally — Ferrum Edge cannot raise it. Recommended floor for production: 65,536.

Environment How to raise the hard cap
systemd unit LimitNOFILE=1048576 in the [Service] section
Docker / Podman --ulimit nofile=1048576:1048576
Kubernetes Configure nofile on the node/container runtime (for example containerd/runc or the kubelet/systemd service); Pod securityContext does not expose ulimit/nofile.
Bare shell (dev) ulimit -n 1048576 before launching the binary
/etc/security/limits.conf * hard nofile 1048576 (and matching soft line)

When the effective soft cap after startup is below 65,536, Ferrum Edge emits one structured warn! line at startup (greppable as "soft FD limit") and continues. Below the floor, the gateway will still serve, but its 95% FD-critical threshold will trigger earlier under load.

Concurrency planning. Each inbound TCP/TLS connection consumes ~1 FD; HTTP/2 multiplexes many requests onto one. Linux splice(2) adds 2 pipe FDs per TCP relay. Plan for ~2–4× the target concurrent-connection count when sizing nofile.

Gateway Comparison

Historical local comparison summary (macOS Apple Silicon, 100 concurrent, 30s; run date not recorded in this summary):

All gateways run in Docker containers for apples-to-apples comparison:

Gateway Key-Auth req/s Key-Auth Latency vs Ferrum
Ferrum Edge 27,979 3.44 ms
Envoy 1.37 (Lua filter) 26,787 3.64 ms Ferrum 4% faster
Kong 3.14 25,009 3.91 ms Ferrum 12% faster
Tyk v5.12 19,186 5.08 ms Ferrum 46% faster

Ferrum also won the E2E TLS /api/users test outright — 29,808 req/s, the highest throughput of any gateway in any scenario, beating Envoy by 13%. Ferrum's authentication adds effectively zero overhead — authenticated requests match unauthenticated throughput thanks to the pre-computed ConsumerIndex with Arc<Consumer> zero-copy credential resolution and lock-free ArcSwap reads. See comparison/README.md and comparison/run_comparison.sh for the reproducible Docker gateway comparison harness, and tests/performance/README.md for the benchmark provenance checklist.

Troubleshooting

Issue Solution
FERRUM_MODE not set Set the FERRUM_MODE environment variable
duplicate listen_path Ensure all proxy listen_path values are unique
Database connection failed Verify FERRUM_DB_TYPE and FERRUM_DB_URL
401 on Admin API Check JWT is signed with FERRUM_ADMIN_JWT_SECRET
404 on proxy request Verify request path matches a configured listen_path
502 Bad Gateway Backend unreachable — check X-Gateway-Error header for details
504 Gateway Timeout Increase backend_read_timeout_ms
429 Too Many Requests Rate limit exceeded — check plugin config
DP not receiving config Verify FERRUM_CP_DP_GRPC_JWT_SECRET matches on both CP and DP

Documentation

Start at the documentation index — every document under docs/, grouped by audience.

Topic Link
Documentation index docs/README.md
Production hardening checklist docs/hardening.md
Threat model docs/threat_model.md
Support, versioning & deprecation policy docs/support_policy.md
Full configuration reference docs/configuration.md
Plugin reference docs/plugins.md
Transaction log schema customization docs/log_schema.md
Admin API docs/admin_api.md
Connection pooling docs/connection_pooling.md
Load balancing docs/load_balancing.md
CP/DP distributed mode docs/cp_dp_mode.md
Kubernetes deployment docs/kubernetes_deployment.md
SPIRE deployment for mesh identity docs/spire_deployment.md
TCP/UDP/DTLS proxy docs/tcp_udp_proxy.md
Frontend TLS/mTLS docs/frontend_tls.md
Backend mTLS docs/backend_mtls.md
Database TLS docs/database_tls.md
DNS resolver docs/dns_resolver.md
Routing docs/routing.md
Request path canonicalization docs/request_path_canonicalization.md
Retry logic docs/retry.md
Response streaming docs/response_body_streaming.md
Plugin execution order docs/plugin_execution_order.md
Infrastructure sizing docs/infrastructure_sizing.md
Docker deployment docs/docker.md
CI/CD pipeline docs/ci_cd.md
Database migrations docs/migrations.md
Upgrade procedure (build-out) docs/upgrade_guide.md
Custom plugins CUSTOM_PLUGINS.md
Feature list FEATURES.md
OpenAPI spec openapi.yaml
Gateway API conformance docs/gateway_api_conformance.md (canonical) — indexed from CONFORMANCE.md
Istio + xDS conformance matrix CONFORMANCE.md (run cargo test --test conformance_tests to refresh target/conformance/coverage.md)

CI/CD

On every push to main and PR: format check, tests (unit + integration + E2E), clippy, and performance regression testing. Version tags trigger multi-platform release builds with Docker images.

See docs/ci_cd.md for pipeline details.

Contributing

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-feature)
  3. Write tests for new functionality
  4. Ensure all tests pass (cargo test --all-features)
  5. Run cargo clippy --all-targets --all-features -- -D warnings and cargo fmt
  6. Submit a pull request

License

Copyright (c) 2026 Ferrum Edge

Licensed under the PolyForm Noncommercial License 1.0.0.

TL;DR: Permitted noncommercial use is defined by LICENSE (PolyForm Noncommercial 1.0.0). For-profit infrastructure use and evaluation with anticipated commercial application require a commercial license. See LICENSE and LICENSE-COMMERCIAL.md for the controlling terms and use-case table.

About

Ferrum Edge - API Gateway / AI Gateway / Mesh

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages