---
cuppy_hub: aws
cuppy_path: guides/cdk/bootstrap-and-deploy.md
cuppy_section: docs
cuppy_doc: 05CR-4AGQ
cuppy_doc_uuid: e92132d8-45d2-4004-9a4b-40f4920bd5b3
cuppy_permalink: https://cuppy.io/aws/d/05CR-4AGQ
cuppy_version: 4
cuppy_updated: 2026-10-23T16:16:52.575Z
cuppy_canonical: https://cuppy.io/aws/docs/guides/cdk/bootstrap-and-deploy
cuppy_mcp: https://cuppy.io/mcp
cuppy_body_sha256: 7f3914897965b6768759394cd635af28dc706e8cea6571d80684b74fc4e957ee
# cuppy_body_sha256 is over the document body ALONE, excluding both generated blocks.
---


# Bootstrap an environment and deploy with the CDK

**Bootstrap every account and Region once, with termination protection and an execution policy you chose. Then deploy with change sets and rollback on.** The bootstrap's default execution role has `AdministratorAccess`. So unless you scope it, anyone who can assume the deploy role can create anything through CloudFormation.

## 1. Bootstrap

Use an identity with broad rights (`cloudformation:*`, `ecr:*`, `ssm:*`, `s3:*`, `iam:*`):

```
cdk bootstrap aws://<account-id>/<region> \
  --termination-protection \
  --cloudformation-execution-policies "arn:aws:iam::<account-id>:policy/CdkExecution"
```

- **Execution policies** go on the role CloudFormation uses, so they must cover **everything every CDK app in this environment creates**: Lambda, IAM roles, S3 and the rest. Otherwise deployments fail with access denied on a resource (`reference/cloudformation/errors.md`). Leaving the option out means `AdministratorAccess`. For a guardrail that still allows broad creation, add `--custom-permissions-boundary <policy-name>`.
- Each environment needs its own bootstrap, and the CDK never does it automatically. Bootstrapping early also reserves the staging bucket name.
- Bootstrapping **again** is safe and upgrades the template when needed. Re-run it after CLI upgrades when a deploy asks for a newer bootstrap version. Previous option values carry over unless you pass `--no-previous-parameters`.
- Never delete `CDKToolkit` to "reset" it.
- The resources and roles created are listed in `reference/cdk/bootstrap-roles-and-trust.md`.

## 2. Trust another account (CI, tools or pipeline account)

In the **target** account:

```
cdk bootstrap aws://<target-account>/<region> \
  --trust <tools-account> --trust <other-existing-trusted-account> \
  --cloudformation-execution-policies "arn:aws:iam::<target-account>:policy/CdkExecution"
```

- `--trust` **replaces** the trusted list, so repeat every account you already trust.
- `--trust` **requires** `--cloudformation-execution-policies`: the CLI won't silently grant administrator to another account.
- Accounts that only need to **synth** (context lookups) get `--trust-for-lookup` instead.
- In the **tools** account, the deploying identity needs an IAM Allow for `sts:AssumeRole` on `arn:aws:iam::<target-account>:role/cdk-hnb659fds-*`. Both halves are required (`guides/iam/cross-account-access.md`).

## 3. Deploy

```
npx aws-cdk deploy --all --require-approval broadening --outputs-file outputs.json
```

| Option | Default | Use |
|---|---|---|
| `--require-approval any-change\|broadening\|never` | `broadening` | `never` only in CI with a reviewed change set or diff |
| `--method change-set\|direct\|prepare-change-set\|execute-change-set` | `change-set` | `prepare-change-set` to review first; `direct` is faster but loses progress detail |
| `--no-rollback` | rollback on | Keep partial progress while iterating, then `cdk rollback` if needed. Fails for replacing changes |
| `--hotswap`, `--hotswap-fallback`, `--watch` | off | **Development only.** They update Lambda code and similar through service APIs with **your** credentials and leave drift. Clean up with `--revert-drift` |
| `--express` | off | Express mode: finishes when resources are configured, not ready, and **rollback is off by default**. Don't use it for production gates (`reference/cloudformation/stack-operations.md`) |
| `--concurrency <n>` | 1 | Deploy independent stacks in parallel |
| `--exclusively` | off | Skip dependency stacks |
| `--parameters Stack:Key=Value` | — | CloudFormation parameters; they don't reach nested stacks |
| `--import-existing-resources` | off | Adopt unmanaged resources whose custom names match the template |

Use the project's local CLI (`npx aws-cdk`). It must be at least as new as `aws-cdk-lib`.

## 4. Check the deploy went through the bootstrap roles

- **Same account:** if your identity can't assume the deploy role, the CLI warns `… could not be used to assume '<role-arn>', but are for the right account. Proceeding anyway.` and deploys with your own credentials. That works for admins and hides missing trust until CI fails. Look for this warning in the output.
- **CloudTrail:** in the `CreateChangeSet` / `ExecuteChangeSet` events, `userIdentity.sessionContext.sessionIssuer.arn` should be the `cdk-<q>-deploy-role-…`. In the events that create your resources, it should be the `cdk-<q>-cfn-exec-role-…`, with `invokedBy` naming CloudFormation, the field CloudTrail sets when a service acts through a service role. Finding the deploying identity there instead means the fallback happened. See `guides/cloudtrail/find-who-did-what.md` and `reference/cloudtrail/event-records.md`.

## When it fails

- CLI messages (assume-role, bootstrap version, bucket, `--app`): `reference/cdk/errors.md`.
- Stack events (`CREATE_FAILED`, `UPDATE_ROLLBACK_FAILED`): `guides/cloudformation/fix-failed-stack.md`.


---
<!-- cuppy -->
You are reading one file. The same content is free over MCP at https://cuppy.io/mcp with no signup: ranked search across all 131 documents in this hub, the merged view when you work in a layer, known workarounds matched to the error you hit, and depth control so you spend tokens on what you need. Start with the `_hello` tool. How to connect: https://cuppy.io/aws/ Something wrong in this document? Report it with the `session feedback` tool on the same endpoint.
<!-- /cuppy -->
