How to Fix Terraform Permission Denied on DigitalOcean Droplet
Troubleshooting Guide: Terraform Permission Denied on DigitalOcean Droplet
As a Senior DevOps Engineer, encountering “Permission Denied” errors is a common rite of passage. When working with Terraform on a DigitalOcean Droplet, this usually points to an issue with how Terraform is authenticating with the DigitalOcean API. This guide will walk you through diagnosing and resolving such issues.
1. The Root Cause: API Token Authentication
When Terraform attempts to provision or manage resources on DigitalOcean, it acts on your behalf by making API calls. For these calls to be authorized, Terraform requires a valid DigitalOcean API token with sufficient permissions. The “Permission Denied” error almost invariably means one of the following:
- Missing API Token: Terraform cannot find any DigitalOcean API token configured in its environment or configuration files.
- Invalid API Token: The provided token is incorrect, expired, or has been revoked.
- Insufficient Permissions (Scope): The API token exists and is valid, but it lacks the necessary read/write scopes to perform the specific actions Terraform is attempting (e.g., a read-only token trying to create a Droplet).
The DigitalOcean Droplet itself is merely the execution environment. It does not inherently grant Terraform permissions to manage other DigitalOcean resources; the API token is the key.
2. Quick Fix (CLI): Verify and Set Environment Variables
The fastest way to test and resolve token issues is by using environment variables. Terraform’s DigitalOcean provider prioritizes environment variables if no token is explicitly defined in the provider block.
Steps:
-
Check for Existing Token: First, see if any DigitalOcean token is already set in your current shell session on the Droplet.
echo $DO_TOKEN echo $DIGITALOCEAN_TOKENIf either command returns a long string, you have a token set. If it’s empty, no token is configured via these common environment variables.
-
Generate/Retrieve a DigitalOcean API Token:
- Log in to your DigitalOcean Control Panel.
- Navigate to API (in the left sidebar).
- Under “Tokens/Keys,” you can either:
- Find an existing read/write token (ensure it has the necessary permissions).
- Generate a New Token. Give it a descriptive name (e.g.,
terraform-droplet-access) and ensure it has Read and Write permissions.
- Copy the token immediately. DigitalOcean only displays it once.
-
Set the Token as an Environment Variable: On your Droplet, use the
exportcommand to set the token for your current shell session.export DO_TOKEN="your_digitalocean_api_token_here" # Alternatively, you can use DIGITALOCEAN_TOKEN # export DIGITALOCEAN_TOKEN="your_digitalocean_api_token_here"Replace
"your_digitalocean_api_token_here"with the actual token you copied from the DigitalOcean Control Panel. -
Re-run Terraform: After setting the environment variable, try your Terraform command again:
terraform plan # or terraform applyIf the issue was a missing or incorrect token, this should now proceed without a “Permission Denied” error.
Note: The export command sets the variable only for the current shell session. If you close the terminal or start a new session, the variable will be gone. For persistence, see the “Configuration Check” section.
3. Configuration Check: Persistent Solutions
For a more robust and persistent solution, you’ll want to configure the API token in a way that Terraform can reliably find it.
A. Terraform Provider Block Configuration (main.tf or provider.tf)
While environment variables are good for quick fixes and CI/CD pipelines, you can also define the token within your Terraform configuration using variables.
1. Define a Variable for the Token (variables.tf):
# variables.tf
variable "do_token" {
description = "DigitalOcean API Token"
type = string
sensitive = true # Mark as sensitive to prevent logging
}
2. Configure the Provider (main.tf or provider.tf):
# main.tf or provider.tf
terraform {
required_providers {
digitalocean = {
source = "digitalocean/digitalocean"
version = "~> 2.0" # Use your desired version
}
}
}
provider "digitalocean" {
token = var.do_token
}
3. Provide the Variable Value:
You have several secure options to provide the do_token value:
-
Via Environment Variable (Recommended for CI/CD/Ephemeral Execution): As shown in the “Quick Fix,” Terraform automatically picks up
TF_VAR_do_tokenif defined:export TF_VAR_do_token="your_digitalocean_api_token_here" -
Via
terraform.tfvars(for local development, with caution): Create a file namedterraform.tfvarsin your Terraform project root:# terraform.tfvars do_token = "your_digitalocean_api_token_here"CRITICAL SECURITY WARNING: Never commit
terraform.tfvars(or any file containing sensitive data) to version control (Git)! Addterraform.tfvarsto your.gitignorefile immediately:# .gitignore *.tfvars *.tfstate *.tfstate.backup .terraform/ -
Via CLI Flag (Least Recommended for Security/Usability):
terraform plan -var="do_token=your_digitalocean_api_token_here"This exposes the token in your shell history. Avoid.
B. Persistent Environment Variable in Droplet’s Shell RC File
To make the DO_TOKEN environment variable permanent for your user on the Droplet, add it to your shell’s configuration file:
-
Open your shell’s RC file:
- For Bash:
nano ~/.bashrc - For Zsh:
nano ~/.zshrc
- For Bash:
-
Add the
exportline: Add the following line to the end of the file:# DigitalOcean API Token for Terraform export DO_TOKEN="your_digitalocean_api_token_here"Replace
"your_digitalocean_api_token_here"with your actual token. -
Save and Exit:
- For Nano:
Ctrl+O,Enter,Ctrl+X
- For Nano:
-
Source the file: Apply the changes to your current session:
source ~/.bashrc # or source ~/.zshrcNow, the
DO_TOKENwill be available in all new shell sessions.
4. Verification
After applying any of the fixes above, verify that Terraform can now successfully authenticate and plan changes.
-
Run
terraform plan:cd /path/to/your/terraform/project terraform init # Ensure providers are initialized terraform plan -
Expected Outcome:
- Success: You should see a plan output detailing the resources Terraform intends to create, modify, or destroy, without any “Permission Denied” errors. This confirms successful API authentication.
- Failure: If you still encounter “Permission Denied,” double-check:
- The token itself in the DigitalOcean Control Panel (Is it valid? Is it revoked? Does it have Read and Write permissions?).
- Typos in the token when setting the environment variable or in
terraform.tfvars. - Whether the environment variable is correctly sourced or the
terraform.tfvarsfile is in the right place and ignored by.gitignore.
By systematically checking your API token and its configuration, you can quickly overcome “Permission Denied” errors and get back to deploying your infrastructure on DigitalOcean.