Skip to content

Instantly share code, notes, and snippets.

@pdmtt
Last active June 23, 2025 22:38
Show Gist options
  • Save pdmtt/7d48b95bd8c0592671f659e21d8a965e to your computer and use it in GitHub Desktop.
Save pdmtt/7d48b95bd8c0592671f659e21d8a965e to your computer and use it in GitHub Desktop.
Backblaze B2 bucket as Terraform's backend
set -e
BUCKET_NAME="terraformBackend"
TERRAFORM_BACKEND_CONFIG_FILE="terraform-backend-config.tfvars"
TERRAFORM_BACKEND_CREDENTIALS_FILE="terraform-backend-credentials.env"
# Install `b2` utility in a virtual environment.
python3 -m venv .venv
source .venv/bin/activate
pip3 install --upgrade --quiet b2
# Interactive authentication flow. Use an application key that can create buckets.
b2 account authorize
# Create the bucket that will be used to store Terraform's files.
b2 bucket create --default-server-side-encryption SSE-B2 "$BUCKET_NAME" allPrivate
# https://github.com/hashicorp/terraform/issues/36704
for varName in AWS_REQUEST_CHECKSUM_CALCULATION AWS_RESPONSE_CHECKSUM_VALIDATION; do
echo "$varName=\"when_required\"" >> "$TERRAFORM_CREDENTIALS_FILE"
done
# Complete Terraform's partial configuration.
# More info at https://developer.hashicorp.com/terraform/language/backend#partial-configuration.
echo "endpoints = { s3 = $(b2 account get | jq .s3endpoint) }" >> "$TERRAFORM_BACKEND_CONFIG_FILE"
echo "bucket = \"${BUCKET_NAME}\"" >> "$TERRAFORM_BACKEND_CONFIG_FILE"
# Using a subshell to avoid leaking secrets into the environment.
(
# Create a more restrictive application key to allow Terraform's access to the bucket.
mapfile -d ' ' -t arrKey <<< "$(\
b2 key create --bucket "$BUCKET_NAME" agenticCollabTerraformKey listBuckets,listAllBucketNames,readFiles,writeFiles \
| tr -d '\n' \
)"
# Variables that will be used by Terraform to authenticate with its backend storage service.
echo "$AWS_ACCESS_KEY_ID=\"${arrKey[0]}\"" >> "$TERRAFORM_CREDENTIALS_FILE"
echo "$AWS_SECRET_ACCESS_KEY=\"${arrKey[1]%$'\n'}\"" >> "$TERRAFORM_CREDENTIALS_FILE"
)
# Sensitive file! Restrict its access to user-only.
chmod 600 "$TERRAFORM_BACKEND_CREDENTIALS_FILE"
# According to Terraform's documentation, this is the recommended way to supply credentials:
# > Warning: We recommend using environment variables to supply credentials and other sensitive
# > data. If you use -backend-config or hardcode these values directly in your configuration,
# > Terraform will include these values in both the .terraform subdirectory and in plan files.
# https://developer.hashicorp.com/terraform/language/backend/s3#credentials-and-shared-configuration
#
# Using a subshell to avoid leaking secrets into the interactive shell's environment.
(
set -ea
source "$TERRAFORM_BACKEND_CREDENTIALS_FILE"
terraform init -backend-config="$TERRAFORM_BACKEND_CONFIG_FILE"
)
# Thanks to https://www.reddit.com/r/backblaze/comments/1j6sugw/how_to_use_backblaze_b2_as_a_terraform_backend/
terraform {
backend "s3" {
key = "terraform.tfstate"
region = "us-east-003" # Not used by Backblaze B2, but a required attribute for Terraform.
# As of May 2025, using a Backblaze B2 bucket as storage for the lockfile will render a 501 error:
# "A header you provided implies functionality that is not implemented"
#use_lockfile = true
# Skip all validations because this backend is not 100% compatible with Backblaze B2.
skip_credentials_validation = true
skip_metadata_api_check = true
skip_region_validation = true
skip_requesting_account_id = true
skip_s3_checksum = true
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment