Create Outstanding AWS Infrastructure with Terraform and Qovery

Terraform combined with Qovery is like giving superpower to DevOps and developers. I am super excited to launch a brand new GitHub repository with "ready-to-use" examples to deploy crazy AWS cloud architecture with Terraform and Qovery. Feel free to use them, modify them and share them with us and our community.

Romaric Philogène

Romaric Philogène

June 22, 2022 · 4 min read
Create Outstanding AWS Infrastructure with Terraform and Qovery - Qovery
Written byRomaric Philogène

Romaric Philogène

CEO and co-founder of Qovery. Romaric has 10+ years of experience in R&D. From the Ad-Tech to the financial industry, he has deep expertise in highly-reliable and performant systems.

See all articles
TerraformQoveryAWS

It's an excellent way to familiarize yourself with Terraform, AWS, and how to use Qovery. Thousands of developers and DevOps build outstanding infrastructure on top of AWS. We are eager to share the best practices and ready-to-use architecture for your personal and professional projects.

If you are not familiar with Terraform and Qovery, watch our introduction video.

AWS architecture examples

The Terraform Examples can help you to jumpstart using AWS on production-ready infrastructure like the following one

Deploy an application with a PostgreSQL database on AWS and 3 environments (Production, Staging, Development)

Full Production, Staging and Dev environments on AWS with Kubernetes and RDS
Full Production, Staging and Dev environments on AWS with Kubernetes and RDS

Here is an example of what the Terraform looks like to create the production environment. Note: every environment is running into a dedicated VPC.

resource "qovery_aws_credentials" "my_aws_creds" {
  organization_id   = var.qovery_organization_id
  name              = "URL Shortener"
  access_key_id     = var.aws_access_key_id
  secret_access_key = var.aws_secret_access_key
}

resource "qovery_cluster" "production_cluster" {
  organization_id   = var.qovery_organization_id
  credentials_id    = qovery_aws_credentials.my_aws_creds.id
  name              = "Production cluster"
  description       = "Terraform prod demo cluster"
  cloud_provider    = "AWS"
  region            = "us-east-2"
  instance_type     = "T3A_MEDIUM"
  min_running_nodes = 3
  max_running_nodes = 4
  state             = "RUNNING"

  depends_on = [
    qovery_aws_credentials.my_aws_creds
  ]
}

resource "qovery_cluster" "staging_cluster" {
  organization_id   = var.qovery_organization_id
  credentials_id    = qovery_aws_credentials.my_aws_creds.id
  name              = "Staging cluster"
  description       = "Terraform staging demo cluster"
  cloud_provider    = "AWS"
  region            = "us-east-2"
  instance_type     = "T3A_MEDIUM"
  min_running_nodes = 3
  max_running_nodes = 4
  state             = "RUNNING"

  depends_on = [
    qovery_aws_credentials.my_aws_creds
  ]
}

resource "qovery_cluster" "dev_cluster" {
  organization_id   = var.qovery_organization_id
  credentials_id    = qovery_aws_credentials.my_aws_creds.id
  name              = "Dev cluster"
  description       = "Terraform dev demo cluster"
  cloud_provider    = "AWS"
  region            = "us-east-2"
  instance_type     = "T3A_MEDIUM"
  min_running_nodes = 3
  max_running_nodes = 4
  state             = "RUNNING"

  depends_on = [
    qovery_aws_credentials.my_aws_creds
  ]
}


resource "qovery_project" "my_project" {
  organization_id = var.qovery_organization_id
  name            = "Multi-env Project"

  depends_on = [
    qovery_cluster.production_cluster
  ]
}

resource "qovery_environment" "production" {
  project_id = qovery_project.my_project.id
  name       = "production"
  mode       = "PRODUCTION"
  cluster_id = qovery_cluster.production_cluster.id

  depends_on = [
    qovery_project.my_project
  ]
}

resource "qovery_database" "production_psql_database" {
  environment_id = qovery_environment.production.id
  name           = "strapi db"
  type           = "POSTGRESQL"
  version        = "13"
  mode           = "MANAGED" # Use AWS RDS for PostgreSQL (backup and PITR automatically configured by Qovery)
  storage        = 10 # 10GB of storage
  accessibility  = "PRIVATE" # do not make it publicly accessible
  state          = "RUNNING"

  depends_on = [
    qovery_environment.production,
  ]
}

resource "qovery_application" "production_strapi_app" {
  environment_id = qovery_environment.production.id
  name           = "strapi app"
  cpu            = 1000
  memory         = 512
  state          = "RUNNING"
  git_repository = {
    url       = "https://github.com/evoxmusic/strapi-v4.git"
    branch    = "main"
    root_path = "/"
  }
  build_mode            = "DOCKER"
  dockerfile_path       = "Dockerfile"
  min_running_instances = 1
  max_running_instances = 1
  ports                 = [
    {
      internal_port       = 1337
      external_port       = 443
      protocol            = "HTTP"
      publicly_accessible = true
    }
  ]
  environment_variables = [
    {
      key   = "PORT"
      value = "1337"
    },
    {
      key   = "HOST"
      value = "0.0.0.0"
    },
    {
      key   = "DATABASE_HOST"
      value = qovery_database.production_psql_database.internal_host
    },
    {
      key   = "DATABASE_PORT"
      value = qovery_database.production_psql_database.port
    },
    {
      key   = "DATABASE_USERNAME"
      value = qovery_database.production_psql_database.login
    },
    {
      key   = "DATABASE_NAME"
      value = "postgres"
    },
  ]
  secrets = [
    {
      key   = "ADMIN_JWT_SECRET"
      value = var.strapi_admin_jwt_secret
    },
    {
      key   = "API_TOKEN_SALT"
      value = var.strapi_api_token_salt
    },
    {
      key   = "APP_KEYS"
      value = var.strapi_app_keys
    },
    {
      key   = "DATABASE_PASSWORD"
      value = qovery_database.production_psql_database.password
    }
  ]

  depends_on = [
    qovery_environment.production,
    qovery_database.production_psql_database,
  ]
}

Check out the complete Terraform manifest file here.

Behind the scene, Qovery:

  1. Creates 3 Kubernetes clusters (`Production`, `Staging`, `Dev`) on your AWS account (VPC, Security Groups, Subnet, EKS/Kubernetes...)
  2. Creates Qovery Organization `Terraform Demo`
  3. Creates Qovery Project `Strapi V4`
  4. Creates Qovery Environment `production`
  5. Creates Qovery Database `strapi db` (RDS) for `Production`
  6. Application `strapi app` for `Production`
  7. Creates Qovery Environment `staging`
  8. Database `strapi db` (RDS) for `Staging`
  9. Application `strapi app` for `Staging`
  10. Environment `dev`
  11. Database `strapi db` (Container with EBS) for `Dev`
  12. Application `strapi app` for `Dev`
  13. Inject all the Secrets and Environment Variables used by the app for every environment
  14. Builds `strapi app` application for `Production`, `Staging` and `Dev` environments in parallel
  15. Pushes `strapi app` container image in your ECR registry for `Production`, `Staging` and `Dev` environments in parallel
  16. Deploys your PostgreSQL database for `Production` (AWS RDS), `Staging` (AWS RDS) and `Dev` (Container) environments in parallel
  17. Deploys `strapi app` on your `Production`, `Staging` and `Dev` EKS clusters
  18. Creates an AWS Network Load Balancer for all your clusters and apps
  19. Generates a TLS certificate for your app for all your apps
  20. Exposes publicly via HTTPS your Strapi app from `Production`, `Staging` and `Dev` through different endpoints

Terraform takes takes approximately 30 minutes per environment👍 So technically speaking you can have a Production, Staging and Dev environment in less than 2 hours and by letting Terraform and Qovery doing the job for your on your AWS account 😎

What's next?

Check out our Terraform Examples repository now and feel free to contribute.

TerraformQoveryAWS

You might also like

37 minutes to deploy a fullstack app on my new AWS account

Today, I was working on our Terraform Provider, and I noticed that I never tried to deploy an application from scratch on a new and clean AWS account. Meaning, an empty AWS account - with 0 resources created. No VPC, no EC2, no Load Balancer, nothing... just an IAM user to get access to my AWS account programmatically. This post explains what I did and how it took 37 minutes and 33 seconds to literally: create a VPC (10 min) create an EKS cluster and a load balancer (5 min) create an ECR repository (10 sec) deploy an RDS database (15 min) build and deploy my Django app from GitHub (2 min) add a custom domain to my app (2 min) create a TLS for my custom domain (15 sec) And tada! 🎉 😅 Let's explain all of that! - Read more

February 26, 2022 · 5 min read
37 minutes to deploy a fullstack app on my new AWS account