# 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 ```bash # 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 ```env # 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 ```bash # Production mode with PostgreSQL MODE=production docker compose up -d rentcache postgres ``` #### High-Performance Deployment with Redis ```bash # Production with Redis caching MODE=production docker compose --profile redis up -d ``` #### Development with Hot Reload ```bash # Development mode with file watching make dev ``` ## 🌐 Reverse Proxy with Caddy ### Caddy Docker Proxy Integration RentCache is designed to work with [caddy-docker-proxy](https://github.com/lucaslorentz/caddy-docker-proxy) for automatic HTTPS and load balancing. #### Setup External Caddy Network ```bash # 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: ```yaml 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`: ```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 ```yaml 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.): ```env DATABASE_URL=postgresql://username:password@host:5432/database?sslmode=require DATABASE_ECHO=false ``` ### Redis Configuration #### Docker Redis ```yaml 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 ```env 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: ```caddyfile 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 ```bash # 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 ```yaml # 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 ```yaml 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 ```env LOG_FORMAT=json LOG_LEVEL=INFO ``` #### Log Aggregation with Docker ```yaml 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: ```yaml # 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 ```yaml # 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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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 ```bash # Check logs docker compose logs rentcache # Check network docker network ls | grep caddy # Verify configuration docker compose config ``` #### SSL Certificate Issues ```bash # Check Caddy logs docker logs caddy-docker-proxy # Force certificate renewal docker exec caddy-docker-proxy caddy reload ``` #### Database Connection Issues ```bash # 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 ```bash # 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 ```sql -- 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 ```env # 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](ARCHITECTURE.md) for system design details.