Website

We use S3 buckets to host files, and Amazon CloudFront to servce the files.

CloudFront to S3

CloudFront to S3

Minimal working example

The following code creates a client application that will be reachable from https://kattehotell.dev.bymoslo.net:

main.tf
module "application" {
  source           = "git@github.com:BYM-IKT/terraform-byks-module.git"
  team             = var.team
  account_id       = var.account_id
  environment      = var.environment
  region           = var.region
  application_name = var.application_name

  cloudfront_distributions = {
    kattehotell = {}
  }

  providers = {
    aws.route53   = aws.route53
    aws.us-east-1 = aws.us-east-1
    aws.ses       = aws.ses
  }
}

Note

The domain resulting is automatically inferred using the value of environment, i.e.:

`dev`  => `dev.bymoslo.net`
`test` => `test.bymoslo.net`
`prod` => `bymoslo.no`

Tutorial

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: Create a S3 bucket + CloudFront

Add the following code snippet to your Terraform project:

main.tf
module "application" {
  source      = "git@github.com:BYM-IKT/terraform-byks-module.git"
  environment = "test"
  ...
  cloudfront_distributions = {
    kattehotell = {}
  }
}

Create a Pull Request to Terraform apply this change.

This will provision two resources:

  • A new S3 bucket named ${environment}-${application_name}-${service}. In this example: test-kattehotell-kattehotell.
  • A CloudFront distribution that serves the content of the S3 bucket. The resulting FQDN is generated from the key used (here: kattehotell). In this example, the resulting FQDN will therefore become: https://kattehotell.test.bymoslo.net.

Step 2: Compile and push the code to S3 Bucket

  1. Create a GitHub Actions workflow file .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: [master]
      workflow_dispatch:
    
    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:  https://kattehotell.test.bymoslo.net
        steps:
          - uses: actions/checkout@v4
    
          - uses: pnpm/action-setup@v4
            with:
              version: 10
              package_json_file: ./package.json
    
          - uses: actions/setup-node@v4
            with:
              node-version: 24
    
          - name: Install dependencies
            run: pnpm install
    
          - name: Build
            env:
              CI: false
            run: pnpm build --emptyOutDir --outDir 'build'
    
          - name: Upload to S3 and invalidate CloudFront cache
            uses: BYM-IKT/github-actions/upload-to-s3-and-invalidate-cloudfront@master
            with:
              aws-account-id:                      "<<AWS_ACCOUNT_ID>>"
              s3-bucket-name:                      test-kattehotell-kattehotell
              build-directory:                     ./build
              cloudfront-distribution-domain-name: https://kattehotell.test.bymoslo.net
    
    where <<AWS_ACCOUNT_ID>> is replaced with the Id of your AWS Account.
  2. Run the pipeline.
  3. Verify that the website is online.