Core Infrastructure Modules
These foundational modules are required for every DocuStack environment. They establish the networking, compute, storage, and database layers.
Bootstrap
Creates the S3 bucket and DynamoDB table for Terraform remote state storage.
Why This Module?
Terraform needs a backend to store state files. This module creates a HIPAA-compliant backend with:
- Versioning for state history and rollback
- Encryption at rest with KMS
- Locking via DynamoDB to prevent concurrent modifications
- Lifecycle protection to prevent accidental deletion
Key Features
- Server-side encryption with AWS KMS
- Public access blocked
- TLS enforcement for all connections
- Point-in-time recovery enabled
Usage
terraform {
source = "git::git@github.com:docustackapp/docustack-infrastructure-modules.git//modules/bootstrap?ref=v1.0.0"
}
inputs = {
account_id = "123456789012"
aws_region = "us-east-1"
project_name = "docustack"
}
Deployment
This module must be run locally first (not via Terrateam):
cd infrastructure/bootstrap
terragrunt init
terragrunt apply
# After creation, migrate state to S3
terragrunt init -migrate-state
Important Notes
- Deploy once per AWS account, not per environment
- Has
prevent_destroy = true- manual removal required to destroy - Must complete before deploying any other infrastructure
VPC
Creates a HIPAA-compliant VPC with public, private, and database subnets across multiple availability zones.
Why This Module?
A properly architected VPC is critical for security and compliance:
- Network isolation between application tiers
- VPC Flow Logs for audit compliance
- VPC Endpoints to reduce NAT costs and improve security
- Multi-AZ for high availability
Architecture
┌─────────────────────────────────────────────────────────────┐
│ VPC (10.0.0.0/16) │
├─────────────────────────────────────────────────────────────┤
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Public AZ-A │ │ Public AZ-B │ │ Public AZ-C │ │
│ │ 10.0.0.0/24 │ │ 10.0.1.0/24 │ │ 10.0.2.0/24 │ │
│ │ - ALB │ │ - ALB │ │ - ALB │ │
│ │ - NAT GW │ │ - NAT GW │ │ - NAT GW │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │ │
│ ┌──────▼───────┐ ┌──────▼───────┐ ┌──────▼───────┐ │
│ │ Private AZ-A │ │ Private AZ-B │ │ Private AZ-C │ │
│ │ 10.0.10.0/24 │ │ 10.0.11.0/24 │ │ 10.0.12.0/24 │ │
│ │ - ECS Tasks │ │ - ECS Tasks │ │ - ECS Tasks │ │
│ │ - Lambda │ │ - Lambda │ │ - Lambda │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │Database AZ-A │ │Database AZ-B │ │Database AZ-C │ │
│ │ 10.0.20.0/24 │ │ 10.0.21.0/24 │ │ 10.0.22.0/24 │ │
│ │ - RDS │ │ - RDS │ │ - RDS │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────────┘
Usage
inputs = {
vpc_name = "docustack-dev"
vpc_cidr = "10.0.0.0/16"
az_count = 2
database_az_count = 2
environment = "dev"
enable_flow_logs = true
enable_vpc_endpoints = true
vpc_endpoints = [
"s3", "dynamodb", "ecr.api", "ecr.dkr",
"logs", "secretsmanager", "ssm", "kms"
]
}
Environment Configurations
| Environment | AZ Count | NAT Gateways | CIDR Block |
|---|---|---|---|
| Dev | 2 | 1 | 10.0.0.0/16 |
| Staging | 2 | 1 | 10.10.0.0/16 |
| Prod | 3 | 3 | 10.20.0.0/16 |
Cost Optimization
- S3/DynamoDB Gateway Endpoints: Free
- Interface Endpoints: ~$7.20/month each
- NAT Gateway: ~$32/month + data transfer
ECS Cluster
Creates an Amazon ECS Fargate cluster with Spot capacity for cost-optimized container orchestration.
Why This Module?
ECS Fargate provides serverless container orchestration:
- No EC2 management - AWS handles the infrastructure
- Fargate Spot - Up to 70% cost savings
- Container Insights - Enhanced monitoring
- ECS Exec - Interactive debugging
Usage
inputs = {
cluster_name = "docustack-dev"
vpc_id = dependency.vpc.outputs.vpc_id
private_subnet_ids = dependency.vpc.outputs.private_subnet_ids
# Cost optimization: 100% Spot for dev
fargate_spot_weight = 100
fargate_ondemand_weight = 0
enable_container_insights = true
enable_execute_command = true
log_retention_days = 30
}
Capacity Provider Strategy
| Environment | Spot | On-Demand | Rationale |
|---|---|---|---|
| Dev | 100% | 0% | Maximum savings, interruptions acceptable |
| Staging | 80% | 20% | Balance of cost and reliability |
| Prod | 50% | 50% | Reliability prioritized |
ECS Exec for Debugging
# List running tasks
aws ecs list-tasks --cluster docustack-dev --service-name temporal-dev
# Start interactive session
aws ecs execute-command \
--cluster docustack-dev \
--task arn:aws:ecs:us-east-1:123456789012:task/docustack-dev/abc123 \
--container temporal \
--interactive \
--command "/bin/sh"
Cost Comparison
| Configuration | Monthly Cost (1 task, 1 vCPU, 2 GB) |
|---|---|
| 100% On-Demand | ~$30/month |
| 100% Spot | ~$9/month (70% savings) |
| 80% Spot, 20% On-Demand | ~$12/month (60% savings) |
ECR
Creates Amazon Elastic Container Registry repositories with lifecycle policies and encryption.
Why This Module?
ECR provides secure, scalable container image storage:
- Automatic cleanup via lifecycle policies
- Vulnerability scanning on push
- Encryption at rest with AES-256
- No Docker Hub rate limits
Usage
inputs = {
repositories = {
api = {
name = "docustack/api"
image_tag_mutability = "MUTABLE"
scan_on_push = true
force_delete = false
}
slack-bot = {
name = "docustack/slack-bot"
image_tag_mutability = "MUTABLE"
scan_on_push = true
force_delete = false
}
}
lifecycle_policy_max_images = 10
}
Tag Mutability
| Setting | Use Case | Security |
|---|---|---|
| MUTABLE | Development, latest tag | Lower |
| IMMUTABLE | Production, semantic versions | Higher |
Pushing Images
# Authenticate
aws ecr get-login-password --region us-east-1 | \
docker login --username AWS --password-stdin \
123456789012.dkr.ecr.us-east-1.amazonaws.com
# Build and push
docker build -t docustack/api:v1.0.0 .
docker tag docustack/api:v1.0.0 123456789012.dkr.ecr.us-east-1.amazonaws.com/docustack/api:v1.0.0
docker push 123456789012.dkr.ecr.us-east-1.amazonaws.com/docustack/api:v1.0.0
RDS
HIPAA-compliant PostgreSQL RDS instance with encryption, automated backups, and monitoring.
Why This Module?
RDS provides managed PostgreSQL with enterprise features:
- Encryption at rest and in transit (HIPAA required)
- Automated backups with point-in-time recovery
- Multi-AZ for high availability
- Performance Insights for query analysis
Architecture
┌─────────────────────────────────────────────────────────────┐
│ RDS Architecture │
├─────────────────────────────────────────────────────────────┤
│ Application (ECS/Lambda) │
│ │ │
│ │ PostgreSQL (port 5432, SSL/TLS) │
│ v │
│ ┌──────────────────────┐ ┌──────────────────┐ │
│ │ RDS PostgreSQL │◄────────│ Secrets Manager │ │
│ │ (Primary) │ │ (Credentials) │ │
│ │ - Encrypted (KMS) │ └──────────────────┘ │
│ │ - SSL enforced │ │
│ │ - Private subnet │ ┌──────────────────┐ │
│ └──────────┬───────────┘────────►│ CloudWatch Logs │ │
│ │ replication └──────────────────┘ │
│ v │
│ ┌──────────────────────┐ ┌──────────────────┐ │
│ │ RDS PostgreSQL │────────►│ Performance │ │
│ │ (Standby - Multi-AZ)│ │ Insights │ │
│ └──────────────────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────────┘
Usage
inputs = {
identifier = "docustack-dev-postgres"
environment = "dev"
engine = "postgres"
engine_version = "15.4"
instance_class = "db.t3.medium"
allocated_storage = 20
max_allocated_storage = 100
vpc_id = dependency.vpc.outputs.vpc_id
subnet_ids = dependency.vpc.outputs.database_subnet_ids
multi_az = true
backup_retention_period = 35
deletion_protection = true
performance_insights_enabled = true
monitoring_interval = 60
}
Environment Configurations
| Setting | Dev | Staging | Prod |
|---|---|---|---|
| Instance Class | db.t3.small | db.t3.medium | db.r5.large |
| Multi-AZ | No | Yes | Yes |
| Backup Retention | 7 days | 14 days | 35 days |
| Deletion Protection | No | Yes | Yes |
| Storage | 20 GB | 50 GB | 100 GB |
Retrieving Credentials
# Get secret ARN from Terraform output
SECRET_ARN=$(terragrunt output -raw secret_arn)
# Retrieve credentials
aws secretsmanager get-secret-value \
--secret-id $SECRET_ARN \
--query SecretString \
--output text | jq
Connecting via Bastion
# Create bastion
/bastion create dev
# Port forward to RDS
aws ssm start-session \
--target $INSTANCE_ID \
--document-name AWS-StartPortForwardingSessionToRemoteHost \
--parameters '{"host":["your-rds-endpoint.rds.amazonaws.com"],"portNumber":["5432"],"localPortNumber":["5432"]}'
# Connect locally
psql -h localhost -p 5432 -U postgres -d postgres
HIPAA Compliance
| Control | Implementation |
|---|---|
| §164.312(a)(2)(iv) Encryption at rest | KMS encryption |
| §164.312(e)(2)(ii) Encryption in transit | SSL/TLS enforced |
| §164.312(b) Audit controls | Performance Insights, CloudWatch Logs |
| §164.308(a)(7)(ii)(A) Data backup | 35-day automated backups |