|
| 1 | +# Terraform Deployment Guide |
| 2 | + |
| 3 | +This guide walks you through deploying the Fullstack AgentCore Solution Template (FAST) to AWS using Terraform. |
| 4 | + |
| 5 | +> **CDK alternative:** This guide covers Terraform deployment. FAST also supports AWS CDK -- see [Deployment Guide](DEPLOYMENT.md) for the CDK deployment guide. We recommend choosing one infrastructure tool and deleting the other directory (`infra-cdk/` or `infra-terraform/`) from your fork to keep things clean. |
| 6 | +
|
| 7 | +## Prerequisites |
| 8 | + |
| 9 | +Before deploying, ensure you have: |
| 10 | + |
| 11 | +- **Terraform** >= 1.5.0 (see [Install Terraform](https://developer.hashicorp.com/terraform/install)) |
| 12 | +- **AWS CLI** configured with credentials (`aws configure`) - see [AWS CLI Configuration guide](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html) |
| 13 | +- **Python 3.11+** (for the frontend deployment script) |
| 14 | +- **Docker** (only required for `backend_deployment_type = "docker"`) - see [Install Docker Engine](https://docs.docker.com/engine/install/). Verify with `docker ps`. Alternatively, [Finch](https://github.com/runfinch/finch) can be used on Mac. See [below](#docker-cross-platform-build-setup-required-for-non-arm-machines) if you have a non-ARM machine. |
| 15 | +- An AWS account with sufficient permissions to create: |
| 16 | + - S3 buckets |
| 17 | + - Cognito User Pools |
| 18 | + - Amplify Hosting projects |
| 19 | + - Bedrock AgentCore resources |
| 20 | + - IAM roles and policies |
| 21 | + |
| 22 | +## Configuration |
| 23 | + |
| 24 | +### 1. Create Configuration File |
| 25 | + |
| 26 | +```bash |
| 27 | +cd infra-terraform |
| 28 | +cp terraform.tfvars.example terraform.tfvars |
| 29 | +``` |
| 30 | + |
| 31 | +Edit `terraform.tfvars` to customize your deployment: |
| 32 | + |
| 33 | +```hcl |
| 34 | +stack_name_base = "your-project-name" # Base name for all resources (max 35 chars) |
| 35 | +
|
| 36 | +admin_user_email = "admin@example.com" # Optional: auto-creates user & emails credentials |
| 37 | +``` |
| 38 | + |
| 39 | +**Important**: |
| 40 | +- Change `stack_name_base` to a unique name for your project to avoid conflicts |
| 41 | +- Maximum length is 35 characters (due to AWS AgentCore runtime naming constraints) |
| 42 | + |
| 43 | +#### Required Variables |
| 44 | + |
| 45 | +| Variable | Description | |
| 46 | +|----------|-------------| |
| 47 | +| `stack_name_base` | Base name for all resources | |
| 48 | + |
| 49 | +#### Optional Variables |
| 50 | + |
| 51 | +| Variable | Description | Default | |
| 52 | +|----------|-------------|---------| |
| 53 | +| `admin_user_email` | Email for Cognito admin user | `null` | |
| 54 | +| `backend_pattern` | Agent pattern to deploy | `"strands-single-agent"` | |
| 55 | +| `backend_deployment_type` | `"docker"` (ECR container) or `"zip"` (S3 package) | `"docker"` | |
| 56 | +| `backend_network_mode` | Network mode (PUBLIC/VPC) | `"PUBLIC"` | |
| 57 | +| `backend_vpc_id` | VPC ID (required when VPC mode) | `null` | |
| 58 | +| `backend_vpc_subnet_ids` | Subnet IDs (required when VPC mode) | `[]` | |
| 59 | +| `backend_vpc_security_group_ids` | Security group IDs (optional for VPC mode) | `[]` | |
| 60 | + |
| 61 | +**Region:** Set via the `AWS_REGION` environment variable or AWS CLI profile (`aws configure`). The Terraform provider uses the standard AWS SDK resolution chain -- no region variable is needed. |
| 62 | + |
| 63 | +**Tags:** The provider applies default tags (Project, ManagedBy, Repository) to all resources automatically. Add custom tags directly in the provider's `default_tags` block in `main.tf`. |
| 64 | + |
| 65 | +### Deployment Types |
| 66 | + |
| 67 | +Set `backend_deployment_type` in `terraform.tfvars` to `"docker"` (default) or `"zip"`. See [Deployment Types](DEPLOYMENT.md#deployment-types) in the main Deployment Guide for guidance on choosing between them. |
| 68 | + |
| 69 | +**Terraform-specific notes:** |
| 70 | +- ZIP mode does not require Docker installed locally (unlike CDK, where Docker is always needed) |
| 71 | +- **ZIP packaging includes**: The `patterns/<your-pattern>/`, `patterns/utils/`, and `tools/` directories are bundled together with dependencies from `requirements.txt` |
| 72 | + |
| 73 | +### Deployment into existing VPC |
| 74 | + |
| 75 | +By default, the AgentCore Runtime runs in PUBLIC network mode with internet access. To deploy the runtime into an existing VPC for private network isolation, set `backend_network_mode = "VPC"` and provide your VPC details: |
| 76 | + |
| 77 | +```hcl |
| 78 | +backend_network_mode = "VPC" |
| 79 | +backend_vpc_id = "vpc-0abc1234def56789a" |
| 80 | +backend_vpc_subnet_ids = ["subnet-aaaa1111bbbb2222c", "subnet-cccc3333dddd4444e"] |
| 81 | +backend_vpc_security_group_ids = ["sg-0abc1234def56789a"] # Optional |
| 82 | +``` |
| 83 | + |
| 84 | +The `backend_vpc_id` and `backend_vpc_subnet_ids` fields are required when using VPC mode. The `backend_vpc_security_group_ids` field is optional -- if omitted, a default security group is created with HTTPS (TCP 443) self-referencing ingress and all-traffic egress. |
| 85 | + |
| 86 | +For detailed VPC prerequisites -- including required VPC endpoints, subnet requirements, NAT Gateway guidance, and security group configuration -- see [VPC Deployment](DEPLOYMENT.md#vpc-deployment-private-network) in the main Deployment Guide. |
| 87 | + |
| 88 | +**Important:** AgentCore Runtime availability is limited to specific Availability Zones per region. Verify your subnets are in supported AZs before deploying. See [AWS documentation on supported Availability Zones](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/agentcore-vpc.html#agentcore-supported-azs) for details. |
| 89 | + |
| 90 | +## Deployment Steps |
| 91 | + |
| 92 | +### TL;DR |
| 93 | +```bash |
| 94 | +cd infra-terraform |
| 95 | +cp terraform.tfvars.example terraform.tfvars |
| 96 | +# Edit terraform.tfvars with your configuration |
| 97 | +terraform init |
| 98 | +terraform apply |
| 99 | +python scripts/deploy-frontend.py |
| 100 | +``` |
| 101 | + |
| 102 | +### 1. Initialize Terraform |
| 103 | + |
| 104 | +```bash |
| 105 | +cd infra-terraform |
| 106 | +terraform init |
| 107 | +``` |
| 108 | + |
| 109 | +### 2. Deploy Infrastructure |
| 110 | + |
| 111 | +Build and deploy the complete stack: |
| 112 | + |
| 113 | +```bash |
| 114 | +terraform apply |
| 115 | +``` |
| 116 | + |
| 117 | +The deployment will: |
| 118 | + |
| 119 | +1. Create Amplify Hosting app and S3 staging bucket |
| 120 | +1. Create a Cognito User Pool with web and machine clients |
| 121 | +1. Create AgentCore Memory for persistent conversations |
| 122 | +1. Set up OAuth2 Credential Provider for Runtime-to-Gateway authentication |
| 123 | +1. Create AgentCore Gateway with Lambda tool targets |
| 124 | +1. Build and deploy the AgentCore Runtime (Docker image or ZIP package) |
| 125 | +1. Create the Feedback API (API Gateway + Lambda + DynamoDB) |
| 126 | +1. Store configuration in SSM Parameters |
| 127 | + |
| 128 | +- **Docker mode** (default): Automatically builds an ARM64 Docker image, pushes to ECR, and creates the runtime. Requires Docker to be running locally. |
| 129 | +- **Zip mode**: Deploys a packager Lambda that bundles your agent code with ARM64 wheels, uploads to S3, and creates the runtime. No Docker required. |
| 130 | + |
| 131 | +> **Note:** If you provide a pre-built image via `container_uri`, Terraform skips the build and uses your image directly. |
| 132 | +
|
| 133 | +### 3. Deploy Frontend |
| 134 | + |
| 135 | +```bash |
| 136 | +# From infra-terraform directory |
| 137 | +python scripts/deploy-frontend.py |
| 138 | +``` |
| 139 | + |
| 140 | +This script automatically: |
| 141 | + |
| 142 | +- Generates fresh `aws-exports.json` from Terraform outputs (see [below](#understanding-aws-exportsjson) for more information) |
| 143 | +- Installs/updates npm dependencies if needed |
| 144 | +- Builds the frontend |
| 145 | +- Deploys to AWS Amplify Hosting |
| 146 | + |
| 147 | +You will see the URL for the application in the script's output, which will look similar to this: |
| 148 | + |
| 149 | +``` |
| 150 | +App URL: https://main.d123abc456def7.amplifyapp.com |
| 151 | +``` |
| 152 | + |
| 153 | +A shell alternative is also available for macOS/Linux: |
| 154 | +```bash |
| 155 | +./scripts/deploy-frontend.sh |
| 156 | +``` |
| 157 | + |
| 158 | +### 4. Create a Cognito User (if necessary) |
| 159 | + |
| 160 | +**If you provided `admin_user_email` in config:** |
| 161 | + |
| 162 | +- Check your email for temporary password |
| 163 | +- Sign in and change password on first login |
| 164 | + |
| 165 | +**If you didn't provide email:** |
| 166 | + |
| 167 | +1. Go to the [AWS Cognito Console](https://console.aws.amazon.com/cognito/) |
| 168 | +2. Find your User Pool (named `{stack_name_base}-user-pool`) |
| 169 | +3. Click on the User Pool |
| 170 | +4. Go to "Users" tab |
| 171 | +5. Click "Create user" |
| 172 | +6. Fill in the user details: |
| 173 | + - **Email**: Your email address |
| 174 | + - **Temporary password**: Create a temporary password |
| 175 | + - **Mark email as verified**: Check this box |
| 176 | +7. Click "Create user" |
| 177 | + |
| 178 | +### 5. Access the Application |
| 179 | + |
| 180 | +1. Open the Amplify Hosting URL in your browser |
| 181 | +1. Sign in with the Cognito user you created |
| 182 | +1. You'll be prompted to change your temporary password on first login |
| 183 | + |
| 184 | +## Post-Deployment |
| 185 | + |
| 186 | +### Updating the Application |
| 187 | + |
| 188 | +To update the frontend code: |
| 189 | + |
| 190 | +```bash |
| 191 | +# From infra-terraform directory |
| 192 | +python scripts/deploy-frontend.py |
| 193 | +``` |
| 194 | + |
| 195 | +To update the backend agent: |
| 196 | + |
| 197 | +```bash |
| 198 | +cd infra-terraform |
| 199 | +terraform apply |
| 200 | +``` |
| 201 | + |
| 202 | +Terraform detects code changes automatically and rebuilds/redeploys the runtime. After a backend update that replaces the runtime, redeploy the frontend to pick up the new Runtime ARN: |
| 203 | + |
| 204 | +```bash |
| 205 | +python scripts/deploy-frontend.py |
| 206 | +``` |
| 207 | + |
| 208 | +#### Manual Docker Build (Optional) |
| 209 | + |
| 210 | +If you prefer to build the Docker image separately (e.g., in CI/CD): |
| 211 | +```bash |
| 212 | +./scripts/build-and-push-image.sh |
| 213 | +``` |
| 214 | + |
| 215 | +**Options:** |
| 216 | +```bash |
| 217 | +./scripts/build-and-push-image.sh -h # Show help |
| 218 | +./scripts/build-and-push-image.sh -p langgraph-single-agent # Use LangGraph pattern |
| 219 | +./scripts/build-and-push-image.sh -s my-stack -r us-west-2 # Override stack/region |
| 220 | +``` |
| 221 | + |
| 222 | +### Verify Deployment |
| 223 | + |
| 224 | +```bash |
| 225 | +# Get deployment summary |
| 226 | +terraform output deployment_summary |
| 227 | + |
| 228 | +# Get all outputs |
| 229 | +terraform output |
| 230 | +``` |
| 231 | + |
| 232 | +### Test the Agent (Optional) |
| 233 | + |
| 234 | +```bash |
| 235 | +# From infra-terraform directory |
| 236 | +pip install boto3 requests colorama # First time only |
| 237 | +python scripts/test-agent.py 'Hello, what can you do?' |
| 238 | +``` |
| 239 | + |
| 240 | +### Monitoring and Logs |
| 241 | + |
| 242 | +- **Frontend logs**: Check Amplify build logs in the AWS Console |
| 243 | +- **Backend logs**: Check CloudWatch logs for the AgentCore runtime |
| 244 | +- **Feedback API logs**: Check CloudWatch logs for the feedback Lambda |
| 245 | + |
| 246 | +## Cleanup |
| 247 | + |
| 248 | +To remove all resources: |
| 249 | + |
| 250 | +```bash |
| 251 | +cd infra-terraform |
| 252 | +terraform destroy |
| 253 | +``` |
| 254 | + |
| 255 | +Terraform handles resource dependencies automatically and destroys in the correct order. |
| 256 | + |
| 257 | +**Warning**: This will delete all data including Cognito users, S3 buckets, DynamoDB tables, and ECR images. |
| 258 | + |
| 259 | +### Verify Cleanup |
| 260 | + |
| 261 | +After destroy completes, verify no resources remain: |
| 262 | +```bash |
| 263 | +aws resourcegroupstaggingapi get-resources --tag-filters Key=Project,Values=<your-stack-name> |
| 264 | +``` |
| 265 | + |
| 266 | +## Troubleshooting |
| 267 | + |
| 268 | +### Common Issues |
| 269 | + |
| 270 | +1. **`terraform apply` fails with Docker errors** |
| 271 | + |
| 272 | + - Ensure Docker is installed and the daemon is running: `docker ps` |
| 273 | + - On Mac, open Docker Desktop or start Finch: `finch vm start` |
| 274 | + - On Linux: `sudo systemctl start docker` |
| 275 | + - If using `backend_deployment_type = "zip"`, Docker is not required |
| 276 | + |
| 277 | +2. **"Architecture incompatible" or "exec format error" during Docker build** |
| 278 | + |
| 279 | + - This occurs when deploying from a non-ARM machine without cross-platform build setup |
| 280 | + - Follow the [Docker Cross-Platform Build Setup](#docker-cross-platform-build-setup-required-for-non-arm-machines) instructions below |
| 281 | + - Ensure you've installed QEMU emulation: `docker run --privileged --rm tonistiigi/binfmt --install all` |
| 282 | + - Verify ARM64 support: `docker buildx ls` should show `linux/arm64` in platforms |
| 283 | + |
| 284 | +3. **Terraform Init Fails** |
| 285 | + |
| 286 | + Ensure you have the correct provider versions: |
| 287 | + ```bash |
| 288 | + terraform init -upgrade |
| 289 | + ``` |
| 290 | + |
| 291 | +4. **Authentication errors** |
| 292 | + |
| 293 | + Verify AWS credentials: |
| 294 | + ```bash |
| 295 | + aws sts get-caller-identity |
| 296 | + ``` |
| 297 | + |
| 298 | + Also verify you created a Cognito user and that the user's email is verified. |
| 299 | + |
| 300 | +5. **"Agent Runtime ARN not configured" or 404 errors** |
| 301 | + |
| 302 | + - Ensure the backend deployed successfully |
| 303 | + - Redeploy the frontend to pick up the latest Runtime ARN: |
| 304 | + ```bash |
| 305 | + python scripts/deploy-frontend.py |
| 306 | + ``` |
| 307 | + - Verify SSM parameters match Terraform outputs: |
| 308 | + ```bash |
| 309 | + terraform output runtime_arn |
| 310 | + ``` |
| 311 | + |
| 312 | +6. **Permission errors** |
| 313 | + - Verify your AWS credentials have sufficient permissions |
| 314 | + - Check IAM roles created by the stack |
| 315 | + |
| 316 | +### Getting Help |
| 317 | + |
| 318 | +- Check CloudWatch logs for detailed error messages |
| 319 | +- Review `terraform output` for resource identifiers |
| 320 | +- Ensure all prerequisites are met |
| 321 | + |
| 322 | +## Security Considerations |
| 323 | + |
| 324 | +See [Security Considerations](DEPLOYMENT.md#security-considerations) in the main Deployment Guide. Additionally, consider deploying in [VPC mode](#deployment-into-existing-vpc) for network isolation. |
| 325 | + |
| 326 | +## Docker Cross-Platform Build Setup (Required for non-ARM machines) |
| 327 | + |
| 328 | +Bedrock AgentCore Runtime only supports ARM64 architecture. If you're deploying from a non-ARM machine (x86_64/amd64), you need to enable Docker's cross-platform building capabilities. See [Docker Cross-Platform Build Setup](DEPLOYMENT.md#docker-cross-platform-build-setup-required-for-non-arm-machines) in the main Deployment Guide for setup instructions. |
| 329 | + |
| 330 | + |
| 331 | +## Understanding aws-exports.json |
| 332 | + |
| 333 | +The `aws-exports.json` file provides the frontend with Cognito authentication configuration. See [Understanding aws-exports.json](DEPLOYMENT.md#understanding-aws-exports-json) in the main Deployment Guide for details on its purpose and structure. |
| 334 | + |
| 335 | +For Terraform deployments, the file is generated by `deploy-frontend.py` which fetches configuration from `terraform output -json` (rather than CDK stack outputs). You should not manually edit this file as it's regenerated on each deployment. |
0 commit comments