docker-erpnext/documentation/deployment-guides/aws-managed/00-prerequisites-managed.md
Brian Tan Seng 8894bbf56e ⏺ Perfect! I have successfully created the complete AWS equivalent of the GCP managed services
deployment documentation. Here's a summary of what was created:

  📁 AWS Managed Services Documentation Structure

  Main Documentation Files:

  1. README.md - Comprehensive overview and decision guide
  2. 00-prerequisites-managed.md - AWS setup, VPC, security, and managed services
  3. 01-ecs-managed-deployment.md - Amazon ECS with Fargate deployment
  4. 02-eks-managed-deployment.md - Amazon EKS deployment
  5. 03-production-managed-setup.md - Production hardening and advanced features

  Kubernetes Manifests (kubernetes-manifests/):

  - namespace.yaml - Namespace with resource quotas and network policies
  - storage.yaml - EFS and EBS storage classes and PVCs
  - configmap.yaml - Application configuration and Nginx config
  - secrets.yaml - External Secrets Operator integration with AWS Secrets Manager
  - erpnext-backend.yaml - Backend deployment with RDS connectivity
  - erpnext-frontend.yaml - Frontend deployment with load balancing
  - erpnext-workers.yaml - Worker deployments for different queues
  - ingress.yaml - AWS Load Balancer Controller ingress configuration
  - jobs.yaml - Site creation and backup automation jobs

  Deployment Scripts (scripts/):

  - deploy-ecs.sh - Automated ECS deployment script
  - deploy-eks.sh - Automated EKS deployment script

  🔄 Key AWS Managed Services Used:

  Instead of GCP → AWS Equivalent:
  - Cloud SQL → Amazon RDS for MySQL
  - Memorystore → Amazon MemoryDB for Redis
  - Cloud Run → Amazon ECS with Fargate
  - GKE → Amazon EKS
  - Cloud Storage → Amazon S3
  - Secret Manager → AWS Secrets Manager
  - VPC Access Connector → VPC Endpoints/NAT Gateway

  🎯 Key Features Included:

  Production-Ready Features:

  -  High Availability - Multi-AZ RDS and MemoryDB deployment
  -  Auto-scaling - ECS Service Auto Scaling and EKS HPA
  -  Security - VPC isolation, IAM roles, WAF, encryption
  -  Monitoring - CloudWatch, X-Ray, custom metrics
  -  Backup & DR - Automated backups, cross-region replication
  -  Cost Optimization - Reserved instances, spot instances, right-sizing

  Deployment Options:

  - 🚀 Amazon ECS with Fargate - Serverless containers, minimal ops
  - ⚙️ Amazon EKS - Full Kubernetes with advanced features
  - 🛡️ Production Hardening - WAF, enhanced monitoring, security

  Automation Scripts:

  - 📜 One-click deployment scripts for both ECS and EKS
  - 🔧 Infrastructure as Code approach
  - 📊 Cost estimation and optimization guidance

  The documentation provides a complete migration path from GCP to AWS with equivalent managed
  services, maintaining the same level of reliability and operational efficiency while
  leveraging AWS-native services and best practices.
2025-08-22 19:15:03 +08:00

21 KiB

AWS Prerequisites for ERPNext with Managed Services

Overview

This guide covers the prerequisites and initial setup required for deploying ERPNext on Amazon Web Services (AWS) using managed database services: Amazon RDS for MySQL and Amazon MemoryDB for Redis. This approach provides better reliability, security, and operational efficiency compared to self-hosted databases.

🔧 Required Tools

1. AWS CLI

# Install AWS CLI v2
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install

# Configure AWS CLI
aws configure
# Enter your Access Key ID, Secret Access Key, Default region, and output format

2. kubectl (Kubernetes CLI) - For EKS Option

# Install kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

# Verify installation
kubectl version --client

3. eksctl (EKS CLI) - For EKS Option

# Install eksctl
curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
sudo mv /tmp/eksctl /usr/local/bin

# Verify installation
eksctl version

4. Docker (for local testing and ECS)

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

# Enable Docker BuildKit
export DOCKER_BUILDKIT=1

5. AWS ECS CLI - For ECS Option

# Install ECS CLI
sudo curl -Lo /usr/local/bin/ecs-cli https://amazon-ecs-cli.s3.amazonaws.com/ecs-cli-linux-amd64-latest
sudo chmod +x /usr/local/bin/ecs-cli

# Verify installation
ecs-cli --version

6. Helm (for EKS Kubernetes package management)

# Install Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# Verify installation
helm version

🏗️ AWS Account Setup

1. Create or Configure AWS Account

# Verify AWS account and permissions
aws sts get-caller-identity

# Set default region
export AWS_DEFAULT_REGION=us-east-1
aws configure set default.region us-east-1

# Verify configuration
aws configure list

2. Enable Required AWS Services

# Verify access to required services
aws ec2 describe-regions --output table
aws rds describe-db-instances --output table
aws elasticache describe-cache-clusters --output table
aws ecs list-clusters --output table
aws eks list-clusters --output table

3. Create IAM Policies and Roles

# Create IAM policy for ERPNext managed services
cat > erpnext-managed-policy.json <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "rds:*",
                "elasticache:*",
                "ecs:*",
                "eks:*",
                "ec2:*",
                "iam:PassRole",
                "logs:*",
                "cloudwatch:*",
                "secretsmanager:*",
                "ssm:*"
            ],
            "Resource": "*"
        }
    ]
}
EOF

# Create the policy
aws iam create-policy \
    --policy-name ERPNextManagedPolicy \
    --policy-document file://erpnext-managed-policy.json

# Create service role for ECS tasks
cat > ecs-task-role-trust.json <<EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "ecs-tasks.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
EOF

aws iam create-role \
    --role-name ERPNextECSTaskRole \
    --assume-role-policy-document file://ecs-task-role-trust.json

# Attach policies to ECS task role
aws iam attach-role-policy \
    --role-name ERPNextECSTaskRole \
    --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

aws iam attach-role-policy \
    --role-name ERPNextECSTaskRole \
    --policy-arn $(aws iam list-policies --query "Policies[?PolicyName=='ERPNextManagedPolicy'].Arn" --output text)

🔐 Security Setup

1. VPC and Networking Configuration

# Create VPC for ERPNext deployment
aws ec2 create-vpc \
    --cidr-block 10.0.0.0/16 \
    --tag-specifications 'ResourceType=vpc,Tags=[{Key=Name,Value=erpnext-vpc}]'

# Get VPC ID
VPC_ID=$(aws ec2 describe-vpcs \
    --filters "Name=tag:Name,Values=erpnext-vpc" \
    --query "Vpcs[0].VpcId" --output text)

# Create Internet Gateway
aws ec2 create-internet-gateway \
    --tag-specifications 'ResourceType=internet-gateway,Tags=[{Key=Name,Value=erpnext-igw}]'

IGW_ID=$(aws ec2 describe-internet-gateways \
    --filters "Name=tag:Name,Values=erpnext-igw" \
    --query "InternetGateways[0].InternetGatewayId" --output text)

# Attach Internet Gateway to VPC
aws ec2 attach-internet-gateway \
    --vpc-id $VPC_ID \
    --internet-gateway-id $IGW_ID

# Create subnets
# Public subnet for load balancers
aws ec2 create-subnet \
    --vpc-id $VPC_ID \
    --cidr-block 10.0.1.0/24 \
    --availability-zone us-east-1a \
    --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=erpnext-public-subnet-1a}]'

aws ec2 create-subnet \
    --vpc-id $VPC_ID \
    --cidr-block 10.0.2.0/24 \
    --availability-zone us-east-1b \
    --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=erpnext-public-subnet-1b}]'

# Private subnets for application
aws ec2 create-subnet \
    --vpc-id $VPC_ID \
    --cidr-block 10.0.10.0/24 \
    --availability-zone us-east-1a \
    --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=erpnext-private-subnet-1a}]'

aws ec2 create-subnet \
    --vpc-id $VPC_ID \
    --cidr-block 10.0.11.0/24 \
    --availability-zone us-east-1b \
    --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=erpnext-private-subnet-1b}]'

# Database subnets
aws ec2 create-subnet \
    --vpc-id $VPC_ID \
    --cidr-block 10.0.20.0/24 \
    --availability-zone us-east-1a \
    --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=erpnext-db-subnet-1a}]'

aws ec2 create-subnet \
    --vpc-id $VPC_ID \
    --cidr-block 10.0.21.0/24 \
    --availability-zone us-east-1b \
    --tag-specifications 'ResourceType=subnet,Tags=[{Key=Name,Value=erpnext-db-subnet-1b}]'

2. Route Tables and NAT Gateway

# Get subnet IDs
PUBLIC_SUBNET_1A=$(aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=erpnext-public-subnet-1a" \
    --query "Subnets[0].SubnetId" --output text)

PUBLIC_SUBNET_1B=$(aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=erpnext-public-subnet-1b" \
    --query "Subnets[0].SubnetId" --output text)

PRIVATE_SUBNET_1A=$(aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=erpnext-private-subnet-1a" \
    --query "Subnets[0].SubnetId" --output text)

PRIVATE_SUBNET_1B=$(aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=erpnext-private-subnet-1b" \
    --query "Subnets[0].SubnetId" --output text)

# Create NAT Gateway
aws ec2 allocate-address \
    --domain vpc \
    --tag-specifications 'ResourceType=elastic-ip,Tags=[{Key=Name,Value=erpnext-nat-eip}]'

NAT_EIP=$(aws ec2 describe-addresses \
    --filters "Name=tag:Name,Values=erpnext-nat-eip" \
    --query "Addresses[0].AllocationId" --output text)

aws ec2 create-nat-gateway \
    --subnet-id $PUBLIC_SUBNET_1A \
    --allocation-id $NAT_EIP \
    --tag-specifications 'ResourceType=nat-gateway,Tags=[{Key=Name,Value=erpnext-nat}]'

NAT_ID=$(aws ec2 describe-nat-gateways \
    --filter "Name=tag:Name,Values=erpnext-nat" \
    --query "NatGateways[0].NatGatewayId" --output text)

# Create route tables
# Public route table
aws ec2 create-route-table \
    --vpc-id $VPC_ID \
    --tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=erpnext-public-rt}]'

PUBLIC_RT=$(aws ec2 describe-route-tables \
    --filters "Name=tag:Name,Values=erpnext-public-rt" \
    --query "RouteTables[0].RouteTableId" --output text)

# Private route table
aws ec2 create-route-table \
    --vpc-id $VPC_ID \
    --tag-specifications 'ResourceType=route-table,Tags=[{Key=Name,Value=erpnext-private-rt}]'

PRIVATE_RT=$(aws ec2 describe-route-tables \
    --filters "Name=tag:Name,Values=erpnext-private-rt" \
    --query "RouteTables[0].RouteTableId" --output text)

# Add routes
aws ec2 create-route \
    --route-table-id $PUBLIC_RT \
    --destination-cidr-block 0.0.0.0/0 \
    --gateway-id $IGW_ID

aws ec2 create-route \
    --route-table-id $PRIVATE_RT \
    --destination-cidr-block 0.0.0.0/0 \
    --nat-gateway-id $NAT_ID

# Associate subnets with route tables
aws ec2 associate-route-table \
    --subnet-id $PUBLIC_SUBNET_1A \
    --route-table-id $PUBLIC_RT

aws ec2 associate-route-table \
    --subnet-id $PUBLIC_SUBNET_1B \
    --route-table-id $PUBLIC_RT

aws ec2 associate-route-table \
    --subnet-id $PRIVATE_SUBNET_1A \
    --route-table-id $PRIVATE_RT

aws ec2 associate-route-table \
    --subnet-id $PRIVATE_SUBNET_1B \
    --route-table-id $PRIVATE_RT

3. Security Groups

# Create security group for ALB
aws ec2 create-security-group \
    --group-name erpnext-alb-sg \
    --description "Security group for ERPNext Application Load Balancer" \
    --vpc-id $VPC_ID \
    --tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=erpnext-alb-sg}]'

ALB_SG=$(aws ec2 describe-security-groups \
    --filters "Name=tag:Name,Values=erpnext-alb-sg" \
    --query "SecurityGroups[0].GroupId" --output text)

# Create security group for application
aws ec2 create-security-group \
    --group-name erpnext-app-sg \
    --description "Security group for ERPNext Application" \
    --vpc-id $VPC_ID \
    --tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=erpnext-app-sg}]'

APP_SG=$(aws ec2 describe-security-groups \
    --filters "Name=tag:Name,Values=erpnext-app-sg" \
    --query "SecurityGroups[0].GroupId" --output text)

# Create security group for database
aws ec2 create-security-group \
    --group-name erpnext-db-sg \
    --description "Security group for ERPNext Database" \
    --vpc-id $VPC_ID \
    --tag-specifications 'ResourceType=security-group,Tags=[{Key=Name,Value=erpnext-db-sg}]'

DB_SG=$(aws ec2 describe-security-groups \
    --filters "Name=tag:Name,Values=erpnext-db-sg" \
    --query "SecurityGroups[0].GroupId" --output text)

# Configure security group rules
# ALB security group
aws ec2 authorize-security-group-ingress \
    --group-id $ALB_SG \
    --protocol tcp \
    --port 80 \
    --cidr 0.0.0.0/0

aws ec2 authorize-security-group-ingress \
    --group-id $ALB_SG \
    --protocol tcp \
    --port 443 \
    --cidr 0.0.0.0/0

# Application security group
aws ec2 authorize-security-group-ingress \
    --group-id $APP_SG \
    --protocol tcp \
    --port 8000 \
    --source-group $ALB_SG

aws ec2 authorize-security-group-ingress \
    --group-id $APP_SG \
    --protocol tcp \
    --port 9000 \
    --source-group $ALB_SG

# Database security group
aws ec2 authorize-security-group-ingress \
    --group-id $DB_SG \
    --protocol tcp \
    --port 3306 \
    --source-group $APP_SG

aws ec2 authorize-security-group-ingress \
    --group-id $DB_SG \
    --protocol tcp \
    --port 6379 \
    --source-group $APP_SG

💾 Managed Database Services Setup

1. RDS MySQL Instance

# Create DB subnet group
DB_SUBNET_1A=$(aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=erpnext-db-subnet-1a" \
    --query "Subnets[0].SubnetId" --output text)

DB_SUBNET_1B=$(aws ec2 describe-subnets \
    --filters "Name=tag:Name,Values=erpnext-db-subnet-1b" \
    --query "Subnets[0].SubnetId" --output text)

aws rds create-db-subnet-group \
    --db-subnet-group-name erpnext-db-subnet-group \
    --db-subnet-group-description "Subnet group for ERPNext database" \
    --subnet-ids $DB_SUBNET_1A $DB_SUBNET_1B \
    --tags Key=Name,Value=erpnext-db-subnet-group

# Create RDS MySQL instance
aws rds create-db-instance \
    --db-instance-identifier erpnext-db \
    --db-instance-class db.t3.medium \
    --engine mysql \
    --engine-version 8.0.35 \
    --master-username admin \
    --master-user-password YourSecureDBPassword123! \
    --allocated-storage 100 \
    --storage-type gp3 \
    --storage-encrypted \
    --vpc-security-group-ids $DB_SG \
    --db-subnet-group-name erpnext-db-subnet-group \
    --backup-retention-period 7 \
    --backup-window 03:00-04:00 \
    --maintenance-window sun:04:00-sun:05:00 \
    --auto-minor-version-upgrade \
    --deletion-protection \
    --enable-performance-insights \
    --performance-insights-retention-period 7 \
    --tags Key=Name,Value=erpnext-db

# Wait for instance to be available
aws rds wait db-instance-available --db-instance-identifier erpnext-db

# Create ERPNext database
aws rds create-db-instance \
    --db-instance-identifier erpnext-db \
    --allocated-storage 100 \
    --db-instance-class db.t3.medium \
    --engine mysql \
    --master-username admin \
    --master-user-password YourSecureDBPassword123! \
    --vpc-security-group-ids $DB_SG \
    --db-subnet-group-name erpnext-db-subnet-group

2. MemoryDB for Redis Instance

# Create MemoryDB subnet group
aws memorydb create-subnet-group \
    --subnet-group-name erpnext-redis-subnet-group \
    --description "Subnet group for ERPNext Redis" \
    --subnet-ids $DB_SUBNET_1A $DB_SUBNET_1B \
    --tags Key=Name,Value=erpnext-redis-subnet-group

# Create MemoryDB user
aws memorydb create-user \
    --user-name erpnext-redis-user \
    --authentication-mode Type=password,Passwords=YourSecureRedisPassword123! \
    --access-string "on ~* &* +@all" \
    --tags Key=Name,Value=erpnext-redis-user

# Create MemoryDB ACL
aws memorydb create-acl \
    --acl-name erpnext-redis-acl \
    --user-names erpnext-redis-user \
    --tags Key=Name,Value=erpnext-redis-acl

# Create MemoryDB cluster
aws memorydb create-cluster \
    --cluster-name erpnext-redis \
    --node-type db.t4g.small \
    --engine-version 6.2 \
    --num-shards 1 \
    --num-replicas-per-shard 1 \
    --acl-name erpnext-redis-acl \
    --subnet-group-name erpnext-redis-subnet-group \
    --security-group-ids $DB_SG \
    --maintenance-window sun:05:00-sun:06:00 \
    --sns-topic-arn arn:aws:sns:us-east-1:$(aws sts get-caller-identity --query Account --output text):erpnext-notifications \
    --tls-enabled \
    --tags Key=Name,Value=erpnext-redis

# Wait for cluster to be available
aws memorydb describe-clusters \
    --cluster-name erpnext-redis \
    --query "Clusters[0].Status" --output text

3. AWS Systems Manager Parameter Store for Configuration

# Store database configuration
aws ssm put-parameter \
    --name "/erpnext/database/host" \
    --value $(aws rds describe-db-instances \
        --db-instance-identifier erpnext-db \
        --query "DBInstances[0].Endpoint.Address" --output text) \
    --type "String" \
    --description "ERPNext Database Host"

aws ssm put-parameter \
    --name "/erpnext/database/port" \
    --value "3306" \
    --type "String" \
    --description "ERPNext Database Port"

aws ssm put-parameter \
    --name "/erpnext/database/name" \
    --value "erpnext" \
    --type "String" \
    --description "ERPNext Database Name"

aws ssm put-parameter \
    --name "/erpnext/database/username" \
    --value "admin" \
    --type "String" \
    --description "ERPNext Database Username"

# Store Redis configuration
aws ssm put-parameter \
    --name "/erpnext/redis/host" \
    --value $(aws memorydb describe-clusters \
        --cluster-name erpnext-redis \
        --query "Clusters[0].ClusterEndpoint.Address" --output text) \
    --type "String" \
    --description "ERPNext Redis Host"

aws ssm put-parameter \
    --name "/erpnext/redis/port" \
    --value "6379" \
    --type "String" \
    --description "ERPNext Redis Port"

🔑 AWS Secrets Manager for Sensitive Data

# Store database password
aws secretsmanager create-secret \
    --name "erpnext/database/password" \
    --description "ERPNext Database Password" \
    --secret-string "YourSecureDBPassword123!" \
    --tags '[{"Key":"Application","Value":"ERPNext"},{"Key":"Environment","Value":"Production"}]'

# Store Redis password
aws secretsmanager create-secret \
    --name "erpnext/redis/password" \
    --description "ERPNext Redis Password" \
    --secret-string "YourSecureRedisPassword123!" \
    --tags '[{"Key":"Application","Value":"ERPNext"},{"Key":"Environment","Value":"Production"}]'

# Store ERPNext admin password
aws secretsmanager create-secret \
    --name "erpnext/admin/password" \
    --description "ERPNext Admin Password" \
    --secret-string "YourSecureAdminPassword123!" \
    --tags '[{"Key":"Application","Value":"ERPNext"},{"Key":"Environment","Value":"Production"}]'

# Store API credentials
aws secretsmanager create-secret \
    --name "erpnext/api/credentials" \
    --description "ERPNext API Credentials" \
    --secret-string '{"api_key":"your-api-key-here","api_secret":"your-api-secret-here"}' \
    --tags '[{"Key":"Application","Value":"ERPNext"},{"Key":"Environment","Value":"Production"}]'

📊 CloudWatch and Monitoring Setup

# Create CloudWatch log groups
aws logs create-log-group \
    --log-group-name /aws/ecs/erpnext-backend \
    --retention-in-days 7

aws logs create-log-group \
    --log-group-name /aws/ecs/erpnext-frontend \
    --retention-in-days 7

aws logs create-log-group \
    --log-group-name /aws/ecs/erpnext-worker \
    --retention-in-days 7

# Create SNS topic for alerts
aws sns create-topic \
    --name erpnext-alerts \
    --tags Key=Application,Value=ERPNext

# Subscribe email to alerts (replace with your email)
aws sns subscribe \
    --topic-arn arn:aws:sns:us-east-1:$(aws sts get-caller-identity --query Account --output text):erpnext-alerts \
    --protocol email \
    --notification-endpoint your-email@yourdomain.com

🔍 Verification Checklist

Before proceeding to deployment, verify:

# Check AWS credentials and region
aws sts get-caller-identity
aws configure get region

# Verify VPC and subnets
aws ec2 describe-vpcs --filters "Name=tag:Name,Values=erpnext-vpc"
aws ec2 describe-subnets --filters "Name=vpc-id,Values=$VPC_ID"

# Check security groups
aws ec2 describe-security-groups --filters "Name=vpc-id,Values=$VPC_ID"

# Verify RDS instance
aws rds describe-db-instances --db-instance-identifier erpnext-db

# Check MemoryDB cluster
aws memorydb describe-clusters --cluster-name erpnext-redis

# Verify secrets
aws secretsmanager list-secrets --filters Key=tag-key,Values=Application Key=tag-value,Values=ERPNext

# Check IAM roles
aws iam get-role --role-name ERPNextECSTaskRole

# Verify CloudWatch log groups
aws logs describe-log-groups --log-group-name-prefix /aws/ecs/erpnext

💡 Cost Optimization for Managed Services

1. RDS Optimization

# Use appropriate instance types
# Development: db.t3.micro or db.t3.small
# Production: db.t3.medium or larger

# Enable storage autoscaling
aws rds modify-db-instance \
    --db-instance-identifier erpnext-db \
    --max-allocated-storage 1000 \
    --apply-immediately

# Use Reserved Instances for production (1-3 year terms)
aws rds describe-reserved-db-instances-offerings \
    --db-instance-class db.t3.medium \
    --engine mysql

2. MemoryDB Optimization

# Right-size cluster based on memory usage
# Start with db.t4g.small and scale based on usage
# Monitor memory utilization and adjust

# Use Multi-AZ only for production
# Single-AZ for development/testing environments

3. Network Cost Optimization

# Use same AZ for services to minimize data transfer costs
# Monitor VPC Flow Logs for inter-AZ traffic
# Consider VPC endpoints for AWS services if needed

🚨 Security Best Practices for Managed Services

1. Network Security

  • VPC isolation: All managed services use private subnets
  • Security groups: Restrictive access between tiers
  • No public access: Database and Redis not accessible from internet

2. Access Control

# Enable RDS IAM database authentication
aws rds modify-db-instance \
    --db-instance-identifier erpnext-db \
    --enable-iam-database-authentication \
    --apply-immediately

# Create IAM database user
aws rds create-db-instance-read-replica \
    --db-instance-identifier erpnext-db-read-replica \
    --source-db-instance-identifier erpnext-db \
    --db-instance-class db.t3.small

3. Encryption

  • Encryption at rest: Enabled by default for both services
  • Encryption in transit: SSL/TLS enforced
  • Secrets management: AWS Secrets Manager for credentials

📚 Additional Resources

➡️ Next Steps

After completing prerequisites:

  1. ECS with Managed Services: Follow 01-ecs-managed-deployment.md
  2. EKS with Managed Services: Follow 02-eks-managed-deployment.md
  3. Production Hardening: See 03-production-managed-setup.md

⚠️ Important Notes:

  • Managed services incur continuous costs even when not in use
  • Plan your backup and disaster recovery strategy
  • Monitor costs regularly using AWS Cost Explorer
  • Keep track of all resources created for billing purposes
  • Use AWS Config for compliance and governance