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.
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.
First, identify which credentials Terraform is using:
# 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 accountIf using a service account key file, extract the service account email:
# 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.jsonThe easiest fix is to grant the roles/compute.instanceAdmin.v1 role, which includes the compute.instances.create permission:
# Replace YOUR_PROJECT_ID and SERVICE_ACCOUNT_EMAIL
PROJECT_ID="your-project-id"
SERVICE_ACCOUNT_EMAIL="[email protected]"
# 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
If you need broader compute permissions beyond just instances:
PROJECT_ID="your-project-id"
SERVICE_ACCOUNT_EMAIL="[email protected]"
# 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.
For strict security compliance, create a custom role with only necessary permissions:
# 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.listCreate and assign the custom role:
PROJECT_ID="your-project-id"
SERVICE_ACCOUNT_EMAIL="[email protected]"
# 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"After granting the role, verify the permissions:
PROJECT_ID="your-project-id"
SERVICE_ACCOUNT_EMAIL="[email protected]"
# 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 \
--quietSimpler verification with gcloud:
# Test if the service account can create instances
gcloud compute instances list \
--project=$PROJECT_ID \
--account=$SERVICE_ACCOUNT_EMAIL \
--limit=1After granting permissions, ensure Terraform is configured correctly:
Option 1: Using environment variable
# Set the service account credentials
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account-key.json"
# Run Terraform
terraform plan
terraform applyOption 2: Configure in terraform.tf
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
# 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 applyOnce the service account has the necessary permissions, re-run Terraform:
# 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-approveIf 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
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:
# 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:
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:
gcloud services enable compute.googleapis.com --project=your-project-idTerraform can enable it automatically:
resource "google_project_service" "compute" {
project = "your-project-id"
service = "compute.googleapis.com"
}Error: Error rendering template: template not found
How to fix "template not found" error in Terraform
Error: Error generating private key
How to fix 'Error generating private key' in Terraform
Error creating Kubernetes Service: field is immutable
How to fix "field is immutable" errors in Terraform
Error: Error creating local file: open: permission denied
How to fix "Error creating local file: permission denied" in Terraform
Error: line endings have changed from CRLF to LF
Line endings have changed from CRLF to LF in Terraform