---
title: "Write infrastructure with Terraform"
url: "https://docs.alisx.com/how-to/alis-build/write-infrastructure-with-terraform/"
---
# Write infrastructure with Terraform

Describe a service's cloud resources in its `infra/` folder so that Deploy can apply them into each deployment environment. Deploy runs Terraform with the platform's state backend and injects variables that identify the deployment environment, the product and the version being deployed.

## Prerequisites

- A built image, or at least a Dockerfile in the service folder. See [Write a Dockerfile for your service](https://docs.alisx.com/how-to/alis-build/write-a-dockerfile-for-your-service.md).
- Terraform familiarity: providers, variables, resources.

## Set up the module

Create `infra/main.tf` with the Google provider and a placeholder backend. The bucket and prefix are supplied at deploy time; leave the placeholder strings as they are.

```hcl title="infra/main.tf"
terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = ">= 6.0.0"
    }
  }
  backend "gcs" {
    bucket = "provided_at_runtime_by_alis"
    prefix = "provided_at_runtime_by_alis"
  }
}

provider "google" {
  project = var.ALIS_OS_PROJECT
}
```

## Declare the variables you use

Deploy injects a fixed set of `ALIS_*` variables. Declare the ones your module reads; you do not have to declare them all.

```hcl title="infra/variables.tf"
variable "ALIS_OS_PROJECT" {}                   # the environment's Google Cloud project id
variable "ALIS_OS_PRODUCT_PROJECT" {}           # the product's project, which hosts the image registry
variable "ALIS_OS_NEURON" {}                    # the service id, e.g. orders-v1
variable "ALIS_OS_NEURON_VERSION_COMMIT_SHA" {} # the built commit, used as the image tag
variable "ALIS_REGION" {}                       # the environment's region
variable "ALIS_PRODUCT_REGION" {}               # the product's region
```

Environment variables you set on the deployment environment (see [Manage environment variables](https://docs.alisx.com/how-to/alis-build/manage-environment-variables.md)) arrive as Terraform input variables of the same name. Declare those too:

```hcl
variable "API_URL" {}
```

A variable stored in Secret Manager is left out of the deploy; read it from the secret named after it in the deployment environment's project, for example with `data "google_secret_manager_secret_version"`.

## Deploy a Cloud Run service

```hcl title="infra/cloudrun.tf"
resource "google_project_service" "run" {
  service            = "run.googleapis.com"
  disable_on_destroy = false
}

resource "google_cloud_run_v2_service" "service" {
  name                = var.ALIS_OS_NEURON
  location            = var.ALIS_REGION
  deletion_protection = false

  template {
    scaling { max_instance_count = 10 }
    containers {
      image = "${var.ALIS_PRODUCT_REGION}-docker.pkg.dev/${var.ALIS_OS_PRODUCT_PROJECT}/neurons/${var.ALIS_OS_NEURON}:${var.ALIS_OS_NEURON_VERSION_COMMIT_SHA}"
      ports {
        name           = "h2c" # gRPC needs end-to-end HTTP/2; omit for plain HTTP
        container_port = 8080
      }
      env {
        name  = "ALIS_OS_PROJECT"
        value = var.ALIS_OS_PROJECT
      }
      env {
        name  = "ALIS_REGION"
        value = var.ALIS_REGION
      }
      resources {
        limits   = { cpu = "1000m", memory = "512Mi" }
        cpu_idle = true
      }
    }
    service_account = "alis-build@${var.ALIS_OS_PROJECT}.iam.gserviceaccount.com"
  }

  traffic {
    type    = "TRAFFIC_TARGET_ALLOCATION_TYPE_LATEST"
    percent = 100
  }
}
```

The image tag is the commit the version was built from, so each deploy pins exactly one build. Pass the values your code needs at run time as container `env` blocks; Terraform variables are not visible to the running container by themselves.

## Preview before you apply

Whenever `infra/*.tf` changed, plan first:

```bash title="Terminal"
alis deploy acme.sh.orders.v1 -e <env-id> --plan-only
```

A plan changes nothing and is never gated. When only infrastructure changed and the code did not, skip a rebuild with `alis build acme.sh.orders.v1 --retag --deploy -e <env-id>`.

## Related

- [Terraform variables](https://docs.alisx.com/reference/dbd/terraform-variables.md)
- [Deploy a version](https://docs.alisx.com/how-to/alis-build/deploy-a-version.md)
