Skip to content

Latest commit

Β 

History

History
516 lines (396 loc) Β· 10.4 KB

File metadata and controls

516 lines (396 loc) Β· 10.4 KB

WeatherNote Production Deployment Guide

πŸ“¦ Deployment Options

Option 1: AWS Deployment (Recommended for Scale)

Components:

  • Backend: AWS ECS (Fargate) or EC2 instances
  • Redis: AWS ElastiCache (Redis)
  • Load Balancer: AWS Application Load Balancer (ALB)
  • CDN: AWS CloudFront (optional)

Step-by-Step AWS Deployment:

1. Deploy Redis (ElastiCache)
# Create Redis cluster
aws elasticache create-replication-group \
  --replication-group-id weathernote-redis \
  --replication-group-description "WeatherNote Redis Cache" \
  --engine redis \
  --cache-node-type cache.t3.medium \
  --num-cache-clusters 2 \
  --automatic-failover-enabled
2. Build and Push Docker Image
cd WeatherNote_Backend

# Build for production
docker build -t weathernote-backend:latest .

# Tag for ECR
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin YOUR_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com

docker tag weathernote-backend:latest YOUR_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/weathernote-backend:latest

docker push YOUR_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/weathernote-backend:latest
3. Deploy with ECS (Fargate)

Create task-definition.json:

{
  "family": "weathernote-backend",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "1024",
  "memory": "2048",
  "containerDefinitions": [
    {
      "name": "weathernote-backend",
      "image": "YOUR_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/weathernote-backend:latest",
      "portMappings": [
        {
          "containerPort": 8080,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {
          "name": "PORT",
          "value": "8080"
        },
        {
          "name": "REDIS_URL",
          "value": "redis://your-redis-endpoint:6379"
        },
        {
          "name": "CACHE_TTL_SECONDS",
          "value": "600"
        },
        {
          "name": "RATE_LIMIT_PER_MINUTE",
          "value": "100"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/weathernote-backend",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs"
        }
      }
    }
  ]
}

Deploy:

# Register task definition
aws ecs register-task-definition --cli-input-json file://task-definition.json

# Create service
aws ecs create-service \
  --cluster weathernote-cluster \
  --service-name weathernote-backend \
  --task-definition weathernote-backend \
  --desired-count 3 \
  --launch-type FARGATE \
  --load-balancers targetGroupArn=YOUR_TARGET_GROUP_ARN,containerName=weathernote-backend,containerPort=8080
4. Configure Load Balancer
# Create target group
aws elbv2 create-target-group \
  --name weathernote-backend-tg \
  --protocol HTTP \
  --port 8080 \
  --vpc-id YOUR_VPC_ID \
  --health-check-path /health \
  --health-check-interval-seconds 30 \
  --target-type ip

# Create load balancer
aws elbv2 create-load-balancer \
  --name weathernote-alb \
  --subnets subnet-xxx subnet-yyy \
  --security-groups sg-xxx

Option 2: Google Cloud Platform (GCP)

Components:

  • Backend: Cloud Run (serverless) or GKE
  • Redis: Memorystore for Redis
  • Load Balancer: Cloud Load Balancing

Deploy to Cloud Run:

cd WeatherNote_Backend

# Build and push to GCR
gcloud builds submit --tag gcr.io/YOUR_PROJECT_ID/weathernote-backend

# Deploy to Cloud Run
gcloud run deploy weathernote-backend \
  --image gcr.io/YOUR_PROJECT_ID/weathernote-backend \
  --platform managed \
  --region us-central1 \
  --allow-unauthenticated \
  --set-env-vars REDIS_URL=redis://YOUR_REDIS_IP:6379,CACHE_TTL_SECONDS=600 \
  --memory 1Gi \
  --cpu 2 \
  --min-instances 2 \
  --max-instances 100

Option 3: DigitalOcean / Hetzner (Cost-Effective)

For 50,000-500,000 users:

Recommended Setup:

  • 3-5 x 4GB RAM / 2 vCPU Droplets (Backend)
  • 1 x 8GB RAM / 4 vCPU Droplet (Redis)
  • Load Balancer

Deploy with Docker Compose:

# On each backend server
git clone YOUR_REPO
cd WeatherNote_Backend

# Copy and configure .env
cp .env.example .env
nano .env  # Set REDIS_URL to your Redis server IP

# Start backend
docker-compose up -d backend

# Verify
curl http://localhost:8080/health

Setup Load Balancer:

# nginx.conf
upstream backend {
    least_conn;
    server backend1.example.com:8080;
    server backend2.example.com:8080;
    server backend3.example.com:8080;
}

server {
    listen 80;
    server_name api.weathernote.com;

    location / {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        
        # Rate limiting
        limit_req zone=api burst=20;
    }

    location /health {
        proxy_pass http://backend;
        access_log off;
    }
}

limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

Option 4: Dockerized Self-Hosted

Perfect for initial deployment or smaller scale.

Single Server Setup:

# Install Docker and Docker Compose
curl -fsSL https://get.docker.com -o get-docker.sh
sh get-docker.sh

# Clone and deploy
git clone YOUR_REPO
cd WeatherNote_Backend

# Configure
cp .env.example .env
nano .env

# Start everything
docker-compose up -d

# Check logs
docker-compose logs -f

# Monitor
docker stats

πŸ” Security Checklist

SSL/TLS Configuration

# Using Certbot (Let's Encrypt)
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d api.weathernote.com

Firewall Rules

# Allow only HTTP/HTTPS and SSH
ufw allow 22/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

Redis Security

# redis.conf
bind 127.0.0.1 INTERNAL_IP
requirepass YOUR_STRONG_PASSWORD
maxmemory 512mb
maxmemory-policy allkeys-lru

πŸ“Š Monitoring Setup

Prometheus + Grafana

# docker-compose.monitoring.yml
version: '3.8'

services:
  prometheus:
    image: prom/prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin

Health Check Script

#!/bin/bash
# health-check.sh

BACKEND_URL="http://localhost:8080/health"

response=$(curl -s -o /dev/null -w "%{http_code}" $BACKEND_URL)

if [ $response -eq 200 ]; then
    echo "βœ… Backend is healthy"
    exit 0
else
    echo "❌ Backend is down (HTTP $response)"
    # Send alert (email, Slack, etc.)
    exit 1
fi

# Add to crontab:
# */5 * * * * /path/to/health-check.sh

πŸš€ Auto Scaling Configuration

AWS Auto Scaling

# Create auto-scaling policy
aws autoscaling create-auto-scaling-group \
  --auto-scaling-group-name weathernote-asg \
  --min-size 2 \
  --max-size 20 \
  --desired-capacity 3 \
  --target-group-arns YOUR_TARGET_GROUP_ARN

# CPU-based scaling
aws autoscaling put-scaling-policy \
  --auto-scaling-group-name weathernote-asg \
  --policy-name scale-up \
  --scaling-adjustment 2 \
  --adjustment-type ChangeInCapacity \
  --cooldown 300

πŸ’° Cost Estimates

AWS (US East):

  • ECS Fargate (3 tasks): ~$50/month
  • ElastiCache (t3.medium): ~$50/month
  • ALB: ~$20/month
  • Total: ~$120/month

GCP:

  • Cloud Run (3 instances): ~$40/month
  • Memorystore: ~$60/month
  • Load Balancer: ~$20/month
  • Total: ~$120/month

DigitalOcean:

  • 3 x 4GB Droplets: ~$72/month
  • 1 x 8GB Droplet (Redis): ~$48/month
  • Load Balancer: ~$10/month
  • Total: ~$130/month

Hetzner (Best Value):

  • 3 x CPX21 (2 vCPU, 4GB): ~$30/month
  • 1 x CPX41 (4 vCPU, 8GB): ~$20/month
  • Load Balancer: ~$6/month
  • Total: ~$56/month πŸŽ‰

πŸ”„ CI/CD Pipeline

GitHub Actions

Create .github/workflows/deploy.yml:

name: Deploy to Production

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Build Docker image
        run: docker build -t weathernote-backend WeatherNote_Backend/
      
      - name: Push to registry
        run: |
          echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
          docker tag weathernote-backend:latest ${{ secrets.DOCKER_USERNAME }}/weathernote-backend:latest
          docker push ${{ secrets.DOCKER_USERNAME }}/weathernote-backend:latest
      
      - name: Deploy to server
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /app/WeatherNote_Backend
            docker-compose pull
            docker-compose up -d

πŸ“± Update Flutter App

  1. Update api_constants.dart:
static const String backendUrl = 'https://api.weathernote.com';
  1. Generate unique client ID:
// In main.dart
import 'package:device_info_plus/device_info_plus.dart';

Future<void> initClientId() async {
  final deviceInfo = DeviceInfoPlugin();
  String? deviceId;
  
  if (Platform.isAndroid) {
    final android = await deviceInfo.androidInfo;
    deviceId = android.id;
  } else if (Platform.isIOS) {
    final ios = await deviceInfo.iosInfo;
    deviceId = ios.identifierForVendor;
  }
  
  ApiConstants.clientId = deviceId;
}
  1. Rebuild and deploy app:
cd WeatherNote_App
flutter build apk --release
flutter build ios --release

πŸ§ͺ Load Testing

# Install Apache Bench
sudo apt install apache2-utils

# Test 10,000 requests with 100 concurrent users
ab -n 10000 -c 100 http://api.weathernote.com/api/v1/weather?lat=40.7&lon=-74.0

# Test with siege
siege -c 100 -t 2M http://api.weathernote.com/health

πŸ“ž Support & Monitoring

Useful Commands:

# Check backend logs
docker-compose logs -f backend --tail=100

# Monitor Redis
redis-cli INFO stats

# Check cache hit rate
redis-cli INFO stats | grep keyspace_hits

# Monitor system resources
htop

🎯 Success Metrics

After deployment, monitor:

  • Cache Hit Rate: Should be >95%
  • API Response Time: <100ms (cached), <500ms (fresh)
  • Open-Meteo API Calls: <5,000/day for 500k users
  • Server CPU: <60% average
  • Memory Usage: <70%

You're ready for production! πŸš€