Documentation Index Fetch the complete documentation index at: https://mcp-server-langgraph.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
AWS Backend Setup
Configure S3 bucket and DynamoDB table for Terraform remote state management with encryption, versioning, and state locking.
Overview
Terraform backend stores infrastructure state in S3 with DynamoDB for state locking, preventing concurrent modifications.
Benefits
Team collaboration : Shared state across team members
State locking : Prevents concurrent modifications
Version history : S3 versioning for rollback capability
Encryption : KMS encryption for sensitive data
Audit trail : Access logging for compliance
Architecture
Quick Setup
Navigate to backend setup
cd terraform/backend-setup
Create terraform.tfvars
project_name = "mcp-langgraph"
environment = "prod"
region = "us-east-1"
Initialize and deploy
terraform init
terraform plan
terraform apply
Creates :
S3 bucket: mcp-langgraph-terraform-state-prod
DynamoDB table: mcp-langgraph-terraform-lock-prod
KMS key for encryption
S3 bucket for access logs
Note the outputs
Save these values for backend configuration:
state_bucket_name
lock_table_name
Backend Configuration
For Environment Deployments
# terraform/environments/prod/main.tf
terraform {
backend "s3" {
bucket = "mcp-langgraph-terraform-state-prod"
key = "prod/terraform.tfstate"
region = "us-east-1"
dynamodb_table = "mcp-langgraph-terraform-lock-prod"
encrypt = true
}
}
Initialize Backend
cd terraform/environments/prod
terraform init
# You'll see:
# Initializing the backend...
# Successfully configured the backend "s3"!
Features
S3 State Bucket
Versioning
Encryption
Access Logging
Lifecycle
Enabled for rollback capability# List all versions
aws s3api list-object-versions \
--bucket mcp-langgraph-terraform-state-prod \
--prefix prod/terraform.tfstate
# Restore previous version if needed
aws s3api copy-object \
--bucket mcp-langgraph-terraform-state-prod \
--copy-source mcp-langgraph-terraform-state-prod/prod/terraform.tfstate?versionId=VERSION_ID \
--key prod/terraform.tfstate
KMS encryption at restresource "aws_s3_bucket_server_side_encryption_configuration" "state" {
bucket = aws_s3_bucket . terraform_state . id
rule {
apply_server_side_encryption_by_default {
kms_master_key_id = aws_kms_key . terraform_state . arn
sse_algorithm = "aws:kms"
}
}
}
All access logged to separate bucket# View access logs
aws s3 ls s3://mcp-langgraph-terraform-logs-prod/
Old versions deleted after 90 daysresource "aws_s3_bucket_lifecycle_configuration" "state" {
bucket = aws_s3_bucket . terraform_state . id
rule {
id = "delete-old-versions"
status = "Enabled"
noncurrent_version_expiration {
days = 90
}
}
}
DynamoDB Lock Table
State Locking
On-Demand Billing
Prevents concurrent Terraform runs # Check for active locks
aws dynamodb scan \
--table-name mcp-langgraph-terraform-lock-prod \
--query "Items[].LockID.S"
# Should be empty when no terraform running
Pay per request (no capacity planning)resource "aws_dynamodb_table" "terraform_lock" {
name = " ${ var . project_name } -terraform-lock- ${ var . environment } "
billing_mode = "PAY_PER_REQUEST"
hash_key = "LockID"
attribute {
name = "LockID"
type = "S"
}
}
Cost : ~$0.01/month (minimal usage)
Multiple Environments
Separate State Per Environment
# Production
terraform {
backend "s3" {
bucket = "mcp-langgraph-terraform-state-prod"
key = "prod/terraform.tfstate"
# ...
}
}
# Staging
terraform {
backend "s3" {
bucket = "mcp-langgraph-terraform-state-staging"
key = "staging/terraform.tfstate"
# ...
}
}
# Development
terraform {
backend "s3" {
bucket = "mcp-langgraph-terraform-state-dev"
key = "dev/terraform.tfstate"
# ...
}
}
Same Bucket, Different Keys
terraform {
backend "s3" {
bucket = "mcp-langgraph-terraform-state"
key = "${ environment }/terraform.tfstate" # Variable not allowed here
# Must hardcode environment name in each environment's config
}
}
Security Best Practices
Restrict access to authorized users only {
"Version" : "2012-10-17" ,
"Statement" : [
{
"Effect" : "Allow" ,
"Principal" : {
"AWS" : [
"arn:aws:iam::123456789012:user/terraform-admin" ,
"arn:aws:iam::123456789012:role/github-actions"
]
},
"Action" : [
"s3:GetObject" ,
"s3:PutObject" ,
"s3:DeleteObject"
],
"Resource" : "arn:aws:s3:::mcp-langgraph-terraform-state-prod/*"
}
]
}
Minimal permissions for state locking {
"Version" : "2012-10-17" ,
"Statement" : [
{
"Effect" : "Allow" ,
"Action" : [
"dynamodb:PutItem" ,
"dynamodb:GetItem" ,
"dynamodb:DeleteItem"
],
"Resource" : "arn:aws:dynamodb:us-east-1:123456789012:table/mcp-langgraph-terraform-lock-prod"
}
]
}
Require MFA to delete state versions # Enable MFA delete (requires root account)
aws s3api put-bucket-versioning \
--bucket mcp-langgraph-terraform-state-prod \
--versioning-configuration Status=Enabled,MFADelete=Enabled \
--mfa "arn:aws:iam::123456789012:mfa/root-account-mfa-device XXXXXX"
Disaster Recovery
State Backup
Manual backup
# Download current state
aws s3 cp s3://mcp-langgraph-terraform-state-prod/prod/terraform.tfstate \
./terraform.tfstate.backup- $( date +%Y%m%d )
Cross-region replication
resource "aws_s3_bucket_replication_configuration" "state" {
bucket = aws_s3_bucket . terraform_state . id
role = aws_iam_role . replication . arn
rule {
id = "replicate-state"
status = "Enabled"
destination {
bucket = aws_s3_bucket . terraform_state_replica . arn
storage_class = "STANDARD_IA"
encryption_configuration {
replica_kms_key_id = aws_kms_key . replica . arn
}
}
}
}
State Recovery
List versions
aws s3api list-object-versions \
--bucket mcp-langgraph-terraform-state-prod \
--prefix prod/terraform.tfstate \
--query 'Versions[].[VersionId,LastModified,IsLatest]' \
--output table
Restore specific version
# Download specific version
aws s3api get-object \
--bucket mcp-langgraph-terraform-state-prod \
--key prod/terraform.tfstate \
--version-id VERSION_ID \
terraform.tfstate.restored
# Upload as current version
aws s3 cp terraform.tfstate.restored \
s3://mcp-langgraph-terraform-state-prod/prod/terraform.tfstate
Verify state
cd terraform/environments/prod
terraform init
terraform plan # Should show no changes if restored correctly
Troubleshooting
Error: Failed to get existing workspaces
Cause : S3 bucket doesn’t exist or no accessSolution :# Verify bucket exists
aws s3 ls s3://mcp-langgraph-terraform-state-prod
# Check IAM permissions
aws iam get-user
aws iam list-user-policies --user-name YOUR_USER
Error: Error acquiring the state lock
Cause : Previous Terraform run didn’t release lock (e.g., Ctrl+C during apply)Solution :# Check for stuck lock
aws dynamodb scan \
--table-name mcp-langgraph-terraform-lock-prod
# Force unlock (use with caution!)
terraform force-unlock LOCK_ID
Error: NoSuchBucket: The specified bucket does not exist
Cause : Backend not created yetSolution :# Run backend setup first
cd terraform/backend-setup
terraform init
terraform apply
Cost
Component Monthly Cost Notes S3 Storage ~$0.02 ~1 MB state file S3 Requests ~$0.01 Minimal GET/PUT DynamoDB ~$0.01 Pay-per-request KMS $1.00 First 20K requests/month free Total ~$1.04/month Negligible cost
Terraform AWS AWS infrastructure modules
EKS Production Production deployment guide
GCP Backend GCP backend setup (GCS + Cloud Storage)