Skip to main content

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

EnvironmentAZ CountNAT GatewaysCIDR Block
Dev2110.0.0.0/16
Staging2110.10.0.0/16
Prod3310.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

EnvironmentSpotOn-DemandRationale
Dev100%0%Maximum savings, interruptions acceptable
Staging80%20%Balance of cost and reliability
Prod50%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

ConfigurationMonthly 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

SettingUse CaseSecurity
MUTABLEDevelopment, latest tagLower
IMMUTABLEProduction, semantic versionsHigher

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

SettingDevStagingProd
Instance Classdb.t3.smalldb.t3.mediumdb.r5.large
Multi-AZNoYesYes
Backup Retention7 days14 days35 days
Deletion ProtectionNoYesYes
Storage20 GB50 GB100 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

ControlImplementation
§164.312(a)(2)(iv) Encryption at restKMS encryption
§164.312(e)(2)(ii) Encryption in transitSSL/TLS enforced
§164.312(b) Audit controlsPerformance Insights, CloudWatch Logs
§164.308(a)(7)(ii)(A) Data backup35-day automated backups