{"id":48643504,"url":"https://github.com/ferrum-edge/ferrum-edge","last_synced_at":"2026-06-27T10:00:58.556Z","repository":{"id":342921560,"uuid":"1175627632","full_name":"ferrum-edge/ferrum-edge","owner":"ferrum-edge","description":"Ferrum Edge - API Gateway / AI Gateway / Mesh","archived":false,"fork":false,"pushed_at":"2026-06-22T04:46:40.000Z","size":57377,"stargazers_count":3,"open_issues_count":14,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-22T05:04:18.678Z","etag":null,"topics":["ai-gateway","api","api-gateway","loadbalancing","mesh","networking","security"],"latest_commit_sha":null,"homepage":"https://ferrumedge.com","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ferrum-edge.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-08T00:36:44.000Z","updated_at":"2026-06-22T04:23:39.000Z","dependencies_parsed_at":null,"dependency_job_id":"f914469b-e9f2-4d02-bfb3-7017e5a4615f","html_url":"https://github.com/ferrum-edge/ferrum-edge","commit_stats":null,"previous_names":["quicklaunchweb/ferrum-gateway","ferrum-edge/ferrum-edge"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ferrum-edge/ferrum-edge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferrum-edge%2Fferrum-edge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferrum-edge%2Fferrum-edge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferrum-edge%2Fferrum-edge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferrum-edge%2Fferrum-edge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ferrum-edge","download_url":"https://codeload.github.com/ferrum-edge/ferrum-edge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ferrum-edge%2Fferrum-edge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34848932,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-27T02:00:06.362Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-gateway","api","api-gateway","loadbalancing","mesh","networking","security"],"created_at":"2026-04-09T23:27:55.695Z","updated_at":"2026-06-27T10:00:58.549Z","avatar_url":"https://github.com/ferrum-edge.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n  \u003cimg src=\"assets/ferrum_edge.png\" alt=\"Ferrum Edge\" width=\"300\"\u003e\n\u003c/p\u003e\n\n\u003ch1 align=\"center\"\u003eFerrum Edge\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003eA high-performance edge proxy built in Rust\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/ferrum-edge/ferrum-edge/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://github.com/ferrum-edge/ferrum-edge/actions/workflows/ci.yml/badge.svg?branch=main\" alt=\"CI\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/ferrum-edge/ferrum-edge/actions/workflows/coverage.yml\"\u003e\u003cimg src=\"https://github.com/ferrum-edge/ferrum-edge/actions/workflows/coverage.yml/badge.svg?branch=main\" alt=\"Coverage\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/ferrum-edge/ferrum-edge/releases/latest\"\u003e\u003cimg src=\"https://img.shields.io/github/v/release/ferrum-edge/ferrum-edge\" alt=\"Release\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/ferrum-edge/ferrum-edge/blob/main/LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-PolyForm%20Noncommercial-blue\" alt=\"License\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://hub.docker.com/r/ferrumedge/ferrum-edge\"\u003e\u003cimg src=\"https://img.shields.io/docker/pulls/ferrumedge/ferrum-edge\" alt=\"Docker Pulls\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n## Overview\n\nFerrum 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.\n\n**Key highlights:**\n\n- **Multi-protocol**: HTTP/1.1, HTTP/2, HTTP/3 (QUIC), WebSocket, gRPC, raw TCP/UDP with TLS/DTLS\n- **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\n- **Eight operating modes**: Database, File, Control Plane, Data Plane, Mesh, Injector, Node Agent, and Migrate\n- **Lock-free hot path**: All request-path reads use `ArcSwap` or `DashMap` — no mutexes on the proxy path\n- **Zero-downtime config reloads**: Atomic config swap via DB polling, SIGHUP, or CP push\n- **Service mesh**: Six topologies (sidecar, ambient, 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](docs/mesh.md)\n- **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\n- **Kubernetes mesh translation**: Gateway API and Istio VirtualService route splits, Istio AuthorizationPolicy/RequestAuthentication/PeerAuthentication, and sidecar injection webhook\n\nFor the full feature list, see [FEATURES.md](FEATURES.md).\n\n## Operating Modes\n\n| Mode | Env Var | Description | Admin API | Proxy |\n|------|---------|-------------|-----------|-------|\n| **Database** | `FERRUM_MODE=database` | Single-instance, DB-backed (PostgreSQL/MySQL/SQLite/MongoDB) | Read/Write | Yes |\n| **File** | `FERRUM_MODE=file` | Single-instance, YAML/JSON config, SIGHUP reload | Read-only | Yes |\n| **Control Plane** | `FERRUM_MODE=cp` | Centralized config authority, gRPC distribution to DPs | Read/Write | No |\n| **Data Plane** | `FERRUM_MODE=dp` | Horizontally scalable traffic processing nodes | Read-only | Yes |\n| **Mesh** | `FERRUM_MODE=mesh` | Service-mesh data plane consuming native MeshSubscribe, xDS ADS, or a localized config file with six topologies | Read-only | Yes |\n| **Injector** | `FERRUM_MODE=injector` | Kubernetes admission webhook that injects Ferrum mesh sidecars/init capture | No | No |\n| **Node Agent** | `FERRUM_MODE=node_agent` | Per-node eBPF capture manager for ambient mesh; no proxy listeners. See [docs/node_agent.md](docs/node_agent.md) | Optional (read-only) | No |\n| **Migrate** | `FERRUM_MODE=migrate` | Runs DB schema migrations then exits | No | No |\n\nSee [docs/cp_dp_mode.md](docs/cp_dp_mode.md) for distributed deployment details.\n\n## Prerequisites\n\n- **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.\n- **protoc** (Protocol Buffers compiler) for gRPC code generation\n- **Database** (optional): PostgreSQL, MySQL, SQLite, or MongoDB (for database and CP modes)\n\n## Installation\n\n### From Source\n\n```bash\ngit clone https://github.com/ferrum-edge/ferrum-edge.git\ncd ferrum-edge\ncargo build --release\n\n# Install to PATH\nsudo cp target/release/ferrum-edge /usr/local/bin/\nferrum-edge version\n```\n\n### Pre-built Binaries\n\nDownload from [GitHub Releases](https://github.com/ferrum-edge/ferrum-edge/releases) for Linux x86_64/ARM64 and macOS x86_64/ARM64.\n\n```bash\n# Example: Linux x86_64\ncurl -LO https://github.com/ferrum-edge/ferrum-edge/releases/latest/download/ferrum-edge-x86_64-unknown-linux-gnu.tar.gz\ntar xzf ferrum-edge-x86_64-unknown-linux-gnu.tar.gz\nsudo mv ferrum-edge /usr/local/bin/\nferrum-edge version\n```\n\n### Docker\n\n```bash\ndocker pull ghcr.io/ferrum-edge/ferrum-edge:latest\n\ndocker run -d --name ferrum-edge \\\n  -p 8000:8000 -p 9000:9000 \\\n  -e FERRUM_MODE=database \\\n  -e FERRUM_DB_TYPE=sqlite \\\n  -e FERRUM_DB_URL=\"sqlite:////data/ferrum.db?mode=rwc\" \\\n  -e FERRUM_ADMIN_JWT_SECRET=\"dev-secret\" \\\n  -v ferrum_data:/data \\\n  ghcr.io/ferrum-edge/ferrum-edge:latest\n```\n\nSee [docs/docker.md](docs/docker.md) for Docker Compose examples and production deployment.\n\n## Getting Started\n\n### File Mode (quickest start)\n\n```bash\n# Using the CLI (recommended)\nferrum-edge run --spec tests/config.yaml -v\n\n# Using environment variables\nFERRUM_MODE=file \\\nFERRUM_FILE_CONFIG_PATH=tests/config.yaml \\\nFERRUM_LOG_LEVEL=info \\\ncargo run --release -- run\n```\n\nWith smart defaults, if `./ferrum.conf` and `./resources.yaml` exist in the current directory:\n\n```bash\nferrum-edge run\n```\n\nSee [docs/cli.md](docs/cli.md) for the full CLI reference.\n\n### Database Mode (SQLite)\n\n```bash\nFERRUM_MODE=database \\\nFERRUM_DB_TYPE=sqlite \\\nFERRUM_DB_URL=\"sqlite://ferrum.db?mode=rwc\" \\\nFERRUM_ADMIN_JWT_SECRET=\"my-super-secret-jwt-key\" \\\nFERRUM_LOG_LEVEL=info \\\ncargo run --release -- run\n```\n\n### Database Mode (PostgreSQL)\n\n```bash\nFERRUM_MODE=database \\\nFERRUM_DB_TYPE=postgres \\\nFERRUM_DB_URL=\"postgres://user:pass@localhost/ferrum\" \\\nFERRUM_ADMIN_JWT_SECRET=\"my-super-secret-jwt-key\" \\\ncargo run --release -- run\n```\n\n### Database Mode (MongoDB)\n\n```bash\nFERRUM_MODE=database \\\nFERRUM_DB_TYPE=mongodb \\\nFERRUM_DB_URL=\"mongodb://user:pass@localhost:27017/ferrum?authSource=admin\" \\\nFERRUM_MONGO_DATABASE=ferrum \\\nFERRUM_ADMIN_JWT_SECRET=\"my-super-secret-jwt-key\" \\\ncargo run --release -- run\n```\n\n### Control Plane + Data Plane\n\n```bash\n# Control Plane\nFERRUM_MODE=cp \\\nFERRUM_DB_TYPE=sqlite \\\nFERRUM_DB_URL=\"sqlite://ferrum.db?mode=rwc\" \\\nFERRUM_ADMIN_JWT_SECRET=\"admin-secret\" \\\nFERRUM_CP_GRPC_LISTEN_ADDR=\"0.0.0.0:50051\" \\\nFERRUM_CP_DP_GRPC_JWT_SECRET=\"grpc-secret\" \\\ncargo run --release -- run\n\n# Data Plane (single CP)\nFERRUM_MODE=dp \\\nFERRUM_DP_CP_GRPC_URLS=\"http://localhost:50051\" \\\nFERRUM_CP_DP_GRPC_JWT_SECRET=\"grpc-secret\" \\\ncargo run --release -- run\n\n# Data Plane (multi-CP failover — connects to primary, fails over to secondary)\nFERRUM_MODE=dp \\\nFERRUM_DP_CP_GRPC_URLS=\"https://cp1:50051,https://cp2:50051,https://cp3:50051\" \\\nFERRUM_CP_DP_GRPC_JWT_SECRET=\"grpc-secret\" \\\ncargo run --release -- run\n```\n\nFor production CP/DP with TLS, see [docs/cp_dp_mode.md](docs/cp_dp_mode.md#transport-security-tlsmtls). For multi-region high availability, see [docs/multi_region_ha.md](docs/multi_region_ha.md).\n\n## Default Ports\n\n| Port | Protocol | Purpose |\n|------|----------|---------|\n| `8000` | HTTP | Proxy traffic |\n| `8443` | HTTPS | Proxy traffic (TLS) |\n| `9000` | HTTP | Admin API |\n| `9443` | HTTPS | Admin API (TLS) |\n| `50051` | gRPC | Control Plane → Data Plane sync |\n\nAll 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.\n\n## Configuration\n\nFerrum Edge is configured through environment variables, with an optional `ferrum.conf` file for defaults. Environment variables take precedence.\n\n### Essential Variables\n\n| Variable | Required | Default | Description |\n|---|---|---|---|\n| `FERRUM_MODE` | **Yes** | — | `database`, `file`, `cp`, `dp`, `mesh`, `injector`, `node_agent`, `migrate` |\n| `FERRUM_LOG_LEVEL` | No | `warn` | `error`, `warn`, `info`, `debug`, `trace` |\n| `FERRUM_LOG_BUFFER_CAPACITY` | No | `128000` | Max buffered log lines in the non-blocking writer channel |\n| `FERRUM_PROXY_HTTP_PORT` | No | `8000` | HTTP proxy port (`0` = disabled) |\n| `FERRUM_PROXY_HTTPS_PORT` | No | `8443` | HTTPS proxy port |\n| `FERRUM_ACCEPT_THREADS` | No | `0` (auto-detect) | Parallel accept loops via SO_REUSEPORT (0 = CPU cores; Unix only, non-Unix falls back to one loop) |\n| `FERRUM_ADMIN_HTTP_PORT` | No | `9000` | Admin API HTTP port (`0` = disabled) |\n| `FERRUM_ADMIN_JWT_SECRET` | DB/CP | — | HS256 secret for Admin API (min 32 chars) |\n| `FERRUM_DB_TYPE` | DB/CP | — | `postgres`, `mysql`, `sqlite`, `mongodb` |\n| `FERRUM_DB_URL` | DB/CP | — | Database connection string |\n| `FERRUM_FILE_CONFIG_PATH` | File mode | — | Path to YAML/JSON config file |\n\nFor the full list of 300+ environment variables, see [docs/configuration.md](docs/configuration.md).\n\nOperational note: all logging flows through a **non-blocking writer** (channel → dedicated background thread → stdout), 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, tune `FERRUM_LOG_BUFFER_CAPACITY` to reduce log loss (the default 128,000 line buffer is lossy — new events are dropped when full to avoid backpressure).\n\n### File Mode Config Format\n\n```yaml\nproxies:\n  - id: \"my-api\"\n    listen_path: \"/api/v1\"\n    backend_scheme: http\n    backend_host: \"backend-service\"\n    backend_port: 3000\n    strip_listen_path: true\n    plugins:\n      - plugin_config_id: \"log-plugin\"\n\nconsumers:\n  - id: \"user-1\"\n    username: \"alice\"\n    credentials:\n      keyauth:\n        - key: \"alice-api-key\"\n    acl_groups:\n      - \"engineering\"\n\nplugin_configs:\n  - id: \"log-plugin\"\n    plugin_name: \"stdout_logging\"\n    config: {}\n    scope: global\n    enabled: true\n```\n\nSee [docs/configuration.md](docs/configuration.md) for stream proxy config, service discovery, and the `ferrum.conf` reference.\n\n## Admin API\n\nJWT-protected REST API for managing proxies, consumers, plugins, and upstreams at runtime.\n\n```bash\n# Health check (no auth required)\ncurl http://localhost:9000/health\n\n# List proxies\ncurl -H \"Authorization: Bearer $TOKEN\" http://localhost:9000/proxies\n\n# Create a proxy\ncurl -X POST -H \"Authorization: Bearer $TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"listen_path\": \"/api\", \"backend_scheme\": \"http\", \"backend_host\": \"backend\", \"backend_port\": 3000}' \\\n  http://localhost:9000/proxies\n\n# Backup / Restore\ncurl -H \"Authorization: Bearer $TOKEN\" http://localhost:9000/backup \u003e backup.json\ncurl -X POST -H \"Authorization: Bearer $TOKEN\" -d @backup.json \"http://localhost:9000/restore?confirm=true\"\n```\n\nSubmit an OpenAPI/Swagger spec to atomically provision a proxy, upstream, and plugins in one call — see [docs/api_specs.md](docs/api_specs.md).\n\nSee [docs/admin_api.md](docs/admin_api.md) for the full endpoint reference, and [openapi.yaml](openapi.yaml) for the OpenAPI specification.\n\n## Plugin System\n\nPlugins execute in a defined pipeline with priority ordering (lower = runs first):\n\n| Phase | Plugins |\n|-------|---------|\n| **Tracing** (25) | `otel_tracing` |\n| **Early** (50-275) | `correlation_id` (50), `cors` (100), `request_termination` (125), `ip_restriction` (150), `geo_restriction` (175), `bot_detection` (200), `grpc_method_router` (275) |\n| **Authentication** (950-1500) | `mtls_auth` (950), `jwks_auth` (1000), `oauth2_introspection` (1050), `oidc_relying_party` (1075), `jwt_auth` (1100), `key_auth` (1200), `ldap_auth` (1250), `basic_auth` (1300), `hmac_auth` (1400), `soap_ws_security` (1500) |\n| **Admission** (2000-2999) | `access_control` (2000), `tcp_connection_throttle` (2050), `mesh_authz` (2075), `opa` (2080), `adaptive_concurrency` (2090 target-aware backend admission), `request_deduplication` (2750), `request_size_limiting` (2800), `ws_message_size_limiting` (2810), `graphql` (2850), `rate_limiting` (2900), `ws_rate_limiting` (2910), `udp_rate_limiting` (2915), `ai_prompt_shield` (2925), `waf` (2930), `fault_injection` (2940), `body_validator` (2950), `openapi_validator` (2960), `ai_semantic_firewall` (2968), `ai_request_guard` (2975), `ai_semantic_cache` (2980), `ai_federation` (2985), `mcp_gateway` (2992), `a2a_gateway` (2993) |\n| **Transform** (3000-3999) | `request_transformer` (3000), `serverless_function` (3025), `grpc_deadline` (3050), `response_size_limiting` (3490), `response_caching` (3500) |\n| **Response** (4000-4999) | `response_transformer` (4000), `compression` (4050), `ai_response_guard` (4075), `security_headers` (4080), `ai_token_metrics` (4100), `ai_rate_limiter` (4200) |\n| **Logging** (9000-9999) | `stdout_logging` (9000), `ws_frame_logging` (9050), `statsd_logging` (9075), `http_logging` (9100), `tcp_logging` (9125), `loki_logging` (9155), `udp_logging` (9160), `ws_logging` (9175), `transaction_debugger` (9200), `proxy_alerts` (9250), `prometheus_metrics` (9300) |\n\nPlugins are protocol-aware — the gateway automatically skips plugins that don't apply to the current protocol (e.g., CORS is never invoked on TCP streams).\n\nSee [docs/plugins.md](docs/plugins.md) for detailed configuration of each plugin, and [docs/plugin_execution_order.md](docs/plugin_execution_order.md) for the full protocol support matrix.\n\n\n### AI / LLM Plugins\n\nNine plugins for AI and agent gateway use cases — cost visibility, budget enforcement, semantic policy, request policy, PII protection, output guardrails, multi-provider routing, MCP tool routing, and response caching:\n\n- **`ai_token_metrics`** — Extract token usage from LLM responses for observability (SSE metrics require explicit buffered opt-in)\n- **`ai_request_guard`** — Enforce model whitelists, token limits, and request policy\n- **`ai_rate_limiter`** — Rate-limit by token consumption instead of request count (supports centralized Redis mode; compatible with any RESP-protocol server: Redis, Valkey, DragonflyDB, KeyDB, Garnet)\n- **`ai_prompt_shield`** — Scan for PII and reject, redact, or warn\n- **`ai_semantic_firewall`** — Semantic prompt/response firewall for prompt injection, jailbreaks, data exfiltration intent, tool abuse, and topic allow/deny policy\n- **`ai_semantic_cache`** — LLM response caching with normalized exact-match keys, optional embedding-based semantic similarity, and local or Redis exact-response storage\n- **`ai_response_guard`** — Output-side content guardrails: PII detection, blocked phrases, response format validation\n- **`ai_federation`** — Universal AI gateway routing requests to 11+ providers with model-based routing and priority fallback\n- **`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\n- **`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\n\nAuto-detects OpenAI, Anthropic, Google Gemini, Cohere, Mistral, and AWS Bedrock response formats. See [docs/plugins.md](docs/plugins.md#ai--llm-plugins) for configuration and a composition example.\n\n### Centralized Rate Limiting\n\nAll three rate limiting plugins (`rate_limiting`, `ai_rate_limiter`, `ws_rate_limiting`) support centralized mode via `sync_mode: \"redis\"` for coordinated limits across multiple gateway instances. 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.\n\n### Custom Plugins\n\nDrop-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](CUSTOM_PLUGINS.md).\n\n## Routing\n\n- **Longest prefix match** on `listen_path` with unique path enforcement\n- **Host-based routing** with exact and wildcard prefix support (`*.example.com`)\n- **Host-only routing** — omit `listen_path` on HTTP proxies to match any path under the specified hosts\n- **Regex routes** with auto-anchored full-path matching (prefix with `~`)\n- **Method filtering** via `allowed_methods` per-proxy (405 on mismatch)\n- **Path forwarding**: `strip_listen_path` (default: true; no-op on host-only proxies), optional `backend_path` prefix\n\nSee [docs/routing.md](docs/routing.md) for detailed routing behavior.\n\n### Protocol-Specific Proxying\n\n| Protocol | Config | Notes |\n|----------|--------|-------|\n| **HTTP/1.1** | `backend_scheme: http` / `https` | Default, with connection pooling |\n| **HTTP/2** | ALPN-negotiated on `https` | Automatic via `pool_enable_http2: true`; startup capability classification decides when the direct H2 pool is used |\n| **HTTP/3** | `backend_scheme: https` | Startup capability classification probes HTTPS backends for H3 support and plain HTTP traffic uses QUIC automatically when supported |\n| **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: http` → `ws://` upstream; `https` → `wss://`. Same plugin pipeline across all three frontends; H3 sessions controlled by `FERRUM_HTTP3_WEBSOCKET_ENABLED` (default on) |\n| **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 |\n| **TCP** | `backend_scheme: tcp` / `tcps` | Dedicated-port stream proxy (plaintext or TLS) |\n| **UDP** | `backend_scheme: udp` / `dtls` | Datagram proxy with session tracking (plaintext or DTLS) |\n\nSee [docs/tcp_udp_proxy.md](docs/tcp_udp_proxy.md) for TCP/UDP/DTLS proxy configuration.\n\n## Load Balancing \u0026 Resilience\n\n- **Six algorithms**: Round Robin, Weighted Round Robin, Least Connections, Least Latency, Consistent Hashing, Random\n- **Health checks**: Active probes (HTTP, TCP SYN, UDP) and passive monitoring\n- **Circuit breaker**: Three-state pattern (Closed/Open/Half-Open)\n- **Retry**: Connection and HTTP-level retries with fixed/exponential backoff\n- **Service discovery**: DNS-SD, Kubernetes, and Consul providers\n- **Config caching**: All modes maintain in-memory config cache for resilience during source outages\n- **Startup failover**: `FERRUM_DB_CONFIG_BACKUP_PATH` for DB outage recovery in Kubernetes\n- **Multi-URL failover**: `FERRUM_DB_FAILOVER_URLS` for database high availability\n\nSee [docs/load_balancing.md](docs/load_balancing.md), [docs/retry.md](docs/retry.md), and [docs/error_classification.md](docs/error_classification.md).\n\n## Connection Pooling\n\nLock-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.\n\nSee [docs/connection_pooling.md](docs/connection_pooling.md) for sizing guidance, pool warmup, and configuration.\n\n## Security\n\n### TLS\n\n- **Frontend TLS/mTLS**: Proxy and admin HTTPS with optional client certificate verification — [docs/frontend_tls.md](docs/frontend_tls.md)\n- **Backend mTLS**: Per-proxy client certificates for backend authentication — [docs/backend_mtls.md](docs/backend_mtls.md)\n- **Database TLS**: PostgreSQL and MySQL TLS/mTLS connections — [docs/database_tls.md](docs/database_tls.md)\n- **TLS hardening**: Configurable cipher suites, key exchange groups, and protocol versions — [docs/frontend_tls.md](docs/frontend_tls.md#tls-policy-hardening)\n\n### Client IP Resolution\n\nSecure originating IP detection via trusted proxy configuration with `X-Forwarded-For` right-to-left walk. See [docs/client_ip_resolution.md](docs/client_ip_resolution.md).\n\n### DNS\n\nIn-memory async DNS cache with startup warmup, stale-while-revalidate, per-proxy TTL overrides, and static overrides. See [docs/dns_resolver.md](docs/dns_resolver.md).\n\n## Performance\n\nMulti-protocol benchmark results (macOS Apple Silicon, 200 concurrent, 10s, 64-byte payload):\n\n| Protocol | Gateway RPS | Gw P50 | Gw P99 | Direct RPS | Direct P50 | Direct P99 | Overhead |\n|----------|------------|--------|--------|------------|------------|------------|----------|\n| HTTP/1.1 | 102,183 | 1.89ms | 3.85ms | 209,910 | 939μs | 1.81ms | ~51% |\n| HTTP/1.1+TLS | 101,317 | 1.90ms | 3.84ms | 209,361 | 941μs | 1.81ms | ~52% |\n| HTTP/2 | 108,138 | 1.67ms | 6.38ms | 355,544 | 486μs | 1.53ms | ~70% |\n| HTTP/3 (QUIC) | 53,085 | 3.51ms | 5.87ms | 83,592 | 2.38ms | 2.80ms | ~37% |\n| gRPC | 68,352 | 2.53ms | 12.02ms | 205,927 | 821μs | 3.15ms | ~67% |\n| WebSocket | 103,830 | 1.88ms | 3.15ms | 207,507 | 952μs | 1.72ms | ~50% |\n| TCP | 108,841 | 1.83ms | 2.59ms | 214,113 | 928μs | 1.65ms | ~49% |\n| TCP+TLS | 107,340 | 1.84ms | 2.68ms | 207,103 | 949μs | 1.78ms | ~48% |\n| UDP | 82,042 | 2.46ms | 2.93ms | 276,526 | 682μs | 1.27ms | ~70% |\n| UDP+DTLS | 76,107 | 2.61ms | 3.69ms | 101,839 | 1.96ms | 2.47ms | ~25% |\n\n**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.\n\n**Linux socket tuning**: (`TCP_FASTOPEN`, `IP_BIND_ADDRESS_NO_PORT`), TLS handshake offload to dedicated runtimes, 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](FEATURES.md) for details.\n\nSee `tests/performance/` for the full benchmark suite.\n\n### Production tuning\n\n**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**.\n\n| Environment | How to raise the hard cap |\n|---|---|\n| systemd unit | `LimitNOFILE=1048576` in the `[Service]` section |\n| Docker / Podman | `--ulimit nofile=1048576:1048576` |\n| Kubernetes | Configure nofile on the node/container runtime (for example containerd/runc or the kubelet/systemd service); Pod `securityContext` does not expose ulimit/nofile. |\n| Bare shell (dev) | `ulimit -n 1048576` before launching the binary |\n| `/etc/security/limits.conf` | `* hard nofile 1048576` (and matching soft line) |\n\nWhen 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.\n\n**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`.\n\n### Gateway Comparison (All-Docker, macOS Apple Silicon, 100 concurrent, 30s)\n\nAll gateways run in Docker containers for apples-to-apples comparison:\n\n| Gateway | Key-Auth req/s | Key-Auth Latency | vs Ferrum |\n|---------|---------------|-----------------|-----------|\n| **Ferrum Edge** | **27,979** | **3.44 ms** | — |\n| Envoy 1.37 (Lua filter) | 26,787 | 3.64 ms | Ferrum 4% faster |\n| Kong 3.14 | 25,009 | 3.91 ms | Ferrum 12% faster |\n| Tyk v5.12 | 19,186 | 5.08 ms | Ferrum 46% faster |\n\nFerrum 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\u003cConsumer\u003e` zero-copy credential resolution and lock-free `ArcSwap` reads. See `comparison/` for the full benchmark suite and methodology.\n\n## Troubleshooting\n\n| Issue | Solution |\n|---|---|\n| `FERRUM_MODE not set` | Set the `FERRUM_MODE` environment variable |\n| `duplicate listen_path` | Ensure all proxy `listen_path` values are unique |\n| `Database connection failed` | Verify `FERRUM_DB_TYPE` and `FERRUM_DB_URL` |\n| `401 on Admin API` | Check JWT is signed with `FERRUM_ADMIN_JWT_SECRET` |\n| `404 on proxy request` | Verify request path matches a configured `listen_path` |\n| `502 Bad Gateway` | Backend unreachable — check `X-Gateway-Error` header for details |\n| `504 Gateway Timeout` | Increase `backend_read_timeout_ms` |\n| `429 Too Many Requests` | Rate limit exceeded — check plugin config |\n| DP not receiving config | Verify `FERRUM_CP_DP_GRPC_JWT_SECRET` matches on both CP and DP |\n\n## Documentation\n\n| Topic | Link |\n|-------|------|\n| Full configuration reference | [docs/configuration.md](docs/configuration.md) |\n| Plugin reference | [docs/plugins.md](docs/plugins.md) |\n| Transaction log schema customization | [docs/log_schema.md](docs/log_schema.md) |\n| Admin API | [docs/admin_api.md](docs/admin_api.md) |\n| Connection pooling | [docs/connection_pooling.md](docs/connection_pooling.md) |\n| Load balancing | [docs/load_balancing.md](docs/load_balancing.md) |\n| CP/DP distributed mode | [docs/cp_dp_mode.md](docs/cp_dp_mode.md) |\n| Kubernetes deployment | [docs/kubernetes_deployment.md](docs/kubernetes_deployment.md) |\n| SPIRE deployment for mesh identity | [docs/spire_deployment.md](docs/spire_deployment.md) |\n| TCP/UDP/DTLS proxy | [docs/tcp_udp_proxy.md](docs/tcp_udp_proxy.md) |\n| Frontend TLS/mTLS | [docs/frontend_tls.md](docs/frontend_tls.md) |\n| Backend mTLS | [docs/backend_mtls.md](docs/backend_mtls.md) |\n| Database TLS | [docs/database_tls.md](docs/database_tls.md) |\n| DNS resolver | [docs/dns_resolver.md](docs/dns_resolver.md) |\n| Routing | [docs/routing.md](docs/routing.md) |\n| Retry logic | [docs/retry.md](docs/retry.md) |\n| Response streaming | [docs/response_body_streaming.md](docs/response_body_streaming.md) |\n| Plugin execution order | [docs/plugin_execution_order.md](docs/plugin_execution_order.md) |\n| Infrastructure sizing | [docs/infrastructure_sizing.md](docs/infrastructure_sizing.md) |\n| Docker deployment | [docs/docker.md](docs/docker.md) |\n| CI/CD pipeline | [docs/ci_cd.md](docs/ci_cd.md) |\n| Database migrations | [docs/migrations.md](docs/migrations.md) |\n| Custom plugins | [CUSTOM_PLUGINS.md](CUSTOM_PLUGINS.md) |\n| Feature list | [FEATURES.md](FEATURES.md) |\n| OpenAPI spec | [openapi.yaml](openapi.yaml) |\n| Istio + xDS conformance matrix | [CONFORMANCE.md](CONFORMANCE.md) (run `cargo test --test conformance_tests` to refresh `target/conformance/coverage.md`) |\n\n## CI/CD\n\nOn 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.\n\nSee [docs/ci_cd.md](docs/ci_cd.md) for pipeline details.\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/my-feature`)\n3. Write tests for new functionality\n4. Ensure all tests pass (`cargo test --all-features`)\n5. Run `cargo clippy --all-targets --all-features -- -D warnings` and `cargo fmt`\n6. Submit a pull request\n\n## License\n\nCopyright (c) 2026 Ferrum Edge\n\nLicensed under the [PolyForm Noncommercial License 1.0.0](LICENSE).\n\n**TL;DR**: Free to use as long as you're not reselling our technology. Hobbyists, students, researchers, nonprofits — go wild. Companies evaluating Ferrum for a proof-of-concept or demo? Also totally fine, kick the tires. But if you're dropping this into your production network stack, we kindly ask that you grab a [commercial license](LICENSE-COMMERCIAL.md) and help fund our caffeine supply. Open source doesn't run on exposure — it runs on coffee, and coffee costs money.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fferrum-edge%2Fferrum-edge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fferrum-edge%2Fferrum-edge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fferrum-edge%2Fferrum-edge/lists"}