AI Initiative logoAI Initiative
Reading room / Manthan

Manthan AWS — Terraform (D-002)

Manthan AWS — Terraform (D-002). Covers What this stack creates; First-apply workflow; 0. Pre-req on your host: AWS creds with admin or comparable IAM; 1. One-shot bootstrap stack — creates the S3+DynamoDB used for remote state.

Deployment / operations method; execution not repeated
This is the retained source text, not a new validation of its claims. Numerical results and comparative claims require the accompanying source review before public reuse.

Read the connected case study or article →

Not explicitly stated in source · Date not established

Provenance, authorship and editorial notes

Manthan AWS — Terraform (D-002)

Id

manthan-infra-terraform-readme

Project

Manthan

Source path

manthan/infra/terraform/README.md

Source sha256

34d83dc2ca81496d472054e787973680a41baa473a8d17785023864b906a5552

Local copy sha256

34d83dc2ca81496d472054e787973680a41baa473a8d17785023864b906a5552

Repo head

3a94084024a3434cef331fecac91c2c3b43f0313

Date
Not recorded
Date basis

Original publication date not established; Git revision date retained separately.

Author

Not explicitly stated in source

Author basis

Unknown; Git committer not substituted for document author.

Last source commit

8b75d1b0157c20a0a463f0e31008ef9f73099beb

Last source commit date

2026-06-08T07:40:14Z

Document status

Deployment / operations method; execution not repeated

Summary

Manthan AWS — Terraform (D-002). Covers What this stack creates; First-apply workflow; 0. Pre-req on your host: AWS creds with admin or comparable IAM; 1. One-shot bootstrap stack — creates the S3+DynamoDB used for remote state.

Topics
  • Operating the system
  • What this stack creates
  • First-apply workflow
  • 0. Pre-req on your host: AWS creds with admin or comparable IAM
Theme

Operating the system

Priority

reference

Related ids

No entries recorded.

Evidence concerns
  • Recovered source text is preserved verbatim. Assertions, comparisons, commands and results belong to its original context; they were not re-executed or externally re-verified during this corpus review.
Word count

951

Bytes

7165

Source relative

infra/terraform/README.md

Remote mirror

manthan/infra/terraform/README.md

Full text preserved

True

Manthan AWS — Terraform (D-002)

Infrastructure-as-code for the Manthan testnet/production deployment.

What this stack creates

First-apply workflow

# 0. Pre-req on your host: AWS creds with admin or comparable IAM
aws sts get-caller-identity

# 1. One-shot bootstrap stack — creates the S3+DynamoDB used for remote state
cd infra/terraform/bootstrap
terraform init
terraform apply -var aws_region=eu-west-2
# Note the backend_config_snippet output. Paste it into ../backend.tf.

# 2. Main stack (after un-commenting backend.tf with the bootstrap output)
cd ..
terraform init -reconfigure
cp envs/testnet.tfvars envs/testnet.local.tfvars
$EDITOR envs/testnet.local.tfvars   # set domain_name + route53_zone_id

# 3. ECR-only first to get a repo URL we can push the D-001 image to
terraform plan  -var-file=envs/testnet.local.tfvars -out=plan.bin
terraform apply -target=module.storage.aws_ecr_repository.node \
                -var-file=envs/testnet.local.tfvars
ECR_URL=$(terraform output -raw ecr_repository_url)

# 4. Push the D-001 image (run on the host where the image was built)
aws ecr get-login-password --region eu-west-2 \
  | docker login --username AWS --password-stdin "${ECR_URL%%/*}"
docker tag manthan-testnet-node:0.2.0 "$ECR_URL:0.2.0"
docker push "$ECR_URL:0.2.0"

# 5. Full apply
terraform apply -var-file=envs/testnet.local.tfvars

Layout

infra/terraform/
├── README.md
├── versions.tf         # provider version pins
├── backend.tf          # remote state (uncomment after bootstrap)
├── providers.tf        # primary + dr-region providers, default tags
├── variables.tf        # input vars (region, domain, node_names, sizing, …)
├── locals.tf           # AZ slicing, hostname maps
├── main.tf             # ECS cluster + module wiring
├── outputs.tf          # ALB DNS, ECR URL, secret ARNs, KMS ARN, …
├── bootstrap/          # one-shot tfstate bucket + lock table
│   └── main.tf
├── envs/
│   ├── testnet.tfvars
│   └── production.tfvars
└── modules/
    ├── network/        # VPC, ALB, ACM, security groups
    ├── storage/        # KMS, EFS+access points, S3, ECR, Secrets Manager
    ├── node/           # per-node ECS service, target groups, listener rules
    └── observability/  # baseline CloudWatch alarms (D-004 extends this)

Per-node hostnames

Each node is reachable on two hostnames behind the same ALB:

HostnamePortPurpose
<node>.<domain>443HTTPS HTTP API (/healthz, /charter, /metrics, /sth, /entries, /canary)
<node>-mwp.<domain>443WSS MWP gossip endpoint

The container itself listens on plaintext 0.0.0.0:9120 (HTTP) and 0.0.0.0:9220 (WS). ALB terminates TLS at the edge and forwards over the VPC SG-private path.

D-004 — populating webhook secrets

After the first apply, three Secrets Manager entries exist with placeholder
values (so the alertmanager_definition has something to render). Populate
them with the real PagerDuty integration key, MS Teams webhook URL, and
Slack webhook URL:

PD_ARN=$(terraform output -json alertmanager_secret_arns | jq -r .pagerduty)
TEAMS_ARN=$(terraform output -json alertmanager_secret_arns | jq -r .teams)
SLACK_ARN=$(terraform output -json alertmanager_secret_arns | jq -r .slack)

aws secretsmanager update-secret --secret-id "$PD_ARN"    --secret-string "<your-pagerduty-events-api-v2-integration-key>"
aws secretsmanager update-secret --secret-id "$TEAMS_ARN" --secret-string "<your-teams-webhook-url>"
aws secretsmanager update-secret --secret-id "$SLACK_ARN" --secret-string "<your-slack-webhook-url>"

# Re-render the alertmanager definition with the new values:
terraform apply -var-file=envs/testnet.local.tfvars \
  -replace=module.observability.aws_prometheus_alert_manager_definition.this[0]

For Teams the URL can point at either:

accept Alertmanager's native JSON shape), or

Both are just opaque webhook URLs to Alertmanager; pick whichever format
matches your tested setup.

Routing baked into the alertmanager definition:

SeverityPagerDutyTeamsSlack
SEV-1✓——
SEV-2✓✓✓
SEV-3—✓✓

Toggle individual receivers on/off via enable_pagerduty, enable_teams,
enable_slack in tfvars.

Notes & gotchas

Continue exploring