Skip to content

A high-performance database proxy service built with Go, designed for Kubernetes environments. Provides secure and scalable database connection management with support for multiple database types.

License

Notifications You must be signed in to change notification settings

hasirciogluhq/xdatabase-proxy

Repository files navigation

XDatabase Proxy

xdatabase-proxy v2.0.0 banner

XDatabase Proxy in Action: The screenshot demonstrates a successful, secure PostgreSQL connection established through xdatabase-proxy. The proxy automatically generates and manages TLS certificates, ensuring encrypted traffic between your client and the database. This seamless integration with Kubernetes and real-time certificate handling provides both security and ease of use for your cloud-native database workloads.

XDatabase Proxy is a production-grade, enterprise-ready proxy solution for database deployments. Designed with flexibility in mind, it runs seamlessly in Kubernetes clusters, containers, VMs, or bare-metal environments.

Features

  • 🔄 Dynamic Service Discovery: Automatic backend discovery via Kubernetes API or static configuration
  • 🎯 Deployment-Based Routing: Route connections based on deployment IDs
  • 🌊 Connection Pooling Support: Works with any pooler (pgbouncer, odyssey, etc.)
  • 🚀 Multi-Runtime Support: Kubernetes, Container, VM, or Bare-Metal deployments
  • 📊 Smart Load Balancing: Intelligent routing between backends
  • 🔍 Real-Time Monitoring: Live service discovery and health checks
  • 🔀 Multi-Node Cluster Support: Works with any cluster manager (pgpool-II, patroni, etc.)
  • 🔒 Enterprise TLS/SSL:
    • Automatic certificate generation and renewal
    • Certificate expiration monitoring
    • Multiple certificate sources (file, Kubernetes secret, memory)
    • Self-signed certificate support for development
  • 🏷️ Label-Based Configuration: No hard dependencies on specific implementations
  • 🔌 Flexible Discovery: Kubernetes API or static backend configuration
  • 🩺 Health Check Endpoints: Built-in health and readiness checks
  • 🪵 Structured Logging: JSON-formatted logs with debug mode
  • 🏗️ Production-Grade Architecture: Factory pattern, dependency injection, configuration-driven

Supported Databases

Database Status
PostgreSQL ✅ Full Support
MySQL 📋 Planned
MongoDB 📋 Planned

Requirements

  • Go 1.23.4 or higher
  • Kubernetes cluster (optional - for Kubernetes discovery mode)
  • kubectl configuration (optional - for remote Kubernetes access)

Installation

# Clone the project
git clone https://github.com/hasirciogluhq/xdatabase-proxy.git
cd xdatabase-proxy

# Install dependencies
go mod download

# Build the project
go build -o xdatabase-proxy cmd/proxy/main.go

Configuration

Environment Variables

Core Configuration

Variable Description Required Default Example Value
DATABASE_TYPE Database type to proxy No postgresql postgresql
PROXY_START_PORT Port for proxy listener No 5432 5432
HEALTH_SERVER_PORT Health check server port No 8080 8080
DEBUG Enable debug logging No false true

Runtime Configuration

Variable Description Required Default Example Value When to Use
RUNTIME Execution environment: kubernetes, container, vm No Auto-detect kubernetes Set explicitly only if auto-detection fails
NAMESPACE Kubernetes namespace Conditional default production Required when RUNTIME=kubernetes OR TLS_MODE=kubernetes

Runtime Auto-Detection:

  • kubernetes: Detected if /var/run/secrets/kubernetes.io/serviceaccount exists
  • container: Detected if /.dockerenv exists
  • vm: Default fallback

Configuration Rules:

  • ✅ If RUNTIME=kubernetes: NAMESPACE is mandatory for service discovery
  • ✅ If RUNTIME=container|vm + TLS_MODE=kubernetes: NAMESPACE is mandatory for TLS secret access
  • ✅ If RUNTIME=container|vm + TLS_MODE=file|memory: NAMESPACE is optional

Backend Discovery

Variable Description Required Default Example Value When to Use
DISCOVERY_MODE Discovery strategy: kubernetes or static No kubernetes static Auto-set to static if STATIC_BACKENDS is provided
STATIC_BACKENDS Static backend mapping (deployment_id[.pool]=host:port comma-separated) Conditional - db1=10.0.1.5:5432,db1.pool=10.0.1.5:6432 Required when not using Kubernetes discovery
KUBECONFIG Path to kubeconfig file Conditional ~/.kube/config /path/to/config Required when DISCOVERY_MODE=kubernetes AND running outside cluster (VM/Container)
KUBE_CONTEXT Kubernetes context name No - production-cluster Use for multi-cluster setups with kubeconfig

Discovery Modes:

  • kubernetes: Dynamic discovery via Kubernetes API
    • Works from inside Kubernetes (in-cluster)
    • Works from outside Kubernetes (with KUBECONFIG)
    • Can run in VM/Container and connect to remote Kubernetes
  • static: Static backend list (no Kubernetes dependency)

Configuration Rules:

  • In Kubernetes Pod: DISCOVERY_MODE=kubernetes (default, uses in-cluster config)
  • VM/Container → Remote K8s: DISCOVERY_MODE=kubernetes + KUBECONFIG=/path/to/config
  • Static Backends: STATIC_BACKENDS='db1=host:5432,db1.pool=host:6432' (auto-sets DISCOVERY_MODE=static)
  • ⚠️ Cannot mix: Cannot use both STATIC_BACKENDS and DISCOVERY_MODE=kubernetes at same time
  • ⚠️ KUBECONFIG required: If DISCOVERY_MODE=kubernetes + not in cluster → must provide KUBECONFIG
  • ⚠️ NAMESPACE required: If DISCOVERY_MODE=kubernetes → must provide NAMESPACE

Static Backends Format:

  • deployment_id=host:port → direct connections
  • deployment_id.pool=host:port → pooled connections (optional)
  • Multiple entries comma-separated, e.g. db1=10.0.1.5:5432,db1.pool=10.0.1.5:6432

TLS/SSL Configuration

Variable Description Required Default Example Value When to Use
TLS_ENABLED Enable/disable TLS completely No true false Set to false for development or internal non-encrypted networks
TLS_MODE TLS provider: file, kubernetes, memory No Auto kubernetes Auto-detected based on other TLS settings
TLS_CERT_FILE Path to TLS certificate file Conditional - /certs/tls.crt Required when TLS_MODE=file AND TLS_AUTO_GENERATE=false
TLS_KEY_FILE Path to TLS private key file Conditional - /certs/tls.key Required when TLS_MODE=file AND TLS_AUTO_GENERATE=false
TLS_SECRET_NAME Kubernetes secret name for TLS certificate Conditional - xdatabase-proxy-tls Required when TLS_MODE=kubernetes
TLS_AUTO_GENERATE Generate self-signed certificate if none exists No true true Recommended true for development, false for production with real certs
TLS_AUTO_RENEW Automatically renew certificate if expired or invalid No true false Set false if using externally managed certificates
TLS_RENEWAL_THRESHOLD_DAYS Days before expiry to trigger renewal No 30 60 Adjust based on cert renewal process

TLS Mode Auto-Detection:

  1. file: When TLS_CERT_FILE is set
  2. kubernetes: When TLS_SECRET_NAME is set
  3. memory: Default fallback (in-memory certificate)

TLS Certificate Lifecycle:

  • If certificate doesn't exist and TLS_AUTO_GENERATE=true: Generate new self-signed certificate
  • If certificate is invalid/expired and TLS_AUTO_RENEW=true: Regenerate certificate
  • Kubernetes secret automatically created if it doesn't exist
  • Multi-instance safe: Race condition handling for concurrent pod startups

Configuration Rules:

  • No TLS: TLS_ENABLED=false → All other TLS settings ignored
  • Auto TLS in K8s: TLS_MODE=kubernetes + TLS_SECRET_NAME=my-tls + TLS_AUTO_GENERATE=true → Auto-creates secret
  • Existing K8s Secret: TLS_MODE=kubernetes + TLS_SECRET_NAME=existing-tls + TLS_AUTO_GENERATE=false
  • File-based TLS: TLS_MODE=file + TLS_CERT_FILE=/path/cert + TLS_KEY_FILE=/path/key
  • Auto-generated File TLS: TLS_MODE=file + TLS_AUTO_GENERATE=true → Creates certs in ./development_data/
  • Memory TLS: TLS_MODE=memory + TLS_AUTO_GENERATE=true → In-memory self-signed cert
  • ⚠️ TLS_MODE=file + No files: Must have TLS_AUTO_GENERATE=true OR provide TLS_CERT_FILE + TLS_KEY_FILE
  • ⚠️ TLS_MODE=kubernetes: Requires NAMESPACE + TLS_SECRET_NAME
  • ⚠️ Kubernetes Secret Access: Requires proper RBAC permissions for secret read/write

Common TLS Scenarios:

Scenario TLS_ENABLED TLS_MODE TLS_AUTO_GENERATE TLS_SECRET_NAME Notes
Production K8s with auto TLS true kubernetes true xdatabase-proxy-tls Recommended for production in K8s
Production K8s with existing cert true kubernetes false my-existing-tls Use pre-created TLS secret
Development (no TLS) false - - - Fast local testing
Development (with TLS) true file true - Auto-creates local cert files
VM/Container with file certs true file false - Requires TLS_CERT_FILE + TLS_KEY_FILE

Legacy Support (Backward Compatibility)

Legacy Variable Maps To
POSTGRESQL_PROXY_ENABLED Sets DATABASE_TYPE=postgresql
POSTGRESQL_PROXY_START_PORT PROXY_START_PORT
TLS_ENABLE_SELF_SIGNED TLS_AUTO_GENERATE
POD_NAMESPACE NAMESPACE

Kubernetes Service Discovery

Labels act as a composite index for service discovery. Proxy uses (xdatabase-proxy-deployment-id, xdatabase-proxy-database-type, xdatabase-proxy-pooled) as the lookup key.

Label Matching Strategy:

  • Proxy searches for services matching the composite index
  • If multiple services match the same criteria, the first one is used (like findFirst() in databases)
  • Extra labels are ignored (safe to add additional labels)
  • Missing optional labels are handled gracefully
Label Type Description Example Value Index
xdatabase-proxy-deployment-id String Database deployment ID (routing key) db-deployment-1 ✅ YES
xdatabase-proxy-database-type String Database type (filter) postgresql ✅ YES
xdatabase-proxy-pooled Boolean Pooled connections (true/false) true ✅ YES
xdatabase-proxy-destination-port Integer Target port for the database connection 5432
xdatabase-proxy-enabled Boolean (Deprecated) Whether service is managed by proxy true

Label Indexing Example:

When proxy receives connection: postgres://user.db-prod.pool@proxy:5432/db

  • Extracts: deployment_id=db-prod, pooled=true
  • Searches: services with deployment_id=db-prod AND pooled=true
  • Returns: first matching service (even if multiple exist)
Cluster Services:
1. Service: db-prod-1     (deployment_id=db-prod, pooled=true)   → ✅ MATCHED & USED
2. Service: db-prod-2     (deployment_id=db-prod, pooled=true)   → ⏭️ SKIPPED (duplicate)
3. Service: db-prod-pool  (deployment_id=db-prod, pooled=false)  → ⏭️ SKIPPED (diff pooled)
4. Service: db-staging    (deployment_id=db-staging, pooled=true)→ ⏭️ SKIPPED (diff id)

Connection String Routing:

  • postgres://user.db-prod@proxy:5432/db → uses deployment_id=db-prod, pooled=false
  • postgres://user.db-prod.pool@proxy:5432/db → uses deployment_id=db-prod, pooled=true

PoC/PoW

XDatabase Proxy in Action

Usage Examples

1. Kubernetes Deployment (In-Cluster)

# Apply production configuration
kubectl apply -f kubernetes/examples/production/deploy.yaml

The proxy auto-detects Kubernetes runtime and uses in-cluster config.

2. Container with Remote Kubernetes Discovery

docker run -d \
  -e DATABASE_TYPE=postgresql \
  -e DISCOVERY_MODE=kubernetes \
  -e KUBECONFIG=/kubeconfig/config \
  -e KUBE_CONTEXT=production-cluster \
  -e TLS_AUTO_GENERATE=true \
  -v /path/to/kubeconfig:/kubeconfig \
  -p 5432:5432 \
  -p 8080:8080 \
  ghcr.io/hasirciogluhq/xdatabase-proxy:latest

3. VM with Static Backends

export DATABASE_TYPE=postgresql
export RUNTIME=vm
export DISCOVERY_MODE=static
export STATIC_BACKENDS='db1=10.0.1.5:5432,db1.pool=10.0.1.5:6432,db2=10.0.1.6:5432'
export TLS_AUTO_GENERATE=true
export TLS_AUTO_RENEW=true

./xdatabase-proxy

4. Local Development

export DATABASE_TYPE=postgresql
export DEBUG=true
export RUNTIME=vm
export DISCOVERY_MODE=kubernetes
export KUBECONFIG=~/.kube/config
export KUBE_CONTEXT=minikube
export TLS_AUTO_GENERATE=true

./xdatabase-proxy

5. Production Kubernetes with External TLS

export DATABASE_TYPE=postgresql
export RUNTIME=kubernetes
export NAMESPACE=production
export TLS_MODE=kubernetes
export TLS_SECRET_NAME=xdatabase-proxy-tls
export TLS_AUTO_GENERATE=true
export TLS_AUTO_RENEW=true
export TLS_RENEWAL_THRESHOLD_DAYS=30

Connection String Format

postgresql://username.deployment_id[.pool]@proxy-host:port/dbname

Examples:

# Direct PostgreSQL Connection
postgresql://myuser.db-deployment-1@localhost:5432/mydb

# Connection through Pooler
postgresql://myuser.db-deployment-1.pool@localhost:5432/mydb

# Multi-node Cluster
postgresql://myuser.db-deployment-1.pool@localhost:5432/mydb

Architecture

┌───────────────────────────────────────────────────────────────┐
│                       xdatabase-proxy                         │
│                                                               │
│  ┌──────────────────┐    ┌──────────────────────┐             │
│  │ Config & Runtime  │    │ Orchestrator (app.go)│             │
│  │  env -> types    │ →  │ wires factories      │             │
│  └──────────────────┘    └──────────────────────┘             │
│            |                          |                       │
│            v                          v                       │
│  ┌──────────────────┐    ┌──────────────────────┐             │
│  │ ResolverFactory  │    │ TLSFactory           │             │
│  │ (k8s | static)   │    │ (k8s | file | memory) │             │
│  └──────────────────┘    └──────────────────────┘             │
│            \                          /                       │
│             v                        v                        │
│              ┌────────────────────────────────┐               │
│              │ ProxyFactory (PostgreSQL)      │               │
│              │ builds ConnectionHandler       │               │
│              └────────────────────────────────┘               │
│                               |                               │
│                 ┌────────────────────────┐                    │
│                 │ Core Server            │                    │
│                 │ (TCP accept loop)      │                    │
│                 └────────────────────────┘                    │
│                               |                               │
│                 ┌────────────────────────┐                    │
│                 │ Health Server          │                    │
│                 │ /health, /ready        │                    │
│                 └────────────────────────┘                    │
└───────────────────────────────────────────────────────────────┘

Flow

  • Env → config: validates runtime, discovery, TLS, ports.
  • app.Application: initializes logger, resolver, TLS provider (optional), proxy handler, listener.
  • Factories: runtime-aware resolver (k8s/static), pluggable TLS (k8s/file/memory), protocol proxy.
  • core.Server: TCP accept loop, delegates to connection handler.
  • api.HealthServer: /health liveness, /ready readiness.

Health Check Endpoints

  • GET /health - Basic health check
  • GET /ready - Readiness check (returns 200 when proxy is ready)
curl http://localhost:8080/health
curl http://localhost:8080/ready

Security

  • TLS/SSL Encryption: All connections encrypted
  • Certificate Auto-Renewal: Prevents expired certificates
  • Deployment Isolation: Separate routing per deployment
  • Connection Validation: Parameter validation and sanitization
  • Multi-Instance Safe: Race condition handling

Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Create a Pull Request

License

MIT License - see LICENSE file for details.

Contact

GitHub Issues: https://github.com/hasirciogluhq/xdatabase-proxy/issues


Note: This is production-grade software designed for enterprise use cases. For questions, feature requests, or bug reports, please use GitHub Issues.

About

A high-performance database proxy service built with Go, designed for Kubernetes environments. Provides secure and scalable database connection management with support for multiple database types.

Topics

Resources

License

Stars

Watchers

Forks

Packages