How to Use DigitalOcean's Spaces as a Remote State Backend for IaC


I recently started building a remote homelab within Digital Ocean’s cloud space and I wanted to see if I could leverage their “Spaces Object Storage” as a compatible remote backend for OpenTofu. At this point I have been using OpenTofu’s “local” backend setup to manage my state file but this isn’t a sustainable method nor actually used in professional setting. So lets migrate our local state over to a remote object storage.
Prerequisites:
Using
=>1.6
OpenTofu versionCreate your Digital Ocean account and project
Create a Spaces storage bucket (click here for instructions)
Create a Spaces access key (click here for instructions)
Approach
Spaces Object Storage is an S3 compatible object storage service. With this in mind we are going to reuse OpenTofu’s S3 backend support and extend it to a Spaces storage bucket. If you have have completed the required prerequisites, we can proceed forward.
Instructions
Set up required Environment Variables
Using environment variables is the recommended way to provide your Spaces access key. Other methods, such as tofu init -backend-config
or hardcoding values, may expose secrets in your .terraform
folder and plan files.
OpenTofu’s S3 backend leverages AWS_
prefixed environment variables for configuration. We will use these same variables but supply our Spaces access key values in place of AWS values.
export AWS_ACCESS_KEY_ID="<your_access_key>"
export AWS_SECRET_ACCESS_KEY="<your_secret_key>"
Replace the <your_access_key>
and <your_secret_key>
placeholders with your actual values.
Setup S3 Backend Configuration
Here is an example of my remote backend configuration. It uses OpenTofu’s S3
backend with DigitalOcean Spaces bucket values.
terraform {
required_version = "~> 1.9.0"
backend "s3" {
endpoints = {
s3 = "<spaces_bucket_region>.digitaloceanspaces.com"
}
bucket = "<spaces_bucket_name>"
key = "<path/and/state/file/name>"
# Deactivate a few AWS-specific checks
skip_credentials_validation = true
skip_requesting_account_id = true
skip_metadata_api_check = true
skip_region_validation = true
skip_s3_checksum = true
region = "us-east-1"
}
}
Values required:
S3
: Replace<spaces_bucket_region>
with the region of the bucket you created.bucket
: Replace<spaces_bucket_name>
with the name of your bucket.key
: Update<path/and/state/file/name>
with path and file name you would like to store your OpenTofu state under. If the path does not exist OpenTofu will create it when your initialize your IaC space.
Migrate or Initialize your State
At this point you should be ready to start using your newly setup remote state in DigitalOcean
Migrate local state to remote
tofu init -migrate-state
Initialize empty OpenTofu space
tofu init
Reference
Subscribe to my newsletter
Read articles from Christian Herrera directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Christian Herrera
Christian Herrera
Hey, I'm Chris 👨🏽💻👋🏽🤙🏽 I’m a seasoned Platform Engineer based in the LA area with extensive experience leading cloud engineering projects. I specialize in designing, deploying, and managing scalable, high-performance infrastructure using Kubernetes, Terraform, and cloud-native technologies. 💻 Currently, I’m leading Kubernetes-focused initiatives to enhance Developer Experience (DevEx) across cloud platforms like GCP and AWS. By streamlining workflows, optimizing infrastructure, and automating processes, I’m driving efficiency and empowering development teams to work faster and smarter. I’m deeply committed to building scalable, reliable, and cost-effective systems while mentoring teams to implement cloud-native best practices and elevate the overall development process.