All blog posts
Article

Introducing the Koyeb Terraform Provider

12 min

Koyeb provides developers the fastest way to deploy full stack applications and APIs globally. Sign up today to start using Terraform and deploy 2 services for free forever!

Today, we are glad to release the Koyeb Terraform Provider and announce that we are a Hashicorp Technology partner. Terraform has become an essential tool for many developers who manage infrastructure and applications running in the cloud. We are excited to offer our users a way to manage their Koyeb resources using Terraform.

Using the Koyeb Terraform provider allows you to keep track of your changes across your Koyeb resources: apps, services, domains, and secrets. This provider enriches the Koyeb developer toolbox, which already includes the Koyeb CLI, SDKs, and API.

Ready to start using Terraform to manage your Koyeb resources? In this post, we will showcase how to use the Koyeb Terraform Provider to deploy a minimalistic application configured with a custom domain.

What is Terraform?

Terraform is a popular infrastructure-as-code tool that allows you to define, change, and version manage your infrastructure in a safe, efficient, and declarative way. It uses a high-level configuration syntax called HCL (HashiCorp Configuration Language) to describe your infrastructure, which lets you organize your infrastructure in small pieces for better maintainability and reusability.

When using Terraform, you create a .tf configuration file, which contains a declarative description of your infrastructure. Terraform then uses this configuration to generate an execution plan describing what the desired state of your infrastructure should be, and then executes this plan to reflect the actual changes to your infrastructure.

Installing Terraform and the Koyeb provider

To get started, if you don't already have Terraform installed on your machine, follow the installation instruction for your system.

The Koyeb Terraform provider is officially available on the Terraform Registry, and will be installed automatically when specified in the required_providers block of the Terraform configuration file:

terraform {
  required_providers {
    koyeb = {
      source = "koyeb/koyeb"
      version = "0.1.2"
    }
  }
}

Configure your API key

To be able to manage Koyeb resources using Terraform, you first need a Koyeb API access token to allow Terraform to authenticate to Koyeb. To retrieve your Koyeb API access token, go to your Account settings and click the Create API Access Token button.

Give your API access token a name and description to differentiate it from other tokens and save the generated token in a safe place, you will not be able to see it again.

Then, to use your Koyeb API access token to authenticate the Terraform Koyeb provider, set the KOYEB_TOKEN environment variable running the following command:

export KOYEB_TOKEN=<YOUR_KOYEB_API_ACCESS_TOKEN>

We are now ready to create and deploy our first application using Terraform.

Create and deploy an application

We will first create and deploy a simple Golang application on Koyeb. Then, in another section, we will add a custom domain to reach our Koyeb App using your own custom domain.

Open your terminal and navigate to a location of your choice and create a directory that will store the Terraform configuration file and variable definition:

mkdir koyeb-terraform/
cd koyeb-terraform/

Create a new file named variables.tf with the following content. This file is used to store the variable definition that we will use in the Terraform configuration file:

variable "app_name" {
  description = "Koyeb app name"
  default     = "sample-app"
}

variable "service_name" {
  description = "Koyeb service name"
  default     = "sample-service"
}

variable "domain_name" {
  description = "Koyeb domain name"
  default     = "your.domain.tld"
}

You are fed to change the default values above with your own. The app_name and service_name variables will be used to name the Koyeb app and service that will be created. The domain_name variable contains the custom domain we will assign to the Koyeb app.

Then, create a new file main.tf with the following content:

terraform {
  required_providers {
    koyeb = {
      source = "koyeb/koyeb"
      version = "0.1.2"
    }
  }
}

resource "koyeb_app" "sample-app" {
  name = var.app_name
}

resource "koyeb_service" "sample-service" {
  app_name = var.app_name
  definition {
    name = var.service_name
    instance_types {
      type = "micro"
    }
    ports {
      port     = 8080
      protocol = "http"
    }
    scalings {
      min = 1
      max = 1
    }
    env {
      key   = "PORT"
      value = "8080"
    }
    routes {
      path = "/"
      port = 8080
    }
    regions = ["fra"]
    git {
      repository = "github.com/koyeb/example-golang"
      branch     = "main"
    }
  }

  depends_on = [
    koyeb_app.sample-app
  ]
}

The configuration below describes our infrastructure and contains the resources that we will provision on Koyeb:

  • A Koyeb app named sample-app defined under the koyeb_app resource block
  • A Koyeb service sample-service defined in the koyeb_service resource block containing the service definition

You may notice that we use var.xxx to reference the variables defined in the variables.tf file to give the name of the Koyeb app and service resource.

Initialize Terraform

Before creating a plan file and applying the changes, we need to run the terraform init command to initialize our Terraform working directory:

terraform init

If you followed the previous steps properly, the initialization should occur successfully.

Create a plan file

Before applying the configuration, we will run the terraform plan command. This command reports the changes that will be made to your infrastructure but does not apply them.

In a terminal, run the following command to visualize the changes that will be made to our infrastructure:

$ terraform plan -out tf.plan

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:

  # koyeb_app.sample-app will be created
  + resource "koyeb_app" "sample-app" {
      + created_at      = (known after apply)
      + domains         = (known after apply)
      + id              = (known after apply)
      + name            = "sample-app"
      + organization_id = (known after apply)
      + updated_at      = (known after apply)
    }

  # koyeb_service.sample-service will be created
  + resource "koyeb_service" "sample-service" {
      + active_deployment = (known after apply)
      + app_id            = (known after apply)
      + app_name          = "sample-app"
      + created_at        = (known after apply)
      + id                = (known after apply)
      + latest_deployment = (known after apply)
      + messages          = (known after apply)
      + name              = (known after apply)
      + organization_id   = (known after apply)
      + paused_at         = (known after apply)
      + resumed_at        = (known after apply)
      + status            = (known after apply)
      + terminated_at     = (known after apply)
      + updated_at        = (known after apply)
      + version           = (known after apply)

      + definition {
          + name    = "sample-service"
          + regions = [
              + "fra",
            ]

          + env {
              + key   = "PORT"
              + value = "8080"
            }

          + git {
              + branch     = "main"
              + repository = "github.com/koyeb/example-golang"
            }

          + instance_types {
              + type = "micro"
            }

          + ports {
              + port     = 8080
              + protocol = "http"
            }

          + routes {
              + path = "/"
              + port = 8080
            }

          + scalings {
              + max = 1
              + min = 1
            }
        }
    }

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

──────────────────────────────────────────────────────────────────────────────────────────────────

Saved the plan to: tf.plan

To perform exactly these actions, run the following command to apply:
    terraform apply "tf.plan"

Above is the output of the terraform plan command. It shows a wealth of information about the resources that will be created and the changes that will be made to your infrastructure.

Apply the changes

With the plan file created and everything looking as expected, we can apply the generated plan by running the command:

$ terraform apply tf.plan

koyeb_app.sample-app: Creating...
koyeb_app.sample-app: Creation complete after 0s [id=78eef767-211f-4d02-a468-cea43c9f9201]
koyeb_service.sample-service: Creating...
koyeb_service.sample-service: Creation complete after 1s [id=164e971f-fbb7-4176-97cd-e7205787f01e]

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Koyeb console

Now, if you go to the Koyeb console, you should see the Koyeb app and service have been created successfully using the configuration defined in the main.tf file.

Once your Koyeb service becomes healthy, you can perform a request to the Koyeb app public domain to ensure the application is properly running:

curl https://sample-app-<your-org-name>.koyeb.app/
Hello from Koyeb

Update Terraform configuration to add a custom domain

We've learned how to create and deploy an application from scratch using Terraform on Koyeb.

We will now discover how to update the Terraform configuration to add a custom domain so we will be able to access our Koyeb Apps using our own domain. In this post, we use Cloudflare to manage our DNS and will use the Cloudflare Terraform provider to automatically create the DNS entry once the Koyeb domain is created.

Depending on your DNS provider, you may need to change the configuration slightly to match your provider. Various DNS providers have a Terraform provider to interact with their services like NS1, DNSimple, and more. You can explore the Terraform registry to find the provider that suits your needs.

If you use Cloudflare, you will need to create an API token and find your zone ID. You can learn how to by reading the following documentation.

Open the variables.tf file to add the variable cloudflare_zone_id we need to use with the Cloudflare Terraform provider:

variable "app_name" {
  description = "Koyeb app name"
  default     = "sample-app"
}

variable "service_name" {
  description = "Koyeb service name"
  default     = "sample-service"
}

variable "domain_name" {
  description = "Koyeb domain name"
  default     = "your.domain.tld"
}

variable "cloudflare_zone_id" { 
    description = "Cloudflare zone ID"
    default     = "your-cloudflare-zone-id"
} 

Then, open the main.tf file to add:

  • Cloudflare as a required provider
  • The koyeb_domain resource block to define the domain we will create on Koyeb and assign it to the Koyeb app
  • The cloudflare_record resource block used to create the CNAME record on Cloudflare once the Koyeb domain is created
terraform {
  required_providers {
    koyeb = {
      source = "koyeb/koyeb"
    }
    cloudflare = { 
      source  = "cloudflare/cloudflare"
      version = "~> 3.0"
    } 
  }
}

resource "koyeb_app" "sample-app" {
  name = var.app_name
}

resource "koyeb_service" "sample-service" {
  app_name = var.app_name
  definition {
    name = var.service_name
    instance_types {
      type = "micro"
    }
    ports {
      port     = 8080
      protocol = "http"
    }
    scalings {
      min = 1
      max = 1
    }
    env {
      key   = "PORT"
      value = "8080"
    }
    routes {
      path = "/"
      port = 8080
    }
    regions = ["fra"]
    git {
      repository = "github.com/koyeb/example-golang"
      branch     = "main"
    }
  }

  depends_on = [
    koyeb_app.sample-app
  ]
}

+resource "koyeb_domain" "sample-custom-domain" {
+  name     = var.domain_name
+  app_name = var.app_name
+  depends_on = [
+    koyeb_app.sample-app
+  ]
+}

+resource "cloudflare_record" "www" {
+  zone_id = var.cloudflare_zone_id
+  name    = "terraform"
+  value   = koyeb_domain.sample-custom-domain.intended_cname
+  type    = "CNAME"
+  ttl     = 3600
+}

As we edit our configuration to use a new provider, we need to run the terraform init -upgrade command to download the provider.

Then, set the CLOUDFLARE_API_TOKEN environment variable with your Cloudflare API token as the value to allow Terraform to interact with the Cloudflare API.

export CLOUDFLARE_API_TOKEN=<YOUR_CLOUDFLARE_API_TOKEN>

We can now generate a new plan and preview incoming changes:

$ terraform plan -out tf.plan

koyeb_app.sample-app: Refreshing state... [id=78eef767-211f-4d02-a468-cea43c9f9201]
koyeb_service.sample-service: Refreshing state... [id=164e971f-fbb7-4176-97cd-e7205787f01e]

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:

  # cloudflare_record.www will be created
  + resource "cloudflare_record" "www" {
      + allow_overwrite = false
      + created_on      = (known after apply)
      + hostname        = (known after apply)
      + id              = (known after apply)
      + metadata        = (known after apply)
      + modified_on     = (known after apply)
      + name            = "terraform"
      + proxiable       = (known after apply)
      + ttl             = 3600
      + type            = "CNAME"
      + value           = (known after apply)
      + zone_id         = "e24547a91acfd4f769259fad48f97e5e"
    }

  # koyeb_domain.sample-custom-domain will be created
  + resource "koyeb_domain" "sample-custom-domain" {
      + app_name         = "sample-app"
      + created_at       = (known after apply)
      + deployment_group = (known after apply)
      + id               = (known after apply)
      + intended_cname   = (known after apply)
      + messages         = (known after apply)
      + name             = "your.domain.tld"
      + organization_id  = (known after apply)
      + status           = (known after apply)
      + type             = (known after apply)
      + updated_at       = (known after apply)
      + verified_at      = (known after apply)
      + version          = (known after apply)
    }

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

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

Saved the plan to: tf.plan

To perform exactly these actions, run the following command to apply:
    terraform apply "tf.plan"

Note that the plan indicates 2 to add, 0 to change, 0 to destroy. This is expected as we only add new resources to our configuration and didn't delete or modify the existing ones.

Apply the plan by running:

terraform apply tf.plan

Check the Koyeb control panel, our domain has been created and is now assigned to our app. On the Cloudflare control panel, the CNAME record has been created and is now pointing to the Koyeb domain.

You can now access your app on the domain you defined in the variables.tf file, for example your.domain.tld.

Conclusion

You now have everything you need to manage your Koyeb resources using Terraform. The provider is available via the official Terraform Registry and you can learn more about available resources and how to use them by reading the documentation.

If you have any comments, feature requests or simply want to contribute, the code is available on GitHub.

Ready to give the platform a try? Sign up for Koyeb and receive $5 per month of free credit. This lets you run two nano services and use up to 512MB of RAM each month. 😉

Not ready to say goodbye? You're welcome to join the friendliest serverless community or tweet us at @gokoyeb. We'd love to hear from you!

Koyeb

Welcome to Koyeb

Koyeb is a developer-friendly serverless platform to deploy any apps globally.

  • Start for free, pay as you grow
  • Deploy your first app in no time
Start for free
The fastest way to deploy applications globally.