How to fix Required compute.instances.create permission in Terraform

TerraformINTERMEDIATEMEDIUMUpdated Dec 30, 2025· 96 views

The 'Required compute.instances.create permission' error occurs when your Terraform service account or user lacks the necessary IAM permissions to create Compute Engine VM instances on Google Cloud Platform. This happens when the identity used by Terraform doesn't have the compute.instances.create permission, typically because it's been granted an insufficient IAM role.

Quick fix

Fixes PERMISSION_DENIED

# Check GOOGLE_APPLICATION_CREDENTIALS environment variable
echo $GOOGLE_APPLICATION_CREDENTIALS

# Or check the terraform configuration
grep -r "credentials" terraform/

# Verify the service account in use
gcloud auth list

# Show the currently active service account
gcloud config get-value account
  1. Verify which service account Terraform is using
  2. Grant the compute.instanceAdmin.v1 role to the service account
  3. Alternative: Use compute.admin role for broader permissions
  4. Use a custom IAM role with minimal permissions (advanced)
terraform — error
# Check GOOGLE_APPLICATION_CREDENTIALS environment variable
echo $GOOGLE_APPLICATION_CREDENTIALS
# Or check the terraform configuration
grep -r "credentials" terraform/
# Verify the service account in use
gcloud auth list
# Show the currently active service account
gcloud config get-value account
Required compute.instances.create permission

What this error means

The "Required compute.instances.create permission" error indicates that Terraform is attempting to create a Google Compute Engine VM instance (using the `google_compute_instance` resource), but the authentication identity (service account or user) doesn't have the `compute.instances.create` IAM permission. This error occurs when: - Your service account has been granted roles with insufficient permissions - The service account only has project-level viewer roles without admin permissions - The IAM policy was not properly configured before running Terraform - A custom IAM role is missing the required permission - The service account credentials are expired or invalid - Cross-project resource creation is attempted without proper cross-project permissions This is a common issue when first setting up Terraform on GCP, as the principle of least privilege requires granting specific permissions rather than broad admin access.

Typical symptoms

  • Terraform apply fails immediately when creating google_compute_instance resources
  • Error message appears: 'Error 403: Required compute.instances.create permission'
  • Other GCP resources (networks, firewalls) can be created, but VM instances fail
  • The error occurs during terraform plan or terraform apply
  • Running terraform manually with gcloud works, but Terraform fails
  • Service account can read existing instances but cannot create new ones

Common causes

  1. Service account assigned only 'Viewer' role instead of compute admin roles
  2. Using a custom IAM role that doesn't include the compute.instances.create permission
  3. Service account permissions were revoked or never granted
  4. Using the wrong service account (check GOOGLE_APPLICATION_CREDENTIALS)
  5. Terraform provider credentials are configured with an insufficiently privileged user
  6. Cross-project deployment without proper service account configuration

How to fix "Required compute.instances.create permission"

1Verify which service account Terraform is using

First, identify which credentials Terraform is using:

bash
# Check GOOGLE_APPLICATION_CREDENTIALS environment variable
echo $GOOGLE_APPLICATION_CREDENTIALS

# Or check the terraform configuration
grep -r "credentials" terraform/

# Verify the service account in use
gcloud auth list

# Show the currently active service account
gcloud config get-value account

If using a service account key file, extract the service account email:

bash
# Extract service account email from key file
cat ~/.config/gcloud/service-account-key.json | grep "client_email"

# Or using jq
jq .client_email ~/.config/gcloud/service-account-key.json
2Grant the compute.instanceAdmin.v1 role to the service account

The easiest fix is to grant the roles/compute.instanceAdmin.v1 role, which includes the compute.instances.create permission:

bash
# Replace YOUR_PROJECT_ID and SERVICE_ACCOUNT_EMAIL
PROJECT_ID="your-project-id"
SERVICE_ACCOUNT_EMAIL="terraform@your-project-id.iam.gserviceaccount.com"

# Grant the role
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \
  --role="roles/compute.instanceAdmin.v1"

Note: roles/compute.instanceAdmin.v1 includes these key permissions:
- compute.instances.create
- compute.instances.delete
- compute.instances.get
- compute.instances.list
- compute.instances.setMetadata
- And many more compute-related permissions

3Alternative: Use compute.admin role for broader permissions

If you need broader compute permissions beyond just instances:

bash
PROJECT_ID="your-project-id"
SERVICE_ACCOUNT_EMAIL="terraform@your-project-id.iam.gserviceaccount.com"

# Grant the compute.admin role (most permissive for Compute Engine)
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \
  --role="roles/compute.admin"

This role grants full control over all Compute Engine resources. Use this if your Terraform manages networks, firewalls, and other compute resources.

4Use a custom IAM role with minimal permissions (advanced)

For strict security compliance, create a custom role with only necessary permissions:

yaml
# custom-terraform-role.yaml
title: "Terraform Compute Instance Manager"
description: "Minimal permissions for Terraform to manage Compute instances"
includedPermissions:
  - compute.instances.create
  - compute.instances.delete
  - compute.instances.get
  - compute.instances.list
  - compute.instances.setMetadata
  - compute.instances.setLabels
  - compute.instances.setServiceAccount
  - compute.disks.create
  - compute.disks.delete
  - compute.disks.get
  - compute.networks.get
  - compute.networks.list
  - compute.subnetworks.get
  - compute.subnetworks.list
  - compute.firewalls.create
  - compute.firewalls.delete
  - compute.firewalls.get
  - compute.firewalls.list
  - compute.images.get
  - compute.images.list

Create and assign the custom role:

bash
PROJECT_ID="your-project-id"
SERVICE_ACCOUNT_EMAIL="terraform@your-project-id.iam.gserviceaccount.com"

# Create the custom role
gcloud iam roles create terraformComputeManager \
  --project=$PROJECT_ID \
  --file=custom-terraform-role.yaml

# Grant the custom role to the service account
gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:$SERVICE_ACCOUNT_EMAIL" \
  --role="projects/$PROJECT_ID/roles/terraformComputeManager"
5Verify the service account has the required permissions

After granting the role, verify the permissions:

bash
PROJECT_ID="your-project-id"
SERVICE_ACCOUNT_EMAIL="terraform@your-project-id.iam.gserviceaccount.com"

# List all roles granted to the service account
gcloud projects get-iam-policy $PROJECT_ID \
  --flatten="bindings[].members" \
  --filter="bindings.members:serviceAccount:$SERVICE_ACCOUNT_EMAIL"

# Verify specific permission
gcloud projects test-iam-permissions $PROJECT_ID \
  --permissions="compute.instances.create" \
  --condition-from-file=condition.yaml \
  --quiet

Simpler verification with gcloud:

bash
# Test if the service account can create instances
gcloud compute instances list \
  --project=$PROJECT_ID \
  --account=$SERVICE_ACCOUNT_EMAIL \
  --limit=1
6Update Terraform with the corrected credentials

After granting permissions, ensure Terraform is configured correctly:

Option 1: Using environment variable

bash
# Set the service account credentials
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account-key.json"

# Run Terraform
terraform plan
terraform apply

Option 2: Configure in terraform.tf

hcl
terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

provider "google" {
  project     = "your-project-id"
  region      = "us-central1"
  credentials = file("~/.config/gcloud/service-account-key.json")
}

Option 3: Use gcloud for authentication

bash
# Authenticate with a service account
gcloud auth activate-service-account \
  --key-file=/path/to/service-account-key.json

# Set the project
gcloud config set project your-project-id

# Now Terraform will use these credentials
terraform plan
terraform apply
7Re-run Terraform with corrected permissions

Once the service account has the necessary permissions, re-run Terraform:

bash
# Refresh Terraform state to clear any cached errors
terraform refresh

# Re-run the plan
terraform plan

# If plan succeeds, apply the changes
terraform apply

# Monitor the apply process
terraform apply -auto-approve

If the error persists, check:
1. The role grant has fully propagated (can take up to 60 seconds)
2. You're using the correct service account
3. The credentials file hasn't been revoked
4. The project ID in terraform is correct

Advanced notes

Understanding GCP IAM Permissions

GCP uses a hierarchical permission model:
- Permissions are specific actions (e.g., compute.instances.create)
- Roles are collections of permissions (e.g., roles/compute.instanceAdmin.v1)
- Bindings connect members (users, service accounts) to roles on resources

The compute.instances.create permission specifically allows creating new Compute Engine VM instances via the Compute API.

Service Account Best Practices

1. Use a dedicated service account for Terraform: Never use a user account's personal credentials. Create a service account specifically for infrastructure provisioning.

2. Apply the principle of least privilege: Grant only the minimum permissions needed. Use custom roles rather than basic Editor/Owner roles when possible.

3. Rotate credentials regularly: Service account keys should be rotated every 90 days. Use Workload Identity for GKE instead of key files when possible.

4. Monitor service account usage: Enable Cloud Audit Logs to track what actions the service account performs.

5. Separate production and development service accounts: Use different service accounts with different permission levels.

Common Role Reference

| Role | Best For | Key Permissions |
|------|----------|-----------------|
| roles/compute.admin | Full compute control | All compute permissions |
| roles/compute.instanceAdmin.v1 | VM instance management | Create, delete, manage instances |
| roles/compute.networkAdmin | Network configuration | Networks, firewalls, routes |
| roles/compute.storageAdmin | Persistent disks | Create, manage storage |
| roles/serviceusage.admin | API enablement | Enable/disable APIs |

Cross-Project Service Accounts

If your Terraform needs to manage resources in multiple projects:

bash
# Grant permissions in the target project
gcloud projects add-iam-policy-binding TARGET_PROJECT_ID \
  --member="serviceAccount:terraform@SOURCE_PROJECT_ID.iam.gserviceaccount.com" \
  --role="roles/compute.instanceAdmin.v1"

# In Terraform, specify the target project explicitly
provider "google" {
  project = "target-project-id"
}

Terraform Service Account in Google Cloud

Use the google_service_account resource to create and manage service accounts via Terraform:

hcl
resource "google_service_account" "terraform" {
  account_id   = "terraform-sa"
  display_name = "Terraform Service Account"
  description  = "Service account used by Terraform for IaC"
}

resource "google_project_iam_member" "terraform_compute_admin" {
  project = "your-project-id"
  role    = "roles/compute.instanceAdmin.v1"
  member  = "serviceAccount:${google_service_account.terraform.email}"
}

However, this requires initial bootstrapping with an account that already has admin permissions. This is typically done in a separate bootstrap Terraform run.

Troubleshooting Authentication Issues

If you see authentication errors before the permission error:
1. Verify the key file exists and is readable
2. Check that the JSON format is valid (jq empty on the file)
3. Confirm the service account hasn't been deleted
4. Verify GOOGLE_APPLICATION_CREDENTIALS path is absolute

API Enablement

Before using google_compute_instance, ensure the Compute Engine API is enabled:

bash
gcloud services enable compute.googleapis.com --project=your-project-id

Terraform can enable it automatically:

hcl
resource "google_project_service" "compute" {
  project = "your-project-id"
  service = "compute.googleapis.com"
}

Frequently asked questions

What does "PERMISSION_DENIED" mean?
create IAM permission. This error occurs when: - Your service account has been granted roles with insufficient permissions - The service account only has project-level viewer roles without admin permissions - The IAM policy was not properly configured before running Terraform - A custom IAM role is missing the required permission - The service account credentials are expired or invalid - Cross-project resource creation is attempted without proper cross-project permissions This is a common issue when first setting up Terraform on GCP, as the principle of least privilege requires granting specific permissions rather than broad admin access.
How do I fix "PERMISSION_DENIED"?
The 'Required compute.instances.create permission' error occurs when your Terraform service account or user lacks the necessary IAM permissions to create Compute Engine VM instances on Google Cloud Platform. This happens when the identity used by Terraform doesn't have the compute.instances.create permission, typically because it's been granted an insufficient IAM role.
What causes "PERMISSION_DENIED"?
Service account assigned only 'Viewer' role instead of compute admin roles Using a custom IAM role that doesn't include the compute.instances.create permission Service account permissions were revoked or never granted
Is the "PERMISSION_DENIED" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading