Deploy a Project with Terraform

Deploy a Bahriya project with Terraform: set handle, name and regions, read quota outputs and attach vault items and configs with per-type resources.

Updated 18 Sept 20264 min read

A project is the top-level grouping for your containers, secrets, registries, and Memcached instances. Every other resource belongs to a project.

Required fields

FieldTypeDescription
handlestringA unique, permanent identifier. Cannot be reused after deletion.
namestringA human-readable display name.
regionslistOne or more region IDs where the project operates.

Minimal example

resource "bahriya_project" "app" {
  handle  = "my-app"
  name    = "My Application"
  regions = ["falkenstein-1"]
}

Multi-region project

resource "bahriya_project" "app" {
  handle  = "my-app"
  name    = "My Application"
  regions = ["falkenstein-1", "helsinki-1", "virginia-1"]
}

Using a data source to pick regions

data "bahriya_regions" "active" {
  status_filter = "active"
}
 
resource "bahriya_project" "app" {
  handle  = "my-app"
  name    = "My Application"
  regions = [data.bahriya_regions.active.regions[0].id]
}

Outputs

After creation, the project exposes:

AttributeDescription
idThe project UUID. Pass this to other resources as their project attribute.
handleThe handle you set.
effectivequotarequestcpuReserved CPU available to the project, per region.
effectivequotarequestmemoryReserved memory available to the project, per region.
effectivequotalimitcpuThe project's CPU ceiling, per region.
effectivequotalimitmemoryThe project's memory ceiling, per region.
output "project_id" {
  value = bahriya_project.app.id
}

Reading the quota from Terraform

The four effectivequota* attributes are the allowance every deployment into this project is checked against, and they are always populated — whether the project is on the standard allowance or has been granted a larger one. Read them when you want a plan to fail on your terms rather than on a refused apply:

output "project_cpu_allowance" {
  value = bahriya_project.app.effectivequotarequestcpu
}

The allowance applies separately in each region, so a project spanning three regions gets the full allowance in all three rather than a third of it in each. See Project Quotas for how the four figures relate and what to do when you need more.

There is also a matching set of plain quota* attributes. Those are null unless your project has been granted an allowance of its own, so prefer the effectivequota* ones in any expression that has to produce a number.

Attaching vault items, configs, registries, and secrets

The bahriya_project resource manages only the project's core fields (name, handle, regions). Attachments are managed by a separate per-type resource so each one is a first-class Terraform object you can plan, import, and destroy independently.

Available attachment resources:

ResourceAttaches
bahriya_project_registry_attachmentContainer registry credentials
bahriya_project_secret_attachmentOpaque secret
bahriya_project_tls_bundle_attachmentTLS bundle (CA + cert + key)
bahriya_project_x509_cert_attachmentX.509 certificate
bahriya_project_gpg_keypair_attachmentGPG keypair
bahriya_project_ssh_keypair_attachmentSSH keypair
bahriya_project_encryption_key_attachmentSymmetric encryption key
bahriya_project_env_file_attachment.env file
bahriya_project_yaml_config_attachmentYAML config
bahriya_project_json_config_attachmentJSON config
bahriya_project_plain_config_attachmentPlain-text config

Each resource takes a project_id (UUID) and a handle referring to an existing org-level item. Both attributes force replacement — to change either, Terraform will detach then re-attach.

resource "bahriya_project" "app" {
  handle  = "my-app"
  name    = "My Application"
  regions = ["falkenstein-1"]
}
 
resource "bahriya_tls_bundle" "edge" {
  handle = "edge-cert"
  name   = "Edge TLS"
  ca     = file("ca.pem")
  cert   = file("cert.pem")
  key    = file("key.pem")
}
 
resource "bahriya_project_tls_bundle_attachment" "edge_to_app" {
  project_id = bahriya_project.app.id
  handle     = bahriya_tls_bundle.edge.handle
}

Outputs

Each attachment exposes:

AttributeDescription
idComposite ID — {project_id}:{handle}. Use this when importing.
join_idIdentifier of the underlying project-attachment join row (returned by the API).

Importing

terraform import bahriya_project_tls_bundle_attachment.edge_to_app <project_uuid>:edge-cert

Wiring attached items into a container

Once an item is project-attached, container resources reference it via their own blocks (e.g. tls_bundles { handle = "edge-cert"; mount_path = "/etc/tls" } on the bahriya_container resource). Use Terraform's depends_on (or natural attribute references) to ensure the attachment lands before the container is created.

Notes

  • The id (UUID) is what other resources need — always use bahriya_project.x.id, not .handle, when setting the project attribute on containers, Memcached, etc.
  • Changing the handle forces Terraform to destroy and recreate the project.
  • Projects are soft-deleted. The handle is permanently consumed once used.