From c6d4422d82ee080299ee1fd2f510cb96f4a9649a Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Mon, 12 Jan 2026 18:21:18 +0100 Subject: [PATCH 1/8] Added base docs for ECS atmos deployment --- .gitignore | 2 + .../software-delivery/ecs-atmos/ecs-atmos.mdx | 560 ++++++++++++++++++ .../ecs-ecspresso/ecs-ecspresso.mdx | 9 +- .../layers/software-delivery/fundamentals.mdx | 3 +- .../software-delivery/software-delivery.mdx | 66 ++- 5 files changed, 632 insertions(+), 8 deletions(-) create mode 100644 docs/layers/software-delivery/ecs-atmos/ecs-atmos.mdx diff --git a/.gitignore b/.gitignore index e5e4be9b5..8933ae269 100644 --- a/.gitignore +++ b/.gitignore @@ -110,3 +110,5 @@ yarn.lock **/llms.txt **/llms-full.txt + +.claude/settings.local.json diff --git a/docs/layers/software-delivery/ecs-atmos/ecs-atmos.mdx b/docs/layers/software-delivery/ecs-atmos/ecs-atmos.mdx new file mode 100644 index 000000000..86373fb4e --- /dev/null +++ b/docs/layers/software-delivery/ecs-atmos/ecs-atmos.mdx @@ -0,0 +1,560 @@ +--- +title: "ECS with Atmos" +sidebar_label: "ECS with Atmos" +sidebar_position: 5 +--- +import Intro from '@site/src/components/Intro'; +import KeyPoints from '@site/src/components/KeyPoints'; +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import CollapsibleText from '@site/src/components/CollapsibleText'; + + + Deploy containerized applications to AWS ECS Fargate using [Atmos](https://atmos.tools) for configuration orchestration and [OpenTofu](https://opentofu.org) for infrastructure-as-code. This approach provides a self-contained, elegant solution with automated CI/CD pipelines that leverage Atmos stack configurations for multi-environment deployments. + + + +- Deploy Docker containers to ECS Fargate with infrastructure defined in Terraform/OpenTofu +- Use Atmos stacks for environment-specific configurations (dev, staging, prod, preview) +- Automated CI/CD with GitHub Actions using Atmos for both authentication and deployment +- Preview environments for pull requests with automatic cleanup +- Release promotion workflow from dev through staging to production + + +```mermaid +--- +title: Atmos ECS Deployment Lifecycle +--- +sequenceDiagram + actor dev as Developer + + participant commit as Application + + box GitHub Action Workflow + participant ci as CI + participant deploy as CD + end + + box ECS + participant ecr as ECR + participant service as ECS Service + participant cluster as ECS Cluster + end + activate cluster + + dev ->>+ commit: Create Commit + commit ->>+ ci: Trigger + ci ->> ecr: Build & Push Image + ci ->>+ deploy: Trigger + deactivate ci + deactivate commit + + deploy ->>+ service: atmos terraform deploy + + loop + deploy --> commit: Wait
Deployment Status + end + + service ->>+ cluster: Update Tasks + deactivate service + + loop + cluster ->> cluster: Remove old tasks + cluster ->> cluster: Add new tasks + end + deactivate cluster +``` + +## Overview + +This approach uses Atmos to orchestrate the deployment of ECS services through Terraform/OpenTofu components. Each environment (dev, staging, prod, preview) is defined as an Atmos stack, allowing consistent configuration management across all environments. + +Key benefits: + +- **Simplified configuration**: Atmos stacks provide a single source of truth for environment-specific settings +- **Native AWS authentication**: Use `atmos auth exec` for secure credential management +- **Infrastructure as Code**: ECS task definitions and services are managed through Terraform components +- **GitOps workflow**: Configuration changes flow through Git with automated deployments + +:::tip Latest Examples + +Check out our [example app-on-ecs-v2](https://github.com/cloudposse-examples/app-on-ecs-v2) for the latest example of how to deploy ECS applications with Atmos and GitHub Actions. + +::: + +## GitHub Action Workflows + +The deployment process uses four main workflows that cover the complete development lifecycle. + + + + The feature branch workflow builds a Docker image and deploys to a preview environment when the `deploy` label is added to a pull request. + + + ```yaml title=".github/workflows/feature-branch.yml" + name: Feature Branch + on: + pull_request: + branches: ["main"] + types: [opened, synchronize, reopened, labeled] + + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + + permissions: + id-token: write + contents: read + + jobs: + build: + runs-on: ["ubuntu-latest"] + steps: + - name: Install Atmos + uses: cloudposse/github-action-setup-atmos@v2 + with: + install-wrapper: false + + - name: Checkout + uses: actions/checkout@v4 + + - name: ECR password + shell: bash + run: | + atmos auth exec --identity plat-dev/admin -- aws configure export-credentials --format env-no-export >> $GITHUB_ENV + env: + ATMOS_CLI_CONFIG_PATH: .github + + - name: Mask ECR credentials + shell: bash + run: | + echo "::add-mask::${{ env.AWS_SECRET_ACCESS_KEY }}" + echo "::add-mask::${{ env.AWS_ACCESS_KEY_ID }}" + echo "::add-mask::${{ env.AWS_SESSION_TOKEN }}" + + - name: Login to ECR + uses: docker/login-action@v3 + with: + registry: ${{ vars.ECR_REGISTRY }} + + - name: Build + id: build + uses: cloudposse/github-action-docker-build-push@v2 + with: + organization: cloudposse-examples + repository: app-on-ecs-v2 + registry: ${{ vars.ECR_REGISTRY }} + workdir: app + + outputs: + image: ${{ steps.build.outputs.image }} + tag: ${{ steps.build.outputs.tag }} + + deploy: + needs: [build] + runs-on: ["ubuntu-latest"] + if: ${{ contains(github.event.pull_request.labels.*.name, 'deploy') }} + environment: + name: preview + url: ${{ steps.deploy.outputs.url }} + steps: + - name: Install Atmos + uses: cloudposse/github-action-setup-atmos@v2 + with: + install-wrapper: false + + - name: Checkout + uses: actions/checkout@v4 + + - uses: opentofu/setup-opentofu@v1 + with: + tofu_wrapper: false + tofu_version_file: .opentofu-version + + - name: Deploy ECS Service + shell: bash + id: deploy + env: + APP_IMAGE: "${{ needs.build.outputs.image }}:${{ needs.build.outputs.tag }}" + PR_NUMBER: ${{ github.event.pull_request.number }} + ATMOS_CLI_CONFIG_PATH: .github + run: | + atmos terraform deploy app -s preview + URL=$(atmos terraform output app -s preview --skip-init -- -raw url) + echo "url=$URL" >> $GITHUB_OUTPUT + ``` + + + + + The preview cleanup workflow destroys preview environments when pull requests are closed or when the `deploy` label is removed. + + + ```yaml title=".github/workflows/preview-cleanup.yml" + name: Preview Cleanup + on: + pull_request: + branches: ["main"] + types: [closed, unlabeled] + + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + + permissions: + id-token: write + contents: read + + jobs: + cleanup: + runs-on: ["ubuntu-latest"] + if: ${{ github.event.pull_request.state == 'closed' || !contains(github.event.pull_request.labels.*.name, 'deploy') }} + steps: + - name: Install Atmos + uses: cloudposse/github-action-setup-atmos@v2 + with: + install-wrapper: false + + - name: Checkout + uses: actions/checkout@v4 + + - uses: opentofu/setup-opentofu@v1 + with: + tofu_wrapper: false + tofu_version_file: .opentofu-version + + - name: Destroy Preview Environment + shell: bash + env: + PR_NUMBER: ${{ github.event.pull_request.number }} + ATMOS_CLI_CONFIG_PATH: .github + run: | + atmos terraform destroy app -s preview -auto-approve + ``` + + + + + The main branch workflow builds a Docker image, deploys to dev, and creates a draft release for promotion. + + + ```yaml title=".github/workflows/main-branch.yaml" + name: Main Branch + on: + push: + branches: [main] + + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + + permissions: + id-token: write + contents: write + + jobs: + build: + runs-on: [ubuntu-latest] + steps: + - name: Install Atmos + uses: cloudposse/github-action-setup-atmos@v2 + with: + install-wrapper: false + + - name: Checkout + uses: actions/checkout@v4 + + - name: ECR password + shell: bash + run: | + atmos auth exec --identity plat-dev/admin -- aws configure export-credentials --format env-no-export >> $GITHUB_ENV + env: + ATMOS_CLI_CONFIG_PATH: .github + + - name: Mask ECR credentials + shell: bash + run: | + echo "::add-mask::${{ env.AWS_SECRET_ACCESS_KEY }}" + echo "::add-mask::${{ env.AWS_ACCESS_KEY_ID }}" + echo "::add-mask::${{ env.AWS_SESSION_TOKEN }}" + + - name: Login to Public ECR + uses: docker/login-action@v3 + with: + registry: ${{ vars.ECR_REGISTRY }} + + - name: Build + id: build + uses: cloudposse/github-action-docker-build-push@v2 + with: + organization: cloudposse-examples + repository: app-on-ecs-v2 + registry: ${{ vars.ECR_REGISTRY }} + workdir: app + + outputs: + image: ${{ steps.build.outputs.image }} + tag: ${{ steps.build.outputs.tag }} + + deploy: + needs: [build] + runs-on: [ubuntu-latest] + environment: + name: dev + url: ${{ steps.deploy.outputs.url }} + steps: + - name: Install Atmos + uses: cloudposse/github-action-setup-atmos@v2 + with: + install-wrapper: false + + - name: Checkout + uses: actions/checkout@v4 + + - uses: opentofu/setup-opentofu@v1 + with: + tofu_wrapper: false + tofu_version_file: .opentofu-version + + - name: Deploy ECS Service + shell: bash + id: deploy + env: + APP_IMAGE: "${{ needs.build.outputs.image }}:${{ needs.build.outputs.tag }}" + ATMOS_CLI_CONFIG_PATH: .github + run: | + atmos terraform deploy app -s dev + URL=$(atmos terraform output app -s dev --skip-init -- -raw url) + echo "url=$URL" >> $GITHUB_OUTPUT + + release: + runs-on: [ubuntu-latest] + needs: [deploy] + steps: + - name: Create/Update Draft release + uses: release-drafter/release-drafter@v6 + with: + publish: false + prerelease: false + config-name: configs/draft-release.yml + commitish: ${{ github.sha }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + ``` + + + + + The release workflow promotes the Docker image tag and deploys to staging and then production with manual approval. + + + ```yaml title=".github/workflows/release.yaml" + name: Release + on: + release: + types: [published] + + concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: false + + permissions: + id-token: write + contents: read + + jobs: + promote: + runs-on: [ubuntu-latest] + steps: + - name: Install Atmos + uses: cloudposse/github-action-setup-atmos@v2 + with: + install-wrapper: false + + - name: Checkout + uses: actions/checkout@v4 + + - name: ECR password + shell: bash + run: | + atmos auth exec --identity plat-dev/admin -- aws configure export-credentials --format env-no-export >> $GITHUB_ENV + env: + ATMOS_CLI_CONFIG_PATH: .github + + - name: Mask ECR credentials + shell: bash + run: | + echo "::add-mask::${{ env.AWS_SECRET_ACCESS_KEY }}" + echo "::add-mask::${{ env.AWS_ACCESS_KEY_ID }}" + echo "::add-mask::${{ env.AWS_SESSION_TOKEN }}" + + - name: Login to Public ECR + uses: docker/login-action@v3 + with: + registry: ${{ vars.ECR_REGISTRY }} + + - uses: cloudposse/github-action-docker-promote@v0.5.0 + id: promote + with: + organization: cloudposse-examples + repository: app-on-ecs-v2 + registry: ${{ vars.ECR_REGISTRY }} + from: sha-${{ github.sha }} + to: ${{ github.event.release.tag_name }} + use_metadata: false + + outputs: + image: ${{ steps.promote.outputs.image }} + tag: ${{ steps.promote.outputs.tag }} + + deploy-staging: + needs: [promote] + runs-on: [ubuntu-latest] + name: deploy / staging + environment: + name: staging + url: ${{ steps.deploy.outputs.url }} + steps: + - name: Install Atmos + uses: cloudposse/github-action-setup-atmos@v2 + with: + install-wrapper: false + + - name: Checkout + uses: actions/checkout@v4 + + - uses: opentofu/setup-opentofu@v1 + with: + tofu_wrapper: false + tofu_version_file: .opentofu-version + + - name: Deploy ECS Service + shell: bash + id: deploy + env: + APP_IMAGE: "${{ needs.promote.outputs.image }}:${{ needs.promote.outputs.tag }}" + ATMOS_CLI_CONFIG_PATH: .github + run: | + atmos terraform deploy app -s staging + URL=$(atmos terraform output app -s staging --skip-init -- -raw url) + echo "url=$URL" >> $GITHUB_OUTPUT + + deploy-production: + needs: [deploy-staging, promote] + runs-on: [ubuntu-latest] + name: deploy / production + environment: + name: prod + url: ${{ steps.deploy.outputs.url }} + steps: + - name: Install Atmos + uses: cloudposse/github-action-setup-atmos@v2 + with: + install-wrapper: false + + - name: Checkout + uses: actions/checkout@v4 + + - uses: opentofu/setup-opentofu@v1 + with: + tofu_wrapper: false + tofu_version_file: .opentofu-version + + - name: Deploy ECS Service + shell: bash + id: deploy + env: + APP_IMAGE: "${{ needs.promote.outputs.image }}:${{ needs.promote.outputs.tag }}" + ATMOS_CLI_CONFIG_PATH: .github + run: | + atmos terraform deploy app -s prod + URL=$(atmos terraform output app -s prod --skip-init -- -raw url) + echo "url=$URL" >> $GITHUB_OUTPUT + ``` + + + + +## Repository Structure + +The example repository follows this structure: + +``` +app-on-ecs-v2/ +├── .github/ +│ └── workflows/ # CI/CD workflow definitions +│ ├── feature-branch.yml +│ ├── preview-cleanup.yml +│ ├── main-branch.yaml +│ ├── release.yaml +│ ├── labeler.yaml +│ └── validate.yml +├── app/ # Application source code +│ ├── main.go +│ └── Dockerfile +├── terraform/ +│ ├── components/ # Terraform/OpenTofu components +│ │ └── ecs-task/ # ECS task definition component +│ └── stacks/ # Atmos stack configurations +│ ├── dev.yaml +│ ├── staging.yaml +│ ├── prod.yaml +│ └── preview.yaml +└── .opentofu-version # OpenTofu version pinning +``` + +## Atmos Stack Configuration + +Each environment is defined as an Atmos stack with environment-specific variables: + +```yaml title="terraform/stacks/dev.yaml" +import: + - catalog/defaults + +vars: + environment: dev + +components: + terraform: + app: + vars: + desired_count: 1 + cpu: 256 + memory: 512 +``` + +## Local Development + +Run the application locally using Podman Compose: + +```bash +# Build and run on http://localhost:8080 +atmos up + +# Stop the application +atmos down +``` + +Run deployments locally using Atmos: + +```bash +# Deploy to dev environment +atmos terraform deploy app -s dev + +# Deploy to staging +atmos terraform deploy app -s staging + +# Deploy to production +atmos terraform deploy app -s prod + +# View outputs +atmos terraform output app -s dev +``` + +## References + +- [app-on-ecs-v2](https://github.com/cloudposse-examples/app-on-ecs-v2): Example application repository +- [Atmos](https://atmos.tools): Configuration orchestration tool +- [OpenTofu](https://opentofu.org): Infrastructure-as-code tool +- [github-action-docker-build-push](https://github.com/cloudposse/github-action-docker-build-push): Docker build action +- [github-action-docker-promote](https://github.com/cloudposse/github-action-docker-promote): Docker image promotion action diff --git a/docs/layers/software-delivery/ecs-ecspresso/ecs-ecspresso.mdx b/docs/layers/software-delivery/ecs-ecspresso/ecs-ecspresso.mdx index 21a112b14..0442eea57 100644 --- a/docs/layers/software-delivery/ecs-ecspresso/ecs-ecspresso.mdx +++ b/docs/layers/software-delivery/ecs-ecspresso/ecs-ecspresso.mdx @@ -1,6 +1,6 @@ --- -title: "ECS with ecspresso" -sidebar_label: "ECS with ecspresso" +title: "ECS with ecspresso (Deprecated)" +sidebar_label: "ECS with ecspresso (Deprecated)" sidebar_position: 10 --- import Intro from '@site/src/components/Intro'; @@ -8,6 +8,11 @@ import KeyPoints from '@site/src/components/KeyPoints'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import CollapsibleText from '@site/src/components/CollapsibleText'; +import Admonition from '@theme/Admonition'; + + + This approach is deprecated. For new ECS deployments, we recommend using [ECS with Atmos](/layers/software-delivery/ecs-atmos/) which provides a simpler, more integrated deployment workflow using Atmos for configuration orchestration. + We use the [`ecspresso`](https://github.com/kayac/ecspresso) deployment tool for Amazon ECS to manage ECS services using a code-driven approach, alongside reusable GitHub Action workflows. This setup allows tasks to be defined with Terraform within the infrastructure repository, and task definitions to reside alongside the application code. Ecspresso provides extensive configuration options via YAML, JSON, and Jsonnet, and includes plugins for enhanced functionality such as Terraform state lookups. diff --git a/docs/layers/software-delivery/fundamentals.mdx b/docs/layers/software-delivery/fundamentals.mdx index 900804c97..5b41fc303 100644 --- a/docs/layers/software-delivery/fundamentals.mdx +++ b/docs/layers/software-delivery/fundamentals.mdx @@ -137,7 +137,8 @@ manual confirmation. Once manually approved, the workflow will continue and depl Refer to our stack specific implementations for more details: - [**Dockerized App on EKS with ArgoCD**](/layers/software-delivery/eks-argocd/) -- [**Dockerized App on ECS with Ecspresso**](/layers/software-delivery/ecs-ecspresso/) +- [**Dockerized App on ECS with Atmos**](/layers/software-delivery/ecs-atmos/) +- [**Dockerized App on ECS with Ecspresso**](/layers/software-delivery/ecs-ecspresso/) (Deprecated) - [**Lambda App**](/layers/software-delivery/lambda) ## FAQ diff --git a/docs/layers/software-delivery/software-delivery.mdx b/docs/layers/software-delivery/software-delivery.mdx index 3592a7132..3538c8324 100644 --- a/docs/layers/software-delivery/software-delivery.mdx +++ b/docs/layers/software-delivery/software-delivery.mdx @@ -30,10 +30,10 @@ import ReactPlayer from 'react-player'; Choose a path for delivery of your services with GitHub Actions. The reference architecture supports deployment to AWS EKS, Amazon ECS, and Lambda functions. - - We use the `ecspresso` deployment tool for Amazon ECS to manage ECS services using a code-driven approach, alongside reusable GitHub Action workflows. This setup allows tasks to be defined with Terraform within the infrastructure repository, and task definitions to reside alongside the application code. + + Deploy containerized applications to AWS ECS Fargate using Atmos for configuration orchestration and OpenTofu for infrastructure-as-code. This approach provides a self-contained, elegant solution with automated CI/CD pipelines that leverage Atmos stack configurations for multi-environment deployments. - Get Started + Get Started Argo CD is an open-source declarative, GitOps continuous delivery tool for Kubernetes applications. It enables developers to manage and deploy applications on Kubernetes clusters using Git repositories as the source of truth for configuration and definitions. Our Argo CD implementation follows the GitOps methodology and integrates with GitHub Actions, ensuring that the entire application configuration, including manifests, parameters, and even application state, is stored in a Git repository. @@ -41,10 +41,20 @@ import ReactPlayer from 'react-player'; Get Started - + Deploy Lambda functions using GitHub Workflows with a code-driven approach. The build process updates S3 with assets and SSM with the new version, requiring a Terraform run for promotion. GitHub Workflows manage the entire lifecycle, from building and packaging Lambda functions to deploying them, with reusable workflows. Get Started + + + :::warning + This approach is deprecated. For new ECS deployments, we recommend using [ECS with Atmos](/layers/software-delivery/ecs-atmos/). + ::: + + We use the `ecspresso` deployment tool for Amazon ECS to manage ECS services using a code-driven approach, alongside reusable GitHub Action workflows. This setup allows tasks to be defined with Terraform within the infrastructure repository, and task definitions to reside alongside the application code. + + View Documentation +
@@ -60,7 +70,51 @@ Once you're done deploying your apps, it's time to start monitoring everything.

Our Examples

-### Reusable Workflows +### ECS with Atmos (Recommended) + +The [app-on-ecs-v2](https://github.com/cloudposse-examples/app-on-ecs-v2) example demonstrates a self-contained approach where workflows are defined directly in the application repository. This approach uses Atmos for configuration orchestration and OpenTofu for infrastructure management. + +With this approach, you need only a few workflows in your application repository: + + 1. `feature-branch.yml` - Build and deploy to preview environments + 2. `preview-cleanup.yml` - Clean up preview environments when PRs close + 3. `main-branch.yaml` - Build, deploy to dev, and create draft release + 4. `release.yaml` - Promote and deploy to staging/production + 5. (optional) `validate.yml` - Run validation checks + 6. (optional) `labeler.yaml` - Auto-label PRs + +```console +app-on-ecs-v2/ +├── .github/ +│ └── workflows/ +│ ├── feature-branch.yml +│ ├── preview-cleanup.yml +│ ├── main-branch.yaml +│ ├── release.yaml +│ ├── validate.yml +│ └── labeler.yaml +├── app/ +│ ├── main.go +│ └── Dockerfile +├── terraform/ +│ ├── components/ +│ │ └── ecs-task/ +│ └── stacks/ +│ ├── dev.yaml +│ ├── staging.yaml +│ ├── prod.yaml +│ └── preview.yaml +└── .opentofu-version +``` + +### ECS with Ecspresso (Deprecated) + +:::warning +The ecspresso-based approach is deprecated. For new projects, use [ECS with Atmos](/layers/software-delivery/ecs-atmos/) instead. +::: + +
+View deprecated ecspresso workflow structure We've consolidated all the workflows into the example applications, including the GitHub reusable workflows. @@ -141,3 +195,5 @@ After moving to a centralized workflow repository, you should have a setup like │ └── workflow-controller-hotfix-release.yml └── ... ``` + +
From 18ebf9575d4b084a3e8609717ccb83a79f560f1f Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Mon, 12 Jan 2026 18:53:01 +0100 Subject: [PATCH 2/8] Added ecs deprication notes --- docs/jumpstart/action-items.mdx | 7 ++++++- .../software-delivery/ecs-ecspresso/ecs-ecspresso.mdx | 7 +++---- .../ecs-ecspresso/ecs-partial-task-definitions.mdx | 5 +++++ docs/layers/software-delivery/ecs-ecspresso/setup.mdx | 4 ++++ 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/docs/jumpstart/action-items.mdx b/docs/jumpstart/action-items.mdx index e651e26c2..d567c157b 100644 --- a/docs/jumpstart/action-items.mdx +++ b/docs/jumpstart/action-items.mdx @@ -198,7 +198,12 @@ If your engagement with Cloud Posse includes Release Engineering, we will also n - ### PATs for ECS with `ecspresso` + ### PATs for ECS with `ecspresso` (Deprecated) + + :::note + This step can likely be skipped. The ecspresso-based ECS deployment approach is deprecated in favor of [ECS with Atmos](/layers/software-delivery/ecs-atmos/), which does not require these PATs. + ::: + - Create one fine-grained PAT with the following permission. Please see [Creating a fine-grained personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token) diff --git a/docs/layers/software-delivery/ecs-ecspresso/ecs-ecspresso.mdx b/docs/layers/software-delivery/ecs-ecspresso/ecs-ecspresso.mdx index 0442eea57..dad75ce0d 100644 --- a/docs/layers/software-delivery/ecs-ecspresso/ecs-ecspresso.mdx +++ b/docs/layers/software-delivery/ecs-ecspresso/ecs-ecspresso.mdx @@ -10,14 +10,13 @@ import TabItem from '@theme/TabItem'; import CollapsibleText from '@site/src/components/CollapsibleText'; import Admonition from '@theme/Admonition'; - - This approach is deprecated. For new ECS deployments, we recommend using [ECS with Atmos](/layers/software-delivery/ecs-atmos/) which provides a simpler, more integrated deployment workflow using Atmos for configuration orchestration. - - We use the [`ecspresso`](https://github.com/kayac/ecspresso) deployment tool for Amazon ECS to manage ECS services using a code-driven approach, alongside reusable GitHub Action workflows. This setup allows tasks to be defined with Terraform within the infrastructure repository, and task definitions to reside alongside the application code. Ecspresso provides extensive configuration options via YAML, JSON, and Jsonnet, and includes plugins for enhanced functionality such as Terraform state lookups. + + This approach is deprecated. For new ECS deployments, we recommend using [ECS with Atmos](/layers/software-delivery/ecs-atmos/) which provides a simpler, more integrated deployment workflow using Atmos for configuration orchestration. + ```mermaid --- diff --git a/docs/layers/software-delivery/ecs-ecspresso/ecs-partial-task-definitions.mdx b/docs/layers/software-delivery/ecs-ecspresso/ecs-partial-task-definitions.mdx index f15fe60a0..f7f9cddda 100644 --- a/docs/layers/software-delivery/ecs-ecspresso/ecs-partial-task-definitions.mdx +++ b/docs/layers/software-delivery/ecs-ecspresso/ecs-partial-task-definitions.mdx @@ -6,11 +6,16 @@ sidebar_position: 20 import Intro from '@site/src/components/Intro'; import Steps from '@site/src/components/Steps'; +import Admonition from '@theme/Admonition' This document describes what partial task definitions are and how we can use them to set up ECS services using Terraform and GitHub Actions. + + This approach is deprecated. For new ECS deployments, we recommend using [ECS with Atmos](/layers/software-delivery/ecs-atmos/) which provides a simpler, more integrated deployment workflow. + + ## The Problem Managing ECS Services is challenging. Ideally, we want our services to be managed by Terraform so everything is living diff --git a/docs/layers/software-delivery/ecs-ecspresso/setup.mdx b/docs/layers/software-delivery/ecs-ecspresso/setup.mdx index c5a92c2a7..adaa20256 100644 --- a/docs/layers/software-delivery/ecs-ecspresso/setup.mdx +++ b/docs/layers/software-delivery/ecs-ecspresso/setup.mdx @@ -16,6 +16,10 @@ import AtmosWorkflow from '@site/src/components/AtmosWorkflow'; This setup guide will help you get started with [ecspresso](https://github.com/kayac/ecspresso). It features an example app, which demonstrates how your GitHub Actions work with your infrastructure repository. + + This approach is deprecated. For new ECS deployments, we recommend using [ECS with Atmos](/layers/software-delivery/ecs-atmos/) which provides a simpler, more integrated deployment workflow. + + | Steps | Actions | | ---------------------------------------------------- | --------------------------------------------------------------------------------- | | 1. Create a repository from the Example App template | [cloudposse-examples/app-on-ecs](https://github.com/cloudposse-examples/app-on-ecs) | From b9f25df525fb81371ec429efcc857b8f92acd3a8 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Mon, 26 Jan 2026 14:16:26 +0100 Subject: [PATCH 3/8] Added ecs atmos deployment --- .../software-delivery/ecs-atmos/setup.mdx | 312 ++++++++++++++++++ 1 file changed, 312 insertions(+) create mode 100644 docs/layers/software-delivery/ecs-atmos/setup.mdx diff --git a/docs/layers/software-delivery/ecs-atmos/setup.mdx b/docs/layers/software-delivery/ecs-atmos/setup.mdx new file mode 100644 index 000000000..47aed718b --- /dev/null +++ b/docs/layers/software-delivery/ecs-atmos/setup.mdx @@ -0,0 +1,312 @@ +--- +title: "Setup ECS with Atmos" +sidebar_label: "Setup" +sidebar_position: 10 +description: "Setup guide for deploying containerized applications to ECS with Atmos and OpenTofu" +--- +import Intro from '@site/src/components/Intro'; +import KeyPoints from '@site/src/components/KeyPoints'; +import Steps from '@site/src/components/Steps' +import Step from '@site/src/components/Step' +import StepNumber from '@site/src/components/StepNumber' +import Note from '@site/src/components/Note' +import Admonition from '@theme/Admonition' +import TaskList from '@site/src/components/TaskList' + + + This setup guide will help you get started deploying containerized applications to AWS ECS Fargate using Atmos for configuration orchestration and OpenTofu + for infrastructure-as-code. The setup uses a self-contained approach where all workflows and infrastructure definitions (except dependencies) reside in the application repository. + + +| Steps | Actions | +| ---------------------------------------------------- | ----------------------------------------------------------------------------------- | +| 1. Deploy supporting infrastructure | Deploy VPC, ECS cluster, Github OIDC Provider, ALB, etc. with `infra` repository | +| 2. Create a repository from the Example App template | [cloudposse-examples/app-on-ecs-v2](https://github.com/cloudposse-examples/app-on-ecs-v2) | +| 3. Provision IAM roles for the app repo | IAM role | +| 4. Provision ECR registry image for the app | Deploy VPC, ECS cluster, ALB, etc. with `infra` repository | +| 2. Configure ECR access | Update `ecr` component with new repository | +| 3. Configure GitHub repository variables | Add `ECR_REGISTRY` variable | +| 4. Configure Atmos authentication | Set up `atmos auth` for GitHub Actions | +| 6. Trigger workflows | Push to main branch to deploy | + +## Requirements + +Before setting up ECS deployments with Atmos, ensure the following prerequisites are met: + + +- [ ] AWS accounts provisioned (dev, staging, prod) +- [ ] VPC deployed in target accounts +- [ ] ECS cluster deployed in target accounts +- [ ] Application Load Balancer (ALB) deployed +- [ ] ECR registry available for container images +- [ ] GitHub OIDC configured for AWS access +- [ ] Atmos installed locally +- [ ] OpenTofu installed locally + + +## Setup Steps + + + + ### Create the Application Repository + + + This step requires access to the GitHub Organization. + + + Create a new repository from the [cloudposse-examples/app-on-ecs-v2](https://github.com/cloudposse-examples/app-on-ecs-v2) template. + + + 1. Navigate to [cloudposse-examples/app-on-ecs-v2](https://github.com/cloudposse-examples/app-on-ecs-v2) + 2. Click "Use this template" → "Create a new repository" + 3. Choose a name for the repository (e.g., `acme/example-app-on-ecs`) + 4. Select "Private" for repository visibility + 5. Click "Create repository" + + + The template includes: + - Sample Go application with Dockerfile + - GitHub Actions workflows for CI/CD + - Terraform/OpenTofu components for ECS task definitions + - Atmos stack configurations for each environment + + + + ### Configure ECR Access + + The application workflows will build and push Docker images to Amazon ECR. Update your `ecr` component to allow access from the new repository. + + Add the following to your ECR component configuration: + + ```yaml + components: + terraform: + ecr: + vars: + github_actions_allowed_repos: + - acme/example-app-on-ecs + # ECR image names must be lowercase + images: + - acme/example-app-on-ecs + ``` + + Apply the updated configuration: + + ```bash + atmos terraform apply ecr -s core-use1-artifacts + ``` + + + + ### Configure GitHub Repository Variables + + The GitHub Actions workflows require a repository variable for the ECR registry. Add the following variable to your repository: + + + 1. Navigate to your repository → Settings → Secrets and variables → Actions + 2. Click the "Variables" tab + 3. Click "New repository variable" + 4. Add the following variable: + + | Name | Value | + |------|-------| + | `ECR_REGISTRY` | `public.ecr.aws` (or your private ECR registry URL) | + + + + If you have multiple application repositories, consider creating an organization-level variable for `ECR_REGISTRY` to avoid repetition. + + + + + ### Configure Atmos Authentication + + The workflows use `atmos auth exec` to obtain AWS credentials for deployments. This requires an Atmos configuration in the `.github` directory of your repository. + + The template includes a sample configuration at `.github/atmos.yaml`. Update this file to match your infrastructure: + + ```yaml title=".github/atmos.yaml" + base_path: "terraform" + + components: + terraform: + base_path: "components" + + stacks: + base_path: "stacks" + name_pattern: "{stage}" + + # Authentication configuration + integrations: + github: + gitops: + opentofu-version: "1.8.1" + terraform-version: "1.5.7" + infracost-enabled: false + artifact-storage: + region: "us-east-1" + bucket: "acme-gitops-artifacts" + table: "acme-gitops-artifacts-lock" + role: "arn:aws:iam::111111111111:role/acme-gitops" + ``` + + + The `atmos auth exec` command uses AWS IAM Identity Center (SSO) or GitHub OIDC to obtain temporary credentials. Ensure your AWS accounts are configured to allow GitHub Actions to assume the necessary roles. + + + + + ### Configure Atmos Stacks + + Update the Atmos stack configurations in `terraform/stacks/` to match your environment: + + ```yaml title="terraform/stacks/dev.yaml" + import: + - catalog/defaults + + vars: + stage: dev + environment: dev + + components: + terraform: + app: + vars: + cluster_name: "acme-plat-use1-dev-ecs-cluster" + vpc_id: "vpc-xxxxxxxxx" + subnet_ids: + - "subnet-xxxxxxxxx" + - "subnet-yyyyyyyyy" + alb_arn: "arn:aws:elasticloadbalancing:..." + desired_count: 1 + cpu: 256 + memory: 512 + ``` + + Repeat for `staging.yaml`, `prod.yaml`, and `preview.yaml` with appropriate values for each environment. + + + + ### Configure GitHub Environments + + Set up GitHub Environments for deployment approvals and environment-specific settings: + + + 1. Navigate to your repository → Settings → Environments + 2. Create the following environments: + - `dev` - Auto-deploy on main branch + - `staging` - Deploy on release + - `prod` - Deploy on release with required reviewers + - `preview` - Auto-deploy on PR with `deploy` label + 3. For production, add required reviewers for deployment approval + + + + + ### Deploy Supporting Infrastructure + + Ensure the supporting infrastructure is deployed in your target AWS accounts. At minimum, you need: + + + - [ ] VPC with public and private subnets + - [ ] ECS Cluster + - [ ] Application Load Balancer + - [ ] Route 53 hosted zone (for DNS) + - [ ] ACM certificate (for HTTPS) + + + If using the Cloud Posse reference architecture, deploy these components: + + ```bash + # Deploy VPC + atmos terraform apply vpc -s plat-use1-dev + + # Deploy ECS Cluster + atmos terraform apply ecs-cluster -s plat-use1-dev + + # Deploy ALB + atmos terraform apply alb -s plat-use1-dev + ``` + + + +## Triggering Workflows + +Once setup is complete, validate the workflows: + + + 1. ### Push to Main Branch + + Push any change to the `main` branch to trigger the main branch workflow: + + ```bash + git add . + git commit -m "Initial setup" + git push origin main + ``` + + This will: + - Build and push a Docker image to ECR + - Deploy to the `dev` environment + - Create a draft release + + 2. ### Create a Pull Request + + Create a PR and add the `deploy` label to deploy a preview environment: + + ```bash + git checkout -b feature/test-preview + # Make changes + git push origin feature/test-preview + ``` + + Then add the `deploy` label to the PR in GitHub. + + 3. ### Publish a Release + + Edit the draft release created by the main branch workflow and click "Publish release". This will: + - Promote the Docker image tag + - Deploy to `staging` + - Wait for approval (if configured) + - Deploy to `prod` + + +## Local Development + +Run the application locally using Podman Compose: + +```bash +# Build and run on http://localhost:8080 +atmos up + +# Stop the application +atmos down +``` + +Deploy manually using Atmos: + +```bash +# Deploy to dev +atmos terraform deploy app -s dev + +# View deployment URL +atmos terraform output app -s dev --skip-init -- -raw url +``` + +## Next Steps + + + - [ ] Customize the application code in the `app/` directory + - [ ] Update Terraform components for your specific requirements + - [ ] Configure monitoring and alerting + - [ ] Set up log aggregation + - [ ] Configure auto-scaling policies + + +## References + +- [app-on-ecs-v2](https://github.com/cloudposse-examples/app-on-ecs-v2): Example application repository +- [Atmos](https://atmos.tools): Configuration orchestration tool +- [OpenTofu](https://opentofu.org): Infrastructure-as-code tool +- [GitHub OIDC with AWS](/layers/github-actions/github-oidc-with-aws): How to configure GitHub OIDC +- [github-action-docker-build-push](https://github.com/cloudposse/github-action-docker-build-push): Docker build action From 804d8fd93791f85499c0e934f617f8c8635679e5 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Mon, 26 Jan 2026 21:03:37 +0100 Subject: [PATCH 4/8] Documented ECS deployment with atmos --- .../software-delivery/ecs-atmos/setup.mdx | 541 ++++++++++++------ 1 file changed, 363 insertions(+), 178 deletions(-) diff --git a/docs/layers/software-delivery/ecs-atmos/setup.mdx b/docs/layers/software-delivery/ecs-atmos/setup.mdx index 47aed718b..1e2f474a4 100644 --- a/docs/layers/software-delivery/ecs-atmos/setup.mdx +++ b/docs/layers/software-delivery/ecs-atmos/setup.mdx @@ -14,52 +14,93 @@ import Admonition from '@theme/Admonition' import TaskList from '@site/src/components/TaskList' - This setup guide will help you get started deploying containerized applications to AWS ECS Fargate using Atmos for configuration orchestration and OpenTofu - for infrastructure-as-code. The setup uses a self-contained approach where all workflows and infrastructure definitions (except dependencies) reside in the application repository. + This setup guide walks you through deploying containerized applications to AWS ECS Fargate using Atmos for configuration orchestration and OpenTofu for infrastructure-as-code. The setup uses a self-contained approach where application infrastructure definitions and workflows reside in the application repository, while shared infrastructure is managed in the infra repository. -| Steps | Actions | -| ---------------------------------------------------- | ----------------------------------------------------------------------------------- | -| 1. Deploy supporting infrastructure | Deploy VPC, ECS cluster, Github OIDC Provider, ALB, etc. with `infra` repository | -| 2. Create a repository from the Example App template | [cloudposse-examples/app-on-ecs-v2](https://github.com/cloudposse-examples/app-on-ecs-v2) | -| 3. Provision IAM roles for the app repo | IAM role | -| 4. Provision ECR registry image for the app | Deploy VPC, ECS cluster, ALB, etc. with `infra` repository | -| 2. Configure ECR access | Update `ecr` component with new repository | -| 3. Configure GitHub repository variables | Add `ECR_REGISTRY` variable | -| 4. Configure Atmos authentication | Set up `atmos auth` for GitHub Actions | -| 6. Trigger workflows | Push to main branch to deploy | +## Overview + +| Step | Action | Repository | +| ---- | ------ | ---------- | +| 1. Deploy platform infrastructure | Deploy VPC, ECS cluster, GitHub OIDC Provider, ALB, etc. | `infra` | +| 2. Provision tfstate-bucket-app | Create Terraform state bucket for app repos (if not exists) | `infra` | +| 3. Create application repository | Create repo from [cloudposse-examples/app-on-ecs-v2](https://github.com/cloudposse-examples/app-on-ecs-v2) template | GitHub | +| 4. Provision ECR registry | Add ECR image repository for the app | `infra` | +| 5. Provision IAM roles | Create IAM roles for the app to assume | `infra` | +| 6. Update tfstate-bucket-app access | Grant IAM roles access to state bucket | `infra` | +| 7. Update profiles/github | Configure GitHub OIDC roles in app repo | `app` | +| 8. Configure GitHub repository | Add `ECR_REGISTRY` variable | GitHub UI | +| 9. Provision shared dependencies | Deploy app dependencies (databases, queues, etc.) | `infra` | +| 10. Configure dependencies | Set up remote state for infra components | `app` | +| 11. Configure container definitions | Define ECS task and container settings | `app` | +| 12. Test configuration | Run `atmos terraform plan app -s preview` | `app` | -## Requirements + + + ### Deploy Platform Infrastructure -Before setting up ECS deployments with Atmos, ensure the following prerequisites are met: + Deploy the foundational infrastructure components in your `infra` repository. - -- [ ] AWS accounts provisioned (dev, staging, prod) -- [ ] VPC deployed in target accounts -- [ ] ECS cluster deployed in target accounts -- [ ] Application Load Balancer (ALB) deployed -- [ ] ECR registry available for container images -- [ ] GitHub OIDC configured for AWS access -- [ ] Atmos installed locally -- [ ] OpenTofu installed locally - + Ensure the following components are deployed in your target AWS accounts: -## Setup Steps + ```bash + # Deploy VPC + atmos terraform deploy vpc -s plat-use1-dev + atmos terraform deploy vpc -s plat-use1-staging + atmos terraform deploy vpc -s plat-use1-prod - - - ### Create the Application Repository + # Deploy ECS Cluster + atmos terraform deploy ecs/cluster -s plat-use1-dev + atmos terraform deploy ecs/cluster -s plat-use1-staging + atmos terraform deploy ecs/cluster -s plat-use1-prod + + # Deploy Github OIDC Provider + atmos terraform deploy github-oidc-provider -s plat-gbl-dev + atmos terraform deploy github-oidc-provider -s plat-gbl-staging + atmos terraform deploy github-oidc-provider -s plat-gbl-prod + ``` - - This step requires access to the GitHub Organization. + + These components are typically deployed once and shared across multiple applications. See the [ECS Cluster](/library/aws/ecs/) documentation for detailed setup instructions. + + + + ### Provision tfstate-bucket-app + + Create a Terraform state bucket for application repositories if one doesn't exist. + + In your `infra` repository, add the tfstate bucket configuration: + + ```yaml title="stacks/catalog/tfstate-backend/apps.yaml" + components: + terraform: + tfstate-backend-apps: + metadata: + component: tfstate-backend + vars: + enabled: true + name: tfstate-backend-apps + # Additional configuration as needed + ``` + + Deploy tfstate bucket: + + ```bash + atmos terraform deploy tfstate-bucket-apps -s plat-use1-dev + atmos terraform deploy tfstate-bucket-apps -s plat-use1-staging + atmos terraform deploy tfstate-bucket-apps -s plat-use1-prod + ``` + + + + ### Create Application Repository Create a new repository from the [cloudposse-examples/app-on-ecs-v2](https://github.com/cloudposse-examples/app-on-ecs-v2) template. 1. Navigate to [cloudposse-examples/app-on-ecs-v2](https://github.com/cloudposse-examples/app-on-ecs-v2) 2. Click "Use this template" → "Create a new repository" - 3. Choose a name for the repository (e.g., `acme/example-app-on-ecs`) + 3. Choose a name for the repository (e.g., `acme/example-app`) 4. Select "Private" for repository visibility 5. Click "Create repository" @@ -72,35 +113,182 @@ Before setting up ECS deployments with Atmos, ensure the following prerequisites - ### Configure ECR Access + ### Provision ECR Registry - The application workflows will build and push Docker images to Amazon ECR. Update your `ecr` component to allow access from the new repository. + Add an ECR image repository for the new application. - Add the following to your ECR component configuration: + In your `infra` repository, update the ECR component configuration: - ```yaml + ```yaml title="stacks/catalog/ecr.yaml" components: terraform: ecr: vars: - github_actions_allowed_repos: - - acme/example-app-on-ecs - # ECR image names must be lowercase images: - - acme/example-app-on-ecs + - acme/example-app + # Additional configuration as needed ``` - Apply the updated configuration: + ```bash + atmos terraform deploy ecr -s core-use1-artifacts + ``` + + + + ### Provision IAM Roles + + Create IAM roles that the application will assume for deployments. + + Create an IAM role configuration for the application: + + ```yaml title="stacks/catalog/iam-role/example-app.yaml" + import: + - catalog/iam-role/defaults + + components: + terraform: + example-app/iam-role: + metadata: + component: iam-role + inherits: + - iam-role/defaults + vars: + name: example-app + attributes: + - "terraform" + role_description: | + Role for GitHub Actions to access the GitOps resources, such as the S3 Bucket and DynamoDB Table. + github_oidc_provider_enabled: true + github_oidc_provider_arn: !terraform.state github-oidc-provider oidc_provider_arn + trusted_github_org: acme + trusted_github_repos: + - example-app + policy_statements: + AllowECRAccess: + effect: "Allow" + actions: + - "ecr:GetAuthorizationToken" + - "ecr:BatchCheckLayerAvailability" + - "ecr:GetDownloadUrlForLayer" + - "ecr:BatchGetImage" + - "ecr:InitiateLayerUpload" + - "ecr:UploadLayerPart" + - "ecr:CompleteLayerUpload" + - "ecr:PutImage" + - "ecr:CreatePullThroughCacheRule" + - "ecr:BatchImportUpstreamImage" + - "ecr:CreateRepository" + resources: + - "*" + AllowAssumeRole: + effect: "Allow" + actions: + - "sts:AssumeRole" + - "sts:TagSession" + - "sts:SetSourceIdentity" + resources: + - "*" + AllowServicesAccess: + effect: "Allow" + actions: + - "s3:*" + - "iam:*" + - "ecs:*" + - "ecr:*" + - "logs:*" + - "ssm:*" + - "ec2:*" + - "elasticloadbalancing:*" + - "application-autoscaling:*" + - "cloudwatch:*" + - "kms:Decrypt" + resources: + - "*" + ``` + + ```bash + atmos terraform deploy example-app/iam-role -s plat-gbl-dev + atmos terraform deploy example-app/iam-role -s plat-gbl-staging + atmos terraform deploy example-app/iam-role -s plat-gbl-prod + ``` + + + + ### Update tfstate-bucket-app Access + + Grant the newly created IAM roles access to the Terraform state bucket. + + Add the IAM role ARN references to your tfstate backend configuration: + + ```yaml title="stacks/catalog/tfstate-backend/apps.yaml" + components: + terraform: + tfstate-backend-apps: + vars: + privileged_principal_arns: + - !terraform.state example-app/iam-role .role.arn + ``` ```bash - atmos terraform apply ecr -s core-use1-artifacts + atmos terraform deploy tfstate-backend-apps -s plat-gbl-dev + atmos terraform deploy tfstate-backend-apps -s plat-gbl-staging + atmos terraform deploy tfstate-backend-apps -s plat-gbl-prod + ``` + + + + ### Update profiles/github + + Configure the app repository with the IAM roles provisioned in the previous steps. + + In your **application repository**, update the Atmos auth configuration with the provisioned IAM roles: + + ```yaml title="profiles/github/atmos.yaml" + # ... + + auth: + providers: + github-oidc: + kind: github/oidc + region: us-west-1 + spec: + audience: sts.amazonaws.com + + identities: + plat-dev/terraform: + kind: aws/assume-role + via: + provider: github-oidc + principal: + assume_role: arn:aws:iam::111111111111:role/acme-plat-gbl-dev-example-app-terraform + + plat-staging/terraform: + kind: aws/assume-role + via: + provider: github-oidc + principal: + assume_role: arn:aws:iam::222222222222:role/acme-plat-gbl-dev-example-app-terraform + + plat-prod/terraform: + kind: aws/assume-role + via: + provider: github-oidc + principal: + assume_role: arn:aws:iam::333333333333:role/acme-plat-gbl-dev-example-app-terraform ``` + + + Get the role ARNs from the outputs of the IAM role deployments in step 5: + ```bash + atmos terraform output example-app/iam-role -s plat-gbl-dev -- -raw role_arn + ``` + - ### Configure GitHub Repository Variables + ### Configure GitHub Repository - The GitHub Actions workflows require a repository variable for the ECR registry. Add the following variable to your repository: + Add repository `ECR_REGISTRY` variable required by the GitHub Actions workflows. 1. Navigate to your repository → Settings → Secrets and variables → Actions @@ -110,7 +298,7 @@ Before setting up ECS deployments with Atmos, ensure the following prerequisites | Name | Value | |------|-------| - | `ECR_REGISTRY` | `public.ecr.aws` (or your private ECR registry URL) | + | `ECR_REGISTRY` | Your ECR registry URL (e.g., `444444444444.dkr.ecr.us-east-1.amazonaws.com`) | @@ -119,189 +307,186 @@ Before setting up ECS deployments with Atmos, ensure the following prerequisites - ### Configure Atmos Authentication + ### Provision Shared Dependencies + + Deploy application dependencies that have a different lifecycle than the application itself (e.g., databases, message queues, caches). - The workflows use `atmos auth exec` to obtain AWS credentials for deployments. This requires an Atmos configuration in the `.github` directory of your repository. + + Skip this step if your application doesn't require external dependencies like databases or caches. + + + + + ### Configure Dependencies - The template includes a sample configuration at `.github/atmos.yaml`. Update this file to match your infrastructure: + Configure the application to read from infrastructure components' remote state. - ```yaml title=".github/atmos.yaml" - base_path: "terraform" + In your **application repository**, create dependency stack files: + ```yaml title="terraform/stacks/deps/vpc.yaml" components: terraform: - base_path: "components" - - stacks: - base_path: "stacks" - name_pattern: "{stage}" - - # Authentication configuration - integrations: - github: - gitops: - opentofu-version: "1.8.1" - terraform-version: "1.5.7" - infracost-enabled: false - artifact-storage: - region: "us-east-1" - bucket: "acme-gitops-artifacts" - table: "acme-gitops-artifacts-lock" - role: "arn:aws:iam::111111111111:role/acme-gitops" + vpc: + metadata: + component: vpc + type: abstract + terraform_workspace: "{{ .vars.tenant }}-{{ .vars.environment }}-{{ .vars.deps_stage }}" + backend_type: s3 + backend: + s3: + bucket: "acme-core-gbl-root-tfstate" + region: "us-east-1" + encrypt: true + key: terraform.tfstate + acl: bucket-owner-full-control + assume_role: + role_arn: "arn:aws:iam::111111111111:role/acme-core-gbl-root-tfstate-ro" ``` - - The `atmos auth exec` command uses AWS IAM Identity Center (SSO) or GitHub OIDC to obtain temporary credentials. Ensure your AWS accounts are configured to allow GitHub Actions to assume the necessary roles. - + ```yaml title="terraform/stacks/deps/ecs-cluster.yaml" + components: + terraform: + vpc: + metadata: + component: vpc + type: abstract + terraform_workspace: "{{ .vars.tenant }}-{{ .vars.environment }}-{{ .vars.deps_stage }}" + backend_type: s3 + backend: + s3: + bucket: "acme-core-gbl-root-tfstate" + region: "us-east-1" + encrypt: true + key: terraform.tfstate + acl: bucket-owner-full-control + assume_role: + role_arn: "arn:aws:iam::111111111111:role/acme-core-gbl-root-tfstate-ro" + ``` + + And any other external dependencies like databases or caches. - ### Configure Atmos Stacks - - Update the Atmos stack configurations in `terraform/stacks/` to match your environment: + ### Configure Container Definitions - ```yaml title="terraform/stacks/dev.yaml" - import: - - catalog/defaults - - vars: - stage: dev - environment: dev + Define the ECS task and container settings for your application. + ```yaml title="terraform/stacks/default/app.yaml" components: terraform: app: vars: - cluster_name: "acme-plat-use1-dev-ecs-cluster" - vpc_id: "vpc-xxxxxxxxx" - subnet_ids: - - "subnet-xxxxxxxxx" - - "subnet-yyyyyyyyy" - alb_arn: "arn:aws:elasticloadbalancing:..." desired_count: 1 cpu: 256 memory: 512 + container_definitions: + app: + image: !env APP_IMAGE + port_mappings: + - containerPort: 8080 + hostPort: 8080 + protocol: "tcp" + environment: + - name: "APP_ENV" + value: "production" + secrets: + - name: "DATABASE_URL" + valueFrom: !terraform.state rds .database_url ``` - Repeat for `staging.yaml`, `prod.yaml`, and `preview.yaml` with appropriate values for each environment. - - - - ### Configure GitHub Environments + And/or update Terraform component (if needed). Modify the ECS task component in `terraform/components/ecs-task/` to match your application requirements: - Set up GitHub Environments for deployment approvals and environment-specific settings: - - - 1. Navigate to your repository → Settings → Environments - 2. Create the following environments: - - `dev` - Auto-deploy on main branch - - `staging` - Deploy on release - - `prod` - Deploy on release with required reviewers - - `preview` - Auto-deploy on PR with `deploy` label - 3. For production, add required reviewers for deployment approval - + - Add additional IAM permissions + - Configure health check settings + - Set up log configuration + - Add sidecar containers - ### Deploy Supporting Infrastructure + ### Test Configuration - Ensure the supporting infrastructure is deployed in your target AWS accounts. At minimum, you need: - - - - [ ] VPC with public and private subnets - - [ ] ECS Cluster - - [ ] Application Load Balancer - - [ ] Route 53 hosted zone (for DNS) - - [ ] ACM certificate (for HTTPS) - - - If using the Cloud Posse reference architecture, deploy these components: + Verify the Atmos configuration works correctly. ```bash - # Deploy VPC - atmos terraform apply vpc -s plat-use1-dev - - # Deploy ECS Cluster - atmos terraform apply ecs-cluster -s plat-use1-dev - - # Deploy ALB - atmos terraform apply alb -s plat-use1-dev + atmos terraform plan app -s preview ``` + + Check that: + - All remote state references resolve correctly + - Container definitions are valid + - IAM roles and permissions are configured + - No errors in the plan output -## Triggering Workflows - -Once setup is complete, validate the workflows: - - - 1. ### Push to Main Branch - - Push any change to the `main` branch to trigger the main branch workflow: - - ```bash - git add . - git commit -m "Initial setup" - git push origin main - ``` +## Quick Checklist - This will: - - Build and push a Docker image to ECR - - Deploy to the `dev` environment - - Create a draft release + +- [ ] Platform infrastructure deployed (VPC, ECS cluster, GitHub OIDC Provider) +- [ ] `tfstate-bucket-apps` provisioned in dev/staging/prod +- [ ] Application repository created from template +- [ ] ECR registry provisioned (`core-use1-artifacts`) +- [ ] IAM roles provisioned in dev/staging/prod +- [ ] `tfstate-backend-apps` updated with IAM role access +- [ ] `profiles/github/atmos.yaml` configured with IAM role ARNs +- [ ] GitHub repo variable `ECR_REGISTRY` configured +- [ ] Shared dependencies provisioned (if applicable) +- [ ] Dependencies configured in `terraform/stacks/deps/` +- [ ] Container definitions configured in `terraform/stacks/default/app.yaml` +- [ ] `atmos terraform plan app -s preview` runs successfully + - 2. ### Create a Pull Request +--- - Create a PR and add the `deploy` label to deploy a preview environment: +## Triggering Workflows - ```bash - git checkout -b feature/test-preview - # Make changes - git push origin feature/test-preview - ``` +Once setup is complete, validate the workflows: - Then add the `deploy` label to the PR in GitHub. + + + ### Create a Pull Request - 3. ### Publish a Release + Create a PR and add the `deploy` label to deploy a preview environment: - Edit the draft release created by the main branch workflow and click "Publish release". This will: - - Promote the Docker image tag - - Deploy to `staging` - - Wait for approval (if configured) - - Deploy to `prod` - + ```bash + git checkout -b feature/test-preview + # Make changes + git push origin feature/test-preview + ``` -## Local Development + Then add the `deploy` label to the PR in GitHub. + -Run the application locally using Podman Compose: + + ### Merge PR into Main Branch -```bash -# Build and run on http://localhost:8080 -atmos up + Push any change to the `main` branch to trigger the main branch workflow: -# Stop the application -atmos down -``` + ```bash + git add . + git commit -m "Initial setup" + git push origin main + ``` -Deploy manually using Atmos: + This will: + - Build and push a Docker image to ECR + - Deploy to the `dev` environment + - Create a draft release + -```bash -# Deploy to dev -atmos terraform deploy app -s dev -# View deployment URL -atmos terraform output app -s dev --skip-init -- -raw url -``` + + ### Publish a Release -## Next Steps + Edit the draft release created by the main branch workflow and click "Publish release". This will: + - Promote the Docker image tag + - Deploy to `staging` + - Wait for approval (if configured) + - Deploy to `prod` + + - - - [ ] Customize the application code in the `app/` directory - - [ ] Update Terraform components for your specific requirements - - [ ] Configure monitoring and alerting - - [ ] Set up log aggregation - - [ ] Configure auto-scaling policies - +--- ## References From e1a0628a4235f7a396af464b09a76fefe8a15298 Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Mon, 26 Jan 2026 21:32:46 +0100 Subject: [PATCH 5/8] Documented ECS deployment with atmos --- docs/layers/software-delivery/ecs-atmos/setup.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/layers/software-delivery/ecs-atmos/setup.mdx b/docs/layers/software-delivery/ecs-atmos/setup.mdx index 1e2f474a4..abc08199a 100644 --- a/docs/layers/software-delivery/ecs-atmos/setup.mdx +++ b/docs/layers/software-delivery/ecs-atmos/setup.mdx @@ -60,7 +60,7 @@ import TaskList from '@site/src/components/TaskList' ``` - These components are typically deployed once and shared across multiple applications. See the [ECS Cluster](/library/aws/ecs/) documentation for detailed setup instructions. + These components are typically deployed once and shared across multiple applications. See the [ECS Cluster](/components/library/aws/ecs/) documentation for detailed setup instructions. From f093f126c1678c71539bf49dacc586c25463fd5e Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 27 Jan 2026 14:23:34 +0100 Subject: [PATCH 6/8] Added software delivery --- docs/jumpstart/action-items.mdx | 22 ------------------- .../software-delivery/software-delivery.mdx | 1 + 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/docs/jumpstart/action-items.mdx b/docs/jumpstart/action-items.mdx index 7a55ed5bb..f1eb2e927 100644 --- a/docs/jumpstart/action-items.mdx +++ b/docs/jumpstart/action-items.mdx @@ -203,28 +203,6 @@ If your engagement with Cloud Posse includes Release Engineering, we will also n - - ### PATs for ECS with `ecspresso` (Deprecated) - - :::note - This step can likely be skipped. The ecspresso-based ECS deployment approach is deprecated in favor of [ECS with Atmos](/layers/software-delivery/ecs-atmos/), which does not require these PATs. - ::: - - - - Create one fine-grained PAT with the following permission. - Please see [Creating a fine-grained personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token) - - This PAT needs read access to your `infrastructure` repository: - - ```diff - Repository - + Contents: Read-only - + Metadata: Read-only - ``` - - Save the new fine-grained PAT as a GitHub environment secret in the new `example-app` private repository in your Organization. - - - ### PATs for EKS with ArgoCD diff --git a/docs/layers/software-delivery/software-delivery.mdx b/docs/layers/software-delivery/software-delivery.mdx index 3538c8324..e114a8521 100644 --- a/docs/layers/software-delivery/software-delivery.mdx +++ b/docs/layers/software-delivery/software-delivery.mdx @@ -1,5 +1,6 @@ --- title: Software Delivery +sidebar_position: 1 --- import Intro from '@site/src/components/Intro'; import Steps from '@site/src/components/Steps'; From 205135159b9b73790cf7e2d09f974405f0e0e77a Mon Sep 17 00:00:00 2001 From: Igor Rodionov Date: Tue, 27 Jan 2026 16:53:24 +0100 Subject: [PATCH 7/8] Address PR comments --- .../software-delivery/ecs-atmos/setup.mdx | 241 ++++-------------- .../ecs-atmos/triggering-workflows.mdx | 58 +++++ .../stacks/catalog/iam-role/example-app.yaml | 62 +++++ 3 files changed, 167 insertions(+), 194 deletions(-) create mode 100644 docs/layers/software-delivery/ecs-atmos/triggering-workflows.mdx create mode 100644 examples/snippets/stacks/catalog/iam-role/example-app.yaml diff --git a/docs/layers/software-delivery/ecs-atmos/setup.mdx b/docs/layers/software-delivery/ecs-atmos/setup.mdx index abc08199a..fd35b54fa 100644 --- a/docs/layers/software-delivery/ecs-atmos/setup.mdx +++ b/docs/layers/software-delivery/ecs-atmos/setup.mdx @@ -10,8 +10,11 @@ import Steps from '@site/src/components/Steps' import Step from '@site/src/components/Step' import StepNumber from '@site/src/components/StepNumber' import Note from '@site/src/components/Note' -import Admonition from '@theme/Admonition' import TaskList from '@site/src/components/TaskList' +import CollapsibleText from '@site/src/components/CollapsibleText'; +import Admonition from '@theme/Admonition' +import CodeBlock from '@theme/CodeBlock'; +import ApplicationIAMRole from '@site/examples/snippets/stacks/catalog/iam-role/example-app.yaml'; This setup guide walks you through deploying containerized applications to AWS ECS Fargate using Atmos for configuration orchestration and OpenTofu for infrastructure-as-code. The setup uses a self-contained approach where application infrastructure definitions and workflows reside in the application repository, while shared infrastructure is managed in the infra repository. @@ -21,77 +24,36 @@ import TaskList from '@site/src/components/TaskList' | Step | Action | Repository | | ---- | ------ | ---------- | -| 1. Deploy platform infrastructure | Deploy VPC, ECS cluster, GitHub OIDC Provider, ALB, etc. | `infra` | -| 2. Provision tfstate-bucket-app | Create Terraform state bucket for app repos (if not exists) | `infra` | -| 3. Create application repository | Create repo from [cloudposse-examples/app-on-ecs-v2](https://github.com/cloudposse-examples/app-on-ecs-v2) template | GitHub | -| 4. Provision ECR registry | Add ECR image repository for the app | `infra` | -| 5. Provision IAM roles | Create IAM roles for the app to assume | `infra` | -| 6. Update tfstate-bucket-app access | Grant IAM roles access to state bucket | `infra` | -| 7. Update profiles/github | Configure GitHub OIDC roles in app repo | `app` | -| 8. Configure GitHub repository | Add `ECR_REGISTRY` variable | GitHub UI | -| 9. Provision shared dependencies | Deploy app dependencies (databases, queues, etc.) | `infra` | -| 10. Configure dependencies | Set up remote state for infra components | `app` | -| 11. Configure container definitions | Define ECS task and container settings | `app` | -| 12. Test configuration | Run `atmos terraform plan app -s preview` | `app` | +| 1. Verify platform infrastructure | Confirm VPC, ECS cluster, GitHub OIDC Provider, TFstate bucket app are deployed | `infra` | +| 2. Create application repository | Create repo from [cloudposse-examples/app-on-ecs-v2](https://github.com/cloudposse-examples/app-on-ecs-v2) template | GitHub | +| 3. Provision ECR registry | Add ECR image repository for the app | `infra` | +| 4. Provision IAM roles | Create IAM roles for the app to assume | `infra` | +| 5. Update tfstate-bucket-app access | Grant IAM roles access to state bucket | `infra` | +| 6. Update profiles/github | Configure GitHub OIDC roles in app repo | `app` | +| 7. Configure GitHub repository | Add `ECR_REGISTRY` variable | GitHub UI | +| 8. Provision shared dependencies | Deploy app dependencies (databases, queues, etc.) | `infra` | +| 9. Configure dependencies | Set up remote state for infra components | `app` | +| 10. Configure container definitions | Define ECS task and container settings | `app` | +| 11. Test configuration | Run `atmos terraform plan app -s preview` | `app` | - ### Deploy Platform Infrastructure + ### Verify Platform Infrastructure - Deploy the foundational infrastructure components in your `infra` repository. + Before deploying an ECS application, verify that the following platform infrastructure components are already deployed in your target AWS accounts: - Ensure the following components are deployed in your target AWS accounts: - - ```bash - # Deploy VPC - atmos terraform deploy vpc -s plat-use1-dev - atmos terraform deploy vpc -s plat-use1-staging - atmos terraform deploy vpc -s plat-use1-prod - - # Deploy ECS Cluster - atmos terraform deploy ecs/cluster -s plat-use1-dev - atmos terraform deploy ecs/cluster -s plat-use1-staging - atmos terraform deploy ecs/cluster -s plat-use1-prod - - # Deploy Github OIDC Provider - atmos terraform deploy github-oidc-provider -s plat-gbl-dev - atmos terraform deploy github-oidc-provider -s plat-gbl-staging - atmos terraform deploy github-oidc-provider -s plat-gbl-prod - ``` + + - [ ] VPC deployed in each environment (`vpc` component) + - [ ] ECS cluster deployed in each environment (`ecs/cluster` component) + - [ ] GitHub OIDC Provider deployed in each environment (`github-oidc-provider` component) + - [ ] TFstate bucket app deployed in each environment (`tfstate-bucket-app` component) + - These components are typically deployed once and shared across multiple applications. See the [ECS Cluster](/components/library/aws/ecs/) documentation for detailed setup instructions. + These components are typically deployed once and shared across multiple applications. See the [ECS](/layers/ecs/) documentation for detailed setup instructions. - - ### Provision tfstate-bucket-app - - Create a Terraform state bucket for application repositories if one doesn't exist. - - In your `infra` repository, add the tfstate bucket configuration: - - ```yaml title="stacks/catalog/tfstate-backend/apps.yaml" - components: - terraform: - tfstate-backend-apps: - metadata: - component: tfstate-backend - vars: - enabled: true - name: tfstate-backend-apps - # Additional configuration as needed - ``` - - Deploy tfstate bucket: - - ```bash - atmos terraform deploy tfstate-bucket-apps -s plat-use1-dev - atmos terraform deploy tfstate-bucket-apps -s plat-use1-staging - atmos terraform deploy tfstate-bucket-apps -s plat-use1-prod - ``` - - ### Create Application Repository @@ -106,10 +68,12 @@ import TaskList from '@site/src/components/TaskList' The template includes: - - Sample Go application with Dockerfile - - GitHub Actions workflows for CI/CD - - Terraform/OpenTofu components for ECS task definitions - - Atmos stack configurations for each environment + + - [ ] Sample Go application with Dockerfile + - [ ] GitHub Actions workflows for CI/CD + - [ ] Terraform/OpenTofu components for ECS task definitions + - [ ] Atmos stack configurations for each environment + @@ -139,72 +103,10 @@ import TaskList from '@site/src/components/TaskList' Create IAM roles that the application will assume for deployments. - Create an IAM role configuration for the application: + + {ApplicationIAMRole} + - ```yaml title="stacks/catalog/iam-role/example-app.yaml" - import: - - catalog/iam-role/defaults - - components: - terraform: - example-app/iam-role: - metadata: - component: iam-role - inherits: - - iam-role/defaults - vars: - name: example-app - attributes: - - "terraform" - role_description: | - Role for GitHub Actions to access the GitOps resources, such as the S3 Bucket and DynamoDB Table. - github_oidc_provider_enabled: true - github_oidc_provider_arn: !terraform.state github-oidc-provider oidc_provider_arn - trusted_github_org: acme - trusted_github_repos: - - example-app - policy_statements: - AllowECRAccess: - effect: "Allow" - actions: - - "ecr:GetAuthorizationToken" - - "ecr:BatchCheckLayerAvailability" - - "ecr:GetDownloadUrlForLayer" - - "ecr:BatchGetImage" - - "ecr:InitiateLayerUpload" - - "ecr:UploadLayerPart" - - "ecr:CompleteLayerUpload" - - "ecr:PutImage" - - "ecr:CreatePullThroughCacheRule" - - "ecr:BatchImportUpstreamImage" - - "ecr:CreateRepository" - resources: - - "*" - AllowAssumeRole: - effect: "Allow" - actions: - - "sts:AssumeRole" - - "sts:TagSession" - - "sts:SetSourceIdentity" - resources: - - "*" - AllowServicesAccess: - effect: "Allow" - actions: - - "s3:*" - - "iam:*" - - "ecs:*" - - "ecr:*" - - "logs:*" - - "ssm:*" - - "ec2:*" - - "elasticloadbalancing:*" - - "application-autoscaling:*" - - "cloudwatch:*" - - "kms:Decrypt" - resources: - - "*" - ``` ```bash atmos terraform deploy example-app/iam-role -s plat-gbl-dev @@ -226,7 +128,7 @@ import TaskList from '@site/src/components/TaskList' tfstate-backend-apps: vars: privileged_principal_arns: - - !terraform.state example-app/iam-role .role.arn + - !terraform.state example-app/iam-role .role_arn ``` ```bash @@ -395,11 +297,12 @@ import TaskList from '@site/src/components/TaskList' ``` And/or update Terraform component (if needed). Modify the ECS task component in `terraform/components/ecs-task/` to match your application requirements: - - - Add additional IAM permissions - - Configure health check settings - - Set up log configuration - - Add sidecar containers + + 1. Add additional IAM permissions + 2. Configure health check settings + 3. Set up log configuration + 4. Add sidecar containers + @@ -412,17 +315,19 @@ import TaskList from '@site/src/components/TaskList' ``` Check that: - - All remote state references resolve correctly - - Container definitions are valid - - IAM roles and permissions are configured - - No errors in the plan output + + - [ ] All remote state references resolve correctly + - [ ] Container definitions are valid + - [ ] IAM roles and permissions are configured + - [ ] No errors in the plan output + ## Quick Checklist -- [ ] Platform infrastructure deployed (VPC, ECS cluster, GitHub OIDC Provider) +- [ ] Platform infrastructure verified (VPC, ECS cluster, GitHub OIDC Provider) - [ ] `tfstate-bucket-apps` provisioned in dev/staging/prod - [ ] Application repository created from template - [ ] ECR registry provisioned (`core-use1-artifacts`) @@ -436,58 +341,6 @@ import TaskList from '@site/src/components/TaskList' - [ ] `atmos terraform plan app -s preview` runs successfully ---- - -## Triggering Workflows - -Once setup is complete, validate the workflows: - - - - ### Create a Pull Request - - Create a PR and add the `deploy` label to deploy a preview environment: - - ```bash - git checkout -b feature/test-preview - # Make changes - git push origin feature/test-preview - ``` - - Then add the `deploy` label to the PR in GitHub. - - - - ### Merge PR into Main Branch - - Push any change to the `main` branch to trigger the main branch workflow: - - ```bash - git add . - git commit -m "Initial setup" - git push origin main - ``` - - This will: - - Build and push a Docker image to ECR - - Deploy to the `dev` environment - - Create a draft release - - - - - ### Publish a Release - - Edit the draft release created by the main branch workflow and click "Publish release". This will: - - Promote the Docker image tag - - Deploy to `staging` - - Wait for approval (if configured) - - Deploy to `prod` - - - ---- - ## References - [app-on-ecs-v2](https://github.com/cloudposse-examples/app-on-ecs-v2): Example application repository diff --git a/docs/layers/software-delivery/ecs-atmos/triggering-workflows.mdx b/docs/layers/software-delivery/ecs-atmos/triggering-workflows.mdx new file mode 100644 index 000000000..f22026187 --- /dev/null +++ b/docs/layers/software-delivery/ecs-atmos/triggering-workflows.mdx @@ -0,0 +1,58 @@ +--- +title: "Triggering Workflows" +sidebar_label: "Triggering Workflows" +sidebar_position: 20 +description: "How to trigger CI/CD workflows for ECS deployments" +--- +import Intro from '@site/src/components/Intro'; +import Steps from '@site/src/components/Steps' +import Step from '@site/src/components/Step' +import StepNumber from '@site/src/components/StepNumber' + + + Once the ECS application setup is complete, validate the CI/CD workflows by triggering deployments through pull requests and releases. + + + + + ### Create a Pull Request + + Create a PR and add the `deploy` label to deploy a preview environment: + + ```bash + git checkout -b feature/test-preview + # Make changes + git push origin feature/test-preview + ``` + + Then add the `deploy` label to the PR in GitHub. + + + + ### Merge PR into Main Branch + + Push any change to the `main` branch to trigger the main branch workflow: + + ```bash + git add . + git commit -m "Initial setup" + git push origin main + ``` + + This will: + - Build and push a Docker image to ECR + - Deploy to the `dev` environment + - Create a draft release + + + + + ### Publish a Release + + Edit the draft release created by the main branch workflow and click "Publish release". This will: + - Promote the Docker image tag + - Deploy to `staging` + - Wait for approval (if configured) + - Deploy to `prod` + + diff --git a/examples/snippets/stacks/catalog/iam-role/example-app.yaml b/examples/snippets/stacks/catalog/iam-role/example-app.yaml new file mode 100644 index 000000000..534e2e56a --- /dev/null +++ b/examples/snippets/stacks/catalog/iam-role/example-app.yaml @@ -0,0 +1,62 @@ + import: + - catalog/iam-role/defaults + + components: + terraform: + example-app/iam-role: + metadata: + component: iam-role + inherits: + - iam-role/defaults + vars: + name: example-app + attributes: + - "terraform" + role_description: | + Role for GitHub Actions to access the GitOps resources, such as the S3 Bucket and DynamoDB Table. + github_oidc_provider_enabled: true + github_oidc_provider_arn: !terraform.state github-oidc-provider oidc_provider_arn + trusted_github_org: acme + trusted_github_repos: + - example-app + policy_statements: + AllowECRAccess: + effect: "Allow" + actions: + - "ecr:GetAuthorizationToken" + - "ecr:BatchCheckLayerAvailability" + - "ecr:GetDownloadUrlForLayer" + - "ecr:BatchGetImage" + - "ecr:InitiateLayerUpload" + - "ecr:UploadLayerPart" + - "ecr:CompleteLayerUpload" + - "ecr:PutImage" + - "ecr:CreatePullThroughCacheRule" + - "ecr:BatchImportUpstreamImage" + - "ecr:CreateRepository" + resources: + - "*" + AllowAssumeRole: + effect: "Allow" + actions: + - "sts:AssumeRole" + - "sts:TagSession" + - "sts:SetSourceIdentity" + resources: + - "*" + AllowServicesAccess: + effect: "Allow" + actions: + - "s3:*" + - "iam:*" + - "ecs:*" + - "ecr:*" + - "logs:*" + - "ssm:*" + - "ec2:*" + - "elasticloadbalancing:*" + - "application-autoscaling:*" + - "cloudwatch:*" + - "kms:Decrypt" + resources: + - "*" From 98e43212b5aaa65f717ddce5b1644bbcda829228 Mon Sep 17 00:00:00 2001 From: Igor Rodionov <496956+goruha@users.noreply.github.com> Date: Thu, 29 Jan 2026 22:15:28 +0300 Subject: [PATCH 8/8] Update docs/layers/software-delivery/ecs-atmos/setup.mdx Co-authored-by: Dan Miller --- docs/layers/software-delivery/ecs-atmos/setup.mdx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/layers/software-delivery/ecs-atmos/setup.mdx b/docs/layers/software-delivery/ecs-atmos/setup.mdx index fd35b54fa..4b5dd25a5 100644 --- a/docs/layers/software-delivery/ecs-atmos/setup.mdx +++ b/docs/layers/software-delivery/ecs-atmos/setup.mdx @@ -221,9 +221,13 @@ import ApplicationIAMRole from '@site/examples/snippets/stacks/catalog/iam-role/ ### Configure Dependencies - Configure the application to read from infrastructure components' remote state. + Your application needs to reference infrastructure that was already deployed by your infrastructure repository — specifically the VPC and ECS cluster. These dependency files tell Atmos where to find the Terraform backend for those resources, allowing your application stacks to look up output values like VPC IDs, subnet IDs, and cluster ARNs. - In your **application repository**, create dependency stack files: + :::tip + These files don't deploy any infrastructure. They define how to read the remote state of existing infrastructure components. + ::: + + In your **application repository**, create dependency stack files for each infrastructure component you need to reference: ```yaml title="terraform/stacks/deps/vpc.yaml" components: