rentcache/docs/DEPLOYMENT.md
Ryan Malloy 345ad00692 Add comprehensive production documentation
Documentation created:
- Updated README.md with Docker deployment and production domain
- docs/DEPLOYMENT.md: Complete Docker/Caddy deployment guide
- docs/ARCHITECTURE.md: System design and caching strategies
- docs/QUICKSTART.md: 5-minute setup with real examples
- Updated USAGE.md with production URLs

Key updates:
- Production domain: https://rentcache.l.supported.systems
- Docker Compose with Caddy reverse proxy
- Make commands for easy management
- Cost savings examples (70-90% reduction)
- Complete architecture documentation
- Production deployment checklist
- Monitoring and maintenance guides

The system is now fully documented for production deployment.
2025-09-10 14:22:36 -06:00

12 KiB

Deployment Guide

This guide covers deploying RentCache in production using Docker, with Caddy reverse proxy, and comprehensive monitoring.

🐳 Docker Deployment

Prerequisites

  • Docker Engine: 20.10+ with Compose V2
  • External Caddy Network: For reverse proxy integration
  • Domain: Configured with DNS pointing to your server
  • SSL Certificate: Automatic with Caddy (Let's Encrypt)

Quick Production Deployment

# Clone repository
git clone https://git.supported.systems/MCP/rentcache.git
cd rentcache

# Set up environment
cp .env.example .env
nano .env  # Configure your settings

# Deploy with reverse proxy
make setup

This command:

  1. Creates the external Caddy network if needed
  2. Builds the Docker images
  3. Starts services with reverse proxy
  4. Makes RentCache available at your domain

Environment Configuration

Production .env File

# Domain Configuration
DOMAIN=your-domain.com
COMPOSE_PROJECT=rentcache-prod

# Mode Configuration
MODE=production
DEBUG=false
LOG_LEVEL=INFO

# Server Configuration
HOST=0.0.0.0
PORT=8000

# Database Configuration (Production)
DATABASE_URL=postgresql://rentcache:secure_password@postgres:5432/rentcache
DATABASE_ECHO=false

# Redis Configuration (Recommended for Production)
REDIS_URL=redis://redis:6379
REDIS_ENABLED=true

# Cache Settings (Optimized for Production)
DEFAULT_CACHE_TTL=7200
EXPENSIVE_ENDPOINTS_TTL=172800
ENABLE_STALE_WHILE_REVALIDATE=true

# Rate Limiting (Production Limits)
ENABLE_RATE_LIMITING=true
GLOBAL_RATE_LIMIT=2000/hour
PER_ENDPOINT_RATE_LIMIT=100/minute

# Security (Restrict Access)
ALLOWED_HOSTS=your-domain.com,api.your-domain.com
CORS_ORIGINS=https://your-domain.com,https://app.your-domain.com

# Monitoring
ENABLE_METRICS=true
LOG_FORMAT=json

Docker Compose Production Setup

The included docker-compose.yml supports multiple deployment scenarios:

Basic Production Deployment

# Production mode with PostgreSQL
MODE=production docker compose up -d rentcache postgres

High-Performance Deployment with Redis

# Production with Redis caching
MODE=production docker compose --profile redis up -d

Development with Hot Reload

# Development mode with file watching
make dev

🌐 Reverse Proxy with Caddy

Caddy Docker Proxy Integration

RentCache is designed to work with caddy-docker-proxy for automatic HTTPS and load balancing.

Setup External Caddy Network

# Create the external network (if not exists)
docker network create caddy

# Verify network exists
docker network ls | grep caddy

Caddy Labels Configuration

The docker-compose.yml includes automatic Caddy configuration:

services:
  rentcache:
    # ... other config
    networks:
      - caddy
    labels:
      caddy: ${DOMAIN:-rentcache.l.supported.systems}
      caddy.reverse_proxy: "{{upstreams}}"
      caddy.header.X-Forwarded-Proto: https
      caddy.header.X-Real-IP: "{remote_host}"

Manual Caddy Configuration

If using standalone Caddy, create a Caddyfile:

your-domain.com {
    reverse_proxy rentcache:8000
    
    # Security headers
    header {
        X-Content-Type-Options nosniff
        X-Frame-Options DENY
        X-XSS-Protection "1; mode=block"
        Strict-Transport-Security "max-age=31536000;"
    }
    
    # Health check endpoint
    handle /health {
        reverse_proxy rentcache:8000
    }
    
    # API endpoints
    handle /api/* {
        reverse_proxy rentcache:8000
    }
    
    # Admin endpoints (restrict access)
    handle /admin/* {
        reverse_proxy rentcache:8000
        # Add basic auth or IP restrictions here
    }
}

🗄️ Database Configuration

PostgreSQL Production Setup

Using Docker Compose

services:
  postgres:
    image: postgres:15-alpine
    environment:
      POSTGRES_DB: rentcache
      POSTGRES_USER: rentcache
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_INITDB_ARGS: "--auth-host=scram-sha-256"
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - caddy
    restart: unless-stopped
    command: >
      postgres
      -c shared_preload_libraries=pg_stat_statements
      -c max_connections=200
      -c shared_buffers=256MB
      -c effective_cache_size=1GB
      -c maintenance_work_mem=64MB
      -c checkpoint_completion_target=0.9
      -c wal_buffers=16MB
      -c default_statistics_target=100

volumes:
  postgres_data:
    driver: local

External PostgreSQL

For external PostgreSQL (AWS RDS, Google Cloud SQL, etc.):

DATABASE_URL=postgresql://username:password@host:5432/database?sslmode=require
DATABASE_ECHO=false

Redis Configuration

Docker Redis

services:
  redis:
    image: redis:7-alpine
    command: >
      redis-server
      --appendonly yes
      --appendfsync everysec
      --save 900 1
      --save 300 10
      --save 60 10000
      --maxmemory 512mb
      --maxmemory-policy allkeys-lru
    volumes:
      - redis_data:/data
    networks:
      - caddy
    restart: unless-stopped
    profiles:
      - redis

volumes:
  redis_data:
    driver: local

External Redis

REDIS_URL=redis://username:password@host:6379/0
REDIS_ENABLED=true

🔐 Security Configuration

SSL/TLS

With Caddy, SSL is automatic using Let's Encrypt. For manual SSL:

your-domain.com {
    tls your-email@domain.com  # Let's Encrypt
    # OR
    tls /path/to/cert.pem /path/to/key.pem  # Custom certificates
    
    reverse_proxy rentcache:8000
}

API Key Security

# Create production API key with strict limits
docker compose exec rentcache uv run rentcache create-key production_app YOUR_RENTCAST_KEY \
  --daily-limit 5000 \
  --monthly-limit 100000 \
  --expires 2024-12-31

# Create development key with higher limits
docker compose exec rentcache uv run rentcache create-key dev_app YOUR_RENTCAST_KEY \
  --daily-limit 10000 \
  --monthly-limit 200000

Network Security

# Restrict network access
services:
  rentcache:
    networks:
      - caddy
      - internal
    # Don't expose ports directly in production
    
  postgres:
    networks:
      - internal  # Only internal network
    # No external access
    
  redis:
    networks:
      - internal  # Only internal network

networks:
  caddy:
    external: true
  internal:
    driver: bridge

📊 Monitoring and Logging

Health Checks

services:
  rentcache:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

Logging Configuration

JSON Structured Logging

LOG_FORMAT=json
LOG_LEVEL=INFO

Log Aggregation with Docker

services:
  rentcache:
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "5"
        tag: "rentcache-{{.Name}}"

Centralized Logging

For production, consider using:

  • ELK Stack (Elasticsearch, Logstash, Kibana)
  • Grafana Loki with Promtail
  • Fluentd or Fluent Bit

Example Promtail configuration:

# promtail-config.yml
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  - job_name: rentcache
    docker_sd_configs:
      - host: unix:///var/run/docker.sock
        refresh_interval: 5s
    relabel_configs:
      - source_labels: ['__meta_docker_container_label_com_docker_compose_service']
        target_label: 'service'
      - source_labels: ['__meta_docker_container_name']
        target_label: 'container'

Metrics Collection

Prometheus Integration

# prometheus.yml
scrape_configs:
  - job_name: 'rentcache'
    static_configs:
      - targets: ['rentcache:8000']
    metrics_path: '/metrics'
    scrape_interval: 30s
    scrape_timeout: 10s

Grafana Dashboard

Key metrics to monitor:

  • Cache Hit Ratio: Target > 80%
  • Response Time: 95th percentile < 200ms
  • Error Rate: < 1%
  • API Cost: Daily/monthly spending
  • Request Volume: Requests per minute
  • Database Performance: Query time, connection pool

🚀 Production Deployment Checklist

Pre-Deployment

  • Environment Variables: Configure production .env
  • SSL Certificates: Verify domain and SSL setup
  • Database: PostgreSQL configured and accessible
  • Redis: Optional but recommended for performance
  • Monitoring: Health checks and metrics collection
  • Backup Strategy: Database and configuration backups
  • Security: Network restrictions and API key management

Deployment Steps

# 1. Clone and configure
git clone https://git.supported.systems/MCP/rentcache.git
cd rentcache
cp .env.example .env
# Edit .env with production settings

# 2. Deploy
make setup

# 3. Verify deployment
curl https://your-domain.com/health

# 4. Create API keys
make create-key NAME=production_app KEY=your_rentcast_key

# 5. Test API access
curl -H "Authorization: Bearer your_rentcast_key" \
  "https://your-domain.com/api/v1/properties?city=Austin&state=TX&limit=1"

# 6. Monitor metrics
curl https://your-domain.com/metrics

Post-Deployment

  • Monitor Logs: Check for errors and warnings
  • Test All Endpoints: Verify API functionality
  • Cache Performance: Monitor hit ratios
  • Cost Tracking: Track API cost savings
  • Backup Verification: Test restore procedures
  • Performance Baseline: Establish performance metrics

🔄 Maintenance and Updates

Regular Maintenance

# Update containers
docker compose pull
docker compose up -d

# Clean old images
docker system prune -f

# Check logs
make logs

# Monitor health
make health

# View statistics
make stats

Database Maintenance

# PostgreSQL maintenance
docker compose exec postgres psql -U rentcache -d rentcache -c "VACUUM ANALYZE;"

# Clear old cache entries (older than 7 days)
docker compose exec rentcache uv run rentcache clear-cache --older-than 168

Backup Procedures

# Database backup
docker compose exec postgres pg_dump -U rentcache rentcache > backup-$(date +%Y%m%d).sql

# Configuration backup
tar -czf config-backup-$(date +%Y%m%d).tar.gz .env docker-compose.yml

# Restore database
docker compose exec -T postgres psql -U rentcache -d rentcache < backup-20240115.sql

🚨 Troubleshooting

Common Issues

Service Won't Start

# Check logs
docker compose logs rentcache

# Check network
docker network ls | grep caddy

# Verify configuration
docker compose config

SSL Certificate Issues

# Check Caddy logs
docker logs caddy-docker-proxy

# Force certificate renewal
docker exec caddy-docker-proxy caddy reload

Database Connection Issues

# Test database connection
docker compose exec rentcache uv run python -c "
from sqlalchemy import create_engine
engine = create_engine('$DATABASE_URL')
print('Database connection successful!')
"

High Response Times

# Enable Redis if not already
docker compose --profile redis up -d

# Check cache hit ratio
curl https://your-domain.com/metrics | jq '.cache_hit_ratio'

# Monitor database performance
docker compose exec postgres psql -U rentcache -d rentcache -c "
SELECT query, mean_time, calls 
FROM pg_stat_statements 
ORDER BY mean_time DESC 
LIMIT 10;"

Performance Tuning

Database Optimization

-- Create indexes for better performance
CREATE INDEX IF NOT EXISTS idx_cache_entries_endpoint ON cache_entries(endpoint);
CREATE INDEX IF NOT EXISTS idx_cache_entries_created_at ON cache_entries(created_at);
CREATE INDEX IF NOT EXISTS idx_usage_stats_api_key_id ON usage_stats(api_key_id);
CREATE INDEX IF NOT EXISTS idx_usage_stats_created_at ON usage_stats(created_at);

Application Tuning

# Increase cache TTLs for stable data
DEFAULT_CACHE_TTL=7200
EXPENSIVE_ENDPOINTS_TTL=172800

# Optimize rate limits
GLOBAL_RATE_LIMIT=5000/hour
PER_ENDPOINT_RATE_LIMIT=200/minute

Ready for production? Ensure you've followed all security best practices and monitoring is properly configured. Check the Architecture Guide for system design details.