Skip to content

Create a S3 bucket + CloudFront

These steps assume that your repository has a project structure as follows:

GitHub repository containing your source code
├── src/
│   ├── ...
│   └── main.tsx
├── ...
├── package.json
└── index.html

Step 1: Provision the S3 bucket and CloudFront distribution

Infrastructure at BYM is provisioned through Terraform, not the AWS console. You add a small configuration block to your product's Terraform Infrastruktur-repo and a pipeline applies it.

  1. Add the following to main.tf in your Infrastruktur-repo:

    main.tf
    module "application" {
      source = "git@github.com:BYM-IKT/terraform-byks-module.git?ref=v12"
      team             = var.team
      account_id       = var.account_id
      environment      = var.environment
      application_name = var.application_name
    
      cloudfront_distributions = {
        kattehotell = {} # Replace 'kattehotell' with your domain name
      }
    
      providers = {
        aws.route53   = aws.route53
        aws.us-east-1 = aws.us-east-1
        aws.ses       = aws.ses
      }
    }
    
  2. Set application_name and environment in environment.tf:

    environment.tf
    # ...
    variable "environment" {
      default = "test" # dev, test or prod
    }
    
    variable "application_name" {
      default = "katteapp" # Replace with your application name
    }
    # ...
    
  3. Open a pull request against the Infrastruktur-repo and merge it.

Merging provisions two resources:

  • An S3 bucket named ${environment}-${application_name}-${domain_name}, for example test-katteapp-kattehotell.
  • A CloudFront distribution that serves the bucket's content over HTTPS at a domain generated from the key used above, for example https://kattehotell.test.bymoslo.net.

See adding more domains if the app needs to answer on more than one URL.

Step 2: Request pipeline access from Team Cloud

The GitHub Actions workflow in the next step needs permission to write to your AWS account and invalidate the CloudFront cache. Contact Team Cloud on the #cloud-infrastructure Slack channel and provide:

  • The full name of your GitHub repository, for example BYM-IKT/KatteApp
  • The AWS account names that need access, for example BYM-DP-Katteapp-Test and BYM-DP-Katteapp-Prod

See GitHub Actions OIDC for how this access works.

Step 3: Add the GitHub Actions workflow file

In your application's source code, create a workflow file at .github/workflows/deploy-to-test.yml:

.
├── .github/
│   └── workflows/
│       └── deploy-to-test.yml
├── src/
│   ├── ...
│   └── main.tsx
├── ...
├── package.json
└── index.html

with the following content:

./.github/workflows/deploy-to-test.yml
name: Build and deploy website to TEST

on:
  push:
    branches: [main]

env:
  APP_URL: https://kattehotell.test.bymoslo.net # Replace with your application URL without quotes
  AWS_ACCOUNT_ID: "<<AWS_ACCOUNT_ID>>"
  S3_BUCKET_NAME: "<<S3_BUCKET_NAME>>"
  PROJECT_DIRECTORY: "."
  BUILD_PATH: "build"

jobs:
  deploy-to-test:
    name: Build app and deploy to TEST
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    environment:
      name: testing
      url: ${{ env.APP_URL }}
    steps:
      - name: Check out repository
        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3

      - name: Set up pnpm
        uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
        with:
          version: 10
          package_json_file: ./package.json

      - name: Set up Node.js
        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
        with:
          node-version: 24

      - name: Install dependencies
        run: pnpm install

      - name: Build
        env:
          CI: false
        run: pnpm build --emptyOutDir --outDir '${{ env.BUILD_PATH }}'

      - name: Upload to S3 and invalidate CloudFront cache
        uses: BYM-IKT/github-actions/upload-to-s3-and-invalidate-cloudfront@master
        with:
          aws-account-id:                      ${{ env.AWS_ACCOUNT_ID }}
          s3-bucket-name:                      ${{ env.S3_BUCKET_NAME }}
          build-directory:                     ${{ env.PROJECT_DIRECTORY }}/${{ env.BUILD_PATH }}
          cloudfront-distribution-domain-name: ${{ env.APP_URL }}

Replace <<AWS_ACCOUNT_ID>> with the ID of your AWS account and <<S3_BUCKET_NAME>> with the bucket name from Step 1.

Tip

Not sure about the AWS account ID? Look for the default-account.tf file in your product's Terraform Infrastruktur-repo. The AWS account ID is the 12-digit number used for the account_id variable.

You can also log in to the AWS Access Portal to find the account ID.

Step 4: Push and verify

Push to main. The workflow builds the app and uploads it to S3, then invalidates the CloudFront cache.

  1. Open the Actions tab in the application repository and confirm the workflow run succeeds.
  2. Visit APP_URL from the workflow and confirm the app loads.