diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..16ec552 --- /dev/null +++ b/.env.example @@ -0,0 +1,38 @@ +# Database Configuration (AWS RDS) +DB_USER=recipes_user +DB_PASSWORD=your_secure_password_here +DB_NAME=recipes_db +DB_HOST=your-rds-endpoint.region.rds.amazonaws.com +DB_PORT=5432 +DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME} + +# Email Configuration +SMTP_HOST=smtp.gmail.com +SMTP_PORT=587 +SMTP_USER=your-email@gmail.com +SMTP_PASSWORD=your-app-password +SMTP_FROM=your-email@gmail.com + +# Google OAuth +GOOGLE_CLIENT_ID=your-google-client-id +GOOGLE_CLIENT_SECRET=your-google-client-secret +GOOGLE_REDIRECT_URI=https://your-domain.com/auth/google/callback +FRONTEND_URL=https://your-domain.com + +# Microsoft Entra ID (Azure AD) OAuth +AZURE_CLIENT_ID=your-azure-client-id +AZURE_CLIENT_SECRET=your-azure-client-secret +AZURE_TENANT_ID=consumers +AZURE_REDIRECT_URI=https://your-domain.com/auth/azure/callback + +# Cloudflare R2 Backup Configuration +R2_ENDPOINT=https://your-account-id.r2.cloudflarestorage.com +R2_ACCESS_KEY=your-r2-access-key +R2_SECRET_KEY=your-r2-secret-key + +# Automatic Backup Schedule +# Options: test (every 1 minute), daily, weekly, disabled +BACKUP_INTERVAL=weekly + +# Frontend API URL (for frontend container) +VITE_API_URL=https://your-domain.com diff --git a/AWS_DEPLOYMENT.md b/AWS_DEPLOYMENT.md new file mode 100644 index 0000000..b374735 --- /dev/null +++ b/AWS_DEPLOYMENT.md @@ -0,0 +1,237 @@ +# AWS EC2 Deployment Guide + +This guide explains how to deploy the my-recipes application on AWS EC2 with RDS database. + +## Prerequisites + +1. AWS Account with EC2 and RDS access +2. Docker and Docker Compose installed on EC2 instance +3. RDS PostgreSQL database instance created +4. Domain name (optional, but recommended) +5. SSL certificate (optional, but recommended for production) + +## Step 1: Set Up AWS RDS + +1. **Create RDS PostgreSQL Instance:** + - Go to AWS RDS Console + - Click "Create database" + - Choose PostgreSQL engine + - Select version 15 or higher + - Choose appropriate instance size (db.t3.micro for testing, db.t3.small+ for production) + - Set Master username (e.g., `recipes_user`) + - Set Master password (strong password) + - Database name: `recipes_db` + - Enable public accessibility if needed (not recommended for production) + - Configure VPC security group to allow connections from EC2 + +2. **Security Group Configuration:** + - Create/modify security group for RDS + - Add inbound rule: PostgreSQL (port 5432) from EC2 security group + - Note the endpoint: `your-db-instance.xxxx.region.rds.amazonaws.com` + +3. **Initialize Database Schema:** + ```bash + # Connect to RDS and run schema.sql + psql -h your-rds-endpoint.region.rds.amazonaws.com \ + -U recipes_user \ + -d recipes_db \ + -f backend/schema.sql + ``` + +## Step 2: Set Up AWS EC2 + +1. **Launch EC2 Instance:** + - Choose Ubuntu 22.04 LTS or Amazon Linux 2023 + - Instance type: t3.micro (minimum), t3.small+ (recommended) + - Configure security group: + - SSH (port 22) - your IP only + - HTTP (port 80) - 0.0.0.0/0 + - HTTPS (port 443) - 0.0.0.0/0 + - Custom TCP (port 8000) - optional, for direct API access + - Add storage: 20GB minimum + - Assign Elastic IP (recommended) + +2. **Connect to EC2:** + ```bash + ssh -i your-key.pem ec2-user@your-ec2-public-ip + # or for Ubuntu: + ssh -i your-key.pem ubuntu@your-ec2-public-ip + ``` + +3. **Install Docker and Docker Compose:** + ```bash + # Update system + sudo yum update -y # For Amazon Linux + # sudo apt update && sudo apt upgrade -y # For Ubuntu + + # Install Docker + sudo yum install docker -y # Amazon Linux + # sudo apt install docker.io -y # Ubuntu + + sudo systemctl start docker + sudo systemctl enable docker + sudo usermod -a -G docker ec2-user # or ubuntu + + # Install Docker Compose + sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose + sudo chmod +x /usr/local/bin/docker-compose + + # Logout and login again for group changes to take effect + exit + ``` + +## Step 3: Deploy Application + +1. **Clone Repository:** + ```bash + cd ~ + git clone https://your-repo-url/my-recipes.git + cd my-recipes + ``` + +2. **Configure Environment Variables:** + ```bash + # Copy the example env file from root to backend directory + cp .env.example backend/.env + nano backend/.env # or vim backend/.env + ``` + + Update the following variables: + ```env + # Database Configuration (from RDS) + DB_USER=recipes_user + DB_PASSWORD=your_rds_password + DB_NAME=recipes_db + DB_HOST=your-rds-endpoint.region.rds.amazonaws.com + DB_PORT=5432 + + # Frontend URL (your domain or EC2 public IP) + FRONTEND_URL=http://your-ec2-ip + # or FRONTEND_URL=https://your-domain.com + + # Update OAuth redirect URIs + GOOGLE_REDIRECT_URI=http://your-ec2-ip/auth/google/callback + AZURE_REDIRECT_URI=http://your-ec2-ip/auth/azure/callback + + # Update other configurations as needed + ``` + +3. **Build and Start Services:** + ```bash + cd /home/ec2-user/my-recipes # or /home/ubuntu/my-recipes + docker-compose up -d --build + ``` + +4. **Verify Services:** + ```bash + docker-compose ps + docker-compose logs -f + ``` + +## Step 4: Configure Domain and SSL (Optional but Recommended) + +1. **Set Up Domain:** + - Point your domain's A record to EC2 Elastic IP + - Update FRONTEND_URL in .env file + +2. **Install Nginx and Certbot:** + ```bash + sudo yum install nginx certbot python3-certbot-nginx -y # Amazon Linux + # sudo apt install nginx certbot python3-certbot-nginx -y # Ubuntu + ``` + +3. **Configure Nginx:** + Create `/etc/nginx/conf.d/recipes.conf`: + ```nginx + server { + listen 80; + server_name your-domain.com; + + location / { + proxy_pass http://localhost:80; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } + + location /api { + proxy_pass http://localhost:8000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } + } + ``` + +4. **Get SSL Certificate:** + ```bash + sudo certbot --nginx -d your-domain.com + sudo systemctl restart nginx + ``` + +## Step 5: Monitoring and Maintenance + +1. **View Logs:** + ```bash + docker-compose logs -f backend + docker-compose logs -f frontend + ``` + +2. **Restart Services:** + ```bash + docker-compose restart + ``` + +3. **Update Application:** + ```bash + git pull + docker-compose down + docker-compose up -d --build + ``` + +4. **Backup Database:** + Backups are automatic based on BACKUP_INTERVAL setting. Manual backup: + ```bash + docker-compose exec backend python backup_db.py + ``` + +## Troubleshooting + +1. **Can't connect to RDS:** + - Check security group rules + - Verify VPC and subnet configuration + - Test connection: `telnet rds-endpoint 5432` + +2. **Services won't start:** + ```bash + docker-compose logs + ``` + +3. **Database connection errors:** + - Verify DATABASE_URL format + - Check DB credentials + - Ensure RDS is accessible from EC2 + +4. **Port conflicts:** + ```bash + sudo netstat -tulpn | grep :80 + sudo netstat -tulpn | grep :8000 + ``` + +## Security Best Practices + +1. Use strong passwords for DB and admin accounts +2. Enable SSL/TLS for all connections +3. Keep EC2 security groups restrictive +4. Don't expose RDS publicly +5. Use IAM roles for AWS service access +6. Regularly update Docker images and system packages +7. Enable CloudWatch monitoring +8. Set up automated backups +9. Use secrets management (AWS Secrets Manager or Parameter Store) + +## Cost Optimization + +1. Use reserved instances for long-term deployments +2. Enable auto-shutdown for non-production environments +3. Monitor and optimize RDS instance size +4. Use S3 or R2 for backups (already configured) +5. Consider using Application Load Balancer for multiple instances diff --git a/backend/.env.example b/backend/.env.example new file mode 100644 index 0000000..16ec552 --- /dev/null +++ b/backend/.env.example @@ -0,0 +1,38 @@ +# Database Configuration (AWS RDS) +DB_USER=recipes_user +DB_PASSWORD=your_secure_password_here +DB_NAME=recipes_db +DB_HOST=your-rds-endpoint.region.rds.amazonaws.com +DB_PORT=5432 +DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME} + +# Email Configuration +SMTP_HOST=smtp.gmail.com +SMTP_PORT=587 +SMTP_USER=your-email@gmail.com +SMTP_PASSWORD=your-app-password +SMTP_FROM=your-email@gmail.com + +# Google OAuth +GOOGLE_CLIENT_ID=your-google-client-id +GOOGLE_CLIENT_SECRET=your-google-client-secret +GOOGLE_REDIRECT_URI=https://your-domain.com/auth/google/callback +FRONTEND_URL=https://your-domain.com + +# Microsoft Entra ID (Azure AD) OAuth +AZURE_CLIENT_ID=your-azure-client-id +AZURE_CLIENT_SECRET=your-azure-client-secret +AZURE_TENANT_ID=consumers +AZURE_REDIRECT_URI=https://your-domain.com/auth/azure/callback + +# Cloudflare R2 Backup Configuration +R2_ENDPOINT=https://your-account-id.r2.cloudflarestorage.com +R2_ACCESS_KEY=your-r2-access-key +R2_SECRET_KEY=your-r2-secret-key + +# Automatic Backup Schedule +# Options: test (every 1 minute), daily, weekly, disabled +BACKUP_INTERVAL=weekly + +# Frontend API URL (for frontend container) +VITE_API_URL=https://your-domain.com diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..1613318 --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,70 @@ +version: "3.9" + +services: + backend: + build: ./backend + container_name: recipes-backend + restart: unless-stopped + ports: + - "8000:8000" + environment: + # Database Configuration (RDS) + DATABASE_URL: postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME} + DB_USER: ${DB_USER} + DB_PASSWORD: ${DB_PASSWORD} + DB_NAME: ${DB_NAME} + DB_HOST: ${DB_HOST} + DB_PORT: ${DB_PORT:-5432} + + # Email Configuration + SMTP_HOST: ${SMTP_HOST} + SMTP_PORT: ${SMTP_PORT:-587} + SMTP_USER: ${SMTP_USER} + SMTP_PASSWORD: ${SMTP_PASSWORD} + SMTP_FROM: ${SMTP_FROM} + + # Google OAuth + GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID} + GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET} + GOOGLE_REDIRECT_URI: ${GOOGLE_REDIRECT_URI} + + # Microsoft Azure OAuth + AZURE_CLIENT_ID: ${AZURE_CLIENT_ID} + AZURE_CLIENT_SECRET: ${AZURE_CLIENT_SECRET} + AZURE_TENANT_ID: ${AZURE_TENANT_ID:-consumers} + AZURE_REDIRECT_URI: ${AZURE_REDIRECT_URI} + + # Frontend URL + FRONTEND_URL: ${FRONTEND_URL} + + # Cloudflare R2 Backup Configuration + R2_ENDPOINT: ${R2_ENDPOINT} + R2_ACCESS_KEY: ${R2_ACCESS_KEY} + R2_SECRET_KEY: ${R2_SECRET_KEY} + + # Backup Schedule + BACKUP_INTERVAL: ${BACKUP_INTERVAL:-weekly} + env_file: + - ./backend/.env + volumes: + - ./backend/backups:/app/backups + - ./backend/restores:/app/restores + networks: + - recipes-network + + frontend: + build: ./frontend + container_name: recipes-frontend + restart: unless-stopped + ports: + - "80:80" + environment: + VITE_API_URL: ${VITE_API_URL:-http://localhost:8000} + depends_on: + - backend + networks: + - recipes-network + +networks: + recipes-network: + driver: bridge