Skip to content
cloudhostDocs
Get started

Terraform and OpenTofu

Write a project's infrastructure as code, keep it in git and make it with one apply. The provider is a client of the public API and nothing else: it sends the same requests the dashboard and the CLI send.

Install#

The provider installs from our own registry on ibel.ai, because the public registries are not reliable from inside Iran. It works with Terraform 1.5 or later and OpenTofu 1.6 or later.

terraform {
  required_providers {
    cloudhost = {
      source = "ibel.ai/cloudhost/cloudhost"
    }
  }
}

provider "cloudhost" {}

Sign in#

Make an API key (dashboard, Settings, API keys; or cloudhost keys create) and give it to the provider in the environment. Without it, the provider uses the key cloudhost login saved.

Terminal
export CLOUDHOST_API_KEY=chk_live_…
terraform init
terraform plan
SettingDefault
api_keyCLOUDHOST_API_KEY, then the key from cloudhost login
api_urlCLOUDHOST_API_URL, then https://api.ibel.ai
The key's role is what Terraform may do: viewer and billing keys only read; team members and webhooks need admin, and changing a member's role owner. A key belongs to one team, and everything is made in that team.

Resources#

Each resource has a data source of the same name that reads one that already exists, and every resource can be brought into the state with terraform import.

ResourceWhat it makesImport id
cloudhost_projecta function or an app (kind); renamed in place<name>
cloudhost_environment_variablea variable for some environments or one branch; plain or sensitive<project>/<KEY>
cloudhost_domaina custom domain; the DNS records to set in records<domain>
cloudhost_databasea SQL database; the password and connection string once<name>
cloudhost_cachea cache for any cache client and HTTP; the token once<name>
cloudhost_bucketa bucket; the team's storage key with its first bucket<name>
cloudhost_alertan alert rule; any change replaces the rule<id>
cloudhost_team_memberan invite, until the person joins; role and project limits<email>
cloudhost_webhooka signed webhook for the team or one project; the secret once<id>

A whole project#

resource "cloudhost_project" "api" {
  name = "shop-api"
  kind = "function"
}

resource "cloudhost_database" "shop" {
  name = "shop"
}

resource "cloudhost_cache" "sessions" {
  name          = "shop-sessions"
  max_memory_mb = 128
}

resource "cloudhost_environment_variable" "database_url" {
  project = cloudhost_project.api.name
  key     = "DATABASE_URL"
  value   = cloudhost_database.shop.connection_string
  type    = "sensitive"
}

resource "cloudhost_domain" "api" {
  project = cloudhost_project.api.name
  name    = "api.example.ir"
}

resource "cloudhost_alert" "errors" {
  project   = cloudhost_project.api.name
  metric    = "error_rate"
  op        = ">"
  threshold = 0.05
  channels  = { email = true }
}

resource "cloudhost_webhook" "deploys" {
  url     = "https://hooks.example.ir/deploys"
  events  = ["deployment.ready", "deployment.failed"]
  project = cloudhost_project.api.name
}

output "dns_records" {
  value = [for r in cloudhost_domain.api.records : "${r.host} ${r.type} ${r.value}"]
}

Ship code with cloudhost deploy or a git push as before; Terraform makes what the code runs on. A changed environment variable applies at once, without a new deployment.

Secrets in the state#

A database password, a cache token, the storage secret and a webhook's signing secret are shown by the API once, when they are made. The provider keeps them in the state so other resources can use them; keep the state where only your team can read it, and encrypted.

  • After an import these values are not known. For a database, change password_rotation to get a new password.
  • A sensitive variable's value never comes back; Terraform keeps the configured one. A plain value is read back, so a change made outside Terraform shows in the plan.

What does not change in place#

  • Databases, caches and buckets do not change in place: another max_memory_mb is a new, empty cache. Read the plan.
  • A database, cache or bucket a live version binds cannot be deleted, nor a bucket with objects in it. Remove the binding (deploy without it) or empty the bucket first.
  • Alerts have no update: a changed rule is made again.
  • A team member comes by invite; until they accept, status is invited. A role change on an invite withdraws it and sends a new one.
  • A webhook's project does not change in place: a new webhook and a new secret.