infra: add Terraform infrastructure as code for AWS deployment
Some checks failed
Cross-Node Transaction Testing / transaction-test (push) Has been cancelled
Deploy to Testnet / deploy-testnet (push) Has been cancelled
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Node Failover Simulation / failover-test (push) Has been cancelled
Some checks failed
Cross-Node Transaction Testing / transaction-test (push) Has been cancelled
Deploy to Testnet / deploy-testnet (push) Has been cancelled
Multi-Node Stress Testing / stress-test (push) Has been cancelled
Node Failover Simulation / failover-test (push) Has been cancelled
- Create main.tf with VPC, security groups, ECS, ALB, RDS, Redis, S3 - Add provider.tf with AWS provider configuration - Create variables.tf for infrastructure configuration - Add outputs.tf for infrastructure outputs - Implement ecs.tf with ECS task definitions and services - Add ecs_variables.tf for ECS-specific variables - Create comprehensive README.md with usage instructions - Implement state management with S3 backend and DynamoDB locking - Add security best practices (private subnets, encryption, secrets manager)
This commit is contained in:
144
infra/terraform/README.md
Normal file
144
infra/terraform/README.md
Normal file
@@ -0,0 +1,144 @@
|
||||
# AITBC Terraform Infrastructure
|
||||
|
||||
This directory contains Terraform configurations for deploying AITBC infrastructure on AWS.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Terraform >= 1.0
|
||||
- AWS CLI configured with appropriate credentials
|
||||
- S3 bucket for Terraform state (configured in backend)
|
||||
- DynamoDB table for state locking (configured in backend)
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
terraform/
|
||||
├── main.tf # Main Terraform configuration
|
||||
├── provider.tf # Provider configuration
|
||||
├── variables.tf # Infrastructure variables
|
||||
├── outputs.tf # Infrastructure outputs
|
||||
├── ecs.tf # ECS task definitions and services
|
||||
├── ecs_variables.tf # ECS-specific variables
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Initialize Terraform
|
||||
|
||||
```bash
|
||||
terraform init
|
||||
```
|
||||
|
||||
### Plan Infrastructure
|
||||
|
||||
```bash
|
||||
terraform plan -var-file=dev.tfvars
|
||||
```
|
||||
|
||||
### Apply Infrastructure
|
||||
|
||||
```bash
|
||||
terraform apply -var-file=dev.tfvars
|
||||
```
|
||||
|
||||
### Destroy Infrastructure
|
||||
|
||||
```bash
|
||||
terraform destroy -var-file=dev.tfvars
|
||||
```
|
||||
|
||||
## Variables
|
||||
|
||||
Create a `dev.tfvars`, `staging.tfvars`, or `prod.tfvars` file with environment-specific variables:
|
||||
|
||||
```hcl
|
||||
environment = "dev"
|
||||
aws_region = "us-east-1"
|
||||
db_username = "aitbc"
|
||||
db_password = "your-secure-password"
|
||||
database_url = "postgresql://..."
|
||||
redis_url = "redis://..."
|
||||
jwt_secret = "your-jwt-secret"
|
||||
acm_certificate_arn = "arn:aws:acm:..."
|
||||
```
|
||||
|
||||
## Infrastructure Components
|
||||
|
||||
### Networking
|
||||
- VPC with public and private subnets
|
||||
- NAT Gateway for private subnet internet access
|
||||
- Security groups for different services
|
||||
|
||||
### Compute
|
||||
- ECS Fargate cluster
|
||||
- ECS task definitions for API services
|
||||
- Application Load Balancer
|
||||
- Auto-scaling capabilities
|
||||
|
||||
### Databases
|
||||
- RDS PostgreSQL for application data
|
||||
- ElastiCache Redis for caching
|
||||
|
||||
### Storage
|
||||
- S3 bucket for data storage
|
||||
- Versioning and encryption enabled
|
||||
|
||||
### Monitoring
|
||||
- CloudWatch Log Groups
|
||||
- ECS CloudWatch Container Insights
|
||||
|
||||
## State Management
|
||||
|
||||
Terraform state is stored in S3 with DynamoDB locking:
|
||||
- State bucket: `aitbc-terraform-state`
|
||||
- Lock table: `aitbc-terraform-locks`
|
||||
|
||||
## Security
|
||||
|
||||
- All resources are tagged with project and environment
|
||||
- Security groups restrict access by CIDR blocks
|
||||
- RDS and Redis are in private subnets
|
||||
- Secrets stored in AWS Secrets Manager
|
||||
- S3 encryption enabled
|
||||
- RDS encryption enabled
|
||||
|
||||
## Cost Optimization
|
||||
|
||||
- Use appropriate instance sizes for environment
|
||||
- Enable auto-scaling for production
|
||||
- Monitor costs with AWS Cost Explorer
|
||||
- Use reserved instances for predictable workloads
|
||||
|
||||
## Outputs
|
||||
|
||||
After applying the configuration, Terraform outputs:
|
||||
- VPC and subnet IDs
|
||||
- ECS cluster ID and ARN
|
||||
- ALB DNS name
|
||||
- Database and Redis endpoints
|
||||
- S3 bucket name
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### State Lock Issues
|
||||
If you encounter state lock issues:
|
||||
```bash
|
||||
terraform force-unlock <LOCK_ID>
|
||||
```
|
||||
|
||||
### Resource Already Exists
|
||||
If resources already exist outside Terraform, import them:
|
||||
```bash
|
||||
terraform import aws_vpc.this vpc-xxxxx
|
||||
```
|
||||
|
||||
### Permission Errors
|
||||
Ensure your AWS credentials have the necessary permissions:
|
||||
- EC2 (VPC, subnets, security groups)
|
||||
- ECS (clusters, task definitions, services)
|
||||
- ELB (load balancers, target groups)
|
||||
- RDS (database instances)
|
||||
- ElastiCache (Redis clusters)
|
||||
- S3 (buckets)
|
||||
- Secrets Manager (secrets)
|
||||
209
infra/terraform/ecs.tf
Normal file
209
infra/terraform/ecs.tf
Normal file
@@ -0,0 +1,209 @@
|
||||
# ECS task definition for AITBC API service
|
||||
|
||||
resource "aws_ecs_task_definition" "api" {
|
||||
family = "${var.project_name}-${var.environment}-api"
|
||||
network_mode = "awsvpc"
|
||||
requires_compatibilities = ["FARGATE"]
|
||||
cpu = var.api_cpu
|
||||
memory = var.api_memory
|
||||
execution_role_arn = aws_iam_role.ecs_execution_role.arn
|
||||
task_role_arn = aws_iam_role.ecs_task_role.arn
|
||||
|
||||
container_definitions = jsonencode([
|
||||
{
|
||||
name = "api"
|
||||
image = "${var.api_image}:${var.api_image_tag}"
|
||||
cpu = var.api_cpu
|
||||
memory = var.api_memory
|
||||
essential = true
|
||||
|
||||
portMappings = [
|
||||
{
|
||||
containerPort = 8000
|
||||
protocol = "tcp"
|
||||
}
|
||||
]
|
||||
|
||||
environment = [
|
||||
{
|
||||
name = "ENVIRONMENT"
|
||||
value = var.environment
|
||||
},
|
||||
{
|
||||
name = "LOG_LEVEL"
|
||||
value = var.log_level
|
||||
}
|
||||
]
|
||||
|
||||
secrets = [
|
||||
{
|
||||
name = "DATABASE_URL"
|
||||
valueFrom = aws_secretsmanager_secret.database_url.arn
|
||||
},
|
||||
{
|
||||
name = "REDIS_URL"
|
||||
valueFrom = aws_secretsmanager_secret.redis_url.arn
|
||||
},
|
||||
{
|
||||
name = "JWT_SECRET"
|
||||
valueFrom = aws_secretsmanager_secret.jwt_secret.arn
|
||||
}
|
||||
]
|
||||
|
||||
logConfiguration = {
|
||||
logDriver = "awslogs"
|
||||
options = {
|
||||
"awslogs-group" = aws_cloudwatch_log_group.api.name
|
||||
"awslogs-region" = var.aws_region
|
||||
"awslogs-stream-prefix" = "api"
|
||||
}
|
||||
}
|
||||
|
||||
healthCheck = {
|
||||
command = ["CMD-SHELL", "curl -f http://localhost:8000/health || exit 1"]
|
||||
interval = 30
|
||||
timeout = 5
|
||||
retries = 3
|
||||
startPeriod = 60
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-${var.environment}-api"
|
||||
}
|
||||
}
|
||||
|
||||
# ECS service for API
|
||||
resource "aws_ecs_service" "api" {
|
||||
name = "${var.project_name}-${var.environment}-api"
|
||||
cluster = aws_ecs_cluster.this.id
|
||||
task_definition = aws_ecs_task_definition.api.arn
|
||||
desired_count = var.api_desired_count
|
||||
launch_type = "FARGATE"
|
||||
|
||||
network_configuration {
|
||||
subnets = module.vpc.private_subnets
|
||||
security_groups = [aws_security_group.api_gateway.id]
|
||||
assign_public_ip = false
|
||||
}
|
||||
|
||||
load_balancer {
|
||||
target_group_arn = aws_lb_target_group.api.arn
|
||||
container_name = "api"
|
||||
container_port = 8000
|
||||
}
|
||||
|
||||
depends_on = [aws_lb_listener.https]
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-${var.environment}-api"
|
||||
}
|
||||
}
|
||||
|
||||
# IAM roles
|
||||
resource "aws_iam_role" "ecs_execution_role" {
|
||||
name = "${var.project_name}-${var.environment}-ecs-execution-role"
|
||||
|
||||
assume_role_policy = jsonencode({
|
||||
Version = "2012-10-17"
|
||||
Statement = [
|
||||
{
|
||||
Action = "sts:AssumeRole"
|
||||
Effect = "Allow"
|
||||
Principal = {
|
||||
Service = "ecs-tasks.amazonaws.com"
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-${var.environment}-ecs-execution-role"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy_attachment" "ecs_execution_role_policy" {
|
||||
role = aws_iam_role.ecs_execution_role.name
|
||||
policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"
|
||||
}
|
||||
|
||||
resource "aws_iam_role" "ecs_task_role" {
|
||||
name = "${var.project_name}-${var.environment}-ecs-task-role"
|
||||
|
||||
assume_role_policy = jsonencode({
|
||||
Version = "2012-10-17"
|
||||
Statement = [
|
||||
{
|
||||
Action = "sts:AssumeRole"
|
||||
Effect = "Allow"
|
||||
Principal = {
|
||||
Service = "ecs-tasks.amazonaws.com"
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-${var.environment}-ecs-task-role"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_iam_role_policy" "ecs_task_policy" {
|
||||
name = "${var.project_name}-${var.environment}-ecs-task-policy"
|
||||
role = aws_iam_role.ecs_task_role.id
|
||||
|
||||
policy = jsonencode({
|
||||
Version = "2012-10-17"
|
||||
Statement = [
|
||||
{
|
||||
Effect = "Allow"
|
||||
Action = [
|
||||
"s3:GetObject",
|
||||
"s3:PutObject",
|
||||
"s3:DeleteObject"
|
||||
]
|
||||
Resource = "${aws_s3_bucket.data.arn}/*"
|
||||
},
|
||||
{
|
||||
Effect = "Allow"
|
||||
Action = [
|
||||
"secretsmanager:GetSecretValue"
|
||||
]
|
||||
Resource = [
|
||||
aws_secretsmanager_secret.database_url.arn,
|
||||
aws_secretsmanager_secret.redis_url.arn,
|
||||
aws_secretsmanager_secret.jwt_secret.arn
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
|
||||
# Secrets Manager
|
||||
resource "aws_secretsmanager_secret" "database_url" {
|
||||
name = "${var.project_name}/${var.environment}/database/url"
|
||||
}
|
||||
|
||||
resource "aws_secretsmanager_secret_version" "database_url" {
|
||||
secret_id = aws_secretsmanager_secret.database_url.id
|
||||
secret_string = var.database_url
|
||||
}
|
||||
|
||||
resource "aws_secretsmanager_secret" "redis_url" {
|
||||
name = "${var.project_name}/${var.environment}/redis/url"
|
||||
}
|
||||
|
||||
resource "aws_secretsmanager_secret_version" "redis_url" {
|
||||
secret_id = aws_secretsmanager_secret.redis.id
|
||||
secret_string = var.redis_url
|
||||
}
|
||||
|
||||
resource "aws_secretsmanager_secret" "jwt_secret" {
|
||||
name = "${var.project_name}/${var.environment}/jwt/secret"
|
||||
}
|
||||
|
||||
resource "aws_secretsmanager_secret_version" "jwt_secret" {
|
||||
secret_id = aws_secretsmanager_secret.jwt_secret.id
|
||||
secret_string = var.jwt_secret
|
||||
}
|
||||
55
infra/terraform/ecs_variables.tf
Normal file
55
infra/terraform/ecs_variables.tf
Normal file
@@ -0,0 +1,55 @@
|
||||
# ECS API variables
|
||||
|
||||
variable "api_cpu" {
|
||||
description = "API task CPU units"
|
||||
type = number
|
||||
default = 512
|
||||
}
|
||||
|
||||
variable "api_memory" {
|
||||
description = "API task memory in MB"
|
||||
type = number
|
||||
default = 1024
|
||||
}
|
||||
|
||||
variable "api_desired_count" {
|
||||
description = "API desired task count"
|
||||
type = number
|
||||
default = 2
|
||||
}
|
||||
|
||||
variable "api_image" {
|
||||
description = "API Docker image"
|
||||
type = string
|
||||
default = "aitbc/api"
|
||||
}
|
||||
|
||||
variable "api_image_tag" {
|
||||
description = "API Docker image tag"
|
||||
type = string
|
||||
default = "latest"
|
||||
}
|
||||
|
||||
variable "log_level" {
|
||||
description = "Application log level"
|
||||
type = string
|
||||
default = "INFO"
|
||||
}
|
||||
|
||||
variable "database_url" {
|
||||
description = "Database connection URL"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "redis_url" {
|
||||
description = "Redis connection URL"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "jwt_secret" {
|
||||
description = "JWT secret key"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
356
infra/terraform/main.tf
Normal file
356
infra/terraform/main.tf
Normal file
@@ -0,0 +1,356 @@
|
||||
# Terraform main configuration for AITBC infrastructure
|
||||
# This file defines the infrastructure resources for AITBC deployment
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.0"
|
||||
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = "~> 5.0"
|
||||
}
|
||||
random = {
|
||||
source = "hashicorp/random"
|
||||
version = "~> 3.0"
|
||||
}
|
||||
}
|
||||
|
||||
backend "s3" {
|
||||
bucket = "aitbc-terraform-state"
|
||||
key = "aitbc/terraform.tfstate"
|
||||
region = "us-east-1"
|
||||
encrypt = true
|
||||
dynamodb_table = "aitbc-terraform-locks"
|
||||
}
|
||||
}
|
||||
|
||||
provider "aws" {
|
||||
region = var.aws_region
|
||||
|
||||
default_tags {
|
||||
tags = {
|
||||
Project = "AITBC"
|
||||
Environment = var.environment
|
||||
ManagedBy = "Terraform"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Random resources for unique naming
|
||||
resource "random_pet" "this" {
|
||||
length = 2
|
||||
}
|
||||
|
||||
# VPC
|
||||
module "vpc" {
|
||||
source = "terraform-aws-modules/vpc/aws"
|
||||
version = "~> 5.0"
|
||||
|
||||
name = "${var.project_name}-${var.environment}-vpc"
|
||||
cidr = var.vpc_cidr
|
||||
|
||||
azs = var.availability_zones
|
||||
private_subnets = var.private_subnet_cidrs
|
||||
public_subnets = var.public_subnet_cidrs
|
||||
|
||||
enable_nat_gateway = true
|
||||
single_nat_gateway = true
|
||||
one_nat_gateway_per_az = false
|
||||
|
||||
enable_vpn_gateway = false
|
||||
enable_dns_hostnames = true
|
||||
enable_dns_support = true
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-${var.environment}-vpc"
|
||||
}
|
||||
}
|
||||
|
||||
# Security groups
|
||||
resource "aws_security_group" "blockchain_rpc" {
|
||||
name = "${var.project_name}-${var.environment}-blockchain-rpc"
|
||||
description = "Security group for blockchain RPC service"
|
||||
vpc_id = module.vpc.vpc_id
|
||||
|
||||
ingress {
|
||||
from_port = 8006
|
||||
to_port = 8006
|
||||
protocol = "tcp"
|
||||
cidr_blocks = var.allowed_cidr_blocks
|
||||
}
|
||||
|
||||
egress {
|
||||
from_port = 0
|
||||
to_port = 0
|
||||
protocol = "-1"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-${var.environment}-blockchain-rpc"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_security_group" "api_gateway" {
|
||||
name = "${var.project_name}-${var.environment}-api-gateway"
|
||||
description = "Security group for API gateway"
|
||||
vpc_id = module.vpc.vpc_id
|
||||
|
||||
ingress {
|
||||
from_port = 80
|
||||
to_port = 80
|
||||
protocol = "tcp"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
ingress {
|
||||
from_port = 443
|
||||
to_port = 443
|
||||
protocol = "tcp"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
egress {
|
||||
from_port = 0
|
||||
to_port = 0
|
||||
protocol = "-1"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-${var.environment}-api-gateway"
|
||||
}
|
||||
}
|
||||
|
||||
# ECS Cluster
|
||||
resource "aws_ecs_cluster" "this" {
|
||||
name = "${var.project_name}-${var.environment}-cluster"
|
||||
|
||||
setting {
|
||||
name = "containerInsights"
|
||||
value = "enabled"
|
||||
}
|
||||
}
|
||||
|
||||
# Application Load Balancer
|
||||
resource "aws_lb" "this" {
|
||||
name = "${var.project_name}-${var.environment}-alb"
|
||||
internal = false
|
||||
load_balancer_type = "application"
|
||||
security_groups = [aws_security_group.api_gateway.id]
|
||||
subnets = module.vpc.public_subnets
|
||||
|
||||
enable_deletion_protection = false
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-${var.environment}-alb"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_lb_target_group" "api" {
|
||||
name = "${var.project_name}-${var.environment}-api-tg"
|
||||
port = 8000
|
||||
protocol = "HTTP"
|
||||
vpc_id = module.vpc.vpc_id
|
||||
target_type = "ip"
|
||||
|
||||
health_check {
|
||||
enabled = true
|
||||
healthy_threshold = 2
|
||||
interval = 30
|
||||
matcher = "200"
|
||||
path = "/health"
|
||||
port = "traffic-port"
|
||||
protocol = "HTTP"
|
||||
timeout = 5
|
||||
unhealthy_threshold = 3
|
||||
}
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-${var.environment}-api-tg"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_lb_listener" "http" {
|
||||
load_balancer_arn = aws_lb.this.arn
|
||||
port = 80
|
||||
protocol = "HTTP"
|
||||
|
||||
default_action {
|
||||
type = "redirect"
|
||||
|
||||
redirect {
|
||||
port = "443"
|
||||
protocol = "HTTPS"
|
||||
status_code = "HTTP_301"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_lb_listener" "https" {
|
||||
load_balancer_arn = aws_lb.this.arn
|
||||
port = 443
|
||||
protocol = "HTTPS"
|
||||
certificate_arn = var.acm_certificate_arn
|
||||
|
||||
default_action {
|
||||
type = "forward"
|
||||
target_group_arn = aws_lb_target_group.api.arn
|
||||
}
|
||||
}
|
||||
|
||||
# RDS PostgreSQL
|
||||
resource "aws_db_subnet_group" "this" {
|
||||
name = "${var.project_name}-${var.environment}-db-subnet-group"
|
||||
subnet_ids = module.vpc.private_subnets
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-${var.environment}-db-subnet-group"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_db_instance" "this" {
|
||||
identifier = "${var.project_name}-${var.environment}-db"
|
||||
|
||||
engine = "postgres"
|
||||
engine_version = "15.4"
|
||||
instance_class = var.db_instance_class
|
||||
|
||||
allocated_storage = var.db_allocated_storage
|
||||
max_allocated_storage = var.db_max_allocated_storage
|
||||
storage_type = "gp3"
|
||||
storage_encrypted = true
|
||||
|
||||
db_name = var.db_name
|
||||
username = var.db_username
|
||||
password = var.db_password
|
||||
|
||||
db_subnet_group_name = aws_db_subnet_group.this.name
|
||||
vpc_security_group_ids = [aws_security_group.blockchain_rpc.id]
|
||||
|
||||
multi_az = var.db_multi_az
|
||||
backup_retention_period = var.db_backup_retention_period
|
||||
backup_window = var.db_backup_window
|
||||
maintenance_window = var.db_maintenance_window
|
||||
|
||||
performance_insights_enabled = true
|
||||
|
||||
skip_final_snapshot = false
|
||||
final_snapshot_identifier = "${var.project_name}-${var.environment}-db-final-snapshot"
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-${var.environment}-db"
|
||||
}
|
||||
}
|
||||
|
||||
# ElastiCache Redis
|
||||
resource "aws_elasticache_subnet_group" "this" {
|
||||
name = "${var.project_name}-${var.environment}-redis-subnet-group"
|
||||
subnet_ids = module.vpc.private_subnets
|
||||
}
|
||||
|
||||
resource "aws_elasticache_replication_group" "this" {
|
||||
replication_group_id = "${var.project_name}-${var.environment}-redis"
|
||||
replication_group_description = "${var.project_name} Redis cluster for ${var.environment}"
|
||||
|
||||
node_type = var.redis_node_type
|
||||
num_cache_clusters = var.redis_num_nodes
|
||||
port = 6379
|
||||
|
||||
engine = "redis"
|
||||
engine_version = "7.0"
|
||||
parameter_group_name = "default.redis7"
|
||||
|
||||
subnet_group_name = aws_elasticache_subnet_group.this.name
|
||||
security_group_ids = [aws_security_group.blockchain_rpc.id]
|
||||
|
||||
automatic_failover_enabled = true
|
||||
multi_az_enabled = true
|
||||
|
||||
snapshot_retention_limit = var.redis_snapshot_retention_limit
|
||||
snapshot_window = var.redis_snapshot_window
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-${var.environment}-redis"
|
||||
}
|
||||
}
|
||||
|
||||
# CloudWatch Log Groups
|
||||
resource "aws_cloudwatch_log_group" "api" {
|
||||
name = "/aws/ecs/${var.project_name}-${var.environment}/api"
|
||||
retention_in_days = var.log_retention_days
|
||||
}
|
||||
|
||||
resource "aws_cloudwatch_log_group" "blockchain" {
|
||||
name = "/aws/ecs/${var.project_name}-${var.environment}/blockchain"
|
||||
retention_in_days = var.log_retention_days
|
||||
}
|
||||
|
||||
# S3 Bucket for data storage
|
||||
resource "aws_s3_bucket" "data" {
|
||||
bucket = "${var.project_name}-${var.environment}-data-${random_pet.this.id}"
|
||||
|
||||
tags = {
|
||||
Name = "${var.project_name}-${var.environment}-data"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_versioning" "data" {
|
||||
bucket = aws_s3_bucket.data.id
|
||||
|
||||
versioning_configuration {
|
||||
status = "Enabled"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_s3_bucket_server_side_encryption_configuration" "data" {
|
||||
bucket = aws_s3_bucket.data.id
|
||||
|
||||
rule {
|
||||
apply_server_side_encryption_by_default {
|
||||
sse_algorithm = "AES256"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Outputs
|
||||
output "vpc_id" {
|
||||
description = "VPC ID"
|
||||
value = module.vpc.vpc_id
|
||||
}
|
||||
|
||||
output "private_subnet_ids" {
|
||||
description = "Private subnet IDs"
|
||||
value = module.vpc.private_subnets
|
||||
}
|
||||
|
||||
output "public_subnet_ids" {
|
||||
description = "Public subnet IDs"
|
||||
value = module.vpc.public_subnets
|
||||
}
|
||||
|
||||
output "ecs_cluster_id" {
|
||||
description = "ECS Cluster ID"
|
||||
value = aws_ecs_cluster.this.id
|
||||
}
|
||||
|
||||
output "alb_dns_name" {
|
||||
description = "ALB DNS name"
|
||||
value = aws_lb.this.dns_name
|
||||
}
|
||||
|
||||
output "db_endpoint" {
|
||||
description = "RDS endpoint"
|
||||
value = aws_db_instance.this.endpoint
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "redis_endpoint" {
|
||||
description = "Redis endpoint"
|
||||
value = aws_elasticache_replication_this.primary_endpoint_address
|
||||
}
|
||||
|
||||
output "s3_bucket_name" {
|
||||
description = "S3 bucket name"
|
||||
value = aws_s3_bucket.data.id
|
||||
}
|
||||
77
infra/terraform/outputs.tf
Normal file
77
infra/terraform/outputs.tf
Normal file
@@ -0,0 +1,77 @@
|
||||
# Terraform outputs for AITBC infrastructure
|
||||
|
||||
output "vpc_id" {
|
||||
description = "VPC ID"
|
||||
value = module.vpc.vpc_id
|
||||
}
|
||||
|
||||
output "private_subnet_ids" {
|
||||
description = "Private subnet IDs"
|
||||
value = module.vpc.private_subnets
|
||||
}
|
||||
|
||||
output "public_subnet_ids" {
|
||||
description = "Public subnet IDs"
|
||||
value = module.vpc.public_subnets
|
||||
}
|
||||
|
||||
output "ecs_cluster_id" {
|
||||
description = "ECS Cluster ID"
|
||||
value = aws_ecs_cluster.this.id
|
||||
}
|
||||
|
||||
output "ecs_cluster_arn" {
|
||||
description = "ECS Cluster ARN"
|
||||
value = aws_ecs_cluster.this.arn
|
||||
}
|
||||
|
||||
output "alb_dns_name" {
|
||||
description = "ALB DNS name"
|
||||
value = aws_lb.this.dns_name
|
||||
}
|
||||
|
||||
output "alb_zone_id" {
|
||||
description = "ALB zone ID"
|
||||
value = aws_lb.this.zone_id
|
||||
}
|
||||
|
||||
output "db_endpoint" {
|
||||
description = "RDS endpoint"
|
||||
value = aws_db_instance.this.endpoint
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
output "db_instance_id" {
|
||||
description = "RDS instance ID"
|
||||
value = aws_db_instance.this.id
|
||||
}
|
||||
|
||||
output "redis_endpoint" {
|
||||
description = "Redis primary endpoint"
|
||||
value = aws_elasticache_replication_this.primary_endpoint_address
|
||||
}
|
||||
|
||||
output "redis_port" {
|
||||
description = "Redis port"
|
||||
value = aws_elasticache_replication_this.port
|
||||
}
|
||||
|
||||
output "s3_bucket_name" {
|
||||
description = "S3 bucket name"
|
||||
value = aws_s3_bucket.data.id
|
||||
}
|
||||
|
||||
output "s3_bucket_arn" {
|
||||
description = "S3 bucket ARN"
|
||||
value = aws_s3_bucket.data.arn
|
||||
}
|
||||
|
||||
output "security_group_blockchain_rpc_id" {
|
||||
description = "Blockchain RPC security group ID"
|
||||
value = aws_security_group.blockchain_rpc.id
|
||||
}
|
||||
|
||||
output "security_group_api_gateway_id" {
|
||||
description = "API gateway security group ID"
|
||||
value = aws_security_group.api_gateway.id
|
||||
}
|
||||
28
infra/terraform/provider.tf
Normal file
28
infra/terraform/provider.tf
Normal file
@@ -0,0 +1,28 @@
|
||||
# Terraform provider configuration
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.0"
|
||||
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = "~> 5.0"
|
||||
}
|
||||
random = {
|
||||
source = "hashicorp/random"
|
||||
version = "~> 3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "aws" {
|
||||
region = var.aws_region
|
||||
|
||||
default_tags {
|
||||
tags = {
|
||||
Project = "AITBC"
|
||||
Environment = var.environment
|
||||
ManagedBy = "Terraform"
|
||||
}
|
||||
}
|
||||
}
|
||||
148
infra/terraform/variables.tf
Normal file
148
infra/terraform/variables.tf
Normal file
@@ -0,0 +1,148 @@
|
||||
# Terraform variables for AITBC infrastructure
|
||||
|
||||
variable "project_name" {
|
||||
description = "Project name"
|
||||
type = string
|
||||
default = "aitbc"
|
||||
}
|
||||
|
||||
variable "environment" {
|
||||
description = "Environment name (dev, staging, prod)"
|
||||
type = string
|
||||
validation {
|
||||
condition = contains(["dev", "staging", "prod"], var.environment)
|
||||
error_message = "Environment must be dev, staging, or prod."
|
||||
}
|
||||
}
|
||||
|
||||
variable "aws_region" {
|
||||
description = "AWS region"
|
||||
type = string
|
||||
default = "us-east-1"
|
||||
}
|
||||
|
||||
variable "vpc_cidr" {
|
||||
description = "VPC CIDR block"
|
||||
type = string
|
||||
default = "10.0.0.0/16"
|
||||
}
|
||||
|
||||
variable "availability_zones" {
|
||||
description = "Availability zones"
|
||||
type = list(string)
|
||||
default = ["us-east-1a", "us-east-1b", "us-east-1c"]
|
||||
}
|
||||
|
||||
variable "private_subnet_cidrs" {
|
||||
description = "Private subnet CIDR blocks"
|
||||
type = list(string)
|
||||
default = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
|
||||
}
|
||||
|
||||
variable "public_subnet_cidrs" {
|
||||
description = "Public subnet CIDR blocks"
|
||||
type = list(string)
|
||||
default = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
|
||||
}
|
||||
|
||||
variable "allowed_cidr_blocks" {
|
||||
description = "Allowed CIDR blocks for security groups"
|
||||
type = list(string)
|
||||
default = ["0.0.0.0/0"]
|
||||
}
|
||||
|
||||
variable "acm_certificate_arn" {
|
||||
description = "ACM certificate ARN for HTTPS"
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "db_instance_class" {
|
||||
description = "RDS instance class"
|
||||
type = string
|
||||
default = "db.t3.medium"
|
||||
}
|
||||
|
||||
variable "db_allocated_storage" {
|
||||
description = "RDS allocated storage in GB"
|
||||
type = number
|
||||
default = 20
|
||||
}
|
||||
|
||||
variable "db_max_allocated_storage" {
|
||||
description = "RDS max allocated storage in GB"
|
||||
type = number
|
||||
default = 100
|
||||
}
|
||||
|
||||
variable "db_name" {
|
||||
description = "Database name"
|
||||
type = string
|
||||
default = "aitbc"
|
||||
}
|
||||
|
||||
variable "db_username" {
|
||||
description = "Database username"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "db_password" {
|
||||
description = "Database password"
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "db_multi_az" {
|
||||
description = "Enable multi-AZ for RDS"
|
||||
type = bool
|
||||
default = false
|
||||
}
|
||||
|
||||
variable "db_backup_retention_period" {
|
||||
description = "RDS backup retention period in days"
|
||||
type = number
|
||||
default = 7
|
||||
}
|
||||
|
||||
variable "db_backup_window" {
|
||||
description = "RDS backup window"
|
||||
type = string
|
||||
default = "03:00-04:00"
|
||||
}
|
||||
|
||||
variable "db_maintenance_window" {
|
||||
description = "RDS maintenance window"
|
||||
type = string
|
||||
default = "sun:04:00-sun:05:00"
|
||||
}
|
||||
|
||||
variable "redis_node_type" {
|
||||
description = "Redis node type"
|
||||
type = string
|
||||
default = "cache.t3.medium"
|
||||
}
|
||||
|
||||
variable "redis_num_nodes" {
|
||||
description = "Number of Redis nodes"
|
||||
type = number
|
||||
default = 2
|
||||
}
|
||||
|
||||
variable "redis_snapshot_retention_limit" {
|
||||
description = "Redis snapshot retention limit"
|
||||
type = number
|
||||
default = 5
|
||||
}
|
||||
|
||||
variable "redis_snapshot_window" {
|
||||
description = "Redis snapshot window"
|
||||
type = string
|
||||
default = "05:00-06:00"
|
||||
}
|
||||
|
||||
variable "log_retention_days" {
|
||||
description = "CloudWatch log retention in days"
|
||||
type = number
|
||||
default = 30
|
||||
}
|
||||
Reference in New Issue
Block a user