Heroku

We've chosen to use Heroku to host the app, yet we'll avoid any Heroku specific features so that we can easily move the app elsewhere as required. To start we need to activate the Heroku Terraform provider by adding the following to infrastructure/main.tf,

terraform {
  required_providers {
    ...
    heroku = {
      source  = "heroku/heroku"
      version = ">=4.6.0"
    }
  }
}

and running terraform init to initialise it.

Next we should register with Heroku and retreive an api key from the settings, and then add it and your username to infrastructure/secrets.auto.tfvars,

heroku_api_key  = "abcd"
heroku_username = "you@something.tld"

Which we can use to configure the provider by adding the following to infrastructure/heroku.tf,

variable "heroku_api_key" {
  sensitive = true
}

variable "heroku_username" {
  sensitive = true
}

provider "heroku" {
  email   = var.heroku_username
  api_key = var.heroku_api_key
}

Heroku splits deployments into apps and we'll need one for our app. This should be based in the eu or us and use the container stack (as we'll deploy our docker container). In addition we should add the minimal configuration, consisting of a secret key and a base url. The following should be added to infrastructure/heroku.tf,

variable "secret_key" {
  sensitive = true
}

resource "heroku_app" "tozo" {
  name   = "tozo"
  region = "eu"
  stack  = "container"

  config_vars = {
    BASE_URL = "https://tozo.dev"
    QUART_AUTH_COOKIE_NAME = "__Host-tozo-session"
  }

  sensitive_config_vars = {
    SECRET_KEY = var.secret_key
  }
}

Note

You'll need to create a value for the secret key and place it in infrastructure/secrets.auto.tfvars.

We'll then need to add a postgresql database to this app by adding the following to infrastructure/heroku.tf,

resource "heroku_addon" "tozo-db" {
  app  = heroku_app.tozo.name
  plan = "heroku-postgresql:hobby-dev"
}

Fortunately this adds the DATABASE_URL environment (config) variable for us.

Tip

After the first deployment you may want to define a formation, which is Heroku's term for the actual instances that run the app. We want a web formation, which is defined by adding the following to infrastructure/heroku.tf,

resource "heroku_formation" "tozo-web" {
  app      = heroku_app.tozo.name
  type     = "web"
  quantity = 1
  size     = "Hobby"
}

We've used small hobby instances for the DB and app instances, you may want bigger machines depending on your workload.