Deploy an app on AWS with GitHub, Qovery and Terraform
Tags: terraform, aws
Published: 2022-06-19 14:09:40

This ready to use tutorial show you how to deploy an application from GitHub on AWS and make it accessible via HTTPS. All of that in just a few lines of Terraform file.

## Behind the scene

Behind the scene, Qovery will:

1. Create a full Kubernetes infrastructure on your AWS account (VPC, Security Groups, Subnet, EKS...)
2. Create Qovery resources:
   1. Organization `Terraform Demo`
   2. Project `URL Shortener`
   3. Environment `production`
   4. Application `web app`
3. Build the `web app` application
4. Push the `web app` container image in your ECR registry
5. Deploy it on your EKS cluster (created by Qovery)
6. Create an AWS Network Load Balancer
7. Generate a TLS certificate for your app
8. Expose publicly via HTTPS your application

It will take approximately **20 minutes to create your infrastructure** and **less than 5 minutes to deploy your application**.

## How to use

1. Clone this repository
2. Sign in to [Qovery](https://www.qovery.com)
3. Install the Qovery CLI and generate an API Token with this guide.
4. Generate your AWS credentials (`Access Key ID` and `Secret Access Key`)
   with [this guide](https://hub.qovery.com/docs/using-qovery/configuration/cloud-service-provider/amazon-web-services/#connect-your-aws-account)
5. Open you terminal and run the following command by changing the values:

```shell
export TF_VAR_aws_access_key_id=YOUR_AWS_ACCESS_KEY_ID \
TF_VAR_aws_secret_access_key=YOUR_AWS_SECRET_ACCESS_KEY \
TF_VAR_qovery_access_token=YOUR_QOVERY_API_TOKEN \
TF_VAR_qovery_organization_id=YOUR_QOVERY_ORG_ID
```

6. Clone my [URL Shortener application](https://github.com/evoxmusic/ShortMe-URL-Shortener.git)
7. Edit the `main.tf` file and change `https://github.com/evoxmusic/ShortMe-URL-Shortener.git` with yours
8. You can now run the Terraform commands

```shell
terraform init
```

```shell
terraform plan
```

```shell
terraform apply
```

7. Open your Qovery console to find out the HTTPS URL of your deployed app.
8. To tear down your infrastructure and avoid unnecessary cloud costs you can run `terraform destroy`.

--

And here is what happened when running `terraform apply`

```
terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated
with the following symbols:
  + create

Terraform will perform the following actions:

  # qovery_application.backend will be created
  + resource "qovery_application" "backend" {
      + auto_preview                   = false
      + build_mode                     = "BUILDPACKS"
      + buildpack_language             = "PYTHON"
      + built_in_environment_variables = [
        ] -> (known after apply)
      + cpu                            = 500
      + environment_id                 = (known after apply)
      + environment_variables          = [
          + {
              + id    = (known after apply)
              + key   = "DEBUG"
              + value = "false"
            },
          + {
              + id    = (known after apply)
              + key   = "PORT"
              + value = "3333"
            },
        ]
      + git_repository                 = {
          + branch    = "main"
          + root_path = "/"
          + url       = "https://github.com/evoxmusic/ShortMe-URL-Shortener.git"
        }
      + id                             = (known after apply)
      + max_running_instances          = 1
      + memory                         = 256
      + min_running_instances          = 1
      + name                           = "backend"
      + ports                          = [
          + {
              + external_port       = 443
              + id                  = (known after apply)
              + internal_port       = 3333
              + protocol            = "HTTP"
              + publicly_accessible = true
            },
        ]
      + state                          = "RUNNING"
    }

  # qovery_aws_credentials.my_aws_creds will be created
  + resource "qovery_aws_credentials" "my_aws_creds" {
      + access_key_id     = (sensitive value)
      + id                = (known after apply)
      + name              = "URL Shortener"
      + organization_id   = "67df37d8-6139-42eb-8c60-452395d12222"
      + secret_access_key = (sensitive value)
    }

  # qovery_cluster.my_cluster will be created
  + resource "qovery_cluster" "my_cluster" {
      + cloud_provider    = "AWS"
      + credentials_id    = (known after apply)
      + description       = "Terraform demo cluster"
      + features          = {
          + vpc_subnet = (known after apply)
        }
      + id                = (known after apply)
      + instance_type     = "T3A_MEDIUM"
      + max_running_nodes = 4
      + min_running_nodes = 3
      + name              = "Demo cluster"
      + organization_id   = "67df37d8-6139-42eb-8c60-452395d1c2ab"
      + region            = "us-east-2"
      + state             = "RUNNING"
    }

  # qovery_environment.production will be created
  + resource "qovery_environment" "production" {
      + built_in_environment_variables = [
        ] -> (known after apply)
      + cluster_id                     = (known after apply)
      + id                             = (known after apply)
      + mode                           = "DEVELOPMENT"
      + name                           = "dev"
      + project_id                     = (known after apply)
    }

  # qovery_project.my_project will be created
  + resource "qovery_project" "my_project" {
      + built_in_environment_variables = [
        ] -> (known after apply)
      + description                    = (known after apply)
      + id                             = (known after apply)
      + name                           = "URL Shortener"
      + organization_id                = "67df37d8-6139-42eb-8c60-452395d1c2ab"
    }

Plan: 5 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

qovery_aws_credentials.my_aws_creds: Creating...
qovery_aws_credentials.my_aws_creds: Creation complete after 0s [id=d2cfe19d-6381-4676-99e6-6721182f0c4c]
qovery_cluster.my_cluster: Creating...
qovery_cluster.my_cluster: Still creating... [10s elapsed]
qovery_cluster.my_cluster: Still creating... [20s elapsed]
qovery_cluster.my_cluster: Still creating... [30s elapsed]
qovery_cluster.my_cluster: Still creating... [40s elapsed]
qovery_cluster.my_cluster: Still creating... [50s elapsed]
qovery_cluster.my_cluster: Still creating... [1m0s elapsed]
qovery_cluster.my_cluster: Still creating... [1m10s elapsed]
qovery_cluster.my_cluster: Still creating... [1m20s elapsed]
qovery_cluster.my_cluster: Still creating... [1m30s elapsed]
qovery_cluster.my_cluster: Still creating... [1m40s elapsed]
qovery_cluster.my_cluster: Still creating... [1m50s elapsed]
qovery_cluster.my_cluster: Still creating... [2m0s elapsed]
qovery_cluster.my_cluster: Still creating... [2m10s elapsed]
qovery_cluster.my_cluster: Still creating... [2m20s elapsed]
qovery_cluster.my_cluster: Still creating... [2m30s elapsed]
qovery_cluster.my_cluster: Still creating... [2m40s elapsed]
qovery_cluster.my_cluster: Still creating... [2m50s elapsed]
qovery_cluster.my_cluster: Still creating... [3m0s elapsed]
qovery_cluster.my_cluster: Still creating... [3m10s elapsed]
qovery_cluster.my_cluster: Still creating... [3m20s elapsed]
qovery_cluster.my_cluster: Still creating... [3m30s elapsed]
qovery_cluster.my_cluster: Still creating... [3m40s elapsed]
qovery_cluster.my_cluster: Still creating... [3m50s elapsed]
qovery_cluster.my_cluster: Still creating... [4m0s elapsed]
qovery_cluster.my_cluster: Still creating... [4m10s elapsed]
qovery_cluster.my_cluster: Still creating... [4m20s elapsed]
qovery_cluster.my_cluster: Still creating... [4m30s elapsed]
qovery_cluster.my_cluster: Still creating... [4m40s elapsed]
qovery_cluster.my_cluster: Still creating... [4m50s elapsed]
qovery_cluster.my_cluster: Still creating... [5m0s elapsed]
qovery_cluster.my_cluster: Still creating... [5m10s elapsed]
qovery_cluster.my_cluster: Still creating... [5m20s elapsed]
qovery_cluster.my_cluster: Still creating... [5m30s elapsed]
qovery_cluster.my_cluster: Still creating... [5m40s elapsed]
qovery_cluster.my_cluster: Still creating... [5m50s elapsed]
qovery_cluster.my_cluster: Still creating... [6m0s elapsed]
qovery_cluster.my_cluster: Still creating... [6m10s elapsed]
qovery_cluster.my_cluster: Still creating... [6m20s elapsed]
qovery_cluster.my_cluster: Still creating... [6m30s elapsed]
qovery_cluster.my_cluster: Still creating... [6m40s elapsed]
qovery_cluster.my_cluster: Still creating... [6m50s elapsed]
qovery_cluster.my_cluster: Still creating... [7m0s elapsed]
qovery_cluster.my_cluster: Still creating... [7m10s elapsed]
qovery_cluster.my_cluster: Still creating... [7m20s elapsed]
qovery_cluster.my_cluster: Still creating... [7m30s elapsed]
qovery_cluster.my_cluster: Still creating... [7m40s elapsed]
qovery_cluster.my_cluster: Still creating... [7m50s elapsed]
qovery_cluster.my_cluster: Still creating... [8m0s elapsed]
qovery_cluster.my_cluster: Still creating... [8m10s elapsed]
qovery_cluster.my_cluster: Still creating... [8m20s elapsed]
qovery_cluster.my_cluster: Still creating... [8m30s elapsed]
qovery_cluster.my_cluster: Still creating... [8m40s elapsed]
qovery_cluster.my_cluster: Still creating... [8m50s elapsed]
qovery_cluster.my_cluster: Still creating... [9m0s elapsed]
qovery_cluster.my_cluster: Still creating... [9m10s elapsed]
qovery_cluster.my_cluster: Still creating... [9m20s elapsed]
qovery_cluster.my_cluster: Still creating... [9m30s elapsed]
qovery_cluster.my_cluster: Still creating... [9m40s elapsed]
qovery_cluster.my_cluster: Still creating... [9m50s elapsed]
qovery_cluster.my_cluster: Still creating... [10m0s elapsed]
qovery_cluster.my_cluster: Still creating... [10m10s elapsed]
qovery_cluster.my_cluster: Still creating... [10m20s elapsed]
qovery_cluster.my_cluster: Still creating... [10m30s elapsed]
qovery_cluster.my_cluster: Still creating... [10m40s elapsed]
qovery_cluster.my_cluster: Still creating... [10m50s elapsed]
qovery_cluster.my_cluster: Still creating... [11m0s elapsed]
qovery_cluster.my_cluster: Still creating... [11m10s elapsed]
qovery_cluster.my_cluster: Still creating... [11m20s elapsed]
qovery_cluster.my_cluster: Still creating... [11m30s elapsed]
qovery_cluster.my_cluster: Still creating... [11m40s elapsed]
qovery_cluster.my_cluster: Still creating... [11m50s elapsed]
qovery_cluster.my_cluster: Still creating... [12m0s elapsed]
qovery_cluster.my_cluster: Still creating... [12m10s elapsed]
qovery_cluster.my_cluster: Still creating... [12m20s elapsed]
qovery_cluster.my_cluster: Still creating... [12m30s elapsed]
qovery_cluster.my_cluster: Still creating... [12m40s elapsed]
qovery_cluster.my_cluster: Still creating... [12m50s elapsed]
qovery_cluster.my_cluster: Still creating... [13m0s elapsed]
qovery_cluster.my_cluster: Still creating... [13m10s elapsed]
qovery_cluster.my_cluster: Still creating... [13m20s elapsed]
qovery_cluster.my_cluster: Still creating... [13m30s elapsed]
qovery_cluster.my_cluster: Still creating... [13m40s elapsed]
qovery_cluster.my_cluster: Still creating... [13m50s elapsed]
qovery_cluster.my_cluster: Still creating... [14m0s elapsed]
qovery_cluster.my_cluster: Still creating... [14m10s elapsed]
qovery_cluster.my_cluster: Still creating... [14m20s elapsed]
qovery_cluster.my_cluster: Still creating... [14m30s elapsed]
qovery_cluster.my_cluster: Still creating... [14m40s elapsed]
qovery_cluster.my_cluster: Still creating... [14m50s elapsed]
qovery_cluster.my_cluster: Still creating... [15m0s elapsed]
qovery_cluster.my_cluster: Still creating... [15m10s elapsed]
qovery_cluster.my_cluster: Still creating... [15m20s elapsed]
qovery_cluster.my_cluster: Still creating... [15m30s elapsed]
qovery_cluster.my_cluster: Still creating... [15m40s elapsed]
qovery_cluster.my_cluster: Still creating... [15m50s elapsed]
qovery_cluster.my_cluster: Still creating... [16m0s elapsed]
qovery_cluster.my_cluster: Still creating... [16m10s elapsed]
qovery_cluster.my_cluster: Still creating... [16m20s elapsed]
qovery_cluster.my_cluster: Still creating... [16m30s elapsed]
qovery_cluster.my_cluster: Still creating... [16m40s elapsed]
qovery_cluster.my_cluster: Still creating... [16m50s elapsed]
qovery_cluster.my_cluster: Still creating... [17m0s elapsed]
qovery_cluster.my_cluster: Still creating... [17m10s elapsed]
qovery_cluster.my_cluster: Still creating... [17m20s elapsed]
qovery_cluster.my_cluster: Still creating... [17m30s elapsed]
qovery_cluster.my_cluster: Still creating... [17m40s elapsed]
qovery_cluster.my_cluster: Still creating... [17m50s elapsed]
qovery_cluster.my_cluster: Still creating... [18m0s elapsed]
qovery_cluster.my_cluster: Still creating... [18m10s elapsed]
qovery_cluster.my_cluster: Creation complete after 18m12s [id=782f5b71-5786-4ff6-895a-277cd432dc1e]
qovery_project.my_project: Creating...
qovery_project.my_project: Creation complete after 0s [id=2fa442d0-f798-46f8-9a1a-b33317c507ea]
qovery_environment.production: Creating...
qovery_environment.production: Creation complete after 0s [id=8418d920-c508-4ea2-b669-72b1fedc3a3e]
qovery_application.backend: Creating...
qovery_application.backend: Still creating... [10s elapsed]
qovery_application.backend: Still creating... [20s elapsed]
qovery_application.backend: Still creating... [30s elapsed]
qovery_application.backend: Still creating... [40s elapsed]
qovery_application.backend: Still creating... [50s elapsed]
qovery_application.backend: Still creating... [1m0s elapsed]
qovery_application.backend: Still creating... [1m10s elapsed]
qovery_application.backend: Still creating... [1m20s elapsed]
qovery_application.backend: Still creating... [1m30s elapsed]
qovery_application.backend: Still creating... [1m40s elapsed]
qovery_application.backend: Still creating... [1m50s elapsed]
qovery_application.backend: Still creating... [2m0s elapsed]
qovery_application.backend: Still creating... [2m10s elapsed]
qovery_application.backend: Still creating... [2m20s elapsed]
qovery_application.backend: Creation complete after 2m23s [id=8dd99960-939c-4328-9a38-fdea20d7db8a]

Apply complete! Resources: 5 added, 0 changed, 0 destroyed.
```

I hope you liked it!