[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-81820":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":16,"stars30d":16,"stars90d":15,"forks30d":15,"starsTrendScore":15,"compositeScore":17,"rankGlobal":10,"rankLanguage":10,"license":18,"archived":19,"fork":19,"defaultBranch":20,"hasWiki":21,"hasPages":19,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":23,"readmeContent":24,"aiSummary":25,"trendingCount":15,"starSnapshotCount":15,"syncStatus":13,"lastSyncTime":26,"discoverSource":27},81820,"turbine-proxy","turbine-dev\u002Fturbine-proxy","turbine-dev","High-performance MySQL & PostgreSQL proxy with connection pooling, automatic read\u002Fwrite splitting, query analytics, and an embedded dashboard.","https:\u002F\u002Fturbineproxy.com",null,"Rust",33,2,32,0,1,1.43,"Other",false,"master",true,[],"2026-06-12 02:04:20","# TurbineProxy\n\n[![CI](https:\u002F\u002Fgithub.com\u002Fturbineproxy\u002Fturbineproxy\u002Factions\u002Fworkflows\u002Fci.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fturbineproxy\u002Fturbineproxy\u002Factions\u002Fworkflows\u002Fci.yml)\n[![codecov](https:\u002F\u002Fcodecov.io\u002Fgh\u002Fturbineproxy\u002Fturbineproxy\u002Fbranch\u002Fmain\u002Fgraph\u002Fbadge.svg)](https:\u002F\u002Fcodecov.io\u002Fgh\u002Fturbineproxy\u002Fturbineproxy)\n[![Crates.io](https:\u002F\u002Fimg.shields.io\u002Fcrates\u002Fv\u002Fturbineproxy.svg)](https:\u002F\u002Fcrates.io\u002Fcrates\u002Fturbineproxy)\n[![License: Apache-2.0](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-Apache--2.0-blue.svg)](LICENSE-APACHE)\n\n**High-performance MySQL & PostgreSQL proxy** written in Rust — connection pooling, automatic read\u002Fwrite splitting, GTID-aware consistency guarantees, WAN compression, SQL injection protection, an embedded analytics dashboard, and an MCP server that lets AI assistants reason about your query workload in real time.\n\n> [!WARNING]\n> This project is currently under active development.\n> Features, APIs, and configuration may change between releases.\n> If you find bugs, regressions, or unclear behavior, please open an issue with reproduction steps.\n\n![TurbineProxy Dashboard](docs\u002Fstatic\u002Fimg\u002Fdashboard.png)\n\n```\nClient ──TLS──▶ TurbineProxy ──TLS──▶ Primary  (writes + transactions)\n                             │\n                             ├──────▶ Replica 1 (reads — weighted round-robin)\n                             └──────▶ Replica 2 (reads — weighted round-robin)\n```\n\n---\n\n## Table of Contents\n\n- [Feature Overview](#feature-overview)\n- [Quick Start](#quick-start)\n- [Docker](#docker)\n- [Configuration](#configuration)\n- [Security](#security)\n- [MCP Server](#mcp-server)\n- [Prometheus Metrics](#prometheus-metrics)\n- [Building from Source](#building-from-source)\n- [Testing](#testing)\n- [Documentation](#documentation)\n- [Contributing](#contributing)\n- [License](#license)\n\n---\n\n## Feature Overview\n\n| Category | Features |\n|----------|----------|\n| **Protocols** | MySQL 8.0+, MariaDB 10.6+, PostgreSQL 14+ |\n| **Routing** | Auto read\u002Fwrite split, query rules (regex\u002Fdigest\u002Fuser\u002Fschema), per-rule fast-forward, hostgroup pinning, weighted round-robin, backup replicas |\n| **Consistency** | Time-based RYOW, GTID-aware RYOW, sticky connections for user variables and prepared statements |\n| **Pooling** | Per-backend pool, per-backend `max_connections` cap, idle eviction, **1:N connection multiplexing**, bounded wait queue, stmt_conn isolation from tx_conn |\n| **Compression** | zlib (MySQL 5.7+), zstd (MySQL 8.0.18+) on backend connections |\n| **Performance** | Global & per-rule fast-forward mode (zero-overhead passthrough), per-rule QPS rate limiting (token bucket), result cache with TTL, query rewriting (LIMIT injection, timeout hints) |\n| **TLS** | Frontend TLS (client → proxy), backend TLS (proxy → DB), verify-identity for RDS\u002FCloud SQL, NSS Key Log for debugging |\n| **Security** | SQL injection protection (UNION, stacked queries, SLEEP, BENCHMARK, INTO OUTFILE, xp_cmdshell, hex evasion…), per-user rules, read-only enforcement, query allowlist, append-only audit log, **AES-256-GCM at-rest encryption** for stored passwords, external secret references (`env:` \u002F `file:`) |\n| **HA** | Health checks, lag monitoring, automatic failover with **flap protection** (cooldown + min recovery checks), **per-backend circuit breaker** (Closed\u002FOpen\u002FHalf-Open), **bounded wait queue** with timeout, Group Replication \u002F InnoDB Cluster awareness, Galera check, PROXY Protocol v2 (HAProxy, AWS NLB), multi-node cluster config sync |\n| **Observability** | Prometheus metrics (18 metric families + histograms), Grafana dashboard JSON, query heatmap, N+1 detector, index advisor, slow query log, per-query tracer, failure mode reference |\n| **Operations** | Per-port `server_version` string, zero-downtime reload (SIGHUP \u002F dashboard), dry-run query rules, Helm chart, Docker (distroless), AUR \u002F deb \u002F Homebrew packages, systemd unit, logrotate config |\n| **AI \u002F Automation** | Embedded MCP server (7 tools) for AI assistant integration |\n\n---\n\n## Quick Start\n\n### One-line Install\n\n```bash\ncurl -fsSL https:\u002F\u002Fraw.githubusercontent.com\u002Fturbineproxy\u002Fturbineproxy\u002Fmain\u002Fscripts\u002Finstall.sh | sh\n```\n\nInstall a specific release tag:\n\n```bash\ncurl -fsSL https:\u002F\u002Fraw.githubusercontent.com\u002Fturbineproxy\u002Fturbineproxy\u002Fmain\u002Fscripts\u002Finstall.sh | sh -s -- v0.1.0\n```\n\n### Interactive Config Wizard\n\n```bash\nturbineproxy init\nturbineproxy init --output .\u002Fdeploy\u002Fturbineproxy.toml\n```\n\n### Manual Setup\n\n```bash\ncurl -Lo turbineproxy https:\u002F\u002Fgithub.com\u002Fturbineproxy\u002Fturbineproxy\u002Freleases\u002Flatest\u002Fdownload\u002Fturbineproxy-x86_64-unknown-linux-musl\nchmod +x turbineproxy\n.\u002Fturbineproxy --config turbineproxy.toml\n# Dashboard: http:\u002F\u002Flocalhost:8080  MySQL: localhost:3307\n```\n\n---\n\n## Docker\n\n```bash\ndocker run -d \\\n  -v $(pwd)\u002Fturbineproxy.toml:\u002Fetc\u002Fturbineproxy\u002Fturbineproxy.toml:ro \\\n  -p 3307:3307 -p 8080:8080 \\\n  ghcr.io\u002Fturbineproxy\u002Fturbineproxy:latest\n```\n\n---\n\n## Configuration\n\nSee [turbineproxy.example.toml](turbineproxy.example.toml) for the full annotated reference. A typical production setup:\n\n```toml\n[shared]\nmax_connections = 1000\npool_size       = 20\n\n[shared.primary]\naddr     = \"db-primary:3306\"\nuser     = \"proxy\"\npassword = \"secret\"\ndatabase = \"myapp\"\n\n[[shared.replicas]]\naddr        = \"db-replica-1:3306\"\nuser        = \"proxy\"\npassword    = \"secret\"\ndatabase    = \"myapp\"\nweight      = 100\ncompression = \"zstd\"\n\n[mysql]\nenabled          = true\nlisten_addr      = \"0.0.0.0:3307\"\ngtid_aware_ryow  = true\n\n[pgsql]\nenabled               = true\nlisten_addr           = \"0.0.0.0:5432\"\nhealth_check_database = \"postgres\"\n\n[frontend_tls]\nenabled = true\ncert    = \"\u002Fetc\u002Fturbineproxy\u002Fserver.crt\"\nkey     = \"\u002Fetc\u002Fturbineproxy\u002Fserver.key\"\n\n[analytics]\nenabled        = true\ndb_path        = \"turbineproxy_analytics.db\"\nslow_query_ms  = 100\nretention_days = 30\n\n[dashboard]\nenabled     = true\nlisten_addr = \"0.0.0.0:8080\"\nusername    = \"admin\"\npassword    = \"change-me\"\n\n[ha]\nenabled                    = true\nhealth_check_interval_secs = 5\nmax_replica_lag_ms         = 5000\nprimary_failover_threshold = 3\nfailover_cooldown_secs     = 30\nfailover_min_recovery_checks = 3\n\nsql_injection_protection = true\n```\n\n---\n\n## Security\n\nTurbineProxy applies multiple layers of protection:\n\n### SQL Injection Detection\n\nA built-in pattern library (`src\u002Fproxy\u002Fsecurity.rs`) inspects every inbound query before it reaches the backend. Patterns cover:\n\n- Classic UNION-based injection (`UNION SELECT`, `UNION ALL SELECT`)\n- Stacked queries (`;` followed by DML\u002FDDL)\n- Time-delay probes (`SLEEP()`, `BENCHMARK()`, `pg_sleep()`, `WAITFOR DELAY`)\n- Out-of-band extraction (`INTO OUTFILE`, `INTO DUMPFILE`, `LOAD_FILE()`)\n- System command execution (`xp_cmdshell`, `exec()`)\n- Encoding evasion (hex literals, `CHAR()` sequences, URL-encoded payloads)\n- Boolean-based blind patterns (`1=1`, `1=0`, `'a'='a'`)\n- Comment-based obfuscation (`\u002F**\u002F`, `-- -`, `#`)\n\nBlocked queries return a MySQL\u002FPostgreSQL error packet to the client and increment `turbineproxy_sqli_blocked_total`. Enable with:\n\n```toml\nsql_injection_protection = true\n```\n\n> **Threat model:** This is defense in depth, not a replacement for parameterized queries. It stops script-kiddie scanners and misconfigured apps. It does not prevent a determined attacker from crafting a payload that evades pattern matching. Use the query allowlist below for a stronger guarantee.\n\n### Per-User Access Control\n\n```toml\n[[shared.users]]\nname            = \"app_readonly\"\npassword        = \"...\"\nallow_writes    = false\nmax_connections = 50\n\n[[shared.users]]\nname            = \"app_rw\"\npassword        = \"...\"\nallow_writes    = true\nmax_connections = 200\n```\n\nRead-only enforcement is applied at the proxy level — the backend never sees the write.\n\n### Query Allowlist\n\n```toml\nquery_whitelist = [\n  \"SELECT * FROM users WHERE id = ?\",\n  \"INSERT INTO events (user_id, event) VALUES (?, ?)\",\n]\n```\n\n### Audit Log\n\nAppend-only NDJSON log (timestamp, user, client IP, SQL, destination, duration, error). Re-opened on SIGHUP:\n\n```toml\naudit_log = \"\u002Fvar\u002Flog\u002Fturbineproxy\u002Faudit.log\"\n```\n\n### TLS\n\n- **Frontend (client → proxy):** `[frontend_tls]` with cert and key.\n- **Backend (proxy → database):** `tls_mode` per backend (`required`, `verify-ca`, `verify-identity`). Use `verify-identity` for RDS \u002F Cloud SQL \u002F Aurora.\n- **PostgreSQL TLS:** Full TLS upgrade supported for both client (SSLRequest → `sslmode=require`) and backend (SSLRequest → connect). Cloud-managed PostgreSQL (RDS, Cloud SQL, Neon) works with `tls_mode = \"verify-identity\"`.\n- **SSL Key Log:** NSS Key Log for Wireshark. **Debug environments only.**\n\n```toml\n[frontend_tls]\nssl_keylog_file = \"\u002Ftmp\u002Fsslkeys.log\"   # debug only\n```\n\n### Credential Handling\n\n- Passwords in `turbineproxy.toml` are never logged.\n- Dashboard credentials are separate from database credentials.\n- Dashboard login uses **constant-time comparison** (via `subtle`) to prevent timing-based attacks.\n- Session tokens are stored as **SHA-256 hashes** in memory — a process memory dump does not yield usable tokens.\n- Session tokens expire after `token_ttl_secs` (default 24 h). The sweeper task evicts expired tokens every 60 s.\n- Tokens can be refreshed without re-entering credentials: `POST \u002Fapi\u002Fauth\u002Frefresh` atomically revokes the old token and issues a fresh one with a renewed TTL.\n- Login attempts are **rate-limited per source IP** (`login_max_attempts` per minute, default 5). Excessive attempts return HTTP 429.\n- Failed authentication events (wrong password, invalid\u002Fexpired token) increment `turbineproxy_dashboard_auth_failures_total` — monitor this counter for brute-force detection.\n- A **read-only role** (`readonly_username` \u002F `readonly_password`) gives dashboard visibility without write access — POST\u002FPUT\u002FDELETE requests return 403.\n- SHA-1 and SHA-256 auth tokens are pre-computed at startup and cached (`auth_cache_ttl_secs`). Plaintext passwords are not held in memory after the cache is warm.\n\n#### External Secret References\n\nAvoid putting plaintext passwords in config files by using a reference scheme:\n\n```toml\n# Read from environment variable (Docker secrets, Kubernetes envFrom, etc.)\npassword = \"env:DB_PASSWORD\"\n\n# Read from a file (Docker secret mount, Vault agent, etc.)\npassword = \"file:\u002Frun\u002Fsecrets\u002Fdb_pw\"\n```\n\n#### AES-256-GCM At-Rest Encryption\n\nPasswords entered via the dashboard are stored in SQLite. Set `TURBINEPROXY_SECRET_KEY` to a 64-character hex key (256-bit) to encrypt them at rest:\n\n```bash\n# Generate a key\nexport TURBINEPROXY_SECRET_KEY=$(openssl rand -hex 32)\n```\n\nEncrypted values are stored as `enc:\u003Cbase64url(nonce || ciphertext)>` and are transparently decrypted at runtime. Existing plaintext values and `env:`\u002F`file:` references continue to work without any migration.\n\n**Threat model:** Protects against offline file theft (stolen backup, snapshot). Does not protect against a compromised host — the key and the data live on the same machine. For stronger isolation, build with `--features keyring-support` to store the key in the OS keyring (Keychain on macOS, libsecret on Linux) instead of an environment variable.\n\n```bash\n# Store key in OS keyring (requires --features keyring-support build)\nkeyring set turbineproxy encryption-key $(openssl rand -hex 32)\ncargo build --release --features keyring-support\n```\n\nSee [Secret Management](https:\u002F\u002Fdocs.turbineproxy.com\u002Fdocs\u002Ffeatures\u002Fsecret-management) for the full guide.\n\n### Responsible Disclosure\n\nReport vulnerabilities to **security@turbineproxy.com** — see [SECURITY.md](SECURITY.md). Do not open public issues for security bugs.\n\n---\n\n## MCP Server\n\nThe embedded MCP server exposes proxy intelligence to AI coding assistants and automation tools via JSON-RPC 2.0.\n\n**Endpoint:** `POST \u002Fmcp` (same port as the dashboard)\n\n**Authentication:** HTTP Basic with the same `username`\u002F`password` as the dashboard. If no credentials are configured, the endpoint is unauthenticated — always set a password in production.\n\n```toml\n[dashboard]\nenabled     = true\nlisten_addr = \"0.0.0.0:8080\"\nusername    = \"admin\"\npassword    = \"change-me\"\n```\n\n**Usage:**\n\n```jsonc\n{ \"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"tools\u002Flist\", \"params\": {} }\n\n{\n  \"jsonrpc\": \"2.0\", \"id\": 2,\n  \"method\": \"tools\u002Fcall\",\n  \"params\": { \"name\": \"get_slow_queries\", \"arguments\": { \"limit\": 10 } }\n}\n```\n\n| Tool | Key fields returned |\n|------|---------------------|\n| `get_pool_stats` | `primary`, `replicas[]` — idle, in_use, created, evicted |\n| `get_slow_queries` | `fingerprint`, `count`, `p50_ms`, `p95_ms`, `p99_ms`, `max_ms` |\n| `get_n1_candidates` | `fingerprint`, `call_count`, `distinct_params`, `pattern_score` |\n| `get_index_advice` | `table`, `column`, `query_sample`, `estimated_rows`, `suggestion` |\n| `get_backend_health` | `addr`, `role`, `healthy`, `lag_ms`, `consecutive_failures` |\n| `get_query_rules` | `match_pattern`, `destination`, `hit_count`, `last_match_secs` |\n| `get_rewrite_rules` | `match_pattern`, `operation`, `hit_count`, `last_match_secs` |\n\n**VS Code \u002F Claude Desktop** — add to `mcp.json` \u002F `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"turbineproxy\": { \"url\": \"http:\u002F\u002Flocalhost:8080\u002Fmcp\" }\n  }\n}\n```\n\n---\n\n## Prometheus Metrics\n\n`GET http:\u002F\u002Flocalhost:8080\u002Fmetrics` — Prometheus text exposition format v0.0.4.\n\n| Metric | Type | Labels |\n|--------|------|--------|\n| `turbineproxy_build_info` | gauge | `version` |\n| `turbineproxy_connections_total` | counter | — |\n| `turbineproxy_connections_active` | gauge | — |\n| `turbineproxy_queries_total` | counter | `intent` (read\u002Fwrite\u002Fother) |\n| `turbineproxy_query_duration_seconds` | histogram | `intent` — 11 buckets 1ms→5s |\n| `turbineproxy_pool_connections` | gauge | `backend`, `role`, `state` |\n| `turbineproxy_pool_connections_created_total` | counter | `backend`, `role` |\n| `turbineproxy_pool_connections_evicted_total` | counter | `backend`, `role` |\n| `turbineproxy_replica_lag_seconds` | gauge | `backend` |\n| `turbineproxy_backend_healthy` | gauge | `backend`, `role` |\n| `turbineproxy_sqli_blocked_total` | counter | — |\n| `turbineproxy_whitelist_blocked_total` | counter | — |\n| `turbineproxy_sessions_pinned_total` | counter | — |\n| `turbineproxy_multiplex_ratio` | gauge | — |\n| `turbineproxy_pg_replica_lag_seconds` | gauge | `backend` |\n| `turbineproxy_dashboard_auth_failures_total` | counter | — |\n\nA pre-built Grafana dashboard JSON is at `dashboard\u002Fpublic\u002Fgrafana\u002Fturbineproxy.json`.\n\n---\n\n## Building from Source\n\n```bash\ngit clone https:\u002F\u002Fgithub.com\u002Fturbineproxy\u002Fturbineproxy\ncd turbineproxy\ncargo build --release\n# Binary: target\u002Frelease\u002Fturbineproxy\n```\n\nCross-compile for Linux musl (static binary):\n\n```bash\ncross build --release --target x86_64-unknown-linux-musl\n```\n\n---\n\n## Testing\n\n```bash\n# Unit tests (including panic-recovery tests for parking_lot)\ncargo test --bin turbineproxy\n\n# MySQL integration tests\ndocker compose up mysql80 -d\ncargo test --test integration_tests -- --test-threads=1\n\n# PostgreSQL integration tests (includes TLS test; skips if psql not in PATH)\ndocker compose up postgres14 -d\ncargo test --test pg_integration_tests -- --test-threads=1\n\n# Skip PG TLS test if server has SSL disabled\nTEST_PG_SKIP_TLS=1 cargo test --test pg_integration_tests -- --test-threads=1\n\n# Benchmarks\ncargo bench -- hot_path\n```\n\n---\n\n## Documentation\n\nFull documentation at **[docs.turbineproxy.com](https:\u002F\u002Fdocs.turbineproxy.com)**.\n\n- [Getting Started](https:\u002F\u002Fdocs.turbineproxy.com\u002Fdocs\u002Fgetting-started)\n- [Configuration Reference](https:\u002F\u002Fdocs.turbineproxy.com\u002Fdocs\u002Fconfiguration\u002Freference)\n- [Security Guide](https:\u002F\u002Fdocs.turbineproxy.com\u002Fdocs\u002Ffeatures\u002Fsecurity)\n- [Dashboard & Metrics](https:\u002F\u002Fdocs.turbineproxy.com\u002Fdocs\u002Fdashboard)\n- [Migration from ProxySQL](https:\u002F\u002Fdocs.turbineproxy.com\u002Fdocs\u002Fgetting-started\u002Ffrom-proxysql)\n\n---\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md). Security issues: see [SECURITY.md](SECURITY.md).\n\n## License\n\nLicensed under [Apache-2.0](LICENSE-APACHE).\n","TurbineProxy 是一个高性能的 MySQL 和 PostgreSQL 代理，支持连接池、自动读写分离、查询分析和内置仪表盘。它使用 Rust 语言编写，具备连接池管理、基于 GTID 的一致性保证、WAN 压缩、SQL 注入防护等核心功能。此外，TurbineProxy 还提供了一个嵌入式的分析仪表盘，以及一个 MCP 服务器，能够实时处理 AI 助手对查询负载的推理。适用于需要提高数据库访问性能和安全性的场景，如高并发读写操作、分布式数据库环境等。","2026-06-11 04:06:50","CREATED_QUERY"]