Cosmoner Docs
SDKs

Terraform

Manage apps, databases, Redis, buckets, secrets, variables, webhook endpoints, SSH keys and resource groups as code with the Cosmoner Terraform provider.

The Cosmoner provider is published on the Terraform Registry as datablock-dev/cosmoner. It manages your project through the same public API and the same API keys as the SDKs and the CLI, so anything you create with it shows up in the control panel like everything else.

Setup

Add the provider to your configuration:

terraform {
  required_providers {
    cosmoner = {
      source  = "datablock-dev/cosmoner"
      version = "~> 0.2"
    }
  }
}

provider "cosmoner" {}

Then give it a key through the environment, the same variables the CLI reads:

export COSMONER_API_KEY="cos_pk_..."
export COSMONER_PROJECT_ID="your-project-id"
terraform init
VariableProvider argument
COSMONER_API_KEYapi_keyRequired. Keep it in the environment rather than in your configuration, where it would end up in version control.
COSMONER_PROJECT_IDproject_idThe project resources are created in. A resource can set its own project_id instead.
COSMONER_API_URLapi_urlDefaults to https://api.cosmoner.com.

A value set in the provider block wins over the environment.

Use a project key for CI and anything shared. A personal access token also works. A token is not tied to one project, so then set project_id on the provider or on each resource.

What it manages

ResourceWhat it isScopes the key needs
cosmoner_appAn app, built from a repository or run from an imageapps:read, apps:write
cosmoner_postgres_databaseA PostgreSQL databasedatabases:read, databases:write
cosmoner_redis_databaseA Redis databaseredis:read, redis:write
cosmoner_bucketAn object storage bucketobject-storage:read, object-storage:write
cosmoner_secretA project secretsecrets:read, secrets:write
cosmoner_variableA project variablevariables:read, variables:write
cosmoner_webhook_endpointA webhook endpointwebhooks:read, webhooks:write
cosmoner_ssh_keyAn SSH key for serversservers:read, servers:write
cosmoner_resource_groupA resource groupprojects:read, projects:write

The cosmoner_project data source reads the project itself and needs projects:read.

Writing secrets and variables also needs the owner or admin role. A project key acts with its service account's role, so give that service account the admin role if Terraform manages your secrets.

The Registry has the full reference for every resource, with all of its arguments.

Example: an app with a database

resource "cosmoner_postgres_database" "main" {
  name    = "main"
  size    = "postgres-cosmoner-1vcpu-1gb"
  version = "17"
  region  = "se-sto"

  # Changing the size or version replaces the database, and its data with it.
  lifecycle {
    prevent_destroy = true
  }
}

resource "cosmoner_secret" "database_url" {
  name  = "DATABASE_URL"
  value = cosmoner_postgres_database.main.connection_uri
}

resource "cosmoner_app" "api" {
  name          = "api"
  size          = "shared-s"
  region        = "se-sto"
  git_provider  = "github"
  git_repo      = "acme/api"
  git_branch    = "main"
  auto_deploy   = true
  public_port   = 3000
  build_command = "npm run build"
  run_command   = "npm start"
}

output "api_url" {
  value = cosmoner_app.api.url
}

The app reads DATABASE_URL once you link the secret into its environment, which you do in the control panel.

Things to know

Apps, databases, Redis and buckets are billed from the moment they exist, exactly as if you had created them in the control panel. terraform apply waits until each one is ready, up to the create time in its timeouts block. One that fails to start, or is still starting at the deadline, stays in your state marked as tainted: the next apply replaces it and terraform destroy removes it. The provider never deletes it on its own, so you can still read the failed deploy's logs.

Databases and Redis cannot be resized in place. Changing their size, version or region replaces them, data included. Add lifecycle { prevent_destroy = true } to anything that holds data you care about.

Secret values cannot be read back. Cosmoner never returns a secret's value after it is set, so the provider notices a change made elsewhere from the secret's version number instead, and sets your configured value again on the next apply. On Terraform 1.11 or later, use value_wo with value_wo_version to keep the value out of your state file entirely.

Existing resources can be imported as <project_id>/<id>, or just <id> when the provider has a project:

terraform import cosmoner_app.api clx0app

On this page