# TCP Proxy for PostgreSQL
A high-performance TCP proxy that forwards PostgreSQL connections to different target databases (including SSH-tunneled connections) based on runtime target selection.
## Why Use tcproxy?
This tool solves the common problem of switching between different PostgreSQL environments (local, staging, production) without having to update multiple service configurations. Instead of changing connection strings across your applications, you point them all to the proxy and switch targets at the proxy level.
## Quick Start
### 1. Installation
#### Option 1: Install from crates.io (Recommended)
```bash
cargo install tcproxy
```
### 2. Initialize Configuration
```bash
# Generate a default configuration file
tcproxy init-config
# Or specify a custom location
tcproxy init-config --output my-config.yaml
```
### 3. Configure Your Targets
Edit the generated `config.yaml`:
```yaml
proxy:
listen_port: 5433
listen_host: "127.0.0.1"
max_connections: 1000
targets:
local:
host: "localhost"
port: 5432
production:
host: "prod-db.internal"
port: 5432
ssh:
enabled: true
host: "bastion.example.com"
user: "dbuser"
key_file: "/path/to/your/private-key.pem"
port: 22
auto_reconnect: true
max_reconnect_attempts: 5
staging:
host: "staging-db.internal"
port: 5432
ssh:
enabled: true
host: "staging-bastion.example.com"
user: "dbuser"
key_file: "/path/to/staging-key.pem"
connection_management:
health_check_interval_seconds: 30
health_check_timeout_seconds: 5
max_consecutive_failures: 3
```
### 4. Start the Proxy
```bash
# Start with local target
tcproxy start --target local
# Start with production target
tcproxy start --target production
# Override default port
tcproxy start --target local --port 5434
# Override default host
tcproxy start --target local --host 0.0.0.0
```
### 5. Connect Your Applications
Update your application connection strings to point to the proxy:
```bash
# Instead of connecting directly to different databases:
# postgresql://user:pass@localhost:5432/db # local
# postgresql://user:pass@prod-db.internal:5432/db # production
# Connect to the proxy:
postgresql://user:pass@localhost:5433/db
```
## Usage Examples
### Basic Commands
```bash
# Validate your configuration
tcproxy validate-config
# Show current configuration
tcproxy show-config
# List all available targets
tcproxy list-targets
# Check health of all targets
tcproxy health-check
# Check health of specific target
tcproxy health-check --target production
# Enable debug logging
tcproxy --log-level debug start --target local
# Enable JSON logging for structured logs
tcproxy --json-logs start --target production
```
### Configuration Examples
#### Simple Local Setup
```yaml
proxy:
listen_port: 5433
listen_host: "127.0.0.1"
targets:
local:
host: "localhost"
port: 5432
```
#### Production Setup with SSH Tunnel
```yaml
proxy:
listen_port: 5433
listen_host: "127.0.0.1"
max_connections: 500
targets:
production:
host: "10.0.1.100" # Internal database IP
port: 5432
ssh:
enabled: true
host: "bastion.example.com"
user: "deploy"
key_file: "/home/deploy/.ssh/production.pem"
port: 22
timeout_seconds: 30
auto_reconnect: true
reconnect_interval_seconds: 30
max_reconnect_attempts: 5
reconnect_backoff_multiplier: 2.0
connection_pool:
max_size: 20
timeout_seconds: 30
connection_management:
health_check_interval_seconds: 60
health_check_timeout_seconds: 10
max_consecutive_failures: 3
retry_delay_seconds: 5
```
#### Multi-Environment Setup
```yaml
proxy:
listen_port: 5433
listen_host: "127.0.0.1"
targets:
local:
host: "localhost"
port: 5432
development:
host: "dev-db.internal"
port: 5432
ssh:
enabled: true
host: "dev-bastion.example.com"
user: "developer"
key_file: "/path/to/dev-key.pem"
staging:
host: "staging-db.internal"
port: 5432
ssh:
enabled: true
host: "staging-bastion.example.com"
user: "deploy"
key_file: "/path/to/staging-key.pem"
production:
host: "prod-db.internal"
port: 5432
ssh:
enabled: true
host: "prod-bastion.example.com"
user: "deploy"
key_file: "/path/to/prod-key.pem"
```
## Configuration Reference
### Proxy Section
- `listen_port`: Port for the proxy to listen on (default: 5433)
- `listen_host`: Host interface to bind to (default: "127.0.0.1")
- `max_connections`: Maximum concurrent connections (default: 1000)
### Target Section
- `host`: Target PostgreSQL host
- `port`: Target PostgreSQL port
- `ssh`: SSH tunnel configuration (optional)
- `connection_pool`: Connection pool settings
### SSH Configuration
- `enabled`: Enable/disable SSH tunnel
- `host`: SSH bastion host
- `user`: SSH username
- `key_file`: Path to SSH private key
- `port`: SSH port (default: 22)
- `timeout_seconds`: SSH connection timeout (default: 30)
- `auto_reconnect`: Enable automatic reconnection (default: true)
- `reconnect_interval_seconds`: Time between reconnection attempts (default: 30)
- `max_reconnect_attempts`: Maximum reconnection attempts (default: 5)
- `reconnect_backoff_multiplier`: Backoff multiplier for reconnection (default: 2.0)
### Connection Management
- `health_check_interval_seconds`: Interval between health checks (default: 30)
- `health_check_timeout_seconds`: Health check timeout (default: 5)
- `max_consecutive_failures`: Max failures before marking target unhealthy (default: 3)
- `retry_delay_seconds`: Delay between retry attempts (default: 5)
## Logging
tcproxy provides comprehensive structured logging:
```bash
# Set log level
tcproxy --log-level debug start --target local
# Enable JSON logging for log aggregation
tcproxy --json-logs start --target production
# Available log levels: trace, debug, info, warn, error
```
## Health Monitoring
Built-in health monitoring helps ensure your targets are available:
```bash
# Check all targets
tcproxy health-check
# Check specific target
tcproxy health-check --target production
# Health checks run automatically in the background
# Configure intervals in the connection_management section
```
## Development
### Running Tests
```bash
# Run unit tests
cargo test
# Run integration tests (requires PostgreSQL)
cargo test --test integration_tests
# Run PostgreSQL-specific tests
cargo test --test postgresql_integration
```
### Building
```bash
# Debug build
cargo build
# Release build
cargo build --release
# Run with cargo
cargo run -- start --target local
```
## Command Reference
```bash
tcproxy [OPTIONS] [COMMAND]
Commands:
start Start the proxy server
init-config Generate a default configuration file
validate-config Validate configuration file
show-config Show current configuration
list-targets List available targets
health-check Check health status of targets
Options:
-c, --config <CONFIG> Configuration file path [default: config.yaml]
-l, --log-level <LOG_LEVEL> Log level (trace, debug, info, warn, error) [default: info]
--json-logs Enable JSON logging format
-h, --help Print help
-V, --version Print version
Start Command Options:
-t, --target <TARGET> Target to proxy to (required)
-p, --port <PORT> Override listen port
--host <HOST> Override listen host
```
## License
MIT License - see LICENSE file for details.
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.